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 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | using namespace Qt3DCore; |
14 | |
15 | namespace Qt3DRender { |
16 | namespace Render { |
17 | |
18 | Joint::Joint() |
19 | : BackendNode(Qt3DCore::QBackendNode::ReadOnly) |
20 | , m_localPose() |
21 | , m_jointManager(nullptr) |
22 | , m_skeletonManager(nullptr) |
23 | { |
24 | } |
25 | |
26 | void 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 | |
36 | void 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 | |
85 | JointFunctor::JointFunctor(AbstractRenderer *renderer, |
86 | JointManager *jointManager, |
87 | SkeletonManager *skeletonManager) |
88 | : m_renderer(renderer) |
89 | , m_jointManager(jointManager) |
90 | , m_skeletonManager(skeletonManager) |
91 | { |
92 | } |
93 | |
94 | Qt3DCore::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 | |
103 | Qt3DCore::QBackendNode *JointFunctor::get(Qt3DCore::QNodeId id) const |
104 | { |
105 | return m_jointManager->lookupResource(id); |
106 | } |
107 | |
108 | void 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 | |
117 | QT_END_NAMESPACE |
118 | |