1
git-svn-id: svn://db.shs.com.ru/libs@1 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
746
qglview/gltypes.cpp
Normal file
746
qglview/gltypes.cpp
Normal file
@@ -0,0 +1,746 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gltypes.h"
|
||||
#include "qglview.h"
|
||||
|
||||
QGLWidget * currentQGLView;
|
||||
GLTextureManager * currentGLTextureManager;
|
||||
Camera * currentCamera;
|
||||
QMatrix4x4 globCameraMatrix;
|
||||
QMutex globMutex;
|
||||
|
||||
|
||||
QString readCharsUntilNull(QDataStream & s) {
|
||||
QString str;
|
||||
char ch;
|
||||
s.readRawData(&ch, 1);
|
||||
while (ch != '\0') {
|
||||
str += ch;
|
||||
s.readRawData(&ch, 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void glDrawQuad(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
|
||||
glResetAllTransforms();
|
||||
glSetPolygonMode(GL_FILL);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(1.f, 1.f, 1.f);
|
||||
glTexCoord2f(0.f, 0.f); glVertex2f(x, y);
|
||||
glTexCoord2f(1.f, 0.f); glVertex2f(x + w, y);
|
||||
glTexCoord2f(1.f, 1.f); glVertex2f(x + w, y + h);
|
||||
glTexCoord2f(0.f, 1.f); glVertex2f(x, y + h);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
QMatrix4x4 getGLMatrix(GLenum matrix) {
|
||||
GLfloat gm[16];
|
||||
glGetFloatv(matrix, gm);
|
||||
qreal qm[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
qm[i] = gm[i];
|
||||
return QMatrix4x4(qm, 4, 4).transposed();
|
||||
}
|
||||
|
||||
|
||||
void createGLTexture(GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) {
|
||||
glClearError();
|
||||
if (tex == 0) {
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
}
|
||||
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32)
|
||||
glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||
else
|
||||
glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
//qDebug() << QString::number(glGetError(), 16);
|
||||
}
|
||||
|
||||
|
||||
void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format, const GLenum & target) {
|
||||
if (tex == 0) {
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(target, tex);
|
||||
}
|
||||
QImage im = QGLWidget::convertToGLFormat(image);
|
||||
//const QImage & cim(im);
|
||||
//glClearError();
|
||||
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) {
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
}
|
||||
glTexImage2D(target, 0, format, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
|
||||
//qDebug() << tex << im.width() << im.height() << im.bits() << glGetError();
|
||||
}
|
||||
|
||||
|
||||
bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir) {
|
||||
prog->removeAllShaders();
|
||||
QDir d(dir);
|
||||
QFileInfoList sl = d.entryInfoList(QStringList(name + ".geom"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
#if QT_VERSION >= 0x040700
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Geometry, i.absoluteFilePath());
|
||||
#endif
|
||||
sl = d.entryInfoList(QStringList(name + ".vert"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Vertex, i.absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList(name + ".frag"), QDir::Files | QDir::NoDotAndDotDot);
|
||||
foreach (const QFileInfo & i, sl)
|
||||
prog->addShaderFromSourceFile(QGLShader::Fragment, i.absoluteFilePath());
|
||||
if (!prog->link()) {
|
||||
qDebug() << "[QGLView] Shader \"" + name + "\" link error: " + prog->log();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QImage rotateQImageLeft(const QImage & im) {
|
||||
QImage ri(im.height(), im.width(), im.format());
|
||||
QPainter p(&ri);
|
||||
p.rotate(90);
|
||||
p.drawImage(0, -im.height(), im);
|
||||
p.end();
|
||||
return ri;
|
||||
}
|
||||
|
||||
|
||||
QImage rotateQImageRight(const QImage & im) {
|
||||
QImage ri(im.height(), im.width(), im.format());
|
||||
QPainter p(&ri);
|
||||
p.rotate(-90);
|
||||
p.drawImage(-im.width(), 0, im);
|
||||
p.end();
|
||||
return ri;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool GLCubeTexture::create() {
|
||||
//qDebug("create");
|
||||
destroy();
|
||||
glGenTextures(1, &id_);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id_);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
//glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
//glClearError();
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
//qDebug() << glGetError();
|
||||
changed_ = false;
|
||||
return id_ > 0;
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::load() {
|
||||
if (isEmpty()) return;
|
||||
create();
|
||||
if (!path(0).isEmpty()) loadFront(path(0));
|
||||
if (!path(1).isEmpty()) loadBack(path(1));
|
||||
if (!path(2).isEmpty()) loadLeft(path(2));
|
||||
if (!path(3).isEmpty()) loadRight(path(3));
|
||||
if (!path(4).isEmpty()) loadTop(path(4));
|
||||
if (!path(5).isEmpty()) loadBottom(path(5));
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::loadFromDirectory(const QString & dir) {
|
||||
QDir d(dir); QFileInfoList sl;
|
||||
sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath());
|
||||
sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath());
|
||||
}
|
||||
|
||||
|
||||
void GLCubeTexture::loadPathesFromDirectory(const QString & dir) {
|
||||
QDir d(dir); QFileInfoList sl;
|
||||
sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath();
|
||||
sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership) {
|
||||
int tid = ((GLTextureManagerBase*)currentGLTextureManager)->textureID(path);
|
||||
if (tid > 0) {
|
||||
//qDebug() << "[TextureManager] Found" << path << "as" << tid;
|
||||
return tid;
|
||||
}
|
||||
tid = currentQGLView->bindTexture(QImage(path), GL_TEXTURE_2D/*, GL_RGBA, QGLContext::MipmapBindOption*/);
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load" << path;
|
||||
return tid;
|
||||
}
|
||||
qDebug() << "[TextureManager] Loaded" << path << "as" << tid;
|
||||
if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids.insert(path, tid);
|
||||
/*GLenum err(0);
|
||||
im = currentQGLView->convertToGLFormat(im);
|
||||
glClearError();
|
||||
glGenTextures(1, &tid);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
qDebug() << "can`t generate texture," << err;
|
||||
return false;
|
||||
}
|
||||
//glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
glClearError();
|
||||
glBindTexture(GL_TEXTURE_2D, tid);
|
||||
qDebug() << "load" << im.width() << "x" << im.height();
|
||||
glClearError();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
|
||||
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
//glBindTexture(GL_TEXTURE_2D, 0);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
glDeleteTextures(1, &tid);
|
||||
qDebug() << "can`t load" << path << "," << err;
|
||||
return false;
|
||||
}
|
||||
currentGLTextureManager->tex_ids << tid;
|
||||
qDebug() << "loaded" << path << "as" << tid;*/
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
GLuint GLTextureManagerBase::loadTexture(const QImage & image, bool ownership) {
|
||||
GLuint tid = currentQGLView->bindTexture(image);
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load image";
|
||||
return tid;
|
||||
}
|
||||
//qDebug() << "[TextureManager] Loaded image as" << tid;
|
||||
if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids.insert(QString(), tid);
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
void Camera::anglesFromPoints() {
|
||||
QVector3D dv = aim_ - pos_, tv;
|
||||
tv = QVector3D(dv.x(), dv.y(), 0.);
|
||||
angle_z = atan2(tv.x(), tv.y()) * rad2deg;
|
||||
angle_xy = piClamp<GLdouble>(atan2(tv.length(), dv.z()) * rad2deg + 180., angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
}
|
||||
|
||||
|
||||
void Camera::apply(const GLdouble & aspect) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if (aspect <= 1.)
|
||||
glScaled(aspect, aspect, 1.);
|
||||
gluPerspective(fov_, aspect, depth_start, depth_end);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslated(0., 0., -distance());
|
||||
glRotated(angle_xy, 1., 0., 0.);
|
||||
glRotated(angle_roll, 0., -1., 0.);
|
||||
glRotated(angle_z, 0., 0., 1.);
|
||||
//glTranslated(pos_.x(), pos_.y(), pos_.z());
|
||||
//if (mirror_y) glScalef(1,-1,-1);
|
||||
//if (mirror_x) glScalef(-1,1,-1);
|
||||
//glScalef(-1,-1,1);
|
||||
glTranslated(-aim_.x(), -aim_.y(), -aim_.z());
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projection);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
||||
//qDebug() << "viewport" << viewport[0] << viewport[1] << viewport[2] << viewport[3];
|
||||
}
|
||||
|
||||
|
||||
void Camera::panZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::panXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::rotateZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::rotateXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::orbitZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z += a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::orbitXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy += a;
|
||||
angle_xy = piClamp<GLdouble>(angle_xy, angle_limit_lower_xy, angle_limit_upper_xy);
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::setAngleZ(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = QVector2D(dv.x(), dv.y()).length();
|
||||
angle_z = a;
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl, cos(angle_z * deg2rad) * tl, dv.z());
|
||||
aim_ = pos_ + dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::setAngleXY(const double & a) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length(), tc;
|
||||
angle_xy = a;
|
||||
tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
//pos_ = aim_ - dv;
|
||||
aim_ = pos_ + dv;
|
||||
//anglesFromPoints();
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveForward(const double & x, bool withZ) {
|
||||
QVector3D dv;// = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, 0.);
|
||||
if (withZ) dv.setZ(-cos(angle_xy * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveLeft(const double & x, bool withZ) {
|
||||
QVector3D dv;// = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad - M_PI_2) * tc, cos(angle_z * deg2rad - M_PI_2) * tc, 0.);
|
||||
if (withZ) dv.setZ(-sin(angle_roll * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::moveUp(const double & x, bool onlyZ) {
|
||||
QVector3D dv;
|
||||
if (onlyZ)
|
||||
dv = QVector3D(0., 0., x);
|
||||
else {
|
||||
double tc = cos(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tc, cos(angle_z * deg2rad) * tc, -sin(angle_xy * deg2rad));
|
||||
dv.normalize();
|
||||
dv *= x;
|
||||
}
|
||||
pos_ += dv;
|
||||
aim_ += dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyCloser(const double & s) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length() / (1. + s), tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyFarer(const double & s) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tl = dv.length() * (1. + s), tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * tl * tc, cos(angle_z * deg2rad) * tl * tc, -cos(angle_xy * deg2rad) * tl);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
void Camera::flyToDistance(const double & d) {
|
||||
QVector3D dv = aim_ - pos_;
|
||||
double tc = -sin(angle_xy * deg2rad);
|
||||
dv = QVector3D(sin(angle_z * deg2rad) * d * tc, cos(angle_z * deg2rad) * d * tc, -cos(angle_xy * deg2rad) * d);
|
||||
pos_ = aim_ - dv;
|
||||
}
|
||||
|
||||
|
||||
QVector3D Camera::pointFromViewport(int x_, int y_, double z_) {
|
||||
GLsizei mx = x_, my = viewport[3] - y_, mz = z_;
|
||||
GLdouble x,y,z;
|
||||
gluUnProject(mx, my, mz, modelview, projection, viewport, &x, &y, &z);
|
||||
return QVector3D(x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Material::Material(): reflection(512) {
|
||||
color_diffuse = color_specular = Qt::white;
|
||||
color_self_illumination = Qt::black;
|
||||
glass = false;
|
||||
transparency = reflectivity = 0.f;
|
||||
bump_scale = relief_scale = iof = 1.f;
|
||||
dispersion = 0.05f;
|
||||
shine = shine_strength = 0.f;
|
||||
light_model = Phong;
|
||||
}
|
||||
|
||||
|
||||
void Material::apply() {
|
||||
GLfloat mat_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat mat_specular[4] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||
GLfloat mat_emission[4] = {0.f, 0.f, 0.f, 1.0f};
|
||||
mat_diffuse[0] = color_diffuse.redF();
|
||||
mat_diffuse[1] = color_diffuse.greenF();
|
||||
mat_diffuse[2] = color_diffuse.blueF();
|
||||
mat_diffuse[3] = color_diffuse.alphaF() * (1.f - transparency);
|
||||
mat_specular[0] = shine_strength * color_specular.redF();
|
||||
mat_specular[1] = shine_strength * color_specular.greenF();
|
||||
mat_specular[2] = shine_strength * color_specular.blueF();
|
||||
mat_emission[0] = color_self_illumination.redF();
|
||||
mat_emission[1] = color_self_illumination.greenF();
|
||||
mat_emission[2] = color_self_illumination.blueF();
|
||||
glColor4f(mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]);
|
||||
//qDebug() << color_diffuse.alphaF() * (1.f - transparency);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, shine);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse);
|
||||
}
|
||||
|
||||
|
||||
void Material::loadTextures(GLTextureManagerBase * tm) {
|
||||
if (tm == 0) tm = (GLTextureManagerBase*)currentGLTextureManager;
|
||||
if (!diffuse.bitmap_path.isEmpty()) diffuse.bitmap_id = tm->loadTexture(diffuse.bitmap_path);
|
||||
if (!bump.bitmap_path.isEmpty()) bump.bitmap_id = tm->loadTexture(bump.bitmap_path);
|
||||
if (!relief.bitmap_path.isEmpty()) relief.bitmap_id = tm->loadTexture(relief.bitmap_path);
|
||||
if (!diffuse_2.bitmap_path.isEmpty()) diffuse_2.bitmap_id = tm->loadTexture(diffuse_2.bitmap_path);
|
||||
//qDebug() << "load" << reflection.path(0);
|
||||
reflection.load();
|
||||
}
|
||||
|
||||
|
||||
QColor colorFromString(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
double r, g, b;
|
||||
r = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
||||
g = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
|
||||
b = s.toFloat();
|
||||
return QColor(r * 255., g * 255., b * 255.);
|
||||
}
|
||||
|
||||
|
||||
QVector3D orthToVector(const QVector3D & v, const double & scale) {
|
||||
if (v.isNull()) return QVector3D();
|
||||
QVector3D rv, fn, sn;
|
||||
if (v.x() != 0) rv.setZ(1.);
|
||||
else if (v.y() != 0) rv.setX(1.);
|
||||
else rv.setY(1.);
|
||||
fn = QVector3D::crossProduct(v, rv).normalized();
|
||||
sn = QVector3D::crossProduct(v, fn).normalized();
|
||||
return fn * urand(scale) + sn * urand(scale);
|
||||
}
|
||||
|
||||
|
||||
QVector3D rotateVector(const QVector3D & v, const QVector3D & a) {
|
||||
QMatrix4x4 m;
|
||||
m.rotate(a.z(), 0., 0., 1.);
|
||||
m.rotate(a.y(), 0., 1., 0.);
|
||||
m.rotate(a.x(), 1., 0., 0.);
|
||||
return m * v;
|
||||
}
|
||||
|
||||
|
||||
void setVectorLength(QVector3D & v, const double & l) {
|
||||
double vl = v.length();
|
||||
if (vl == 0.) return;
|
||||
double c = l / vl;
|
||||
v *= c;
|
||||
}
|
||||
|
||||
|
||||
void lengthenVector(QVector3D & v, const double & l) {
|
||||
double vl = v.length();
|
||||
if (l == 0. || vl == 0.) return;
|
||||
double c = 1. + l / vl;
|
||||
v *= c;
|
||||
}
|
||||
|
||||
|
||||
Vector3d::Vector3d(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
x = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
||||
y = s.left(i).toFloat(); s = s.right(s.length() - i - 1);
|
||||
z = s.toFloat();
|
||||
}
|
||||
|
||||
|
||||
Vector3i::Vector3i(const QString & str) {
|
||||
QString s = str.trimmed();
|
||||
int i = s.indexOf("\t");
|
||||
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t");
|
||||
p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
|
||||
p2 = s.toInt();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) {
|
||||
QVector3D lp = l.worldPos(), ld = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized();
|
||||
GLfloat pos[] = {0.f, 0.f, 0.f, 0.f};
|
||||
GLfloat dir[] = {0.f, 0.f, 0.f};
|
||||
GLfloat col[] = {0.f, 0.f, 0.f};
|
||||
pos[0] = l.light_type == Light::Directional ? -l.direction.x() : lp.x();
|
||||
pos[1] = l.light_type == Light::Directional ? -l.direction.y() : lp.y();
|
||||
pos[2] = l.light_type == Light::Directional ? -l.direction.z() : lp.z();
|
||||
pos[3] = l.light_type == Light::Directional ? 0. : 1.;
|
||||
dir[0] = ld.x();
|
||||
dir[1] = ld.y();
|
||||
dir[2] = ld.z();
|
||||
col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.;
|
||||
col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.;
|
||||
col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.;
|
||||
glEnable(gl_index);
|
||||
//glLightfv(gl_index, GL_AMBIENT, ambient);
|
||||
glLightfv(gl_index, GL_DIFFUSE, col);
|
||||
glLightfv(gl_index, GL_SPECULAR, col);
|
||||
glLightfv(gl_index, GL_POSITION, pos);
|
||||
glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const);
|
||||
glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear);
|
||||
glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic);
|
||||
if (l.light_type == Light::Cone) {
|
||||
glLightfv(gl_index, GL_SPOT_DIRECTION, dir);
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_spread);
|
||||
glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp);
|
||||
} else {
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, 180.);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) {
|
||||
GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f};
|
||||
if (first_pass) {
|
||||
ambient[0] = view.ambientColor_.redF();
|
||||
ambient[1] = view.ambientColor_.greenF();
|
||||
ambient[2] = view.ambientColor_.blueF();
|
||||
}
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupShadersLights(int lights_count) {
|
||||
/*foreach (QGLShaderProgram * i, view.shaders_ppl) {
|
||||
i->bind();
|
||||
i->setUniformValue("lightsCount", lights_count);
|
||||
i->setUniformValue("acc_light", lights_count > 0);
|
||||
//i->setUniformValue("mat", mvm);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupTextures(GLObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) {
|
||||
if (first_object) {
|
||||
glReleaseTextures();
|
||||
return;
|
||||
}
|
||||
setupShadersTextures(o, rp);
|
||||
Material & mat(o.material_);
|
||||
if (rp.light) {
|
||||
if (o.accept_light) {if (!rp.prev_light) {glSetLightEnabled(true); rp.prev_light = true;}}
|
||||
else {if (rp.prev_light) {glSetLightEnabled(false); rp.prev_light = false;}}
|
||||
}
|
||||
if (rp.fog) {
|
||||
if (o.accept_fog) {if (!rp.prev_fog) {glSetFogEnabled(true); rp.prev_fog = true;}}
|
||||
else {if (rp.prev_fog) {glSetFogEnabled(false); rp.prev_fog = false;}}
|
||||
}
|
||||
if (rp.textures) {
|
||||
if (rp.prev_tex[0] != mat.diffuse.bitmap_id) {
|
||||
rp.prev_tex[0] = mat.diffuse.bitmap_id;
|
||||
glActiveTextureChannel(0); glBindTexture(GL_TEXTURE_2D, mat.diffuse.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
if (rp.prev_tex[1] != mat.bump.bitmap_id) {
|
||||
rp.prev_tex[1] = mat.bump.bitmap_id;
|
||||
glActiveTextureChannel(1); glBindTexture(GL_TEXTURE_2D, mat.bump.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
if (rp.prev_tex[2] != mat.relief.bitmap_id) {
|
||||
rp.prev_tex[2] = mat.relief.bitmap_id;
|
||||
glActiveTextureChannel(2); glBindTexture(GL_TEXTURE_2D, mat.relief.bitmap_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
glActiveTextureChannel(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupLights(int pass, int lights_per_pass) {
|
||||
int light_start, light_end, lmax;
|
||||
light_start = pass * lights_per_pass;
|
||||
light_end = qMin<int>((pass + 1) * lights_per_pass, view.lights_.size());
|
||||
setupAmbientLight(view.ambientColor_, pass == 0);
|
||||
if (!view.lights_.isEmpty()) {
|
||||
setupShadersLights(light_end - light_start);
|
||||
for (int i = light_start; i < light_end; ++i)
|
||||
setupLight(*view.lights_[i], i - light_start, GL_LIGHT0 + i - light_start);
|
||||
lmax = light_start + 8;
|
||||
for (int i = light_end; i < lmax; ++i)
|
||||
glDisable(GL_LIGHT0 + i - light_start);
|
||||
} else {
|
||||
setupShadersLights(0);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::applyFilteringParameters() {
|
||||
if (view.linearFiltering_) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) {
|
||||
RenderingParameters rp;
|
||||
rp.pass = pass;
|
||||
rp.light_pass = light_pass;
|
||||
rp.shaders = shaders;
|
||||
rp.textures = textures;
|
||||
rp.light = rp.prev_light = light;
|
||||
rp.fog = rp.prev_fog = fog;
|
||||
for (int i = 0; i < 32; ++i) rp.prev_tex[i] = 0;
|
||||
rp.prev_light_model = Material::Phong;
|
||||
setupTextures(view.objects_, rp, true);
|
||||
glSetLightEnabled(rp.prev_light);
|
||||
glSetFogEnabled(rp.prev_fog);
|
||||
glSetCapEnabled(GL_TEXTURE_2D, rp.textures);
|
||||
glSetCapEnabled(GL_BLEND, pass == GLObjectBase::Transparent);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
renderSingleObject(view.objects_, rp);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & rp) {
|
||||
if (!o.isInit())
|
||||
o.init();
|
||||
if (!o.isTexturesLoaded())
|
||||
o.loadTextures();
|
||||
if (!o.visible_) return;
|
||||
Material & mat(o.material_);
|
||||
glPushMatrix();
|
||||
if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_);
|
||||
if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.);
|
||||
if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.);
|
||||
if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.);
|
||||
if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_);
|
||||
if (rp.pass == o.pass_) {
|
||||
setupTextures(o, rp, false);
|
||||
mat.apply();
|
||||
glSetPolygonMode(o.render_mode != GLObjectBase::View ? o.render_mode : (view.rmode != GLObjectBase::View ? view.rmode : GL_FILL));
|
||||
glLineWidth(o.line_width > 0. ? o.line_width : view.lineWidth_);
|
||||
glPointSize(o.line_width > 0. ? o.line_width : view.lineWidth_);
|
||||
o.update();
|
||||
if (o.pass_ == GLObjectBase::Transparent) {
|
||||
glActiveTextureChannel(3);
|
||||
if (mat.reflectivity > 0.) {
|
||||
glEnable(GL_TEXTURE_CUBE_MAP);
|
||||
if (!mat.reflection.isEmpty()) mat.reflection.bind();
|
||||
else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
} else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
if (rp.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity};
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc);
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, gm);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadTransposeMatrixf(gm);
|
||||
glScalef(-1., -1., -1.);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glActiveTextureChannel(0);
|
||||
}
|
||||
o.draw();
|
||||
}
|
||||
foreach (GLObjectBase * i, o.children_)
|
||||
renderSingleObject(*i, rp);
|
||||
glPopMatrix();
|
||||
}
|
||||
Reference in New Issue
Block a user