diff options
Diffstat (limited to 'src/render/geometry')
-rw-r--r-- | src/render/geometry/armature.cpp | 1 | ||||
-rw-r--r-- | src/render/geometry/attribute.cpp | 1 | ||||
-rw-r--r-- | src/render/geometry/geometry.cpp | 2 | ||||
-rw-r--r-- | src/render/geometry/geometryrenderer.cpp | 22 | ||||
-rw-r--r-- | src/render/geometry/geometryrenderer_p.h | 9 | ||||
-rw-r--r-- | src/render/geometry/joint.cpp | 61 | ||||
-rw-r--r-- | src/render/geometry/joint_p.h | 1 | ||||
-rw-r--r-- | src/render/geometry/qattribute.cpp | 2 | ||||
-rw-r--r-- | src/render/geometry/qgeometry.cpp | 2 | ||||
-rw-r--r-- | src/render/geometry/qgeometryrenderer.cpp | 16 | ||||
-rw-r--r-- | src/render/geometry/qgeometryrenderer.h | 1 | ||||
-rw-r--r-- | src/render/geometry/qmesh.cpp | 12 | ||||
-rw-r--r-- | src/render/geometry/qmesh.h | 1 | ||||
-rw-r--r-- | src/render/geometry/skeleton.cpp | 249 | ||||
-rw-r--r-- | src/render/geometry/skeleton_p.h | 36 |
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 |