1// Copyright (C) 2014 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 "updateworldtransformjob_p.h"
5
6#include <Qt3DCore/qtransform.h>
7#include <Qt3DCore/private/qtransform_p.h>
8#include <Qt3DCore/private/qaspectmanager_p.h>
9#include <Qt3DRender/private/entity_p.h>
10#include <Qt3DRender/private/transform_p.h>
11#include <Qt3DRender/private/renderlogging_p.h>
12#include <Qt3DRender/private/job_common_p.h>
13#include <Qt3DRender/private/managers_p.h>
14#include <Qt3DRender/private/nodemanagers_p.h>
15
16#include <QThread>
17
18QT_BEGIN_NAMESPACE
19
20namespace Qt3DRender {
21namespace Render {
22
23namespace {
24
25struct TransformUpdate
26{
27 Qt3DCore::QNodeId peerId;
28 QMatrix4x4 worldTransformMatrix;
29};
30
31void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform, QList<TransformUpdate> &updatedTransforms)
32{
33 if (!node->isEnabled())
34 return;
35
36 Matrix4x4 worldTransform(parentTransform);
37 Transform *nodeTransform = node->renderComponent<Transform>();
38
39 const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled();
40 if (hasTransformComponent)
41 worldTransform = worldTransform * nodeTransform->transformMatrix();
42
43 if (*(node->worldTransform()) != worldTransform) {
44 *(node->worldTransform()) = worldTransform;
45 if (hasTransformComponent)
46 updatedTransforms.push_back(t: {.peerId: nodeTransform->peerId(), .worldTransformMatrix: convertToQMatrix4x4(v: worldTransform)});
47 }
48
49 const auto &childrenHandles = node->childrenHandles();
50 for (const HEntity &handle : childrenHandles) {
51 Entity *child = manager->renderNodesManager()->data(handle);
52 if (child)
53 updateWorldTransformAndBounds(manager, node: child, parentTransform: worldTransform, updatedTransforms);
54 }
55}
56
57}
58
59class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJobPrivate : public Qt3DCore::QAspectJobPrivate
60{
61public:
62 UpdateWorldTransformJobPrivate() {}
63 ~UpdateWorldTransformJobPrivate() override {}
64
65 void postFrame(Qt3DCore::QAspectManager *manager) override;
66
67 QList<TransformUpdate> m_updatedTransforms;
68};
69
70UpdateWorldTransformJob::UpdateWorldTransformJob()
71 : Qt3DCore::QAspectJob(*new UpdateWorldTransformJobPrivate())
72 , m_node(nullptr)
73 , m_manager(nullptr)
74{
75 SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTransform, 0)
76}
77
78void UpdateWorldTransformJob::setRoot(Entity *root)
79{
80 m_node = root;
81}
82
83void UpdateWorldTransformJob::setManagers(NodeManagers *manager)
84{
85 m_manager = manager;
86}
87
88void UpdateWorldTransformJob::run()
89{
90 // Iterate over each level of hierarchy in our scene
91 // and update each node's world transform from its
92 // local transform and its parent's world transform
93
94 // TODO: Parallelise this on each level using a parallel_for
95 // implementation.
96
97 Q_D(UpdateWorldTransformJob);
98 qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
99
100 Matrix4x4 parentTransform;
101 Entity *parent = m_node->parent();
102 if (parent != nullptr)
103 parentTransform = *(parent->worldTransform());
104 updateWorldTransformAndBounds(manager: m_manager, node: m_node, parentTransform, updatedTransforms&: d->m_updatedTransforms);
105
106 qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
107}
108
109void UpdateWorldTransformJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
110{
111 const QList<TransformUpdate> updatedTransforms = Qt3DCore::moveAndClear(data&: m_updatedTransforms);
112 for (const TransformUpdate &t : updatedTransforms) {
113 Qt3DCore::QTransform *node =
114 qobject_cast<Qt3DCore::QTransform *>(object: manager->lookupNode(id: t.peerId));
115 if (!node)
116 continue;
117 Qt3DCore::QTransformPrivate *dNode =
118 static_cast<Qt3DCore::QTransformPrivate *>(Qt3DCore::QNodePrivate::get(q: node));
119 dNode->setWorldMatrix(t.worldTransformMatrix);
120 }
121}
122
123} // namespace Render
124} // namespace Qt3DRender
125
126QT_END_NAMESPACE
127

source code of qt3d/src/render/jobs/updateworldtransformjob.cpp