diff --git a/qglview/glcamera.cpp b/qglview/glcamera.cpp new file mode 100644 index 0000000..8bd5ef9 --- /dev/null +++ b/qglview/glcamera.cpp @@ -0,0 +1,255 @@ +/* + 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 . +*/ + +#include "gltypes.h" +#include "qglview.h" + +Camera * currentCamera; +QMatrix4x4 globCameraMatrix; + + +Camera::Camera() { + fov_ = 60.; + angle_limit_lower_xy = -180.; + angle_limit_upper_xy = 180.; + depth_start = 0.1; + depth_end = 1000.; + mirror_x = mirror_y = false; +} + + +void Camera::anglesFromPoints() { + QVector3D dv = aim_ - pos_, tv; + tv = QVector3D(dv.x(), dv.y(), 0.); + angles_.setZ(atan2(tv.x(), tv.y()) * rad2deg); + angles_.setY(piClamp(atan2(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy)); +} + + +void Camera::apply(const GLdouble & aspect) { + glMatrixMode(GL_PROJECTION); + if (aspect <= 1.) + glScaled(aspect, aspect, 1.); + QMatrix4x4 pm;// = glMatrixPerspective(fov_, aspect, depth_start, depth_end); + pm.perspective(fov_, aspect, depth_start, depth_end); + //qDebug() << pm << glMatrixPerspective(fov_, aspect, depth_start, depth_end);; + setGLMatrix(pm); + glMatrixMode(GL_MODELVIEW); + pm.setToIdentity(); + //qDebug() << pm; + pm.translate(0., 0., -distance()); + pm.rotate(angles_.y(), 1., 0., 0.); + pm.rotate(angles_.x(), 0., 1., 0.); + pm.rotate(angles_.z(), 0., 0., 1.); + pm.translate(-aim_); + if (parent_) + pm *= parent_->worldTransform().inverted(); + setGLMatrix(pm); +} + +/* +void Camera::localTransform(QMatrix4x4 & m) { + return; + if (parent_) + m *= parent_->worldTransform(); + QMatrix4x4 ret; + //qDebug() << "local camera"; + ret.translate(0., 0., -distance()); + ret.rotate(angles_.y(), 1., 0., 0.); + ret.rotate(angles_.x(), 0., 1., 0.); + ret.rotate(angles_.z(), 0., 0., 1.); + //m *= ret.inverted(); +} +*/ + +void Camera::assign(const Camera & c) { + pos_ = c.pos_; + aim_ = c.aim_; + fov_ = c.fov_; + angles_ = c.angles_; + angle_limit_lower_xy = c.angle_limit_lower_xy; + angle_limit_upper_xy = c.angle_limit_upper_xy; + buildTransform(); +} + + +void Camera::panZ(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = QVector2D(dv.x(), dv.y()).length(); + angles_.setZ(angles_.z() + a); + dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); + aim_ = pos_ + dv; + buildTransform(); +} + + +void Camera::panXY(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = dv.length(), tc; + angles_.setY(angles_.y() + a); + angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); + tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + aim_ = pos_ + dv * tl; + buildTransform(); +} + + +void Camera::rotateZ(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = QVector2D(dv.x(), dv.y()).length(); + angles_.setZ(angles_.z() + a); + dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); + aim_ = pos_ + dv; + buildTransform(); +} + + +void Camera::rotateXY(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = dv.length(), tc; + angles_.setY(angles_.y() + a); + angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); + tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + aim_ = pos_ + dv * tl; + buildTransform(); +} + + +void Camera::orbitZ(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = QVector2D(dv.x(), dv.y()).length(); + angles_.setZ(angles_.z() + a); + dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); + pos_ = aim_ - dv; + buildTransform(); +} + + +void Camera::orbitXY(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = dv.length(), tc; + angles_.setY(angles_.y() + a); + angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); + tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + pos_ = aim_ - dv * tl; + buildTransform(); +} + + +void Camera::setAngleZ(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = QVector2D(dv.x(), dv.y()).length(); + angles_.setZ(a); + dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); + aim_ = pos_ + dv; + buildTransform(); +} + + +void Camera::setAngleXY(const double & a) { + QVector3D dv = aim_ - pos_; + double tl = dv.length(), tc; + angles_.setY(a); + tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + //pos_ = aim_ - dv; + aim_ = pos_ + dv * tl; + buildTransform(); + //anglesFromPoints(); +} + + +void Camera::moveForward(const double & x, bool withZ) { + QVector3D dv;// = aim_ - pos_; + double tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, 0.); + if (withZ) dv.setZ(-cos(angles_.y() * deg2rad)); + dv.normalize(); + dv *= x; + pos_ += dv; + aim_ += dv; + buildTransform(); +} + + +void Camera::moveLeft(const double & x, bool withZ) { + QVector3D dv;// = aim_ - pos_; + double tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad - M_PI_2) * tc, cos(angles_.z() * deg2rad - M_PI_2) * tc, 0.); + if (withZ) dv.setZ(-sin(angles_.x() * deg2rad)); + dv.normalize(); + dv *= x; + pos_ += dv; + aim_ += dv; + buildTransform(); +} + + +void Camera::moveUp(const double & x, bool onlyZ) { + QVector3D dv; + if (onlyZ) + dv = QVector3D(0., 0., x); + else { + double tc = cos(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -sin(angles_.y() * deg2rad)); + dv.normalize(); + dv *= x; + } + pos_ += dv; + aim_ += dv; + buildTransform(); +} + + +void Camera::flyCloser(const double & s) { + QVector3D dv = aim_ - pos_; + double tl = dv.length() / (1. + s), tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + pos_ = aim_ - dv * tl; + buildTransform(); +} + + +void Camera::flyFarer(const double & s) { + QVector3D dv = aim_ - pos_; + double tl = dv.length() * (1. + s), tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + pos_ = aim_ - dv * tl; + buildTransform(); +} + + +void Camera::flyToDistance(const double & d) { + QVector3D dv = aim_ - pos_; + double tc = -sin(angles_.y() * deg2rad); + dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); + pos_ = aim_ - dv * d; + buildTransform(); +} + +/* +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); +} +*/ diff --git a/qglview/glcamera.h b/qglview/glcamera.h new file mode 100644 index 0000000..6fe3ea3 --- /dev/null +++ b/qglview/glcamera.h @@ -0,0 +1,108 @@ +/* + 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 . +*/ + +#ifndef GLCAMERA_H +#define GLCAMERA_H + +#include "globject.h" + +class Camera; + +extern QMatrix4x4 globCameraMatrix; +extern Camera * currentCamera; + +class Camera: public GLObjectBase +{ + friend class QGLView; + friend class GLParticlesSystem; +public: + Camera(); + + void setPos(const QVector3D & p) {pos_ = p; anglesFromPoints(); buildTransform();} + /*void setPosX(const double & o) {QVector3D dv = aim_ - pos_; pos_.setX(o); aim_ = pos_ + dv;} + void setPosY(const double & o) {QVector3D dv = aim_ - pos_; pos_.setY(o); aim_ = pos_ + dv;} + void setPosZ(const double & o) {QVector3D dv = aim_ - pos_; pos_.setZ(o); aim_ = pos_ + dv;}*/ + void setAim(const QVector3D & p) {aim_ = p; anglesFromPoints(); buildTransform();} + void move(const QVector3D & p) {pos_ += p; aim_ += p; buildTransform();} + void move(const double & x, const double & y = 0., const double & z = 0.) {pos_ += QVector3D(x, y, z); aim_ += QVector3D(x, y, z); buildTransform();} + void moveForward(const double & x, bool withZ = true); + void moveBackward(const double & x, bool withZ = true) {moveForward(-x, withZ);} + void moveLeft(const double & x, bool withZ = true); + void moveRight(const double & x, bool withZ = true) {moveLeft(-x, withZ);} + void moveUp(const double & x, bool onlyZ = false); + void moveDown(const double & x, bool onlyZ = false) {moveUp(-x, onlyZ);} + void rotateZ(const double & a); + void rotateXY(const double & a); + void rotateRoll(const double & a) {angles_.setX(angles_.x() + a); buildTransform();} + void orbitZ(const double & a); + void orbitXY(const double & a); + void panZ(const double & a); + void panXY(const double & a); + void setFOV(const double & f) {fov_ = f;} + void setAngles(const QVector3D & a) {setRotation(a);} + void setAngleZ(const double & a); + void setAngleXY(const double & a); + void setAngleRoll(const double & a) {angles_.setX(a); buildTransform();} + void setAngleLowerLimitXY(const double & a) {angle_limit_lower_xy = a; buildTransform();} + void setAngleUpperLimitXY(const double & a) {angle_limit_upper_xy = a; buildTransform();} + void setAngleLimitsXY(const double & lower, const double & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper; buildTransform();} + void setDepthStart(const double & d) {depth_start = d;} + void setDepthEnd(const double & d) {depth_end = d;} + void setMirrorX(bool yes) {mirror_x = yes;} + void setMirrorY(bool yes) {mirror_y = yes;} + void flyCloser(const double & s); + void flyFarer(const double & s); + void flyToDistance(const double & d); + + QVector3D aim() const {return aim_;} + QVector3D angles() const {return rotation();} + QVector3D direction() const {return (aim_ - pos_).normalized();} + QVector3D directionXY() const {QVector3D tv = aim_ - pos_; return QVector3D(tv.x(), tv.y(), 0.).normalized();} + double FOV() const {return fov_;} + double distance() const {return (pos_ - aim_).length();} + double angleZ() const {return angles_.z();} + double angleXY() const {return angles_.y();} + double angleRoll() const {return angles_.x();} + double angleLowerLimitXY() const {return angle_limit_lower_xy;} + double angleUpperLimitXY() const {return angle_limit_upper_xy;} + double depthStart() const {return depth_start;} + double depthEnd() const {return depth_end;} + bool isMirrorX() const {return mirror_x;} + bool isMirrorY() const {return mirror_y;} + void anglesFromPoints(); + void apply(const GLdouble & aspect = 1.); + void assign(const Camera & c); + //QVector3D pointFromViewport(int x_, int y_, double z_); TODO + +private: + //void localTransform(QMatrix4x4 & m); + + QVector3D aim_; + GLdouble fov_; + GLdouble depth_start; + GLdouble depth_end; + GLdouble angle_limit_lower_xy; + GLdouble angle_limit_upper_xy; + //GLdouble modelview[16], projection[16]; + //GLint viewport[4]; + bool mirror_x; + bool mirror_y; + +}; + +#endif // GLCAMERA_H diff --git a/qglview/glmaterial.cpp b/qglview/glmaterial.cpp index f7e8aed..bb273c9 100644 --- a/qglview/glmaterial.cpp +++ b/qglview/glmaterial.cpp @@ -183,10 +183,10 @@ Material::Material(): map_reflection(512) { color_self_illumination = Qt::black; glass = false; transparency = reflectivity = 0.f; - roughness = 0.5f; + map_specularity.color_amount = 0.5f; + map_specular.color_amount = 1.f; iof = 1.f; dispersion = 0.05f; - specular = 1.f; } @@ -201,16 +201,16 @@ void Material::apply(QGLShaderProgram * prog) { mat_diffuse[1] = color_diffuse.greenF(); mat_diffuse[2] = color_diffuse.blueF(); mat_diffuse[3] = color_diffuse.alphaF() * (1.f - transparency); - mat_specular[0] = specular * color_specular.redF(); - mat_specular[1] = specular * color_specular.greenF(); - mat_specular[2] = specular * color_specular.blueF(); + mat_specular[0] = map_specular.color_amount * color_specular.redF(); + mat_specular[1] = map_specular.color_amount * color_specular.greenF(); + mat_specular[2] = map_specular.color_amount * 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]); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); - glMaterialf(GL_FRONT, GL_SHININESS, (1. - roughness)*100.); + glMaterialf(GL_FRONT, GL_SHININESS, (1. - map_specularity.color_amount)*100.); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse); } @@ -221,9 +221,9 @@ void Material::loadTextures(GLTextureManagerBase * tm) { //qDebug() << "load textures"; if (tm == 0) tm = (GLTextureManagerBase*)currentGLTextureManager; if (!map_diffuse.bitmap_path.isEmpty()) map_diffuse.bitmap_id = tm->loadTexture(map_diffuse.bitmap_path); - if (!map_bump.bitmap_path.isEmpty()) map_bump.bitmap_id = tm->loadTexture(map_bump.bitmap_path, true, true); + if (!map_normal.bitmap_path.isEmpty()) map_normal.bitmap_id = tm->loadTexture(map_normal.bitmap_path, true, true); if (!map_relief.bitmap_path.isEmpty()) map_relief.bitmap_id = tm->loadTexture(map_relief.bitmap_path); - if (!map_roughness.bitmap_path.isEmpty()) map_roughness.bitmap_id = tm->loadTexture(map_roughness.bitmap_path); + if (!map_specularity.bitmap_path.isEmpty()) map_specularity.bitmap_id = tm->loadTexture(map_specularity.bitmap_path); if (!map_specular.bitmap_path.isEmpty()) map_specular.bitmap_id = tm->loadTexture(map_specular.bitmap_path); if (!map_self_illumination.bitmap_path.isEmpty()) map_self_illumination.bitmap_id = tm->loadTexture(map_self_illumination.bitmap_path); //if (!map_diffuse_2.bitmap_path.isEmpty()) map_diffuse_2.bitmap_id = tm->loadTexture(map_diffuse_2.bitmap_path); diff --git a/qglview/glmaterial.h b/qglview/glmaterial.h index 637399d..2c8ca03 100644 --- a/qglview/glmaterial.h +++ b/qglview/glmaterial.h @@ -110,17 +110,15 @@ struct Material { QColor color_specular; QColor color_self_illumination; bool glass; - float roughness; - float specular; float transparency; float reflectivity; float iof; float dispersion; Map map_diffuse; - Map map_bump; + Map map_normal; Map map_relief; Map map_self_illumination; - Map map_roughness; + Map map_specularity; Map map_specular; /*Map map_diffuse_2; Map map_diffuse_3; @@ -130,7 +128,7 @@ struct Material { inline QDataStream & operator <<(QDataStream & s, const Map & m) {s << m.bitmap_path << m.color_amount << m.color_offset << m.animation << m.animation_frame_rate; return s;} inline QDataStream & operator >>(QDataStream & s, Map & m) {s >> m.bitmap_path >> m.color_amount >> m.color_offset >> m.animation >> m.animation_frame_rate; return s;} -inline QDataStream & operator <<(QDataStream & s, const Material & m) {s << m.name << m.color_diffuse << m.color_specular << m.color_self_illumination << m.roughness << m.specular << m.transparency << m.reflectivity << m.glass << m.map_diffuse << m.map_bump << m.map_relief << m.map_specular << m.map_roughness; return s;} -inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.name >> m.color_diffuse >> m.color_specular >> m.color_self_illumination >> m.roughness >> m.specular >> m.transparency >> m.reflectivity >> m.glass >> m.map_diffuse >> m.map_bump >> m.map_relief >> m.map_specular >> m.map_roughness; return s;} +inline QDataStream & operator <<(QDataStream & s, const Material & m) {s << m.name << m.color_diffuse << m.color_specular << m.color_self_illumination << m.transparency << m.reflectivity << m.glass << m.map_diffuse << m.map_normal << m.map_relief << m.map_specular << m.map_specularity << m.map_self_illumination; return s;} +inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.name >> m.color_diffuse >> m.color_specular >> m.color_self_illumination >> m.transparency >> m.reflectivity >> m.glass >> m.map_diffuse >> m.map_normal >> m.map_relief >> m.map_specular >> m.map_specularity >> m.map_self_illumination; return s;} #endif // GLMATERIAL_H diff --git a/qglview/globject.cpp b/qglview/globject.cpp index 9c96e57..d086e66 100644 --- a/qglview/globject.cpp +++ b/qglview/globject.cpp @@ -152,19 +152,23 @@ void GLObjectBase::buildTransform() { itransform_.translate(pos_); itransform_ *= mat_; //qDebug() << "raw_matrix" << itransform_; - } else { - itransform_.translate(pos_); - itransform_.rotate(angles_.z(), 0., 0., 1.); - itransform_.rotate(angles_.y(), 0., 1., 0.); - itransform_.rotate(angles_.x(), 1., 0., 0.); - itransform_.scale(scale_); - } + } else + localTransform(itransform_); //qDebug() << name_ << itransform_; foreach (GLObjectBase * i, children_) i->buildTransform(); } +void GLObjectBase::localTransform(QMatrix4x4 & m) { + m.translate(pos_); + m.rotate(angles_.z(), 0., 0., 1.); + m.rotate(angles_.y(), 0., 1., 0.); + m.rotate(angles_.x(), 1., 0., 0.); + m.scale(scale_); +} + + void GLObjectBase::checkPass() { if (material_.reflectivity > 0.f || material_.color_diffuse.alphaF() * (1.f - material_.transparency) < 1.f) pass_ = Transparent; else pass_ = Solid; diff --git a/qglview/globject.h b/qglview/globject.h index 0b1dcd7..d5a2126 100644 --- a/qglview/globject.h +++ b/qglview/globject.h @@ -99,6 +99,7 @@ public: double posY() const {return pos_.y();} double posZ() const {return pos_.z();} QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();} + QMatrix4x4 worldTransform() const {return itransform_;} QVector3D rotation() const {return angles_;} double rotationX() const {return angles_.x();} @@ -181,6 +182,7 @@ protected: void initInternal() {init(); loadTextures(); foreach (GLObjectBase * i, children_) i->initInternal();} void render(int * id = 0, QMap * ids = 0, int sh_id_loc = 0); void checkPass(); + virtual void localTransform(QMatrix4x4 & m); QMatrix4x4 worldMatrix(QMatrix4x4 parent) const; int pass_; // Pass diff --git a/qglview/glparticles_system.cpp b/qglview/glparticles_system.cpp index 08c45a0..1e7c0ca 100644 --- a/qglview/glparticles_system.cpp +++ b/qglview/glparticles_system.cpp @@ -122,9 +122,9 @@ void GLParticlesSystem::draw(QGLShaderProgram * prog, bool) { tr_b = material_.color_diffuse.blueF(), tr_a = material_.color_diffuse.alphaF() * (1.f - material_.transparency); //cxys = sin(camera.angle_xy * deg2rad); - cxyc = cos(camera.angle_xy * deg2rad); - czs = sin(camera.angle_z * deg2rad); - czc = cos(camera.angle_z * deg2rad); + cxyc = cos(camera.angles_.y() * deg2rad); + czs = sin(camera.angles_.z() * deg2rad); + czc = cos(camera.angles_.z() * deg2rad); dx = -czc; dy = czs; diff --git a/qglview/glparticles_system.h b/qglview/glparticles_system.h index a8b64df..4cd0299 100644 --- a/qglview/glparticles_system.h +++ b/qglview/glparticles_system.h @@ -22,6 +22,7 @@ #include #include "gltexture_manager.h" #include "globject.h" +#include "glcamera.h" class GLParticlesSystem: public GLObjectBase { diff --git a/qglview/glrendererbase.cpp b/qglview/glrendererbase.cpp index 7d31cca..a2235a5 100644 --- a/qglview/glrendererbase.cpp +++ b/qglview/glrendererbase.cpp @@ -25,6 +25,9 @@ GLRendererBase::GLRendererBase(QGLView * view_): view(*view_) { white_image = QImage(1, 1, QImage::Format_ARGB32); white_image.fill(0xFFFFFFFF); white_image_id = 0; + violent_image = QImage(1, 1, QImage::Format_ARGB32); + violent_image.fill(QColor(127, 127, 255)); + violent_image_id = 0; } @@ -105,10 +108,10 @@ void GLRendererBase::setupTextures(GLObjectBase & o, GLRendererBase::RenderingPa } if (rp.textures) { BIND_TEXTURE(0, map_diffuse); - BIND_TEXTURE(1, map_bump); + BIND_TEXTURE(1, map_normal); BIND_TEXTURE(2, map_relief); BIND_TEXTURE(3, map_self_illumination); - BIND_TEXTURE(4, map_roughness); + BIND_TEXTURE(4, map_specularity); BIND_TEXTURE(5, map_specular); glActiveTextureChannel(0); } diff --git a/qglview/glrendererbase.h b/qglview/glrendererbase.h index 12327fe..09b4583 100644 --- a/qglview/glrendererbase.h +++ b/qglview/glrendererbase.h @@ -19,6 +19,7 @@ #ifndef GLRENDERERBASE_H #define GLRENDERERBASE_H +#include "glcamera.h" #include "glshaders.h" class GLRendererBase: public QObject @@ -60,8 +61,8 @@ protected: void renderSingleObject(GLObjectBase & o, RenderingParameters & rp); QGLView & view; - QImage white_image; - GLuint white_image_id; + QImage white_image, violent_image; + GLuint white_image_id, violent_image_id; }; diff --git a/qglview/glshaders.cpp b/qglview/glshaders.cpp index c9b1f08..dbba681 100644 --- a/qglview/glshaders.cpp +++ b/qglview/glshaders.cpp @@ -22,6 +22,8 @@ const char qgl_vertex_head[] = "in vec3 _qgl_Vertex;\n" "in vec3 qgl_Normal;\n" + "in vec3 qgl_Tangent;\n" + "in vec3 qgl_Bitangent;\n" "in vec2 qgl_Texture;\n" "in vec4 qgl_Color;\n" "out vec2 qgl_FragTexture;\n" @@ -65,8 +67,6 @@ const char qgl_structs[] = " sampler2D map;\n" "};\n" "struct QGLMaterial {\n" - " float roughness;\n" - " float specular;\n" " float transparency;\n" " float reflectivity;\n" " float iof;\n" @@ -75,10 +75,10 @@ const char qgl_structs[] = " vec4 color_specular;\n" " vec4 color_self_illumination;\n" " QGLMap map_diffuse;\n" - " QGLMap map_bump;\n" + " QGLMap map_normal;\n" " QGLMap map_relief;\n" " QGLMap map_self_illumination;\n" - " QGLMap map_roughness;\n" + " QGLMap map_specularity;\n" " QGLMap map_specular;\n" "};\n" "uniform QGLLight qgl_AmbientLight;\n" @@ -143,20 +143,22 @@ bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & void setUniformMatrices(QGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view) { QMatrix4x4 mvpm = proj * view; QMatrix3x3 nm = view.normalMatrix(); + //nm.in; prog->setUniformValue("qgl_ModelViewMatrix", view); prog->setUniformValue("qgl_ProjectionMatrix", proj); prog->setUniformValue("qgl_ModelViewProjectionMatrix", mvpm); prog->setUniformValue("qgl_NormalMatrix", nm); + //prog->setUniformValue("qgl_BumpMatrix", nm.); prog->setUniformValue("qgl_ModelViewMatrixTranspose", view.transposed()); prog->setUniformValue("qgl_ProjectionMatrixTranspose", proj.transposed()); prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", mvpm.transposed()); } -void setUniformMap(QGLShaderProgram * prog, QString map_name, const Map & map, int channel) { +void setUniformMap(QGLShaderProgram * prog, QString map_name, const Map & map, int channel, int def_channel) { prog->setUniformValue(("qgl_Material." + map_name + ".offset").toLatin1().constData(), map.color_offset); prog->setUniformValue(("qgl_Material." + map_name + ".amount").toLatin1().constData(), map.color_amount); - prog->setUniformValue(("qgl_Material." + map_name + ".map").toLatin1().constData(), map.bitmap_id > 0 ? channel : 6); + prog->setUniformValue(("qgl_Material." + map_name + ".map").toLatin1().constData(), map.bitmap_id > 0 ? channel : def_channel); } @@ -167,8 +169,6 @@ void setUniformMaterial(QGLShaderProgram * prog, const Material & mat) { mat_diffuse[2] = mat.color_diffuse.blueF(); mat_diffuse[3] = mat.color_diffuse.alphaF() * (1.f - mat.transparency); glVertexAttrib4f(prog->attributeLocation("qgl_Color"), mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]); - prog->setUniformValue("qgl_Material.roughness", mat.roughness); - prog->setUniformValue("qgl_Material.specular", mat.specular); prog->setUniformValue("qgl_Material.transparency", mat.transparency); prog->setUniformValue("qgl_Material.reflectivity", mat.reflectivity); prog->setUniformValue("qgl_Material.iof", mat.iof); @@ -176,19 +176,19 @@ void setUniformMaterial(QGLShaderProgram * prog, const Material & mat) { prog->setUniformValue("qgl_Material.color_diffuse", mat.color_diffuse); prog->setUniformValue("qgl_Material.color_self_illumination", mat.color_self_illumination); prog->setUniformValue("qgl_Material.color_specular", mat.color_specular); - setUniformMap(prog, "map_diffuse", mat.map_diffuse, 0); - setUniformMap(prog, "map_bump", mat.map_bump, 1); - setUniformMap(prog, "map_relief", mat.map_relief, 2); - setUniformMap(prog, "map_self_illumination", mat.map_self_illumination, 3); - setUniformMap(prog, "map_roughness", mat.map_roughness, 4); - setUniformMap(prog, "map_specular", mat.map_specular, 5); + setUniformMap(prog, "map_diffuse", mat.map_diffuse, 0, 6); + setUniformMap(prog, "map_normal", mat.map_normal, 1, 7); + setUniformMap(prog, "map_relief", mat.map_relief, 2, 6); + setUniformMap(prog, "map_self_illumination", mat.map_self_illumination, 3, 6); + setUniformMap(prog, "map_specularity", mat.map_specularity, 4, 6); + setUniformMap(prog, "map_specular", mat.map_specular, 5, 6); } -void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat) { +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, const QVector4D & dp) { for (int i = 0; i < lights.size(); ++i) - setUniformLight(prog, lights[i], QString("qgl_Light[%1]").arg(i), mat); + setUniformLight(prog, lights[i], QString("qgl_Light[%1]").arg(i), mat, dp); } /* " vec3 position;\n" @@ -198,9 +198,10 @@ void setUniformLights(QGLShaderProgram * prog, const QVector & lights, c " float linearAttenuation;\n" " float quadraticAttenuation;\n" */ -void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat) { - QVector4D pos(light->worldPos(), 1.); - pos = mat * pos; +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, const QVector4D & dp) { + QMatrix4x4 m = mat * light->worldTransform(); + QVector4D pos(0, 0, 0, 1.); + pos = m * pos; //qDebug() << "light" << light->name() << ulightn << pos; prog->setUniformValue((ulightn + ".position").toLatin1().constData(), pos); prog->setUniformValue((ulightn + ".intensity").toLatin1().constData(), GLfloat(light->intensity)); diff --git a/qglview/glshaders.h b/qglview/glshaders.h index ac76f60..30556a8 100644 --- a/qglview/glshaders.h +++ b/qglview/glshaders.h @@ -28,9 +28,9 @@ class Light; QString loadShaderFile(QGLShaderProgram * prog, QGLShader::ShaderType type, const QString & file); bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir = QString()); void setUniformMatrices(QGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view); -void setUniformMap(QGLShaderProgram * prog, const Map & map, int channel); +void setUniformMap(QGLShaderProgram * prog, const Map & map, int channel, int def_channel); void setUniformMaterial(QGLShaderProgram * prog, const Material & mat); -void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat); -void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat); +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, const QVector4D & dp); +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat = QMatrix4x4(), const QVector4D & dp = QVector4D()); #endif // GLSHADERS_H diff --git a/qglview/gltypes.cpp b/qglview/gltypes.cpp index 1af680b..c1dc954 100644 --- a/qglview/gltypes.cpp +++ b/qglview/gltypes.cpp @@ -16,12 +16,10 @@ along with this program. If not, see . */ -#include "gltypes.h" +#include "glcamera.h" #include "qglview.h" QGLWidget * currentQGLView; -Camera * currentCamera; -QMatrix4x4 globCameraMatrix; QMutex globMutex; @@ -172,195 +170,6 @@ QImage rotateQImageRight(const QImage & im) { -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(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.); - QMatrix4x4 pm;// = glMatrixPerspective(fov_, aspect, depth_start, depth_end); - pm.perspective(fov_, aspect, depth_start, depth_end); - //qDebug() << pm << glMatrixPerspective(fov_, aspect, depth_start, depth_end);; - setGLMatrix(pm); - 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(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(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(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); -} - - - - QColor colorFromString(const QString & str) { QString s = str.trimmed(); int i = s.indexOf("\t"); @@ -443,9 +252,31 @@ void glDisableDepth() { void glClearFramebuffer(const QColor & color, bool depth) { glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); - glClearDepth(1.); + //glClearDepth(0.); if (depth) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else glClear(GL_COLOR_BUFFER_BIT); } + + + + +QGLViewBase::QGLViewBase() { + camera_ = new Camera(); +} + + +Camera & QGLViewBase::camera() { + return *camera_; +} + + +const Camera & QGLViewBase::camera() const { + return *camera_; +} + + +void QGLViewBase::setCamera(const Camera & camera) { + *camera_ = camera; +} diff --git a/qglview/gltypes.h b/qglview/gltypes.h index 90fa41e..8e8e60a 100644 --- a/qglview/gltypes.h +++ b/qglview/gltypes.h @@ -175,93 +175,8 @@ inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true) //const double rad2deg = 45. / atan(1.); extern QGLWidget * currentQGLView; -extern QMatrix4x4 globCameraMatrix; extern QMutex globMutex; -class Camera -{ - friend class QGLView; - friend class GLParticlesSystem; -public: - Camera() {fov_ = 60.; angle_xy = angle_z = angle_roll = 0.; angle_limit_lower_xy = 180.; angle_limit_upper_xy = 360.; depth_start = 0.1; depth_end = 1000.; mirror_x = mirror_y = false;} - - void setPos(const QVector3D & p) {pos_ = p; anglesFromPoints();} - /*void setPosX(const double & o) {QVector3D dv = aim_ - pos_; pos_.setX(o); aim_ = pos_ + dv;} - void setPosY(const double & o) {QVector3D dv = aim_ - pos_; pos_.setY(o); aim_ = pos_ + dv;} - void setPosZ(const double & o) {QVector3D dv = aim_ - pos_; pos_.setZ(o); aim_ = pos_ + dv;}*/ - void setAim(const QVector3D & p) {aim_ = p; anglesFromPoints();} - void move(const QVector3D & p) {pos_ += p; aim_ += p;} - void move(const double & x, const double & y = 0., const double & z = 0.) {pos_ += QVector3D(x, y, z); aim_ += QVector3D(x, y, z);} - void moveForward(const double & x, bool withZ = true); - void moveBackward(const double & x, bool withZ = true) {moveForward(-x, withZ);} - void moveLeft(const double & x, bool withZ = true); - void moveRight(const double & x, bool withZ = true) {moveLeft(-x, withZ);} - void moveUp(const double & x, bool onlyZ = false); - void moveDown(const double & x, bool onlyZ = false) {moveUp(-x, onlyZ);} - void rotateZ(const double & a); - void rotateXY(const double & a); - void rotateRoll(const double & a) {angle_roll += a;} - void orbitZ(const double & a); - void orbitXY(const double & a); - void panZ(const double & a); - void panXY(const double & a); - void setFOV(const double & f) {fov_ = f;} - void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();} - void setAngleZ(const double & a); - void setAngleXY(const double & a); - void setAngleRoll(const double & a) {angle_roll = a;} - void setAngleLowerLimitXY(const double & a) {angle_limit_lower_xy = a;} - void setAngleUpperLimitXY(const double & a) {angle_limit_upper_xy = a;} - void setAngleLimitsXY(const double & lower, const double & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper;} - void setDepthStart(const double & d) {depth_start = d;} - void setDepthEnd(const double & d) {depth_end = d;} - void setMirrorX(bool yes) {mirror_x = yes;} - void setMirrorY(bool yes) {mirror_y = yes;} - void flyCloser(const double & s); - void flyFarer(const double & s); - void flyToDistance(const double & d); - - QVector3D pos() const {return pos_;} - QVector3D aim() const {return aim_;} - QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);} - QVector3D direction() const {return (aim_ - pos_).normalized();} - QVector3D directionXY() const {QVector3D tv = aim_ - pos_; return QVector3D(tv.x(), tv.y(), 0.).normalized();} - double FOV() const {return fov_;} - double distance() const {return (pos_ - aim_).length();} - double angleZ() const {return angle_z;} - double angleXY() const {return angle_xy;} - double angleRoll() const {return angle_roll;} - double angleLowerLimitXY() const {return angle_limit_lower_xy;} - double angleUpperLimitXY() const {return angle_limit_upper_xy;} - double depthStart() const {return depth_start;} - double depthEnd() const {return depth_end;} - bool isMirrorX() const {return mirror_x;} - bool isMirrorY() const {return mirror_y;} - void anglesFromPoints(); - void apply(const GLdouble & aspect = 1.); - void assign(const Camera & c) {pos_ = c.pos_; aim_ = c.aim_; fov_ = c.fov_; angle_z = c.angle_z; angle_xy = c.angle_xy; angle_roll = c.angle_roll; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy;} - QVector3D pointFromViewport(int x_, int y_, double z_); -private: - - QVector3D pos_; - QVector3D aim_; - GLdouble fov_; - GLdouble depth_start; - GLdouble depth_end; - GLdouble angle_z; - GLdouble angle_xy; - GLdouble angle_roll; - GLdouble angle_limit_lower_xy; - GLdouble angle_limit_upper_xy; - GLdouble modelview[16], projection[16]; - GLint viewport[4]; - bool mirror_x; - bool mirror_y; - -}; - -extern Camera * currentCamera; - struct Box3D { GLfloat x; GLfloat y; @@ -345,6 +260,8 @@ struct Vector2d { Vector2d operator -(const GLfloat v) {return Vector2d(x-v, y-v);} Vector2d operator +(const Vector3d & v) {return Vector3d(x + v.x, y + v.y);} Vector2d operator -(const Vector3d & v) {return Vector3d(x - v.x, y - v.y);} + Vector2d operator +(const Vector2d & v) {return Vector2d(x + v.x, y + v.y);} + Vector2d operator -(const Vector2d & v) {return Vector2d(x - v.x, y - v.y);} Vector2d & operator *=(const GLfloat & v) {x *= v; y *= v; return *this;} Vector2d & operator /=(const GLfloat & v) {x /= v; y /= v; return *this;} Vector2d & operator +=(const GLfloat & v) {x += v; y += v; return *this;} @@ -398,17 +315,19 @@ inline double frac(const double & x, const double & b) {return x - int(x / b) * class GLObjectBase; class QGLView; class Light; +class Camera; class QGLViewBase { friend class GLObjectBase; public: - QGLViewBase() {} - Camera & camera() {return camera_;} - void setCamera(const Camera & camera) {camera_ = camera;} + QGLViewBase(); + Camera & camera(); + const Camera & camera() const; + void setCamera(const Camera & camera); protected: virtual void collectLights() = 0; - Camera camera_; + Camera * camera_; }; #endif // GLTYPES_H diff --git a/qglview/glvbo.cpp b/qglview/glvbo.cpp index 64f40ba..35032c9 100644 --- a/qglview/glvbo.cpp +++ b/qglview/glvbo.cpp @@ -47,9 +47,42 @@ void GLVBO::destroy() { } +void GLVBO::calculateBinormals() { + tangents_.clear(); + bitangents_.clear(); + if (vertices_.isEmpty() || texcoords_.isEmpty()) return; + int vcnt = vertices_.size() / 3; + if (texcoords_.size() != vcnt * 2) return; + int tcnt = vcnt / 3; + //qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "..."; + for (int t = 0; t < tcnt; ++t) { + int vi = t*9, ti = t*6; + Vector3d v0(vertices_[vi + 0], vertices_[vi + 1], vertices_[vi + 2]); + Vector3d v1(vertices_[vi + 3], vertices_[vi + 4], vertices_[vi + 5]); + Vector3d v2(vertices_[vi + 6], vertices_[vi + 7], vertices_[vi + 8]); + Vector2d t0(texcoords_[ti + 0], texcoords_[ti + 1]); + Vector2d t1(texcoords_[ti + 2], texcoords_[ti + 3]); + Vector2d t2(texcoords_[ti + 4], texcoords_[ti + 5]); + Vector3d dv1 = v1 - v0, dv2 = v2 - v0; + Vector2d dt1 = t1 - t0, dt2 = t2 - t0; + Vector3d tan; + Vector3d bitan; + tan = (dv1 * dt2.y - dv2 * dt1.y).normalize(); + bitan = (dv2 * dt1.x - dv1 * dt2.x).normalize(); + for (int i = 0; i < 3; ++i) { + tangents_ << tan.x << tan.y << tan.z; + bitangents_ << bitan.x << bitan.y << bitan.z; + } + //qDebug() << " t" << t << vi << ti << dv1.toQVector3D() << "..."; + } + //qDebug() << "calculateBinormals" << vcnt << tcnt << tangents_.size(); +} + + bool GLVBO::rebuffer(bool clear_) { QVector data; //data.clear(); + calculateBinormals(); data << vertices_; if (!normals_.isEmpty()) { data << normals_; @@ -63,6 +96,10 @@ bool GLVBO::rebuffer(bool clear_) { data << colors_; has_colors = true; } else has_colors = false; + if (!tangents_.isEmpty()) { + data << tangents_ << bitangents_; + has_binormals = true; + } else has_binormals = false; //glBindVertexArray(va_); //qDebug() << "load buffer" << data.size() << buffer_; glBindBuffer(GL_ARRAY_BUFFER, buffer_); @@ -84,7 +121,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { void * offset = (void*)(vert_count * 3 * sizeof(GLfloat)); //glBindVertexArray(va_); - void * offsets[3] = {0, 0, 0}; + void * offsets[5] = {0, 0, 0, 0, 0}; if (has_normals) { offsets[0] = offset; offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); @@ -95,6 +132,12 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { } if (has_colors) { offsets[2] = offset; + offset = (void*)(llong(offset) + vert_count * 4 * sizeof(GLfloat)); + } + if (has_binormals) { + offsets[3] = offset; + offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); + offsets[4] = offset; } glBindBuffer(GL_ARRAY_BUFFER, buffer_); @@ -103,7 +146,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - int loc = prog->attributeLocation("_qgl_Vertex"); + int loc = prog->attributeLocation("_qgl_Vertex"), loc2 = 0; glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0); loc = prog->attributeLocation("qgl_Normal"); @@ -124,6 +167,17 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]); } else glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Tangent"); + loc2 = prog->attributeLocation("qgl_Bitangent"); + if (has_binormals) { + glEnableVertexAttribArray(loc); + glEnableVertexAttribArray(loc2); + glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[3]); + glVertexAttribPointer(loc2, 3, GL_FLOAT, 0, 0, offsets[4]); + } else { + glDisableVertexAttribArray(loc); + glDisableVertexAttribArray(loc2); + } } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, 0); diff --git a/qglview/glvbo.h b/qglview/glvbo.h index 7c07d82..9c69ee0 100644 --- a/qglview/glvbo.h +++ b/qglview/glvbo.h @@ -50,11 +50,13 @@ public: bool loadFromFile(const QString & filename); private: - QVector vertices_, normals_, texcoords_, colors_; + void calculateBinormals(); + + QVector vertices_, normals_, texcoords_, colors_, tangents_, bitangents_; GLenum usage; GLuint buffer_, va_; int vert_count; - bool changed, has_normals, has_texcoords, has_colors; + bool changed, has_normals, has_texcoords, has_colors, has_binormals; }; diff --git a/qglview/loader_3ds.cpp b/qglview/loader_3ds.cpp index 7f8de82..bd446a2 100644 --- a/qglview/loader_3ds.cpp +++ b/qglview/loader_3ds.cpp @@ -328,7 +328,7 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { //qDebug() << " mat map" << QString::number(cur_map, 16) << name; switch (cur_map) { case LOADER_3DS_CHUNK_TEXTURE_MAP: mat.map_diffuse.bitmap_path = name; break; - case LOADER_3DS_CHUNK_BUMP_MAP: mat.map_bump.bitmap_path = name; break; + case LOADER_3DS_CHUNK_BUMP_MAP: mat.map_normal.bitmap_path = name; break; } break; default: /*qDebug() << "???" << QString::number(cc.id, 16).rightJustified(4, '0') << cc.size;*/ stream.skipRawData(cc.size - 6); diff --git a/qglview/loader_ase.cpp b/qglview/loader_ase.cpp index 7547926..d0c1a41 100644 --- a/qglview/loader_ase.cpp +++ b/qglview/loader_ase.cpp @@ -120,13 +120,13 @@ GLObjectBase * loadFromASEFile(const QString & filepath, double scale) { line = stream.readLine().trimmed(); if (line.left(17) == "*MATERIAL_DIFFUSE") {materials[i].color_diffuse = colorFromString(line.right(line.length() - 18)); continue;} //qDebug() << "diffuse " << i << " = " << colorFromString(line.right(line.length() - 18)); if (line.left(18) == "*MATERIAL_SPECULAR") {materials[i].color_specular = colorFromString(line.right(line.length() - 19)); continue;} //qDebug() << "specular " << i << " = " << colorFromString(line.right(line.length() - 19)); - if (line.left(23) == "*MATERIAL_SHINESTRENGTH") {materials[i].specular = line.right(line.length() - 24).toFloat(); continue;} - if (line.left(15) == "*MATERIAL_SHINE") {materials[i].roughness = 2. / exp(line.right(line.length() - 16).toFloat()); continue;} + if (line.left(23) == "*MATERIAL_SHINESTRENGTH") {materials[i].map_specular.color_amount = line.right(line.length() - 24).toFloat(); continue;} + if (line.left(15) == "*MATERIAL_SHINE") {materials[i].map_specularity.color_amount = 2. / exp(line.right(line.length() - 16).toFloat()); continue;} if (line.left(22) == "*MATERIAL_TRANSPARENCY") {materials[i].transparency = line.right(line.length() - 23).toFloat(); continue;} if (line.left(12) == "*MAP_DIFFUSE") { line = stream.readLine().trimmed(); while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].map_bump.color_amount = line.right(line.length() - 12).toFloat(); + materials[i].map_normal.color_amount = line.right(line.length() - 12).toFloat(); while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed(); materials[i].map_diffuse.bitmap_path = line.mid(9, line.length() - 10); /*if (!materials[i].diffuse.bitmap_path.isEmpty()) { @@ -141,10 +141,10 @@ GLObjectBase * loadFromASEFile(const QString & filepath, double scale) { if (line.left(9) == "*MAP_BUMP") { line = stream.readLine().trimmed(); while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].map_bump.color_amount = line.right(line.length() - 12).toFloat(); + materials[i].map_normal.color_amount = line.right(line.length() - 12).toFloat(); //qDebug() << "bump amount" << materials[i].bump.color_amount; while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].map_bump.bitmap_path = line.mid(9, line.length() - 10); + materials[i].map_normal.bitmap_path = line.mid(9, line.length() - 10); /*if (!materials[i].bump.bitmap_path.isEmpty()) { materials[i].bump.bitmap_id = currentQGLView->bindTexture(QImage(materials[i].bump.bitmap_path)); parent->textures << materials[i].bump.bitmap_id; diff --git a/qglview/loader_dae.cpp b/qglview/loader_dae.cpp index 5abcb03..ea3faee 100644 --- a/qglview/loader_dae.cpp +++ b/qglview/loader_dae.cpp @@ -140,7 +140,7 @@ QVector LoaderDAE::readMaterials(QDomElement le, QDomElement li, bool if (col.isValid()) mat.color_diffuse = col; col = readXMLColor(pn.firstChildElement("specular")); if (col.isValid()) mat.color_specular = col; - mat.roughness = 2. / exp(readXMLFloat(pn.firstChildElement("shininess"))); + mat.map_specularity.color_amount = 2. / exp(readXMLFloat(pn.firstChildElement("shininess"))); mat.transparency = readXMLFloat(pn.firstChildElement("transparency")); if (!fbx) mat.transparency = 1. - mat.transparency; text = readXMLTexture(pn.firstChildElement("diffuse"), prof, li); @@ -150,7 +150,7 @@ QVector LoaderDAE::readMaterials(QDomElement le, QDomElement li, bool pn = prof.firstChildElement("technique").firstChildElement("extra").firstChild(); text = readXMLTexture(pn.firstChildElement("bump"), prof, li); - if (!text.isEmpty()) mat.map_bump.bitmap_path = text; + if (!text.isEmpty()) mat.map_normal.bitmap_path = text; ret << mat; /* diff --git a/qglview/loader_obj.cpp b/qglview/loader_obj.cpp index 5ec5672..f16f1a7 100644 --- a/qglview/loader_obj.cpp +++ b/qglview/loader_obj.cpp @@ -156,7 +156,7 @@ QVector readMTL(QString obj_path, QString path) { } if (line.startsWith("Ks")) { Vector3d v = readVector3d(line.mid(2).trimmed()); - mat.specular = v.length(); + mat.map_specular.color_amount = v.length(); double mc = qMax(v.x, qMax(v.y, v.z)); if (mc > 0.) v /= mc; mat.color_specular = QColor::fromRgbF(v.x, v.y, v.z); @@ -164,7 +164,7 @@ QVector readMTL(QString obj_path, QString path) { continue; } if (line.startsWith("Ns")) { - mat.roughness = 2. / exp(line.mid(2).trimmed().toDouble()); + mat.map_specularity.color_amount = 2. / exp(line.mid(2).trimmed().toDouble()); continue; } if (line.startsWith("d")) { @@ -181,9 +181,9 @@ QVector readMTL(QString obj_path, QString path) { line = line.mid(3).trimmed(); QString sv = line.left(line.indexOf(" ")); line = line.mid(sv.size()).trimmed(); - mat.map_bump.color_amount = sv.toDouble(); + mat.map_normal.color_amount = sv.toDouble(); } - mat.map_bump.bitmap_path = findFile(line, sp); + mat.map_normal.bitmap_path = findFile(line, sp); //qDebug() << "BUMP" << mat.name << mat.bump_scale << mat.bump.bitmap_path; continue; } diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index 40ef3ec..b8cff43 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -65,11 +65,16 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() GLTextureManager::addSearchPath("data"); GLTextureManager::addSearchPath("data/images"); GLTextureManager::addSearchPath("data/SU-33_maps"); - obj = loadFromDAEFile("data/test.dae");//new GLPrimitiveEllipsoid(EARTH_WL / 1E+6, EARTH_WL / 1E+6, EARTH_H / 1E+6, 500, 500);//GLPrimitiveCube(); + obj = loadFromDAEFile("data/earth.dae");//new GLPrimitiveEllipsoid(EARTH_WL / 1E+6, EARTH_WL / 1E+6, EARTH_H / 1E+6, 500, 500);//GLPrimitiveCube(); obj->setScale(0.1); //obj = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube(); + for (int i = 0; i < obj->childCount(); ++i) + if (obj->child(i)->type() == GLObjectBase::Light) + ((Light*)obj->child(i))->intensity = 0.; view->addObject(obj); - + //obj->child("Box001")->addChild(&(view->camera())); + //view->camera().flyToDistance(30); + double al = 7.; obj = new GLPrimitiveLine(QVector3D(0, 0, -al), QVector3D(0, 0, al)); obj->material().color_diffuse = Qt::darkBlue; obj->setAcceptLight(false); @@ -87,14 +92,15 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() view->camera().setPos(QVector3D(10, -20, 20)); view->camera().setAim(QVector3D()); - view->camera().flyToDistance(300); + view->camera().flyToDistance(100); + //view->camera().setMode(Camera::AimMatrix); view->setMouseSelectionEnabled(false); view->setSelectionHaloEnabled(false); view->setHoverHaloEnabled(false); Light * l = new Light(view->camera().pos()); - l->intensity = 0.8; + l->intensity = 0.5; l->setName("camera"); - //view->addObject(l); + view->addObject(l); view->start(-1); //view->light(0)->light_type = Light::Omni; //obj = loadFrom3DSFile("34.3DS", 0.03); @@ -167,8 +173,12 @@ void MainWindow::changeEvent(QEvent * e) { void MainWindow::timerEvent(QTimerEvent * ) { static double t = 0.; - view->light(view->lightsCount() - 1)->setPos(view->camera().pos()); + view->light(view->lightsCount() - 1)->setPos(view->camera().worldPos()); ((RendererSimple*)(view->renderer()))->mpos = view->mapFromGlobal(QCursor::pos()); +//qDebug() << view->camera().angles(); + //cam_mat.rotate(e->y(), 0., 1., 0.); + //view->camera().setTransform(cam_mat); + /*obj->child("tor")->rotateX(0.5); obj->child("tor")->rotateZ(0.1); obj->child("cone")->rotateZ(1); @@ -190,6 +200,13 @@ void MainWindow::on_view_glKeyPressEvent(QKeyEvent * e) { } +void MainWindow::on_view_glMouseMoveEvent(QMouseEvent * e) { + cam_mat.rotate(e->x(), 0., 0., 1.); + cam_mat.rotate(e->y(), 0., 1., 0.); + view->camera().setTransform(cam_mat); +} + + void MainWindow::glInit() { //view->bindTexture(QImage("e/bottom.jpg")); diff --git a/qglview/mainwindow.h b/qglview/mainwindow.h index b83cd19..689547f 100644 --- a/qglview/mainwindow.h +++ b/qglview/mainwindow.h @@ -95,6 +95,7 @@ private slots: void on_colorAmbient_colorChanged(QColor color) {view->setAmbientColor(color);} void on_colorHalo_colorChanged(QColor color) {view->setSelectionHaloColor(color);} void on_view_glKeyPressEvent(QKeyEvent * e); + void on_view_glMouseMoveEvent(QMouseEvent * e); void on_view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m); void hoverChanged(GLObjectBase * cur, GLObjectBase * prev) {/*qDebug() << "hovered" << (cur != 0 ? cur->name() : "0") << ", previous" << (prev != 0 ? prev->name() : "0");*/} @@ -105,6 +106,9 @@ public slots: signals: +private: + QMatrix4x4 cam_mat; + }; #endif // MAINWINDOW_H diff --git a/qglview/material_editor.cpp b/qglview/material_editor.cpp index 40854e3..e70c390 100644 --- a/qglview/material_editor.cpp +++ b/qglview/material_editor.cpp @@ -47,8 +47,6 @@ void MaterialEditor::setMaterial(const Material & m) { ui->colorSpecular->setColor(m.color_specular); ui->colorSelfIllum->setColor(m.color_self_illumination); ui->checkGlass->setChecked(m.glass); - ui->spinRoughness->setValue(m.roughness); - ui->spinSpecular->setValue(m.specular); ui->spinTransparent->setValue(m.transparency); ui->spinReflect->setValue(m.reflectivity); ui->spinIOF->setValue(m.iof); @@ -56,8 +54,8 @@ void MaterialEditor::setMaterial(const Material & m) { ui->mapDiffuse->setMap(m.map_diffuse); ui->mapSpecular->setMap(m.map_specular); ui->mapSelfIllum->setMap(m.map_self_illumination); - ui->mapRoughness->setMap(m.map_roughness); - ui->mapBump->setMap(m.map_bump); + ui->mapSpecularity->setMap(m.map_specularity); + ui->mapBump->setMap(m.map_normal); ui->mapRelief->setMap(m.map_relief); ui->lineReflFront->setProperty("GLpath", m.map_reflection.path(0)); ui->lineReflFront->setText(QFileInfo(m.map_reflection.path(0)).fileName()); ui->lineReflBack->setProperty("GLpath", m.map_reflection.path(1)); ui->lineReflBack->setText(QFileInfo(m.map_reflection.path(1)).fileName()); @@ -75,8 +73,6 @@ Material MaterialEditor::material() { m.color_specular = ui->colorSpecular->color(); m.color_self_illumination = ui->colorSelfIllum->color(); m.glass = ui->checkGlass->isChecked(); - m.roughness = ui->spinRoughness->value(); - m.specular = ui->spinSpecular->value(); m.transparency = ui->spinTransparent->value(); m.reflectivity = ui->spinReflect->value(); m.iof = ui->spinIOF->value(); @@ -84,8 +80,8 @@ Material MaterialEditor::material() { m.map_diffuse = ui->mapDiffuse->map(); m.map_specular = ui->mapSpecular->map(); m.map_self_illumination = ui->mapSelfIllum->map(); - m.map_roughness = ui->mapRoughness->map(); - m.map_bump = ui->mapBump->map(); + m.map_specularity = ui->mapSpecularity->map(); + m.map_normal = ui->mapBump->map(); m.map_relief = ui->mapRelief->map(); m.map_reflection.setPath(0, ui->lineReflFront->property("GLpath").toString()); m.map_reflection.setPath(1, ui->lineReflBack->property("GLpath").toString()); diff --git a/qglview/material_editor.ui b/qglview/material_editor.ui index 022b899..8286246 100644 --- a/qglview/material_editor.ui +++ b/qglview/material_editor.ui @@ -7,7 +7,7 @@ 0 0 470 - 692 + 737 @@ -25,12 +25,18 @@ + + font:bold; + Diffuse + + font:normal; + Color: @@ -38,25 +44,38 @@ + + font:normal; + true - + + + font:normal; + + + + font:bold; + Specular + + font:normal; + Color: @@ -64,25 +83,38 @@ + + font:normal; + true - + + + font:normal; + + + + font:bold; + Self illumination + + font:normal; + Color: @@ -90,37 +122,77 @@ + + font:normal; + true - + + + font:normal; + + + + + + + + + + font:bold; + + + Specularity + + + + + + font:normal; + + + + font:bold; + - Bump + Normal - + + + font:normal; + + + + font:bold; + Relief - + + + font:normal; + + @@ -133,65 +205,13 @@ - - - Roughness - - - - - - - 1.000000000000000 - - - 2 - - - 0.100000000000000 - - - 0.010000000000000 - - - - - - - Specular - - - - - - - 64.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - - Transparency - + 1.000000000000000 @@ -207,14 +227,14 @@ - + Reflectivity - + 1.000000000000000 @@ -230,14 +250,14 @@ - + IOF - + 2.000000000000000 @@ -256,14 +276,14 @@ - + Dispersion - + 1.000000000000000 @@ -282,14 +302,14 @@ - + Reflection map - + QFrame::StyledPanel @@ -494,18 +514,6 @@ - - - - Roughness - - - - - - - - @@ -563,38 +571,6 @@ - - spinRoughness - valueChanged(double) - MaterialEditor - materialChanged() - - - 443 - 404 - - - 280 - 95 - - - - - spinSpecular - valueChanged(double) - MaterialEditor - materialChanged() - - - 443 - 426 - - - 283 - 120 - - - spinTransparent valueChanged(double) @@ -772,7 +748,7 @@ - mapRoughness + mapSpecularity changed() MaterialEditor materialChanged() diff --git a/qglview/material_map_editor.cpp b/qglview/material_map_editor.cpp index ab07fd6..c1e9478 100644 --- a/qglview/material_map_editor.cpp +++ b/qglview/material_map_editor.cpp @@ -42,6 +42,8 @@ void MaterialMapEditor::changeEvent(QEvent * e) { void MaterialMapEditor::setMap(const Map & m) { active = false; + ui->sliderAmount->setValue(m.color_amount); + ui->sliderOffset->setValue(m.color_offset); ui->linePath->setProperty("GLpath", m.bitmap_path); ui->linePath->setText(QFileInfo(m.bitmap_path).fileName()); active = true; } diff --git a/qglview/qglview.cpp b/qglview/qglview.cpp index f4f77c2..7d4624e 100644 --- a/qglview/qglview.cpp +++ b/qglview/qglview.cpp @@ -63,10 +63,10 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) { sel_mode = QGLView::SingleSelection; sel_pen = QPen(Qt::black, 1, Qt::DashLine); sel_brush = QBrush(QColor(170, 100, 255, 120)); - camera_.setAim(QVector3D(0,0,5.5)); - camera_.setPos(QVector3D(10, 5, 5.5)); - emit cameraPosChanged(camera_.pos()); - //camera_.aim_ = camera_.pos_; + camera().setAim(QVector3D(0,0,5.5)); + camera().setPos(QVector3D(10, 5, 5.5)); + emit cameraPosChanged(camera().pos()); + //camera().aim_ = camera().pos_; ktm_.restart(); sh_lm_diff << "Phong_diffuse" << "Cook_Torrance_diffuse" << "Minnaert_diffuse" << "Strauss_diffuse" << "Oren_Nayar_diffuse"; sh_lm_spec << "Phong_specular" << "Cook_Torrance_specular" << "Minnaert_specular" << "Strauss_specular" << "Oren_Nayar_specular"; @@ -127,7 +127,7 @@ void QGLView::initializeGL() { makeCurrent(); currentQGLView = (QGLWidget * )viewport(); currentGLTextureManager = &textures_manager; - currentCamera = &camera_; + currentCamera = &camera(); //glEnable(GL_POLYGON_SMOOTH); glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -195,7 +195,7 @@ void QGLView::paintGL() { //QMutexLocker ml_v(&v_mutex); glEnable(GL_CULL_FACE); //glDisable(GL_CULL_FACE); - camera_.apply(aspect); + camera().apply(aspect); start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); //objects_.buildTransform(); @@ -257,7 +257,7 @@ void QGLView::paintGL() { glEnableClientState(GL_COLOR_ARRAY); } - camera_.apply(aspect); + camera().apply(aspect); static GLRendererBase * prev_rend = 0; if (prev_rend != renderer_) { @@ -551,24 +551,25 @@ void QGLView::mouseMoveEvent(QMouseEvent * e) { double dx = e->x() - lastPos.x(); double dy = e->y() - lastPos.y(); if (e->buttons() & Qt::LeftButton) { - //camera_.angle_z += dx / 4.; - //camera_.angle_xy += dy / 4.; + //camera().angle_z += dx / 4.; + //camera().angle_xy += dy / 4.; if (cameraOrbit_) { - camera_.orbitZ(dx / 4.); - camera_.orbitXY(dy / 4.); + camera().orbitZ(dx / 4.); + camera().orbitXY(dy / 4.); } else { - camera_.rotateZ(dx / 4.); - camera_.rotateXY(dy / 4.); + camera().rotateZ(dx / 4.); + camera().rotateXY(dy / 4.); } - emit cameraPosChanged(camera_.pos()); + emit cameraPosChanged(camera().pos()); } else if (e->buttons() & Qt::RightButton) { - camera_.moveLeft(dx / 100.); - camera_.moveUp(dy / 100.); - //camera_.pos.setX(camera_.pos.x() + camera_.pos.z() * dx / 500.); - //camera_.pos.setY(camera_.pos.y() - camera_.pos.z() * dy / 500.); - emit cameraPosChanged(camera_.pos()); + double ad = camera().distance(); + camera().moveLeft(dx / 1000. * ad); + camera().moveUp(dy / 1000. * ad); + //camera().pos.setX(camera().pos.x() + camera().pos.z() * dx / 500.); + //camera().pos.setY(camera().pos.y() - camera().pos.z() * dy / 500.); + emit cameraPosChanged(camera().pos()); } - //lights[0]->pos_ = camera_.pos(); + //lights[0]->pos_ = camera().pos(); } if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons()); lastPos = e->pos(); @@ -600,9 +601,9 @@ void QGLView::wheelEvent(QWheelEvent * e) { QGraphicsView::wheelEvent(e); if (scene()->itemAt(mapToScene(e->pos())) != 0) return; if (mouseRotate_) { - if (e->delta() > 0) camera_.flyCloser(0.1); //camera_.pos.setZ(camera_.pos.z() - 0.1 * camera_.pos.z()); - if (e->delta() < 0) camera_.flyFarer(0.1); //camera_.pos.setZ(camera_.pos.z() + 0.1 * camera_.pos.z()); - emit cameraPosChanged(camera_.pos()); + if (e->delta() > 0) camera().flyCloser(0.1); //camera().pos.setZ(camera().pos.z() - 0.1 * camera().pos.z()); + if (e->delta() < 0) camera().flyFarer(0.1); //camera().pos.setZ(camera().pos.z() + 0.1 * camera().pos.z()); + emit cameraPosChanged(camera().pos()); } emit glWheelEvent(e); } diff --git a/qglview/qglview.h b/qglview/qglview.h index 40355f5..6a9c4cc 100644 --- a/qglview/qglview.h +++ b/qglview/qglview.h @@ -109,9 +109,9 @@ public: QColor backColor() const {return backColor_;} double lineWidth() const {return lineWidth_;} - double FOV() const {return camera_.fov_;} - double depthStart() const {return camera_.depth_start;} - double depthEnd() const {return camera_.depth_end;} + double FOV() const {return camera().fov_;} + double depthStart() const {return camera().depth_start;} + double depthEnd() const {return camera().depth_end;} double currentFPS() const {return fps_;} bool linearFiltering() const {return linearFiltering_;} int anisotropicLevel() const {return anisotropicLevel_;} @@ -264,9 +264,9 @@ private: public slots: void setBackColor(const QColor & arg) {backColor_ = arg;} void setLineWidth(const double & arg) {lineWidth_ = arg;} - void setFOV(const double & arg) {camera_.fov_ = arg;} - void setDepthStart(const double & arg) {camera_.depth_start = arg;} - void setDepthEnd(const double & arg) {camera_.depth_end = arg;} + void setFOV(const double & arg) {camera().fov_ = arg;} + void setDepthStart(const double & arg) {camera().depth_start = arg;} + void setDepthEnd(const double & arg) {camera().depth_end = arg;} void setLinearFiltering(const bool & arg) {linearFiltering_ = arg;} void setAnisotropicLevel(const int & arg) {anisotropicLevel_ = arg;} void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} diff --git a/qglview/renderer_deferred_shading.cpp b/qglview/renderer_deferred_shading.cpp index e3540a3..9c8ee8d 100644 --- a/qglview/renderer_deferred_shading.cpp +++ b/qglview/renderer_deferred_shading.cpp @@ -45,6 +45,12 @@ void RendererDeferredShading::renderScene() { glBindTexture(GL_TEXTURE_2D, white_image_id); glActiveTextureChannel(0); } + if (violent_image_id == 0) { + glActiveTextureChannel(7); + violent_image_id = ((GLTextureManagerBase*)currentGLTextureManager)->loadTexture(violent_image, false); + glBindTexture(GL_TEXTURE_2D, violent_image_id); + glActiveTextureChannel(0); + } glClearFramebuffer(QColor(0, 0, 0, 0)); //glEnable(GL_TEXTURE_2D); glEnableDepth(); @@ -127,12 +133,14 @@ void RendererDeferredShading::reloadShaders() { void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) { shader_ds_0->setUniformValue("has_diffuse", object.material().map_diffuse.bitmap_id != 0); - shader_ds_0->setUniformValue("has_bump", object.material().map_bump.bitmap_id != 0); + shader_ds_0->setUniformValue("has_bump", object.material().map_normal.bitmap_id != 0); shader_ds_0->setUniformValue("has_height", object.material().map_relief.bitmap_id != 0); - shader_ds_0->setUniformValue("bump_scale", object.material().map_bump.color_amount); + shader_ds_0->setUniformValue("bump_scale", object.material().map_normal.color_amount); shader_ds_0->setUniformValue("height_scale", object.material().map_relief.color_amount); glActiveTextureChannel(6); glBindTexture(GL_TEXTURE_2D, white_image_id); + glActiveTextureChannel(7); + glBindTexture(GL_TEXTURE_2D, violent_image_id); } @@ -144,7 +152,7 @@ void RendererDeferredShading::setupDSLights(int pass, int lights_per_pass, const amb_light.intensity = (pass == 0 ? 1. : 0.); amb_light.setColor(pass == 0 ? view.ambientColor() : Qt::black); amb_light.setName("ambient"); - setUniformLight(shader_ds_1, &amb_light, "qgl_AmbientLight", QMatrix4x4()); + setUniformLight(shader_ds_1, &amb_light, "qgl_AmbientLight"); amb_light.intensity = 0.; QVector lv; for (int i = light_start; i < light_end; ++i) @@ -152,7 +160,7 @@ void RendererDeferredShading::setupDSLights(int pass, int lights_per_pass, const amb_light.setName("null"); for (int i = light_end; i < lmax; ++i) lv << &amb_light; - setUniformLights(shader_ds_1, lv, view_matrix); + setUniformLights(shader_ds_1, lv, view_matrix, view.camera().pos()); } diff --git a/qglview/shaders/dsl_pass_0.frag b/qglview/shaders/dsl_pass_0.frag index 8bbe69c..70d68b4 100644 --- a/qglview/shaders/dsl_pass_0.frag +++ b/qglview/shaders/dsl_pass_0.frag @@ -3,6 +3,7 @@ in vec3 src_normal, normal;//, et; in vec4 pos; in float fogCoord; +in mat3 TBN; uniform bool acc_fog; uniform vec2 dt; @@ -18,10 +19,14 @@ void main(void) { //if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord); vec3 n, dn; - dn = (texture2D(qgl_Material.map_bump.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_bump.amount + qgl_Material.map_bump.offset; - dn.x = -dn.x; - dn = dn * mat3(qgl_ModelViewMatrixInverse); - n = normalize(normal - dn); + dn = (texture2D(qgl_Material.map_normal.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_normal.amount + qgl_Material.map_normal.offset; + //float tx = dn.x; + dn.y = -dn.y; + //dn.y = tx; + dn = TBN * dn; + //dn = dn * mat3(qgl_ModelViewMatrix)*10;//*(mat3(qgl_NormalMatrix)); + n = normalize(qgl_NormalMatrix*(normal+dn));//normalize(qgl_NormalMatrix * (normal - dn)); + //n = dn; /*vec2 dpm = normalize(gl_FragCoord.xy * dt * 2. - vec2(1., 1.)), ntc; ntc = gl_FragCoord.xy * dt * 2. - vec2(1., 1.) + dpm * hei; @@ -32,16 +37,15 @@ void main(void) { dc *= texture2D(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset; vec4 spec = texture2D(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset; - spec *= qgl_Material.color_specular * qgl_Material.specular; - vec4 rough = texture2D(qgl_Material.map_roughness.map, tc) * qgl_Material.map_roughness.amount + qgl_Material.map_roughness.offset; - rough *= qgl_Material.roughness; + spec *= qgl_Material.color_specular; + vec4 specularity = texture2D(qgl_Material.map_specularity.map, tc) * qgl_Material.map_specularity.amount + qgl_Material.map_specularity.offset; vec4 self = texture2D(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset; self *= qgl_Material.color_self_illumination; qgl_FragData[0] = vec4(dc.rgb, z); - qgl_FragData[1] = vec4(n.xyz / 2. + vec3(0.5), rough); + qgl_FragData[1] = vec4(n.xyz / 2. + vec3(0.5), specularity); qgl_FragData[2] = vec4(spec.rgb, hei); - qgl_FragData[3] = vec4(pos.xyz, pos.z); + qgl_FragData[3] = vec4(self.rgb, pos.w); //gl_FragData[0] = vec4(et.xyz, pos.w); //gl_FragDepth = gl_FragCoord.z - clamp(hei / pos.z / pos.z / (abs(n.z) + 1), -0.01, 0.01); diff --git a/qglview/shaders/dsl_pass_0.vert b/qglview/shaders/dsl_pass_0.vert index 055a73c..6877795 100644 --- a/qglview/shaders/dsl_pass_0.vert +++ b/qglview/shaders/dsl_pass_0.vert @@ -3,14 +3,16 @@ out vec3 src_normal, normal;//, et; out vec4 pos; out float fogCoord, fs_gid; +out mat3 TBN; uniform bool acc_fog; uniform vec2 dt; uniform vec3 eye; void main(void) { - normal = (qgl_NormalMatrix * qgl_Normal); - pos.xyz = vec3(qgl_ModelViewMatrix * qgl_Vertex); + normal = qgl_Normal;//(qgl_NormalMatrix * qgl_Normal); + pos.xyzw = vec4(qgl_ModelViewMatrix * qgl_Vertex); + TBN = (mat3(qgl_Tangent, qgl_Bitangent, qgl_Normal)); /*if (acc_fog) { fogCoord = (gl_Fog.end - length(pos.xyz) * 0.85) / (gl_Fog.end - gl_Fog.start); fogCoord = 1. - clamp(fogCoord, 0., 1.); diff --git a/qglview/shaders/dsl_pass_1.frag b/qglview/shaders/dsl_pass_1.frag index a217907..0b5eabb 100644 --- a/qglview/shaders/dsl_pass_1.frag +++ b/qglview/shaders/dsl_pass_1.frag @@ -1,8 +1,7 @@ #version 150 //#extension GL_EXT_gpu_shader4 : enable -in vec4 view_dir; -in vec3 view_pos; +in vec4 view_dir, view_pos; uniform vec3 ambient; uniform sampler2D t0, t1, t2, t3, tb; @@ -15,19 +14,21 @@ uniform vec4 back_color; uniform mat4 mat_proji; float light_diffuse(int model, vec3 l, vec3 n) {return max(0., dot(l, n));} -//float light_specular(int model, vec3 l, vec3 n, vec3 h, vec3 v, float shininess) {return max(0., pow(dot(n, h), shininess));} +float light_specular(int model, vec3 l, vec3 n, vec3 h, vec3 v, float shininess) {return max(0., pow(dot(n, h), shininess));} vec4 pos, lpos; vec3 li, si, ldir, halfV; -float sh_pow, sh_mul, dist, NdotL, spot, ldist, diff; +float sh_pow, sh_mul, dist, NdotL, NdotH, spot, ldist, diff; void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { lpos = qgl_Light[index].position; ldir = lpos.xyz - (pos.xyz * lpos.w); ldist = length(ldir); ldir = normalize(ldir); + halfV = normalize(ldir + v); NdotL = max(dot(n, ldir), 0.); - spot = step(0., NdotL); + NdotH = max(dot(n, halfV), 0.); + spot = step(0., NdotL) * qgl_Light[index].intensity; if (NdotL > 0.) { /*if (gl_LightSource[index].spotCutoff < 180.) { spot = max(dot(-ldir, gl_LightSource[index].spotDirection.xyz), 0.); @@ -35,15 +36,18 @@ void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { spot = pow(spot, (gl_LightSource[index].spotExponent + 0.001)); }*/ spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation)); - halfV = normalize(ldir + v); ///li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n); - ///si += spot * gl_LightSource[index].specular.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow); + //si += spot * qgl_Light[index].color.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow); float NdotLs = NdotL*NdotL; + float NdotHs = NdotH*NdotH; float ndlc = (1. - NdotLs) / NdotLs; float der = NdotLs * (sh_mul + ndlc); diff = 2. / (1. + sqrt(1. + (1. - sh_mul) * ndlc)); li += spot * qgl_Light[index].color.rgb * diff;// * light_diffuse(0, ldir, n); + ndlc = (1. - NdotHs) / NdotHs; + der = NdotHs * (sh_mul + ndlc); si += spot * qgl_Light[index].color.rgb * (sh_mul / (der*der) / 3.1416); + //si += der;//dot(n, halfV); } } @@ -63,14 +67,22 @@ void main(void) { //li = vec3(0.); si = vec3(0.); - pos = vec4(sp, 0, 1)*mat_proji; - pos.xyz *= v0.w; + float posz = z_near * z_far / (texture2D(td, tc).r * (z_far - z_near) - z_far); + pos = vec4(sp, 0., 1) * mat_proji; + pos.xy *= v3.w; + pos.z = posz; + pos.xyz += n * height; + //pos = v3; + //pos = vec4(sp, 0, 1.) * mat_proji; + //pos *= v0.w; + //pos.z += 1; //pos.xy *= 10.; //pos.z = v0.w; vec3 v = normalize(-pos.xyz); sh_pow = 1. / max((1. - v1.w), 0.0001); sh_mul = max(1. - v1.w, 0.0001); - //calcLight(0, n, v, v2); + for (int i = 0; i < 16; ++i) + calcLight(i, n, v, v2); /*if (lightsCount > 0) { calcLight(0, n, v, v2); if (lightsCount > 1) { @@ -95,14 +107,9 @@ void main(void) { } } }*/ - //qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb;// + texture2D(tb, tc).rgb; - //vec4 lp = mat*qgl_Light[0].position; - lpos = qgl_Light[0].position; - ldir = lpos.xyz - pos.xyz; - ldist = length(ldir); - float d = texture2D(td, tc).r; - //float z = ((z_near / (z_near-z_far)) * z_far) / (d - (z_far / (z_far-z_near))); - float z = z_near * z_far / (d * (z_far - z_near) - z_far); - //qgl_FragData[0].rgb = vec3(abs((v0.w)+(v3.z))-0.5); - qgl_FragData[0].rgb = vec3((-z*view_pos)); + qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb;// + texture2D(tb, tc).rgb; + //qgl_FragData[0].rgb = vec3(abs(lpos.xyz - pos.xyz)/10); + //qgl_FragData[0].rgb = vec3(li.xyz); + //qgl_FragData[0].rgb = vec3(v1.xyz); + //qgl_FragData[0].a = 0.; } diff --git a/qglview/shaders/dsl_pass_1.vert b/qglview/shaders/dsl_pass_1.vert index 30b8182..e06345c 100644 --- a/qglview/shaders/dsl_pass_1.vert +++ b/qglview/shaders/dsl_pass_1.vert @@ -2,11 +2,12 @@ in vec4 view_corner; out vec4 view_dir; -out vec3 view_pos; +out vec4 view_pos; void main(void) { view_dir = view_corner; - view_pos = vec3(qgl_ModelViewMatrix * vec4(qgl_Vertex.xy, 1, 1)); + view_pos = vec4(qgl_ModelViewMatrix * vec4(qgl_Vertex.xy, 1, 1)); + view_pos /= view_pos.w; qgl_FragTexture = qgl_Texture; qgl_FragColor = qgl_Color; gl_Position = qgl_ftransform();