summaryrefslogtreecommitdiffstats
path: root/src/core/transforms
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-08-06 18:58:46 +0100
committerSean Harmer <sean.harmer@kdab.com>2017-08-16 13:19:23 +0000
commit5c6634f2d1cd9a016142c3641ab6d797f5fe4ba7 (patch)
treeccbad78b2839b26b1f10cf5aa112786df56bd018 /src/core/transforms
parentb236f982170779a1836f7d391428287921422163 (diff)
Update skinned mesh example to expose joints of object
To do this we add a helper Sqt struct that wraps up an affine transformation as a scale vector, rotation quaternion and a translation vector. This is the format in which the animation aspect will animate the joints later so it's easier to keep the transforms split like this. It's also less data to move around compared with a 4x4 matrix (10 vs 16 floats, 12 including the padding). Change-Id: Iaa30b5ef5d1635cc208ead918827140cf2765908 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/core/transforms')
-rw-r--r--src/core/transforms/qmath3d_p.h19
-rw-r--r--src/core/transforms/qskeletonloader.cpp57
-rw-r--r--src/core/transforms/qskeletonloader.h9
-rw-r--r--src/core/transforms/qskeletonloader_p.h15
-rw-r--r--src/core/transforms/sqt_p.h90
-rw-r--r--src/core/transforms/transforms.pri3
6 files changed, 190 insertions, 3 deletions
diff --git a/src/core/transforms/qmath3d_p.h b/src/core/transforms/qmath3d_p.h
index 8c2afac31..a4f33f0b6 100644
--- a/src/core/transforms/qmath3d_p.h
+++ b/src/core/transforms/qmath3d_p.h
@@ -53,6 +53,7 @@
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qquaternion.h>
#include <QtGui/qvector3d.h>
+#include <Qt3DCore/private/sqt_p.h>
#include <cmath>
@@ -189,6 +190,24 @@ inline void decomposeQMatrix4x4(const QMatrix4x4 &m, QVector3D &position, QQuate
position = QVector3D(m(0, 3), m(1, 3), m(2, 3));
}
+inline void decomposeQMatrix4x4(const QMatrix4x4 &m, Qt3DCore::Sqt &sqt)
+{
+ Q_ASSERT(m.isAffine());
+
+ const QMatrix3x3 m3x3(m.toGenericMatrix<3, 3>());
+
+ QMatrix3x3 rot3x3(Qt::Uninitialized);
+ if (hasScale(m)) {
+ decomposeQMatrix3x3(m3x3, rot3x3, sqt.scale, sqt.translation);
+ } else {
+ // we know there is no scaling part; no need for QDU decomposition
+ sqt.scale = QVector3D(1.0f, 1.0f, 1.0f);
+ rot3x3 = m3x3;
+ }
+ sqt.rotation = QQuaternion::fromRotationMatrix(rot3x3);
+ sqt.translation = QVector3D(m(0, 3), m(1, 3), m(2, 3));
+}
+
QT_END_NAMESPACE
#endif // QT3DCORE_QMATH3D_P_H
diff --git a/src/core/transforms/qskeletonloader.cpp b/src/core/transforms/qskeletonloader.cpp
index d069a2a0b..9e0fdae5c 100644
--- a/src/core/transforms/qskeletonloader.cpp
+++ b/src/core/transforms/qskeletonloader.cpp
@@ -39,6 +39,7 @@
#include "qskeletonloader.h"
#include "qskeletonloader_p.h"
+#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qskeletoncreatedchange_p.h>
@@ -49,7 +50,9 @@ namespace Qt3DCore {
QSkeletonLoaderPrivate::QSkeletonLoaderPrivate()
: QAbstractSkeletonPrivate()
, m_source()
+ , m_createJoints(false)
, m_status(QSkeletonLoader::NotReady)
+ , m_rootJoint(nullptr)
{
m_type = QSkeletonCreatedChangeBase::SkeletonLoader;
}
@@ -168,6 +171,18 @@ QSkeletonLoader::Status QSkeletonLoader::status() const
return d->m_status;
}
+bool QSkeletonLoader::isCreateJointsEnabled() const
+{
+ Q_D(const QSkeletonLoader);
+ return d->m_createJoints;
+}
+
+Qt3DCore::QJoint *QSkeletonLoader::rootJoint() const
+{
+ Q_D(const QSkeletonLoader);
+ return d->m_rootJoint;
+}
+
void QSkeletonLoader::setSource(const QUrl &source)
{
Q_D(QSkeletonLoader);
@@ -178,14 +193,51 @@ void QSkeletonLoader::setSource(const QUrl &source)
emit sourceChanged(source);
}
+void QSkeletonLoader::setCreateJointsEnabled(bool createJoints)
+{
+ Q_D(QSkeletonLoader);
+ if (d->m_createJoints == createJoints)
+ return;
+
+ d->m_createJoints = createJoints;
+ emit createJointsEnabledChanged(createJoints);
+}
+
+void QSkeletonLoader::setRootJoint(QJoint *rootJoint)
+{
+ Q_D(QSkeletonLoader);
+ if (rootJoint == d->m_rootJoint)
+ return;
+
+ if (d->m_rootJoint)
+ d->unregisterDestructionHelper(d->m_rootJoint);
+
+ if (rootJoint && !rootJoint->parent())
+ rootJoint->setParent(this);
+
+ d->m_rootJoint = rootJoint;
+
+ // Ensures proper bookkeeping
+ if (d->m_rootJoint)
+ d->registerDestructionHelper(d->m_rootJoint, &QSkeletonLoader::setRootJoint, d->m_rootJoint);
+
+ emit rootJointChanged(d->m_rootJoint);
+}
+
/*! \internal */
void QSkeletonLoader::sceneChangeEvent(const QSceneChangePtr &change)
{
Q_D(QSkeletonLoader);
if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("status"))
+ auto propertyChange = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(change);
+ if (propertyChange->propertyName() == QByteArrayLiteral("status")) {
+ const auto e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
d->setStatus(static_cast<QSkeletonLoader::Status>(e->value().toInt()));
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("rootJoint")) {
+ auto typedChange = qSharedPointerCast<QJointChange>(propertyChange);
+ auto rootJoint = std::move(typedChange->data);
+ setRootJoint(rootJoint.release());
+ }
}
QAbstractSkeleton::sceneChangeEvent(change);
}
@@ -197,6 +249,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QSkeletonLoader::createNodeCreationChange()
auto &data = creationChange->data;
Q_D(const QSkeletonLoader);
data.source = d->m_source;
+ data.createJoints = d->m_createJoints;
return creationChange;
}
diff --git a/src/core/transforms/qskeletonloader.h b/src/core/transforms/qskeletonloader.h
index efebe3684..1185ba6c7 100644
--- a/src/core/transforms/qskeletonloader.h
+++ b/src/core/transforms/qskeletonloader.h
@@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+class QJoint;
class QSkeletonLoaderPrivate;
class QT3DCORESHARED_EXPORT QSkeletonLoader : public QAbstractSkeleton
@@ -55,6 +56,8 @@ class QT3DCORESHARED_EXPORT QSkeletonLoader : public QAbstractSkeleton
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(bool createJointsEnabled READ isCreateJointsEnabled WRITE setCreateJointsEnabled NOTIFY createJointsEnabledChanged)
+ Q_PROPERTY(Qt3DCore::QJoint* rootJoint READ rootJoint NOTIFY rootJointChanged)
public:
explicit QSkeletonLoader(Qt3DCore::QNode *parent = nullptr);
@@ -71,13 +74,18 @@ public:
QUrl source() const;
Status status() const;
+ bool isCreateJointsEnabled() const;
+ Qt3DCore::QJoint* rootJoint() const;
public Q_SLOTS:
void setSource(const QUrl &source);
+ void setCreateJointsEnabled(bool enabled);
Q_SIGNALS:
void sourceChanged(const QUrl &source);
void statusChanged(Status status);
+ void createJointsEnabledChanged(bool createJointsEnabled);
+ void rootJointChanged(Qt3DCore::QJoint* rootJoint);
protected:
explicit QSkeletonLoader(QSkeletonLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
@@ -86,6 +94,7 @@ protected:
private:
Q_DECLARE_PRIVATE(QSkeletonLoader)
QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+ void setRootJoint(QJoint *rootJoint); // Needed for lifetime management of created joints
};
} // namespace Qt3DCore
diff --git a/src/core/transforms/qskeletonloader_p.h b/src/core/transforms/qskeletonloader_p.h
index aca7eae55..ab0babe00 100644
--- a/src/core/transforms/qskeletonloader_p.h
+++ b/src/core/transforms/qskeletonloader_p.h
@@ -54,10 +54,16 @@
#include <Qt3DCore/private/qabstractskeleton_p.h>
#include "qskeletonloader.h"
+#include <Qt3DCore/private/qtypedpropertyupdatechange_p.h>
+
+#include <memory>
+
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+class QJoint;
+
class QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate
{
public:
@@ -68,14 +74,23 @@ public:
Q_DECLARE_PUBLIC(QSkeletonLoader)
QUrl m_source;
+ bool m_createJoints;
+
+ // Set by the backend
QSkeletonLoader::Status m_status;
+ Qt3DCore::QJoint* m_rootJoint;
};
struct QSkeletonLoaderData
{
QUrl source;
+ bool createJoints;
};
+class QJoint;
+typedef QTypedPropertyUpdatedChange<std::unique_ptr<QJoint>> QJointChange;
+typedef QTypedPropertyUpdatedChangePtr<std::unique_ptr<QJoint>> QJointChangePtr;
+
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h
new file mode 100644
index 000000000..baf0cb8fc
--- /dev/null
+++ b/src/core/transforms/sqt_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DCORE_SQT_P_H
+#define QT3DCORE_SQT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qquaternion.h>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+
+struct Sqt
+{
+ QQuaternion rotation;
+ QVector3D scale;
+ float pad1;
+ QVector3D translation;
+ float pad2;
+
+ Sqt()
+ : rotation()
+ , scale(1.0f, 1.0f, 1.0f)
+ , translation()
+ {}
+
+ inline QMatrix4x4 toMatrix() const
+ {
+ QMatrix4x4 m;
+ m.translate(translation);
+ m.rotate(rotation);
+ m.scale(scale);
+ return m;
+ }
+};
+
+} // namespace Qt3DCore
+
+QT_END_NAMESPACE
+
+#endif // QT3DCORE_SQT_P_H
diff --git a/src/core/transforms/transforms.pri b/src/core/transforms/transforms.pri
index aee2dad3f..f83c37a0b 100644
--- a/src/core/transforms/transforms.pri
+++ b/src/core/transforms/transforms.pri
@@ -22,7 +22,8 @@ HEADERS += \
$$PWD/qarmature_p.h \
$$PWD/vector4d_p.h \
$$PWD/vector3d_p.h \
- $$PWD/matrix4x4_p.h
+ $$PWD/matrix4x4_p.h \
+ $$PWD/sqt_p.h
INCLUDEPATH += $$PWD