From 35668c13fc605d7246180f3cff8a33ccd12d6544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Mon, 2 Dec 2019 20:09:18 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@638 a8b55f48-bf90-11e4-a774-851b48703e85 --- qglengine/core/gltransform.cpp | 434 ++++++++++++++++++++++ qglengine/core/gltransform.h | 117 ++++++ qglengine/formats/loader_assimp.cpp | 2 +- qglengine/glcamera.cpp | 119 +++--- qglengine/glcamera.h | 22 +- qglengine/globject.cpp | 204 +++++----- qglengine/globject.h | 101 ++--- qglengine/glrendererbase.cpp | 2 +- qglengine/mouse_controller.cpp | 10 +- qglengine/qglview.cpp | 7 +- qglengine/qglview_test/qglview_window.cpp | 7 +- qglengine/renderer_base.cpp | 2 +- qglengine/renderer_material.cpp | 2 +- qglengine/renderer_service.cpp | 24 +- qglengine/widgets/object_editor.cpp | 2 +- 15 files changed, 792 insertions(+), 263 deletions(-) create mode 100644 qglengine/core/gltransform.cpp create mode 100644 qglengine/core/gltransform.h diff --git a/qglengine/core/gltransform.cpp b/qglengine/core/gltransform.cpp new file mode 100644 index 0000000..d725900 --- /dev/null +++ b/qglengine/core/gltransform.cpp @@ -0,0 +1,434 @@ +/* + QGLView + Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru + + 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 "gltransform.h" +//#include + +#include "gltypes.h" +#include + + +inline void composeQMatrix4x4(const QVector3D & position, const QVector3D & orientation, const QVector3D & scale, QMatrix4x4 &m) { + const QMatrix3x3 rot3x3(Transform::toRotationMatrix(orientation)); + + // set up final matrix with scale, rotation and translation + m(0, 0) = scale.x() * rot3x3(0, 0); m(0, 1) = scale.y() * rot3x3(0, 1); m(0, 2) = scale.z() * rot3x3(0, 2); m(0, 3) = position.x(); + m(1, 0) = scale.x() * rot3x3(1, 0); m(1, 1) = scale.y() * rot3x3(1, 1); m(1, 2) = scale.z() * rot3x3(1, 2); m(1, 3) = position.y(); + m(2, 0) = scale.x() * rot3x3(2, 0); m(2, 1) = scale.y() * rot3x3(2, 1); m(2, 2) = scale.z() * rot3x3(2, 2); m(2, 3) = position.z(); + // no projection term + m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f; +} + +inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D & D, QVector3D & U) { + // Factor M = QR = QDU where Q is orthogonal, D is diagonal, + // and U is upper triangular with ones on its diagonal. + // Algorithm uses Gram-Schmidt orthogonalization (the QR algorithm). + // + // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then + // q0 = m0/|m0| + // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| + // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| + // + // where |V| indicates length of vector V and A*B indicates dot + // product of vectors A and B. The matrix R has entries + // + // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2 + // r10 = 0 r11 = q1*m1 r12 = q1*m2 + // r20 = 0 r21 = 0 r22 = q2*m2 + // + // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00, + // u02 = r02/r00, and u12 = r12/r11. + + // Q = rotation + // D = scaling + // U = shear + + // D stores the three diagonal entries r00, r11, r22 + // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12 + + // build orthogonal matrix Q + float invLen = 1.0f / std::sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0)); + Q(0, 0) = m(0, 0) * invLen; + Q(1, 0) = m(1, 0) * invLen; + Q(2, 0) = m(2, 0) * invLen; + + float dot = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); + Q(0, 1) = m(0, 1) - dot * Q(0, 0); + Q(1, 1) = m(1, 1) - dot * Q(1, 0); + Q(2, 1) = m(2, 1) - dot * Q(2, 0); + invLen = 1.0f / std::sqrt(Q(0, 1) * Q(0, 1) + Q(1, 1) * Q(1, 1) + Q(2, 1) * Q(2, 1)); + Q(0, 1) *= invLen; + Q(1, 1) *= invLen; + Q(2, 1) *= invLen; + + dot = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); + Q(0, 2) = m(0, 2) - dot * Q(0, 0); + Q(1, 2) = m(1, 2) - dot * Q(1, 0); + Q(2, 2) = m(2, 2) - dot * Q(2, 0); + dot = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); + Q(0, 2) -= dot * Q(0, 1); + Q(1, 2) -= dot * Q(1, 1); + Q(2, 2) -= dot * Q(2, 1); + invLen = 1.0f / std::sqrt(Q(0, 2) * Q(0, 2) + Q(1, 2) * Q(1, 2) + Q(2, 2) * Q(2, 2)); + Q(0, 2) *= invLen; + Q(1, 2) *= invLen; + Q(2, 2) *= invLen; + + // guarantee that orthogonal matrix has determinant 1 (no reflections) + const float det = Q(0, 0) * Q(1, 1) * Q(2, 2) + Q(0, 1) * Q(1, 2) * Q(2, 0) + + Q(0, 2) * Q(1, 0) * Q(2, 1) - Q(0, 2) * Q(1, 1) * Q(2, 0) - + Q(0, 1) * Q(1, 0) * Q(2, 2) - Q(0, 0) * Q(1, 2) * Q(2, 1); + if (det < 0.0f) + Q *= -1.0f; + + // build "right" matrix R + QMatrix3x3 R(Qt::Uninitialized); + R(0, 0) = Q(0, 0) * m(0, 0) + Q(1, 0) * m(1, 0) + Q(2, 0) * m(2, 0); + R(0, 1) = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); + R(1, 1) = Q(0, 1) * m(0, 1) + Q(1, 1) * m(1, 1) + Q(2, 1) * m(2, 1); + R(0, 2) = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); + R(1, 2) = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); + R(2, 2) = Q(0, 2) * m(0, 2) + Q(1, 2) * m(1, 2) + Q(2, 2) * m(2, 2); + + // the scaling component + D[0] = R(0, 0); + D[1] = R(1, 1); + D[2] = R(2, 2); + + // the shear component + U[0] = R(0, 1) / D[0]; + U[1] = R(0, 2) / D[0]; + U[2] = R(1, 2) / D[1]; +} + +inline bool hasScale(const QMatrix4x4 &m) { + // If the columns are orthonormal and form a right-handed system, then there is no scale + float t(m.determinant()); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 1) * m(0, 1) + m(1, 1) * m(1, 1) + m(2, 1) * m(2, 1); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + t = m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2); + if (!qFuzzyIsNull(t - 1.0f)) + return true; + return false; +} + +inline void decomposeQMatrix4x4(const QMatrix4x4 & m, QVector3D & position, QVector3D & orientation, QVector3D & scale) { + Q_ASSERT(m.isAffine()); + + const QMatrix3x3 m3x3(m.toGenericMatrix<3, 3>()); + + QMatrix3x3 rot3x3(Qt::Uninitialized); + if (hasScale(m)) { + decomposeQMatrix3x3(m3x3, rot3x3, scale, position); + } else { + // we know there is no scaling part; no need for QDU decomposition + scale = QVector3D(1.0f, 1.0f, 1.0f); + rot3x3 = m3x3; + } + orientation = Transform::fromRotationMatrix(rot3x3); + position = QVector3D(m(0, 3), m(1, 3), m(2, 3)); +} + + + + +Transform::Transform(): m_scale(1.0f, 1.0f, 1.0f), + m_translation(), m_eulerRotationAngles(), m_matrixDirty(false) { +} + + +void Transform::setMatrix(const QMatrix4x4 & m) { + if (m != matrix()) { + m_matrix = m; + m_matrixDirty = false; + QVector3D s; + QVector3D t; + QVector3D r; + decomposeQMatrix4x4(m, t, r, s); + m_scale = s; + m_translation = t; + m_eulerRotationAngles = r; + } +} + + +void Transform::setRotationX(float r) { + if (m_eulerRotationAngles.x() == r) + return; + m_eulerRotationAngles.setX(r); + m_matrixDirty = true; +} + + +void Transform::setRotationY(float r) { + if (m_eulerRotationAngles.y() == r) + return; + m_eulerRotationAngles.setY(r); + m_matrixDirty = true; +} + + +void Transform::setRotationZ(float r) { + if (m_eulerRotationAngles.z() == r) + return; + m_eulerRotationAngles.setZ(r); + m_matrixDirty = true; +} + + +QMatrix4x4 Transform::matrix() const { + buildMatrix(); + return m_matrix; +} + + +QMatrix4x4 Transform::matrixRotate() const { + buildMatrix(); + return m_matrixR; +} + + +QMatrix4x4 Transform::matrixScale() const { + buildMatrix(); + return m_matrixS; +} + + +QMatrix4x4 Transform::matrixRotateScale() const { + buildMatrix(); + return m_matrixWT; +} + + +QVector3D Transform::direction() const { + return matrixRotate().mapVector(QVector3D(0,0,-1)).normalized(); +} + + +void Transform::buildMatrix() const { + if (m_matrixDirty) { + composeQMatrix4x4(m_translation, m_eulerRotationAngles, m_scale, m_matrix); + composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, m_scale, m_matrixWT); + composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, QVector3D(1,1,1), m_matrixR); + composeQMatrix4x4(QVector3D(), QVector3D(), m_scale, m_matrixS); + m_matrixDirty = false; + } +} + + +float Transform::rotationX() const { + return m_eulerRotationAngles.x(); +} + + +float Transform::rotationY() const { + return m_eulerRotationAngles.y(); +} + + +float Transform::rotationZ() const { + return m_eulerRotationAngles.z(); +} + + +void Transform::setScale(const QVector3D & s) { + if (s != m_scale) { + m_scale = s; + m_matrixDirty = true; + } +} + + +void Transform::setScaleX(float s) { + if (s != m_scale.x()) { + m_scale.setX(s); + m_matrixDirty = true; + } +} + + +void Transform::setScaleY(float s) { + if (s != m_scale.y()) { + m_scale.setY(s); + m_matrixDirty = true; + } +} + + +void Transform::setScaleZ(float s) { + if (s != m_scale.z()) { + m_scale.setZ(s); + m_matrixDirty = true; + } +} + + +QVector3D Transform::scale3D() const { + return m_scale; +} + + +float Transform::scale() const { + return m_scale.x(); +} + + +void Transform::setRotation(const QVector3D & r) { + if (r != m_eulerRotationAngles) { + m_eulerRotationAngles = r; + m_matrixDirty = true; + } +} + + +QVector3D Transform::rotation() const { + return m_eulerRotationAngles; +} + + +void Transform::setTranslation(const QVector3D & t) { + if (t != m_translation) { + m_translation = t; + m_matrixDirty = true; + } +} + + +void Transform::setTranslationX(float t) { + if (t != m_translation.x()) { + m_translation.setX(t); + m_matrixDirty = true; + } +} + + +void Transform::setTranslationY(float t) { + if (t != m_translation.y()) { + m_translation.setY(t); + m_matrixDirty = true; + } +} + + +void Transform::setTranslationZ(float t) { + if (t != m_translation.z()) { + m_translation.setZ(t); + m_matrixDirty = true; + } +} + + +QVector3D Transform::translation() const { + return m_translation; +} + + +QQuaternion Transform::fromAxisAndAngle(const QVector3D & axis, float angle) { + return QQuaternion::fromAxisAndAngle(axis, angle); +} + + +QQuaternion Transform::fromAxisAndAngle(float x, float y, float z, float angle) { + return QQuaternion::fromAxisAndAngle(x, y, z, angle); +} + + +QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2) { + const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); + const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); + return q2 * q1; +} + + +QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2, + const QVector3D & axis3, float angle3) { + const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); + const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); + const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3); + return q3 * q2 * q1; +} + + +QQuaternion Transform::fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { + return QQuaternion::fromAxes(xAxis, yAxis, zAxis); +} + + +QVector3D Transform::fromDirection(QVector3D d) { + QVector3D ret; + //QMatrix3x3 m = QQuaternion::fromDirection(d, QVector3D()).toRotationMatrix(); + //ret[0] = -atan2(m(0, 2), m(1, 2)); + //ret[1] = acos (m(2, 2)); + //ret[2] = atan2(m(2, 0), m(2, 1)); + d.normalize(); + ret[0] = M_PI - acos(d.z()); + ret[2] = -atan2(d.x(), d.y()); + return ret * rad2deg; +} + + +QVector3D Transform::fromRotationMatrix(const QMatrix3x3 & m) { + //return QQuaternion::fromRotationMatrix(m); + float sy = sqrt(m(0,0) * m(0,0) + m(1,0) * m(1,0)); + bool singular = sy < 1.E-6; // If + float x, y, z; + if (!singular) { + x = atan2( m(2,1), m(2,2)); + y = atan2(-m(2,0), sy); + z = atan2( m(1,0), m(0,0)); + } else { + x = atan2(-m(1,2), m(1,1)); + y = atan2(-m(2,0), sy); + z = 0.; + } + return QVector3D(x, y, z) * rad2deg; +} + + +QMatrix3x3 Transform::toRotationMatrix(const QVector3D & r) { + QMatrix4x4 m; + if (r.z() != 0.f) m.rotate(r.z(), 0., 0., 1.); + if (r.y() != 0.f) m.rotate(r.y(), 0., 1., 0.); + if (r.x() != 0.f) m.rotate(r.x(), 1., 0., 0.); + return m.toGenericMatrix<3,3>(); +} + + +QMatrix4x4 Transform::rotateAround(const QVector3D & point, float angle, const QVector3D & axis) { + QMatrix4x4 m; + m.translate(point); + m.rotate(angle, axis); + m.translate(-point); + return m; +} + + +QMatrix4x4 Transform::rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { + return QMatrix4x4(xAxis.x(), yAxis.x(), zAxis.x(), 0.0f, + xAxis.y(), yAxis.y(), zAxis.y(), 0.0f, + xAxis.z(), yAxis.z(), zAxis.z(), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} diff --git a/qglengine/core/gltransform.h b/qglengine/core/gltransform.h new file mode 100644 index 0000000..6dbadbf --- /dev/null +++ b/qglengine/core/gltransform.h @@ -0,0 +1,117 @@ +/* + QGLView + Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru + + 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 GLTRANSFORM_H +#define GLTRANSFORM_H + +#include +#include +#include +#include + + +class Transform { + friend QDataStream & operator >>(QDataStream & s, Transform & v); +public: + Transform(); + + float scale() const; + QVector3D scale3D() const; + QVector3D rotation() const; + QVector3D translation() const; + QMatrix4x4 matrix() const; + QMatrix4x4 matrixRotate() const; + QMatrix4x4 matrixScale() const; + QMatrix4x4 matrixRotateScale() const; + QVector3D direction() const; + + float rotationX() const; + float rotationY() const; + float rotationZ() const; + + void setScale(float s) {setScale(QVector3D(s, s, s));} + void setScale(const QVector3D & s); + void setScaleX(float s); + void setScaleY(float s); + void setScaleZ(float s); + + void setRotation(const QVector3D & r); + void setRotationX(float r); + void setRotationY(float r); + void setRotationZ(float r); + + void setTranslation(const QVector3D & t); + void setTranslationX(float t); + void setTranslationY(float t); + void setTranslationZ(float t); + + void setMatrix(const QMatrix4x4 & matrix); + + + static QQuaternion fromAxisAndAngle(const QVector3D & axis, float angle); + static QQuaternion fromAxisAndAngle(float x, float y, float z, float angle); + + static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2); + static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, + const QVector3D & axis2, float angle2, + const QVector3D & axis3, float angle3); + static QQuaternion fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); + + static QVector3D fromDirection(QVector3D d); + static QVector3D fromRotationMatrix(const QMatrix3x3 & m); + static QMatrix3x3 toRotationMatrix(const QVector3D & r); + + static QMatrix4x4 rotateAround(const QVector3D & point, float angle, const QVector3D & axis); + static QMatrix4x4 rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); + +protected: + void buildMatrix() const; + + QVector3D m_scale; + QVector3D m_translation; + QVector3D m_eulerRotationAngles; + + mutable QMatrix4x4 m_matrix, m_matrixWT, m_matrixR, m_matrixS; + mutable bool m_matrixDirty; + +}; + + +inline QDataStream & operator <<(QDataStream & s, const Transform & v) { + //ChunkStream cs; + //cs.add(1, v.matrix()); + //s << cs.data(); return s; + s << v.matrix(); return s; +} +inline QDataStream & operator >>(QDataStream & s, Transform & v) { + //ChunkStream cs(s); + //while (!cs.atEnd()) { + // switch (cs.read()) { + // case 1: v.setMatrix(cs.getData()); break; + // } + //} + //return s; + QMatrix4x4 m; + s >> m; + v.setMatrix(m); + v.m_matrixDirty = true; + return s; +} + +#endif // QT3DCORE_QTRANSFORM_H diff --git a/qglengine/formats/loader_assimp.cpp b/qglengine/formats/loader_assimp.cpp index d312005..084c0c8 100644 --- a/qglengine/formats/loader_assimp.cpp +++ b/qglengine/formats/loader_assimp.cpp @@ -113,7 +113,7 @@ ObjectBase * assimpObject(const aiNode * n, const QVector & meshes, con } else ret = new ObjectBase(); ret->setName(name); - ret->setTransform(fromAiMatrix4D(n->mTransformation)); + ret->setMatrix(fromAiMatrix4D(n->mTransformation)); //qDebug() << "add object" << ret << ret->name(); if (!light) { for (uint i = 0; i < n->mNumMeshes; ++i) { diff --git a/qglengine/glcamera.cpp b/qglengine/glcamera.cpp index 7c7f6cb..6546f48 100644 --- a/qglengine/glcamera.cpp +++ b/qglengine/glcamera.cpp @@ -25,7 +25,7 @@ Camera::Camera() { fov_ = 60.; angle_limit_lower_xy = 0.f; angle_limit_upper_xy = 360.f; - angles_.setY(270.f); + //setRotationX(90.f); depth_start = 0.1f; depth_end = 1000.f; mirror_x = mirror_y = false; @@ -33,45 +33,16 @@ Camera::Camera() { void Camera::anglesFromPoints() { - QVector3D dv = aim_ - pos_, tv; - tv = QVector3D(dv.x(), dv.y(), 0.); - angles_.setZ(atan2f(tv.x(), tv.y()) * rad2deg); - angles_.setY(piClamp(atan2f(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy) + 180.f); -} - - -void Camera::apply(const GLfloat & aspect) { - glMatrixMode(GL_PROJECTION); - if (aspect <= 1.f) - glScalef(aspect, aspect, 1.f); - 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); - //qDebug() << pm; - //setGLMatrix(pm); - glMatrixMode(GL_MODELVIEW); - pm.setToIdentity(); - 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_) { - QMatrix4x4 pmat = parent_->worldTransform(); - offset_ = pmat.column(3).toVector3D(); - pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; - pmat.translate(aim_); - pm *= pmat.inverted(); - //qDebug() << pmat; - } - //setGLMatrix(pm); - //qDebug() << angles_; + //QVector3D dv = aim_ - pos_, tv; + //tv = QVector3D(dv.x(), dv.y(), 0.); + //angles_.setZ(atan2f(tv.x(), tv.y()) * rad2deg); + //angles_.setY(piClamp(atan2f(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy) + 180.f); } QMatrix4x4 Camera::offsetMatrix() const { QMatrix4x4 ret; - ret.translate(parent_ ? -offset_ : -aim_); + ret.translate(parent_ ? -offset_ : -aim()); return ret; } @@ -91,10 +62,9 @@ void Camera::localTransform(QMatrix4x4 & m) { */ void Camera::assign(const Camera & c) { - pos_ = c.pos_; - aim_ = c.aim_; + trans = c.trans; + aim_dist = c.aim_dist; fov_ = c.fov_; - angles_ = c.angles_; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy; mirror_x = c.mirror_x; @@ -116,10 +86,9 @@ ObjectBase * Camera::clone(bool withChildren) { for (int i = 0; i < children_.size(); ++i) o->addChild(children_[i]->clone(withChildren)); } - o->pos_ = pos_; - o->aim_ = aim_; + o->trans = trans; + o->aim_dist = aim_dist; o->fov_ = fov_; - o->angles_ = angles_; o->angle_limit_lower_xy = angle_limit_lower_xy; o->angle_limit_upper_xy = angle_limit_upper_xy; o->mirror_x = mirror_x; @@ -133,16 +102,18 @@ ObjectBase * Camera::clone(bool withChildren) { QMatrix4x4 Camera::viewMatrix() const { QMatrix4x4 ret; + //qDebug() << pos() << aim(); 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.); + ret *= trans.matrixRotateScale().inverted(); + //ret.rotate(angles_.y(), 1., 0., 0.); + //ret.rotate(angles_.x(), 0., 1., 0.); + //ret.rotate(angles_.z(), 0., 0., 1.); //pm.translate(-aim_); if (parent_) { QMatrix4x4 pmat = parent_->worldTransform(); offset_ = pmat.column(3).toVector3D(); pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; - pmat.translate(aim_); + pmat.translate(aim()); ret *= pmat.inverted(); } return ret; @@ -155,96 +126,106 @@ QMatrix4x4 Camera::projectionMatrix(double aspect) const { void Camera::panZ(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; - buildTransform(); + buildTransform();*/ } void Camera::panXY(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; - buildTransform(); + buildTransform();*/ } void Camera::rotateZ(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; - buildTransform(); + buildTransform();*/ } void Camera::rotateXY(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; - buildTransform(); + buildTransform();*/ } void Camera::orbitZ(const float & a) { - QVector3D dv = aim_ - pos_; + //qDebug() << rotation() << Transform::fromDirection(direction()); + QVector3D pa = aim(); + //trans.rotationRef() *= QQuaternion::fromEulerAngles(0, a, 0); + ObjectBase::rotateZ(-a); + move(pa - aim()); + /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); pos_ = aim_ - dv; - buildTransform(); + buildTransform();*/ } void Camera::orbitXY(const float & a) { - QVector3D dv = aim_ - pos_; + QVector3D pa = aim(); + //trans.rotationRef() *= QQuaternion::fromEulerAngles(a, 0, 0); + ObjectBase::rotateX(-a); + move(pa - aim()); + //qDebug() << pos() << aim(); + /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; - buildTransform(); + buildTransform();*/ } void Camera::setAngleZ(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; - buildTransform(); + buildTransform();*/ } void Camera::setAngleXY(const float & a) { - QVector3D dv = aim_ - pos_; + /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(a); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); //pos_ = aim_ - dv; aim_ = pos_ + dv * tl; - buildTransform(); + buildTransform();*/ //anglesFromPoints(); } void Camera::moveForward(const float & x, bool withZ) { - QVector3D dv;// = aim_ - pos_; + /*Vector3D dv;// = aim_ - pos_; float tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, 0.); if (withZ) dv.setZ(-cosf(angles_.y() * deg2rad)); @@ -252,12 +233,12 @@ void Camera::moveForward(const float & x, bool withZ) { dv *= x; pos_ += dv; aim_ += dv; - buildTransform(); + buildTransform();*/ } void Camera::moveLeft(const float & x, bool withZ) { - QVector3D dv;// = aim_ - pos_; + /*QVector3D dv;// = aim_ - pos_; float tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad - float(M_PI_2)) * tc, cosf(angles_.z() * deg2rad - float(M_PI_2)) * tc, 0.f); if (withZ) dv.setZ(-sinf(angles_.x() * deg2rad)); @@ -265,12 +246,12 @@ void Camera::moveLeft(const float & x, bool withZ) { dv *= x; pos_ += dv; aim_ += dv; - buildTransform(); + buildTransform();*/ } void Camera::moveUp(const float & x, bool onlyZ) { - QVector3D dv; + /*QVector3D dv; if (onlyZ) dv = QVector3D(0., 0., x); else { @@ -281,10 +262,10 @@ void Camera::moveUp(const float & x, bool onlyZ) { } pos_ += dv; aim_ += dv; - buildTransform(); + buildTransform();*/ } - +/* void Camera::flyCloser(const float & s) { QVector3D dv = aim_ - pos_; float tl = dv.length() / (1.f + s), tc = -sinf(angles_.y() * deg2rad); @@ -310,4 +291,4 @@ void Camera::flyToDistance(const float & d) { pos_ = aim_ - dv * d; buildTransform(); } - +*/ diff --git a/qglengine/glcamera.h b/qglengine/glcamera.h index 822a9e3..a6e9d98 100644 --- a/qglengine/glcamera.h +++ b/qglengine/glcamera.h @@ -33,10 +33,6 @@ class Camera: public AimedObject public: Camera(); - void setPos(const QVector3D & p) {pos_ = p; anglesFromPoints(); buildTransform();} - void setAim(const QVector3D & p) {AimedObject::setAim(p); anglesFromPoints(); buildTransform();} - void move(const QVector3D & p) {pos_ += p; aim_ += p; buildTransform();} - void move(const float & x, const float & y = 0., const float & z = 0.) {pos_ += QVector3D(x, y, z); aim_ += QVector3D(x, y, z); buildTransform();} void moveForward(const float & x, bool withZ = true); void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);} void moveLeft(const float & x, bool withZ = true); @@ -45,7 +41,7 @@ public: void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);} void rotateZ(const float & a); void rotateXY(const float & a); - void rotateRoll(const float & a) {angles_.setX(angles_.x() + a); buildTransform();} + void rotateRoll(const float & a) {rotateX(a);} void orbitZ(const float & a); void orbitXY(const float & a); void panZ(const float & a); @@ -54,7 +50,7 @@ public: void setAngles(const QVector3D & a) {setRotation(a);} void setAngleZ(const float & a); void setAngleXY(const float & a); - void setAngleRoll(const float & a) {angles_.setX(a); buildTransform();} + void setAngleRoll(const float & a) {setRotationX(a);} void setAngleLowerLimitXY(const float & a) {angle_limit_lower_xy = a; buildTransform();} void setAngleUpperLimitXY(const float & a) {angle_limit_upper_xy = a; buildTransform();} void setAngleLimitsXY(const float & lower, const float & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper; buildTransform();} @@ -62,18 +58,11 @@ public: void setDepthEnd(const float & d) {depth_end = d;} void setMirrorX(bool yes) {mirror_x = yes;} void setMirrorY(bool yes) {mirror_y = yes;} - void flyCloser(const float & s); - void flyFarer(const float & s); - void flyToDistance(const float & d); - 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();} float FOV() const {return fov_;} - float distance() const {return (pos_ - aim_).length();} - float angleZ() const {return angles_.z();} - float angleXY() const {return angles_.y();} - float angleRoll() const {return angles_.x();} + float angleZ() const {return rotationZ();} + float angleXY() const {return rotationY();} + float angleRoll() const {return rotationZ();} float angleLowerLimitXY() const {return angle_limit_lower_xy;} float angleUpperLimitXY() const {return angle_limit_upper_xy;} float depthStart() const {return depth_start;} @@ -81,7 +70,6 @@ public: bool isMirrorX() const {return mirror_x;} bool isMirrorY() const {return mirror_y;} void anglesFromPoints(); - void apply(const GLfloat & aspect = 1.); void assign(const Camera & c); diff --git a/qglengine/globject.cpp b/qglengine/globject.cpp index 334ddcf..87ca22f 100644 --- a/qglengine/globject.cpp +++ b/qglengine/globject.cpp @@ -27,7 +27,6 @@ ObjectBase::ObjectBase(Mesh * geom, Material * mat) { type_ = glMesh; render_mode = View; pass_ = Solid; - scale_ = QVector3D(1., 1., 1.); parent_ = nullptr; color_ = Qt::white; is_root = is_init = is_tex_loaded = selected_ = false; @@ -67,12 +66,11 @@ ObjectBase * ObjectBase::clone(bool withChildren) { o->accept_light = accept_light; o->accept_fog = accept_fog; o->visible_ = visible_; + o->color_ = color_; o->type_ = type_; o->raw_matrix = raw_matrix; o->mat_ = mat_; - o->pos_ = pos_; - o->angles_ = angles_; - o->scale_ = scale_; + o->trans = trans; o->itransform_ = itransform_; o->bound = bound; o->name_ = name_;// + "_copy"; @@ -215,62 +213,28 @@ void ObjectBase::setVisible(bool v) { } -void ObjectBase::rotateX(GLfloat a) { - raw_matrix = false; - angles_.setX(angles_.x() + a); - buildTransform(); -} - - -void ObjectBase::rotateY(GLfloat a) { - raw_matrix = false; - angles_.setY(angles_.y() + a); - buildTransform(); -} - - void ObjectBase::rotateZ(GLfloat a) { raw_matrix = false; - angles_.setZ(angles_.z() + a); - while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); - while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); - buildTransform(); -} - - -void ObjectBase::setRotationX(GLfloat a) { - raw_matrix = false; - angles_.setX(a); - buildTransform(); -} - - -void ObjectBase::setRotationY(GLfloat a) { - raw_matrix = false; - angles_.setY(a); + trans.setRotationZ(trans.rotationZ() + a); + //angles_.setZ(angles_.z() + a); + //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); + //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); buildTransform(); } void ObjectBase::setRotationZ(GLfloat a) { raw_matrix = false; - angles_.setZ(a); - while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); - while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); + trans.setRotationZ(a); + //angles_.setZ(a); + //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); + //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); buildTransform(); } -void ObjectBase::setRotation(const QVector3D & a) { - raw_matrix = false; - angles_= a; - buildTransform(); -} - - -void ObjectBase::resetRotation() { - raw_matrix = false; - angles_ = QVector3D(0., 0., 0.); +void ObjectBase::setTransform(const Transform & t) { + trans = t; buildTransform(); } @@ -328,15 +292,27 @@ void ObjectBase::removeProperty(const QString & pn) { } -void ObjectBase::setTransform(const QMatrix4x4 & t) { - raw_matrix = true; - mat_ = t; - pos_ = mat_.column(3).toVector3D(); - mat_.setColumn(3, QVector4D(0., 0., 0., 1.)); +void ObjectBase::setMatrix(const QMatrix4x4 & t) { + //raw_matrix = true; + //mat_ = t; + //pos_ = mat_.column(3).toVector3D(); + //mat_.setColumn(3, QVector4D(0., 0., 0., 1.)); + trans.setMatrix(t); buildTransform(); } +QMatrix4x4 ObjectBase::matrix() const { + return trans.matrix(); +} + + +QVector3D ObjectBase::inParentSpace(const QVector3D & v) const { + if (!parent_) return v; + return (parent_->matrix() * QVector4D(v, 1)).toVector3D(); +} + + bool ObjectBase::isSelected(bool check_parents) const { if (!check_parents) return selected_; if (selected_) return true; @@ -397,11 +373,11 @@ void ObjectBase::buildTransform() { ObjectBase * p = parent_; if (p) itransform_ = p->itransform_; - if (raw_matrix) { - itransform_.translate(pos_); - itransform_ *= mat_; - //qDebug() << "raw_matrix" << itransform_; - } else + //if (raw_matrix) { + // itransform_.translate(pos_); + // itransform_ *= mat_; + // //qDebug() << "raw_matrix" << itransform_; + //} else localTransform(itransform_); //qDebug() << name_ << itransform_; foreach (ObjectBase * i, children_) @@ -417,11 +393,7 @@ void ObjectBase::initInternal() { void ObjectBase::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_); + m *= trans.matrix(); } @@ -450,15 +422,16 @@ void ObjectBase::setMeshChanged() { QMatrix4x4 ObjectBase::worldMatrix(QMatrix4x4 parent) const { QMatrix4x4 mat; - mat.translate(pos_); - if (raw_matrix) { - mat *= mat_; - } else { - if (angles_.z() != 0.f) mat.rotate(angles_.z(), 0., 0., 1.); - if (angles_.y() != 0.f) mat.rotate(angles_.y(), 0., 1., 0.); - if (angles_.x() != 0.f) mat.rotate(angles_.x(), 1., 0., 0.); - mat.scale(scale_); - } + //mat.translate(pos_); + //if (raw_matrix) { + // mat *= mat_; + //} else { + // if (angles_.z() != 0.f) mat.rotate(angles_.z(), 0., 0., 1.); + // if (angles_.y() != 0.f) mat.rotate(angles_.y(), 0., 1., 0.); + // if (angles_.x() != 0.f) mat.rotate(angles_.x(), 1., 0., 0.); + // mat.scale(scale_); + //} + mat = trans.matrix(); return parent * mat; } @@ -470,19 +443,56 @@ AimedObject::AimedObject() { } +QVector3D AimedObject::worldAim() const { + QVector3D ret = worldPos() + worldDirection() * aim_dist; + return ret; +} + + void AimedObject::setAim(const QVector3D & p) { - aim_ = p; + QVector3D dir = inParentSpace(p) - pos(), up; + if (!QVector3D::crossProduct(QVector3D(0,0,1), dir).isNull()) + up = QVector3D(0,0,1); + trans.setRotation(Transform::fromDirection(dir)); + aim_dist = dir.length(); + //qDebug() << "setAim" << p << aim(); } QVector3D AimedObject::direction() const { - return (aim_ - pos_).normalized(); + return trans.direction(); } void AimedObject::setDirection(const QVector3D & d) { - double len = qMax(direction().length(), 0.001f); - aim_ = pos_ + (d.normalized() * len); + //double len = qMax(aim_.length(), 0.001f); + //aim_ = d.normalized() * len; +} + + +void AimedObject::flyCloser(double s) { + double tl = 1. / (1. + s); + move(direction() * aim_dist * (1. - tl)); + aim_dist *= tl; +} + + +void AimedObject::flyFarer(double s) { + double tl = 1. * (1. + s); + move(direction() * aim_dist * (1. - tl)); + aim_dist *= tl; +} + + +void AimedObject::flyToDistance(double d) { + move(direction() * (aim_dist - d)); + aim_dist = d; + //qDebug() << d << (aim() - pos()).length() << aim(); +} + + +void AimedObject::transformChanged() { + } @@ -502,12 +512,12 @@ Light::Light(): AimedObject(), shadow_map(0, true, GL_R16F) { Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(0, true, GL_R16F) { type_ = glLight; light_type = Omni; - pos_ = p; intensity = i; color_ = c; angle_start = angle_end = 180.; decay_linear = decay_quadratic = decay_start = 0.; decay_const = decay_end = 1.; + setPos(p); setDirection(0, 0, -1.); } @@ -525,8 +535,8 @@ ObjectBase * Light::clone(bool withChildren) { } o->color_ = color_; o->light_type = light_type; - o->pos_ = pos_; - o->aim_ = aim_; + o->trans = trans; + o->aim_dist = aim_dist; o->angle_start = angle_start; o->angle_end = angle_end; o->intensity = intensity; @@ -548,21 +558,20 @@ QDataStream & operator <<(QDataStream & s, const ObjectBase * p) { //qDebug() << "place" << p->name() << "..."; cs.add(1, int(p->type_)).add(2, p->accept_light).add(3, p->accept_fog).add(4, p->visible_) .add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width) - .add(9, int(p->render_mode)).add(11, p->pos_).add(12, p->angles_) - .add(13, p->scale_).add(14, p->mat_).add(16, p->children_.size()) - .add(17, p->name_).add(18, p->meta).add(19, p->color_); + .add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size()) + .add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans); //qDebug() << "place self done"; if (p->type_ == ObjectBase::glLight) { //qDebug() << "place light ..."; const Light * l = (const Light*)p; - cs.add(100, l->direction()).add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) + cs.add(100, l->aim()).add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) .add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic) - .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)).add(110, l->aim()); + .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)); } if (p->type_ == ObjectBase::glCamera) { //qDebug() << "place camera ..."; const Camera * c = (const Camera*)p; - cs.add(200, c->aim_).add(201, c->fov_).add(202, c->depth_start).add(203, c->depth_end) + cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start).add(203, c->depth_end) .add(204, c->angle_limit_lower_xy).add(205, c->angle_limit_upper_xy) .add(206, c->mirror_x).add(207, c->mirror_y); } @@ -601,22 +610,23 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { case 8: if (p) p->line_width = cs.getData(); break; case 9: if (p) p->render_mode = (ObjectBase::RenderMode)cs.getData(); break; //case 10: if (p) p->material_ = cs.getData(); break; - case 11: if (p) p->pos_ = cs.getData(); break; - case 12: - if (p) p->angles_ = cs.getData(); - if (c) { - c->setAngles(cs.getData()); - cam_angles = c->angles(); - } - break; - case 13: if (p) p->scale_ = cs.getData(); break; + //case 11: if (p) p->pos_ = cs.getData(); break; + //case 12: + // if (p) p->angles_ = cs.getData(); + // if (c) { + // c->setAngles(cs.getData()); + // cam_angles = c->angles(); + // } + //break; + //case 13: if (p) p->scale_ = cs.getData(); break; case 14: if (p) p->mat_ = cs.getData(); break; //case 15: if (p) p->vbo = cs.getData(); break; case 16: if (p) ccnt = cs.getData(); break; case 17: if (p) p->name_ = cs.getData(); break; case 18: if (p) p->meta = cs.getData(); break; case 19: if (p) p->color_ = cs.getData(); break; - case 100: if (l) l->setDirection(cs.getData());break; + case 20: if (p) p->trans = cs.getData(); break; + case 100: if (l) l->setAim(cs.getData()); break; case 101: if (l) l->angle_start = cs.getData(); break; case 102: if (l) l->angle_end = cs.getData(); break; case 103: if (l) l->intensity = cs.getData(); break; @@ -626,7 +636,6 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { case 107: if (l) l->decay_start = cs.getData(); break; case 108: if (l) l->decay_end = cs.getData(); break; case 109: if (l) l->light_type = (Light::Type)cs.getData(); break; - case 110: if (l) l->setAim(cs.getData()); if (l->aim().isNull()) l->setAim(l->direction()); break; case 200: if (c) c->setAim(cs.getData()); break; case 201: if (c) c->setFOV(cs.getData()); break; case 202: if (c) c->setDepthStart(cs.getData()); break; @@ -637,7 +646,7 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { case 207: if (c) c->mirror_y = cs.getData(); break; } } - if (c) c->setAngles(cam_angles); + //if (c) c->setAngles(cam_angles); //qDebug() << p->name() << ccnt; for (int i = 0; i < ccnt; ++i) { ObjectBase * c = nullptr; @@ -646,5 +655,6 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { c->parent_ = p; p->children_ << c; } + p->buildTransform(); return s; } diff --git a/qglengine/globject.h b/qglengine/globject.h index 189abaa..2ec07ce 100644 --- a/qglengine/globject.h +++ b/qglengine/globject.h @@ -22,6 +22,7 @@ #include "glframebuffer.h" #include "glmaterial.h" #include "gltypes.h" +#include "gltransform.h" class ObjectBase @@ -89,61 +90,64 @@ public: void setReceiveShadows(bool on) {rec_shadow = on;} void setCastShadows(bool on) {cast_shadow = on;} - void move(const QVector3D & dv) {pos_ += dv; buildTransform();} - void moveTo(const QVector3D & dv) {pos_ = dv; buildTransform();} + void move(const QVector3D & dv) {trans.setTranslation(pos() + dv); buildTransform();} + void moveTo(const QVector3D & dv) {trans.setTranslation(dv); buildTransform();} void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();} void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();} - void moveX(GLfloat o) {pos_.setX(pos_.x() + o); buildTransform();} - void moveY(GLfloat o) {pos_.setY(pos_.y() + o); buildTransform();} - void moveZ(GLfloat o) {pos_.setZ(pos_.z() + o); buildTransform();} - void setPosX(GLfloat o) {pos_.setX(o); buildTransform();} - void setPosY(GLfloat o) {pos_.setY(o); buildTransform();} - void setPosZ(GLfloat o) {pos_.setZ(o); buildTransform();} - void setPos(GLfloat x, GLfloat y, GLfloat z) {pos_ = QVector3D(x, y, z); buildTransform();} - void setPos(const QVector3D & p) {pos_ = p; buildTransform();} - void resetPos() {pos_ = QVector3D(0., 0., 0.); buildTransform();} + void moveX(GLfloat o) {trans.setTranslationX(posX() + o); buildTransform();} + void moveY(GLfloat o) {trans.setTranslationY(posY() + o); buildTransform();} + void moveZ(GLfloat o) {trans.setTranslationZ(posZ() + o); buildTransform();} + void setPosX(GLfloat o) {trans.setTranslationX(o); buildTransform();} + void setPosY(GLfloat o) {trans.setTranslationY(o); buildTransform();} + void setPosZ(GLfloat o) {trans.setTranslationZ(o); buildTransform();} + void setPos(GLfloat x, GLfloat y, GLfloat z) {trans.setTranslation(QVector3D(x, y, z)); buildTransform();} + void setPos(const QVector3D & p) {trans.setTranslation(p); buildTransform();} + void resetPos() {trans.setTranslation(QVector3D()); buildTransform();} - QVector3D pos() const {return pos_;} - float posX() const {return pos_.x();} - float posY() const {return pos_.y();} - float posZ() const {return pos_.z();} + QVector3D pos() const {return trans.translation();} + float posX() const {return trans.translation().x();} + float posY() const {return trans.translation().y();} + float posZ() const {return trans.translation().z();} QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();} QMatrix4x4 worldTransform() const {return itransform_;} - QVector3D rotation() const {return angles_;} - float rotationX() const {return angles_.x();} - float rotationY() const {return angles_.y();} - float rotationZ() const {return angles_.z();} - void rotateX(GLfloat a); - void rotateY(GLfloat a); + QVector3D rotation() const {return trans.rotation();} + float rotationX() const {return rotation().x();} + float rotationY() const {return rotation().y();} + float rotationZ() const {return rotation().z();} + void rotateX(GLfloat a) {raw_matrix = false; trans.setRotationX(trans.rotationX() + a); buildTransform();} + void rotateY(GLfloat a) {raw_matrix = false; trans.setRotationY(trans.rotationY() + a); buildTransform();} void rotateZ(GLfloat a); - void setRotationX(GLfloat a); - void setRotationY(GLfloat a); + void setRotationX(GLfloat a) {raw_matrix = false; trans.setRotationX(a); buildTransform();} + void setRotationY(GLfloat a) {raw_matrix = false; trans.setRotationY(a); buildTransform();} void setRotationZ(GLfloat a); - void setRotation(const QVector3D & a); - void resetRotation(); + void setRotation(const QVector3D & a) {raw_matrix = false; trans.setRotation(a); buildTransform();} + void resetRotation() {raw_matrix = false; trans.setRotation(QVector3D()); buildTransform();} - QVector3D scale() {return scale_;} - float scaleX() {return scale_.x();} - float scaleY() {return scale_.y();} - float scaleZ() {return scale_.z();} - void scale(const QVector3D & sv) {raw_matrix = false; scale_ *= sv; buildTransform();} + QVector3D scale() {return trans.scale3D();} + float scaleX() {return trans.scale3D().x();} + float scaleY() {return trans.scale3D().y();} + float scaleZ() {return trans.scale3D().z();} + void scale(const QVector3D & sv) {raw_matrix = false; trans.setScale(trans.scale3D() * sv); buildTransform();} void scale(GLfloat sx, GLfloat sy, GLfloat sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();} void scale(GLfloat sx, GLfloat sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();} void scale(GLfloat sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();} - void scaleX(GLfloat a) {raw_matrix = false; scale_.setX(scale_.x() + a); buildTransform();} - void scaleY(GLfloat a) {raw_matrix = false; scale_.setY(scale_.y() + a); buildTransform();} - void scaleZ(GLfloat a) {raw_matrix = false; scale_.setZ(scale_.z() + a); buildTransform();} - void setScale(const QVector3D & a) {raw_matrix = false; scale_ = a; buildTransform();} - void setScale(GLfloat a) {raw_matrix = false; scale_ = QVector3D(a, a, a); buildTransform();} - void setScaleX(GLfloat a) {raw_matrix = false; scale_.setX(a); buildTransform();} - void setScaleY(GLfloat a) {raw_matrix = false; scale_.setY(a); buildTransform();} - void setScaleZ(GLfloat a) {raw_matrix = false; scale_.setZ(a); buildTransform();} - void resetScale() {raw_matrix = false; scale_ = QVector3D(1., 1., 1.); buildTransform();} + void scaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(trans.scale3D().x() + a); buildTransform();} + void scaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(trans.scale3D().y() + a); buildTransform();} + void scaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(trans.scale3D().z() + a); buildTransform();} + void setScale(const QVector3D & a) {raw_matrix = false; trans.setScale(a); buildTransform();} + void setScale(GLfloat a) {raw_matrix = false; trans.setScale(a); buildTransform();} + void setScaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(a); buildTransform();} + void setScaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(a); buildTransform();} + void setScaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(a); buildTransform();} + void resetScale() {raw_matrix = false; trans.setScale(1.f); buildTransform();} - QMatrix4x4 transform() {return mat_;} - void setTransform(const QMatrix4x4 & t); + Transform transform() {return trans;} + void setTransform(const Transform & t); + void setMatrix(const QMatrix4x4 & t); + QMatrix4x4 matrix() const; bool isRawMatrix() {return raw_matrix;} + QVector3D inParentSpace(const QVector3D & v) const; bool isAcceptLight() const {return accept_light;} void setAcceptLight(bool yes) {accept_light = yes;} @@ -190,6 +194,7 @@ public: //QVector d_vertices, d_normals, d_uvs; protected: + virtual void transformChanged() {} void addChildren(QList & list, ObjectBase * where); void loadTextures(bool with_children = false); //void deleteTextures() {foreach (GLuint i, textures) currentQGLView->deleteTexture(i); textures.clear();} @@ -210,7 +215,7 @@ protected: Type type_; RenderMode render_mode; Box3D bound; - QVector3D pos_, angles_, scale_; + Transform trans; QList children_; QMatrix4x4 itransform_, mat_; QString name_; @@ -234,14 +239,20 @@ class AimedObject: public ObjectBase { public: AimedObject(); ~AimedObject() {} - QVector3D aim() const {return aim_;} - QVector3D worldAim() const {return (itransform_ * QVector4D(aim_, 1.)).toVector3D();} + QVector3D aim() const {return pos() + (direction() * aim_dist);} + QVector3D worldAim() const; void setAim(const QVector3D & p); QVector3D direction() const; + QVector3D worldDirection() const {return (itransform_ * QVector4D(direction(), 0.)).toVector3D().normalized();} void setDirection(const QVector3D & d); void setDirection(double x, double y, double z) {setDirection(QVector3D(x, y, z));} + double distance() const {return aim_dist;} + void flyCloser(double s); + void flyFarer(double s); + void flyToDistance(double d); protected: - QVector3D aim_; + void transformChanged() override; + double aim_dist; }; diff --git a/qglengine/glrendererbase.cpp b/qglengine/glrendererbase.cpp index d289782..c7904ad 100644 --- a/qglengine/glrendererbase.cpp +++ b/qglengine/glrendererbase.cpp @@ -213,7 +213,7 @@ void GLRendererBase::renderShadow(Light * l, QOpenGLShaderProgram * prog, QMatri cam.setDepthStart(view->camera()->depthStart()); cam.setDepthEnd(view->camera()->depthEnd()); cam.setFOV(l->angle_end); - cam.apply(1.); + //cam.apply(1.); /*cam.rotateXY(l->angle_end); QVector3D rdir = l->direction * cos(l->angle_end / 2. * deg2rad); l->dir0 = cam.direction() - rdir; diff --git a/qglengine/mouse_controller.cpp b/qglengine/mouse_controller.cpp index f258d3d..81aed7c 100644 --- a/qglengine/mouse_controller.cpp +++ b/qglengine/mouse_controller.cpp @@ -127,13 +127,9 @@ void MouseController::mouseMoveEvent(QMouseEvent * e) { QMatrix4x4 pmat; foreach (ObjectBase * o, objects) { pmat.setToIdentity(); - if (o->parent()) { - pmat = o->parent()->worldTransform(); - pmat.setColumn(3, QVector4D(0,0,0,1)); - double det = pmat.determinant(); - if (det > 0.) pmat /= sqrt(det); - } - o->move((QVector4D(axe_vector, 0) * pmat).toVector3D()); + if (o->parent()) + pmat = o->parent()->worldTransform().inverted(); + o->move((pmat * QVector4D(axe_vector, 0)).toVector3D()); } } if (cur_action == RendererService::haRotate) { diff --git a/qglengine/qglview.cpp b/qglengine/qglview.cpp index 5ee2f63..7c6a8dd 100644 --- a/qglengine/qglview.cpp +++ b/qglengine/qglview.cpp @@ -81,8 +81,9 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed())); camera_ = new Camera(); - camera_->setAim(QVector3D()); camera_->setPos(QVector3D(2, 2, 2)); + camera_->setAim(QVector3D()); + qDebug() << camera_->aim(); camera_->setName("Camera"); emit cameraPosChanged(camera_->pos()); //camera().aim_ = camera().pos_; @@ -230,7 +231,7 @@ void QGLView::focusOn(const Box3D & bb) { QByteArray QGLView::saveCamera() { ChunkStream cs; const Camera * c = camera(); - cs.add(1, c->pos()).add(2, c->aim()).add(3, c->angles()).add(4, c->FOV()); + cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV()); return cs.data(); } @@ -238,7 +239,7 @@ QByteArray QGLView::saveCamera() { void QGLView::restoreCamera(const QByteArray & ba) { if (ba.isEmpty()) return; Camera * c = camera(); - QVector3D pos(c->pos()), aim(c->aim()), ang(c->angles()); + QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation()); float fov(c->FOV()); ChunkStream cs(ba); cs.readAll(); diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp index 60a2600..5ad6ae2 100644 --- a/qglengine/qglview_test/qglview_window.cpp +++ b/qglengine/qglview_test/qglview_window.cpp @@ -31,9 +31,9 @@ QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLView session.addEntry(this); spinViewLineWidth->setValue(lineThickness()*2); - view->view()->camera()->setAim(QVector3D()); - view->view()->camera()->setPos(QVector3D(2, 2, 2)); - view->view()->camera()->flyToDistance(2.); + //view->view()->camera()->setPos(QVector3D(2, 2, 2)); + //view->view()->camera()->setAim(QVector3D()); + //view->view()->camera()->flyToDistance(2.); // view->setFrameShape(QFrame::NoFrame); view->view()->setMouseRotateEnabled(true); view->view()->setMouseSelectionEnabled(true); @@ -91,6 +91,7 @@ QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLView session.load(); + loadFile("axis.DAE.qgl"); //matEditor->setMaterial(const_cast(view->view()->scene()->rootObject()->child(0))->material()); /*Scene * sc = loadScene("truck.obj"); //view->view()->scene()->addScene(sc); diff --git a/qglengine/renderer_base.cpp b/qglengine/renderer_base.cpp index 30ce1b0..f47628c 100644 --- a/qglengine/renderer_base.cpp +++ b/qglengine/renderer_base.cpp @@ -260,7 +260,7 @@ void RendererBase::reloadLightsPositions(Camera * cam) { QMatrix4x4 m = mat * l->worldTransform(); QVector4D pos(0, 0, 0, 1.), dir(l->direction(), 1);//, dir0(light->dir0), dir1(light->dir1); pos = m * pos; - dir = ((m * dir) - pos).normalized(); + dir = (m * QVector4D(l->direction(),0)).normalized();//((m * dir) - pos).normalized(); so.position = pos; so.direction = dir; //so.shadowMatrix = l->shadow_matrix; diff --git a/qglengine/renderer_material.cpp b/qglengine/renderer_material.cpp index 58f56e3..6eab9f6 100644 --- a/qglengine/renderer_material.cpp +++ b/qglengine/renderer_material.cpp @@ -32,8 +32,8 @@ RendererMaterial::RendererMaterial(Renderer * r_): r(r_), fbo_mat_thumb(r->view, 6, true , GL_RGBA16F) { mat_sphere = Primitive::ellipsoid(16, 16); mat_camera = new Camera(); - mat_camera->setAim(QVector3D()); mat_camera->setPos(QVector3D(1, 1, 1)); + mat_camera->setAim(QVector3D()); mat_camera->setFOV(45.); mat_light = new Light(); mat_light->setPos(QVector3D(50, 100, 25)); diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp index dd94ef3..b9d3f52 100644 --- a/qglengine/renderer_service.cpp +++ b/qglengine/renderer_service.cpp @@ -63,17 +63,16 @@ RendererService::RendererService(Renderer * r_): r(r_) { cone_mesh = Primitive::cone(8, 1., 1., 1.); cone_mesh_f = Primitive::coneFrame(8, 1., 1., 1.); QMatrix4x4 mat; - mat.translate(0,0,1); - mat.rotate(180, 1,0,0); + mat.translate(0,0,-1); cone_mesh ->transformPoints(mat); cone_mesh_f->transformPoints(mat); cone_mesh_f->scalePoints(1.5); box_mesh ->scalePoints(1.3); omni_mesh ->scalePoints(1.3); - cone_mesh ->translatePoints(0,0,-1); + cone_mesh ->translatePoints(0,0,0.5); cone_mesh ->scalePoints(1.4); - cone_mesh ->translatePoints(0,0,1); + cone_mesh ->translatePoints(0,0,-0.5); cone_mesh ->scalePoints(1.5); handle_move_mesh = Primitive::arrow(12, 0.06); @@ -153,15 +152,10 @@ QMatrix4x4 RendererService::parentRotationMatrix(ObjectBase * o, bool self_rotat if (!o) return ret; QMatrix4x4 pmat; if (o->parent()) { - pmat = o->parent()->worldTransform(); - pmat.setColumn(3, QVector4D(0,0,0,1)); - double det = pmat.determinant(); - if (det > 0.) pmat /= sqrt(det); + pmat = o->parent()->transform().matrixRotate(); } if (self_rotation) { - ret.rotate(o->angles_.z(), 0., 0., 1.); - ret.rotate(o->angles_.y(), 0., 1., 0.); - ret.rotate(o->angles_.x(), 1., 0., 0.); + ret *= o->transform().matrixRotate(); } ret = pmat * ret; return ret; @@ -197,12 +191,7 @@ void RendererService::fillSpotObjects() { cur_aims.clear(); foreach (Light * l, ll) { QMatrix4x4 m, lm; - //QVector3D up = QVector3D::crossProduct(l->direction, QVector3D(0,0,1)).normalized(); - //if (up.isNull()) - // up = QVector3D::crossProduct(l->direction, QVector3D(0,0,1)).normalized(); - //lm.lookAt(QVector3D(), l->direction, up); - //lm.lookAt(QVector3D(), l->direction, (QVector3D(0,0,1))); - lm.rotate(QQuaternion::fromDirection(l->direction(), QVector3D())); + lm = l->transform().matrixRotate(); m = invariantSizeMatrix(l->worldPos()) * parentRotationMatrix(l) * lm; m.transposed().copyDataTo(o.modelmatrix); o.object_id = l->id_; @@ -391,6 +380,7 @@ void RendererService::renderService() { /// axis f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height()); axis_camera->setPos(-r->view->camera()->direction() * 3.); + axis_camera->setAim(QVector3D()); r->setUniformCamera(prog, axis_camera, true, axis_viewport); axis_mesh->draw(f, 3); f->glViewport(0, 0, r->view->width(), r->view->height()); diff --git a/qglengine/widgets/object_editor.cpp b/qglengine/widgets/object_editor.cpp index 4e59825..906a1bc 100644 --- a/qglengine/widgets/object_editor.cpp +++ b/qglengine/widgets/object_editor.cpp @@ -135,7 +135,7 @@ void ObjectEditor::objectChanged() { l->decay_quadratic = ui->spinLightDecayQuadratic->value(); l->angle_start = ui->spinLightAngleStart->value(); l->angle_end = ui->spinLightAngleEnd->value(); - l->setDirection(QVector3D(ui->spinLightDirectionX->value(), ui->spinLightDirectionY->value(), ui->spinLightDirectionZ->value()).normalized()); + //l->setDirection(QVector3D(ui->spinLightDirectionX->value(), ui->spinLightDirectionY->value(), ui->spinLightDirectionZ->value()).normalized()); l->apply(); } if (object->type() == ObjectBase::glCamera) {