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) {