1// Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "joint_p.h"
5#include <Qt3DRender/private/managers_p.h>
6#include <Qt3DCore/QJoint>
7#include <Qt3DCore/private/qjoint_p.h>
8
9#include <algorithm>
10
11QT_BEGIN_NAMESPACE
12
13using namespace Qt3DCore;
14
15namespace Qt3DRender {
16namespace Render {
17
18Joint::Joint()
19 : BackendNode(Qt3DCore::QBackendNode::ReadOnly)
20 , m_localPose()
21 , m_jointManager(nullptr)
22 , m_skeletonManager(nullptr)
23{
24}
25
26void Joint::cleanup()
27{
28 m_inverseBindMatrix.setToIdentity();
29 m_localPose = Sqt();
30 m_childJointIds.clear();
31 m_name.clear();
32 m_owningSkeleton = HSkeleton();
33 setEnabled(false);
34}
35
36void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
37{
38 const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(object: frontEnd);
39 if (!joint)
40 return;
41
42 bool jointDirty = firstTime;
43 if (m_localPose.scale != joint->scale()) {
44 m_localPose.scale = joint->scale();
45 jointDirty = true;
46 }
47 if (m_localPose.rotation != joint->rotation()) {
48 m_localPose.rotation = joint->rotation();
49 jointDirty = true;
50 }
51 if (m_localPose.translation != joint->translation()) {
52 m_localPose.translation = joint->translation();
53 jointDirty = true;
54 }
55 if (m_inverseBindMatrix != joint->inverseBindMatrix()) {
56 // Setting the inverse bind matrix should be a rare operation. Usually it is
57 // set once and then remains constant for the duration of the skeleton. So just
58 // trigger a rebuild of the skeleton's SkeletonData which will include obtaining
59 // the inverse bind matrix.
60 m_inverseBindMatrix = joint->inverseBindMatrix();
61 m_skeletonManager->addDirtySkeleton(dirtyFlag: SkeletonManager::SkeletonDataDirty, skeletonHandle: m_owningSkeleton);
62 }
63 if (m_name != joint->name()) {
64 // Joint name doesn't affect anything in the render aspect so no need
65 // to mark anything as dirty.
66 m_name = joint->name();
67
68 // TODO: Notify other aspects (animation) about the name change.
69 }
70
71 Qt3DCore::QNodeIdVector childIds = qIdsForNodes(nodes: joint->childJoints());
72 std::sort(first: std::begin(cont&: childIds), last: std::end(cont&: childIds));
73 if (m_childJointIds != childIds)
74 m_childJointIds = childIds;
75
76 if (jointDirty) {
77 markDirty(changes: AbstractRenderer::JointDirty);
78 m_jointManager->addDirtyJoint(jointId: peerId());
79 }
80
81 BackendNode::syncFromFrontEnd(frontEnd, firstTime);
82}
83
84
85JointFunctor::JointFunctor(AbstractRenderer *renderer,
86 JointManager *jointManager,
87 SkeletonManager *skeletonManager)
88 : m_renderer(renderer)
89 , m_jointManager(jointManager)
90 , m_skeletonManager(skeletonManager)
91{
92}
93
94Qt3DCore::QBackendNode *JointFunctor::create(Qt3DCore::QNodeId id) const
95{
96 Joint *backend = m_jointManager->getOrCreateResource(id);
97 backend->setRenderer(m_renderer);
98 backend->setJointManager(m_jointManager);
99 backend->setSkeletonManager(m_skeletonManager);
100 return backend;
101}
102
103Qt3DCore::QBackendNode *JointFunctor::get(Qt3DCore::QNodeId id) const
104{
105 return m_jointManager->lookupResource(id);
106}
107
108void JointFunctor::destroy(Qt3DCore::QNodeId id) const
109{
110 m_jointManager->removeDirtyJoint(jointId: id);
111 m_jointManager->releaseResource(id);
112}
113
114} // namespace Render
115} // namespace Qt3DRender
116
117QT_END_NAMESPACE
118

source code of qt3d/src/render/geometry/joint.cpp