summaryrefslogtreecommitdiffstats
path: root/src/render/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/geometry')
-rw-r--r--src/render/geometry/armature.cpp1
-rw-r--r--src/render/geometry/attribute.cpp1
-rw-r--r--src/render/geometry/geometry.cpp2
-rw-r--r--src/render/geometry/geometryrenderer.cpp22
-rw-r--r--src/render/geometry/geometryrenderer_p.h9
-rw-r--r--src/render/geometry/joint.cpp61
-rw-r--r--src/render/geometry/joint_p.h1
-rw-r--r--src/render/geometry/qattribute.cpp2
-rw-r--r--src/render/geometry/qgeometry.cpp2
-rw-r--r--src/render/geometry/qgeometryrenderer.cpp16
-rw-r--r--src/render/geometry/qgeometryrenderer.h1
-rw-r--r--src/render/geometry/qmesh.cpp12
-rw-r--r--src/render/geometry/qmesh.h1
-rw-r--r--src/render/geometry/skeleton.cpp249
-rw-r--r--src/render/geometry/skeleton_p.h36
15 files changed, 48 insertions, 368 deletions
diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp
index cfa2e572a..6e417952b 100644
--- a/src/render/geometry/armature.cpp
+++ b/src/render/geometry/armature.cpp
@@ -38,7 +38,6 @@
#include <Qt3DCore/qarmature.h>
#include <Qt3DCore/qabstractskeleton.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qarmature_p.h>
diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp
index f241a85e5..de44c5fe3 100644
--- a/src/render/geometry/attribute.cpp
+++ b/src/render/geometry/attribute.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "attribute_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/private/qattribute_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp
index cb401df5b..56ea936be 100644
--- a/src/render/geometry/geometry.cpp
+++ b/src/render/geometry/geometry.cpp
@@ -42,8 +42,6 @@
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/private/qgeometry_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <algorithm>
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index b5c741659..3b460f48c 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -43,8 +43,6 @@
#include <Qt3DRender/private/qgeometryrenderer_p.h>
#include <Qt3DRender/private/qmesh_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qtypedpropertyupdatechange_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
@@ -148,7 +146,7 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
markDirty(AbstractRenderer::GeometryDirty);
}
-void GeometryRenderer::executeFunctor()
+GeometryFunctorResult GeometryRenderer::executeFunctor()
{
Q_ASSERT(m_geometryFactory);
@@ -169,7 +167,8 @@ void GeometryRenderer::executeFunctor()
}
// Load geometry
- std::unique_ptr<QGeometry> geometry((*m_geometryFactory)());
+ QGeometry *geometry = (*m_geometryFactory)();
+ QMesh::Status meshLoaderStatus = QMesh::None;
// If the geometry is null, then we were either unable to load it (Error)
// or the mesh is located at a remote url and needs to be downloaded first (Loading)
@@ -178,24 +177,15 @@ void GeometryRenderer::executeFunctor()
// corresponding QGeometryRenderer
const auto appThread = QCoreApplication::instance()->thread();
geometry->moveToThread(appThread);
-
- auto e = QGeometryChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("geometry");
- e->data = std::move(geometry);
- notifyObservers(e);
}
// Send Status
if (isQMeshFunctor) {
QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(m_geometryFactory);
-
- auto e = QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("status");
- e->setValue(meshLoader->status());
- notifyObservers(e);
+ meshLoaderStatus = meshLoader->status();
}
+
+ return { geometry, meshLoaderStatus };
}
void GeometryRenderer::unsetDirty()
diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h
index da538a00d..d2ddad4bb 100644
--- a/src/render/geometry/geometryrenderer_p.h
+++ b/src/render/geometry/geometryrenderer_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/qgeometryfactory.h>
+#include <Qt3DRender/qmesh.h>
QT_BEGIN_NAMESPACE
@@ -66,6 +67,12 @@ namespace Render {
class GeometryRendererManager;
+struct GeometryFunctorResult
+{
+ QGeometry *geometry;
+ QMesh::Status status;
+};
+
class Q_AUTOTEST_EXPORT GeometryRenderer : public BackendNode
{
public:
@@ -75,7 +82,7 @@ public:
void cleanup();
void setManager(GeometryRendererManager *manager);
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
- void executeFunctor();
+ GeometryFunctorResult executeFunctor();
inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; }
inline int instanceCount() const { return m_instanceCount; }
diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp
index 86d583f51..9791f6c52 100644
--- a/src/render/geometry/joint.cpp
+++ b/src/render/geometry/joint.cpp
@@ -41,9 +41,6 @@
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DCore/QJoint>
#include <Qt3DCore/private/qjoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <algorithm>
@@ -72,69 +69,24 @@ void Joint::cleanup()
setEnabled(false);
}
-// TODOSYNC remove once animation changes don't use messages anymore
-void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("scale")) {
- m_localPose.scale = propertyChange->value().value<QVector3D>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) {
- m_localPose.rotation = propertyChange->value().value<QQuaternion>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) {
- m_localPose.translation = propertyChange->value().value<QVector3D>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("inverseBindMatrix")) {
- // Setting the inverse bind matrix should be a rare operation. Usually it is
- // set once and then remains constant for the duration of the skeleton. So just
- // trigger a rebuild of the skeleton's SkeletonData which will include obtaining
- // the inverse bind matrix.
- m_inverseBindMatrix = propertyChange->value().value<QMatrix4x4>();
- m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("name")) {
- // Joint name doesn't affect anything in the render aspect so no need
- // to mark anything as dirty.
- m_name = propertyChange->value().toString();
-
- // TODO: Notify other aspects (animation) about the name change.
- }
- } else if (e->type() == PropertyValueAdded) {
- const auto addedChange = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (addedChange->propertyName() == QByteArrayLiteral("childJoint"))
- m_childJointIds.push_back(addedChange->addedNodeId());
- } else if (e->type() == PropertyValueRemoved) {
- const auto removedChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (removedChange->propertyName() == QByteArrayLiteral("childJoint"))
- m_childJointIds.removeOne(removedChange->removedNodeId());
- }
- BackendNode::sceneChangeEvent(e);
-}
-
void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(frontEnd);
if (!joint)
return;
+ bool jointDirty = firstTime;
if (m_localPose.scale != joint->scale()) {
m_localPose.scale = joint->scale();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
+ jointDirty = true;
}
if (m_localPose.rotation != joint->rotation()) {
m_localPose.rotation = joint->rotation();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
+ jointDirty = true;
}
if (m_localPose.translation != joint->translation()) {
m_localPose.translation = joint->translation();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
+ jointDirty = true;
}
if (m_inverseBindMatrix != joint->inverseBindMatrix()) {
// Setting the inverse bind matrix should be a rare operation. Usually it is
@@ -154,11 +106,10 @@ void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints());
std::sort(std::begin(childIds), std::end(childIds));
- if (m_childJointIds != childIds) {
+ if (m_childJointIds != childIds)
m_childJointIds = childIds;
- }
- if (firstTime) {
+ if (jointDirty) {
markDirty(AbstractRenderer::JointDirty);
m_jointManager->addDirtyJoint(peerId());
}
diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h
index d0530ac04..de875459e 100644
--- a/src/render/geometry/joint_p.h
+++ b/src/render/geometry/joint_p.h
@@ -69,7 +69,6 @@ public:
Joint();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::Sqt localPose() const { return m_localPose; }
diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp
index a28d0baa6..84d14cfe1 100644
--- a/src/render/geometry/qattribute.cpp
+++ b/src/render/geometry/qattribute.cpp
@@ -41,8 +41,6 @@
#include "qattribute_p.h"
#include <Qt3DRender/qbuffer.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp
index 47fad4302..4b0bca3b3 100644
--- a/src/render/geometry/qgeometry.cpp
+++ b/src/render/geometry/qgeometry.cpp
@@ -43,8 +43,6 @@
#include <private/qnode_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp
index ddea873a7..6e0a24f61 100644
--- a/src/render/geometry/qgeometryrenderer.cpp
+++ b/src/render/geometry/qgeometryrenderer.cpp
@@ -41,9 +41,6 @@
#include "qgeometryrenderer_p.h"
#include <private/qcomponent_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -483,19 +480,6 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory)
d->update();
}
-/*!
- \internal
- */
-void QGeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- auto change = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(e);
- if (change->type() == PropertyUpdated && change->propertyName() == QByteArrayLiteral("geometry")) {
- auto typedChange = qSharedPointerCast<QGeometryChange>(e);
- auto geometry = std::move(typedChange->data);
- setGeometry(geometry.release());
- }
-}
-
Qt3DCore::QNodeCreatedChangeBasePtr QGeometryRenderer::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QGeometryRendererData>::create(this);
diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h
index 81bd1ff67..eceeb9173 100644
--- a/src/render/geometry/qgeometryrenderer.h
+++ b/src/render/geometry/qgeometryrenderer.h
@@ -134,7 +134,6 @@ Q_SIGNALS:
protected:
explicit QGeometryRenderer(QGeometryRendererPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QGeometryRenderer)
diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp
index 66c4a69bc..1d7d33f9a 100644
--- a/src/render/geometry/qmesh.cpp
+++ b/src/render/geometry/qmesh.cpp
@@ -215,18 +215,6 @@ QMesh::QMesh(QMeshPrivate &dd, QNode *parent)
{
}
-/*! \internal */
-void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QMesh);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("status"))
- d->setStatus(e->value().value<QMesh::Status>());
- }
- Qt3DRender::QGeometryRenderer::sceneChangeEvent(change);
-}
-
void QMesh::setSource(const QUrl& source)
{
Q_D(QMesh);
diff --git a/src/render/geometry/qmesh.h b/src/render/geometry/qmesh.h
index 458a21fa4..04fdedc20 100644
--- a/src/render/geometry/qmesh.h
+++ b/src/render/geometry/qmesh.h
@@ -88,7 +88,6 @@ Q_SIGNALS:
protected:
explicit QMesh(QMeshPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QMesh)
diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp
index d4af1fe3c..839a1a056 100644
--- a/src/render/geometry/skeleton.cpp
+++ b/src/render/geometry/skeleton.cpp
@@ -36,24 +36,19 @@
#include "skeleton_p.h"
-#include <Qt3DCore/qjoint.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
+#include <Qt3DCore/qjoint.h>
#include <Qt3DRender/private/abstractrenderer_p.h>
-#include <Qt3DRender/private/gltfskeletonloader_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
-#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/private/qskeletoncreatedchange_p.h>
#include <Qt3DCore/private/qskeleton_p.h>
#include <Qt3DCore/private/qskeletonloader_p.h>
#include <Qt3DCore/private/qmath3d_p.h>
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
QT_BEGIN_NAMESPACE
@@ -119,9 +114,9 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
}
m_createJoints = loaderNode->isCreateJointsEnabled();
- if ((loaderNode->rootJoint() && loaderNode->rootJoint()->id() != m_rootJointId) ||
- (!loaderNode->rootJoint() && !m_rootJointId.isNull())) {
- m_rootJointId = loaderNode->rootJoint() ? loaderNode->rootJoint()->id() : Qt3DCore::QNodeId{};
+ auto newJointId = Qt3DCore::qIdForNode(loaderNode->rootJoint());
+ if (newJointId != m_rootJointId) {
+ m_rootJointId = newJointId;
// If using a QSkeletonLoader to create frontend QJoints, when those joints are
// set on the skeleton, we end up here. In order to allow the subsequent call
@@ -139,239 +134,15 @@ void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
}
}
}
-}
-
-// TODOSYNC remove once animation aspect no longer requires messages
-void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("localPoses")) {
- // When the animation aspect sends us a new set of local poses, all we
- // need to do is copy them into place. The existing jobs will then update
- // the skinning matrix palette.
- m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>();
- }
-
- break;
- }
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node);
+ m_skeletonData.localPoses = d->m_localPoses;
}
void Skeleton::setStatus(QSkeletonLoader::Status status)
{
- if (status != m_status) {
+ if (status != m_status)
m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- notifyObservers(e);
- }
-}
-
-void Skeleton::notifyJointCount()
-{
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("jointCount");
- e->setValue(jointCount());
- notifyObservers(e);
-}
-
-void Skeleton::notifyJointNamesAndPoses()
-{
- auto e = QPropertyUpdatedChangePtr::create(peerId());
- JointNamesAndLocalPoses payload{m_skeletonData.jointNames, m_skeletonData.localPoses};
- e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes);
- e->setPropertyName("jointNamesAndLocalPoses");
- e->setValue(QVariant::fromValue(payload));
- notifyObservers(e);
-}
-
-void Skeleton::loadSkeleton()
-{
- qCDebug(Jobs) << Q_FUNC_INFO << m_source;
- clearData();
-
- // Load the data
- switch (m_dataType) {
- case File:
- loadSkeletonFromUrl();
- break;
-
- case Data:
- loadSkeletonFromData();
- break;
-
- default:
- Q_UNREACHABLE();
- }
-
- // If using a loader inform the frontend of the status change.
- // Don't bother if asked to create frontend joints though. When
- // the backend gets notified of those joints we'll update the
- // status at that point.
- if (m_dataType == File && !m_createJoints) {
- if (jointCount() == 0)
- setStatus(QSkeletonLoader::Error);
- else
- setStatus(QSkeletonLoader::Ready);
- }
- notifyJointCount();
- notifyJointNamesAndPoses();
-
- qCDebug(Jobs) << "Loaded skeleton data:" << *this;
-}
-
-void Skeleton::loadSkeletonFromUrl()
-{
- // TODO: Handle remote files
- QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source);
- QFileInfo info(filePath);
- if (!info.exists()) {
- qWarning() << "Could not open skeleton file:" << filePath;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- qWarning() << "Could not open skeleton file:" << filePath;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- // TODO: Make plugin based for more file type support. For now gltf or native
- const QString ext = info.suffix();
- if (ext == QLatin1String("gltf")) {
- GLTFSkeletonLoader loader;
- loader.load(&file);
- m_skeletonData = loader.createSkeleton(m_name);
-
- // If the user has requested it, create the frontend nodes for the joints
- // and send them to the (soon to be owning) QSkeletonLoader.
- if (m_createJoints) {
- std::unique_ptr<QJoint> rootJoint(createFrontendJoints(m_skeletonData));
- if (!rootJoint) {
- qWarning() << "Failed to create frontend joints";
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- // Move the QJoint tree to the main thread and notify the
- // corresponding QSkeletonLoader
- const auto appThread = QCoreApplication::instance()->thread();
- rootJoint->moveToThread(appThread);
-
- auto e = QJointChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("rootJoint");
- e->data = std::move(rootJoint);
- notifyObservers(e);
-
- // Clear the skeleton data. It will be recreated from the
- // frontend joints. A little bit inefficient but ensures
- // that joints created this way and via QSkeleton go through
- // the same code path.
- m_skeletonData = SkeletonData();
- }
- } else if (ext == QLatin1String("json")) {
- // TODO: Support native skeleton type
- } else {
- qWarning() << "Unknown skeleton file type:" << ext;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
- m_skinningPalette.resize(m_skeletonData.joints.size());
-}
-
-void Skeleton::loadSkeletonFromData()
-{
- // Recurse down through the joint hierarchy and process it into
- // the vector of joints used within SkeletonData. The recursion
- // ensures that a parent always appears before its children in
- // the vector of JointInfo objects.
- //
- // In addition, we set up a mapping from the joint ids to the
- // index of the corresponding JointInfo object in the vector.
- // This will allow us to easily update entries in the vector of
- // JointInfos when a Joint node marks itself as dirty.
- const int rootParentIndex = -1;
- processJointHierarchy(m_rootJointId, rootParentIndex, m_skeletonData);
- m_skinningPalette.resize(m_skeletonData.joints.size());
-}
-
-Qt3DCore::QJoint *Skeleton::createFrontendJoints(const SkeletonData &skeletonData) const
-{
- if (skeletonData.joints.isEmpty())
- return nullptr;
-
- // Create frontend joints from the joint info objects
- QVector<QJoint *> frontendJoints;
- const int jointCount = skeletonData.joints.size();
- frontendJoints.reserve(jointCount);
- for (int i = 0; i < jointCount; ++i) {
- const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose;
- const QString &jointName = skeletonData.jointNames[i];
- const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i];
- frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix));
- }
-
- // Now go through and resolve the parent for each joint
- for (int i = 0; i < frontendJoints.size(); ++i) {
- const auto parentIndex = skeletonData.joints[i].parentIndex;
- if (parentIndex == -1)
- continue;
-
- // It's not enough to just set up the QObject parent-child relationship.
- // We need to explicitly add the child to the parent's list of joints so
- // that information is then propagated to the backend.
- frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]);
- }
-
- return frontendJoints[0];
-}
-
-Qt3DCore::QJoint *Skeleton::createFrontendJoint(const QString &jointName,
- const Qt3DCore::Sqt &localPose,
- const QMatrix4x4 &inverseBindMatrix) const
-{
- auto joint = QAbstractNodeFactory::createNode<QJoint>("QJoint");
- joint->setTranslation(localPose.translation);
- joint->setRotation(localPose.rotation);
- joint->setScale(localPose.scale);
- joint->setInverseBindMatrix(inverseBindMatrix);
- joint->setName(jointName);
- return joint;
-}
-
-void Skeleton::processJointHierarchy(Qt3DCore::QNodeId jointId,
- int parentJointIndex,
- SkeletonData &skeletonData)
-{
- // Lookup the joint, create a JointInfo, and add an entry to the index map
- Joint *joint = m_renderer->nodeManagers()->jointManager()->lookupResource(jointId);
- Q_ASSERT(joint);
- joint->setOwningSkeleton(m_skeletonHandle);
- const JointInfo jointInfo(joint, parentJointIndex);
- skeletonData.joints.push_back(jointInfo);
- skeletonData.localPoses.push_back(joint->localPose());
- skeletonData.jointNames.push_back(joint->name());
-
- const int jointIndex = skeletonData.joints.size() - 1;
- const HJoint jointHandle = m_jointManager->lookupHandle(jointId);
- skeletonData.jointIndices.insert(jointHandle, jointIndex);
-
- // Recurse to the children
- const auto childIds = joint->childJointIds();
- for (const auto childJointId : childIds)
- processJointHierarchy(childJointId, jointIndex, skeletonData);
}
void Skeleton::clearData()
@@ -383,6 +154,12 @@ void Skeleton::clearData()
m_skeletonData.jointIndices.clear();
}
+void Skeleton::setSkeletonData(const SkeletonData &data)
+{
+ m_skeletonData = data;
+ m_skinningPalette.resize(m_skeletonData.joints.size());
+}
+
// Called from UpdateSkinningPaletteJob
void Skeleton::setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose)
{
diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h
index 8247bb317..7a5299944 100644
--- a/src/render/geometry/skeleton_p.h
+++ b/src/render/geometry/skeleton_p.h
@@ -75,6 +75,12 @@ class SkeletonManager;
class Q_AUTOTEST_EXPORT Skeleton : public BackendNode
{
public:
+ enum SkeletonDataType {
+ Unknown,
+ File,
+ Data
+ };
+
Skeleton();
void setSkeletonManager(SkeletonManager *skeletonManager) { m_skeletonManager = skeletonManager; }
@@ -84,52 +90,40 @@ public:
JointManager *jointManager() const { return m_jointManager; }
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setStatus(Qt3DCore::QSkeletonLoader::Status status);
Qt3DCore::QSkeletonLoader::Status status() const { return m_status; }
QUrl source() const { return m_source; }
+ SkeletonDataType dataType() const { return m_dataType; }
+ bool createJoints() const { return m_createJoints; }
void setName(const QString &name) { m_name = name; }
QString name() const { return m_name; }
int jointCount() const { return m_skeletonData.joints.size(); }
- void notifyJointCount();
- void notifyJointNamesAndPoses();
QVector<JointInfo> joints() const { return m_skeletonData.joints; }
+ QVector<QString> jointNames() const { return m_skeletonData.jointNames; }
+ QVector<Qt3DCore::Sqt> localPoses() const { return m_skeletonData.localPoses; }
Qt3DCore::QNodeId rootJointId() const { return m_rootJointId; }
// Called from jobs
- void loadSkeleton();
void setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose);
QVector<QMatrix4x4> calculateSkinningMatrixPalette();
+ void clearData();
+ void setSkeletonData(const SkeletonData &data);
+ const SkeletonData &skeletonData() const { return m_skeletonData; }
+ SkeletonData skeletonData() { return m_skeletonData; }
+
// Allow unit tests to set the data type
-#if !defined(QT_BUILD_INTERNAL)
-private:
-#endif
- enum SkeletonDataType {
- Unknown,
- File,
- Data
- };
#if defined(QT_BUILD_INTERNAL)
public:
void setDataType(SkeletonDataType dataType) { m_dataType = dataType; }
#endif
private:
- void loadSkeletonFromUrl();
- void loadSkeletonFromData();
- Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const;
- Qt3DCore::QJoint *createFrontendJoint(const QString &jointName,
- const Qt3DCore::Sqt &localPose,
- const QMatrix4x4 &inverseBindMatrix) const;
- void processJointHierarchy(Qt3DCore::QNodeId jointId, int parentJointIndex, SkeletonData &skeletonData);
- void clearData();
-
QVector<QMatrix4x4> m_skinningPalette;
// QSkeletonLoader Properties