Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgrendernode.cpp
Go to the documentation of this file.
1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5
7
8#include <QtQuick3DRuntimeRender/private/qssglayerrenderdata_p.h>
9
10#include <QtQuick3DUtils/private/qssgutils_p.h>
11
14
15#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
16
17#include <QtQuick3DUtils/private/qssgplane_p.h>
18
20
21QSSGRenderNode::QSSGRenderNode()
22 : QSSGRenderNode(Type::Node)
23{
24}
25
26QSSGRenderNode::QSSGRenderNode(Type type, QSSGRenderGraphObject::FlagT flags)
27 : QSSGRenderGraphObject(type, flags)
28{
29 localTransform = calculateTransformMatrix({}, initScale, {}, {});
30}
31
32QSSGRenderNode::~QSSGRenderNode()
33 = default;
34
35void QSSGRenderNode::markDirty(DirtyFlag dirtyFlag)
36{
37 if ((flags & FlagT(dirtyFlag)) == 0) { // If not already marked
38 flags |= FlagT(dirtyFlag);
39 const bool markSubtreeDirty = ((FlagT(dirtyFlag) & FlagT(DirtyFlag::GlobalValuesDirty)) != 0);
40 if (markSubtreeDirty) {
41 for (auto &child : children)
42 child.markDirty(dirtyFlag);
43 }
44 }
45}
46
47void QSSGRenderNode::clearDirty(DirtyFlag dirtyFlag)
48{
49 flags &= ~FlagT(dirtyFlag);
50}
51
52void QSSGRenderNode::setState(LocalState state, bool on)
53{
54 const bool changed = (getLocalState(state) != on);
55 if (changed) { // Mark state dirty
56 flags = on ? (flags | FlagT(state)) : (flags & ~FlagT(state));
57
58 // Mark state dirty
59 switch (state) {
60 case QSSGRenderNode::LocalState::Active:
61 markDirty(DirtyFlag::ActiveDirty);
62 if (QSSGRenderRoot *rootNode = QSSGRenderRoot::get(rootNodeRef))
63 rootNode->markDirty(QSSGRenderRoot::DirtyFlag::TreeDirty);
64 break;
65 case QSSGRenderNode::LocalState::Pickable:
66 markDirty(DirtyFlag::PickableDirty);
67 break;
68 }
69 }
70
71}
72
73QMatrix4x4 QSSGRenderNode::calculateTransformMatrix(QVector3D position, QVector3D scale, QVector3D pivot, QQuaternion rotation)
74{
75 QMatrix4x4 transform;
76
77 // Offset the origin (this is our pivot point)
78 auto offset = (-pivot * scale);
79
80 // Scale
81 transform(0, 0) = scale[0];
82 transform(1, 1) = scale[1];
83 transform(2, 2) = scale[2];
84
85 // Offset (before rotation)
86 transform(0, 3) = offset[0];
87 transform(1, 3) = offset[1];
88 transform(2, 3) = offset[2];
89
90 // rotate
91 transform = QMatrix4x4{rotation.toRotationMatrix()} * transform;
92
93 // translate
94 transform(0, 3) += position[0];
95 transform(1, 3) += position[1];
96 transform(2, 3) += position[2];
97
98 return transform;
99}
100
101void QSSGRenderNode::addChild(QSSGRenderNode &inChild)
102{
103 QSSG_ASSERT_X(inChild.parent != this, "Already a child of this node!", return);
104
105 // Adding children to a layer does not reset parent
106 // because layers can share children over with other layers
107 if (type != QSSGRenderNode::Type::Layer && type != QSSGRenderNode::Type::ImportScene) {
108 if (inChild.parent && inChild.parent != this)
109 inChild.parent->removeChild(inChild);
110 inChild.parent = this;
111 }
112
113 QSSG_ASSERT_X(type != QSSGRenderNode::Type::Root || inChild.type == QSSGRenderNode::Type::Layer,
114 "Only layers can be added to the root!", return);
115
116 if (inChild.type != QSSGRenderNode::Type::Root)
117 inChild.rootNodeRef = rootNodeRef;
118
119 children.push_back(inChild);
120 // Don't mark dirty if this is a layer, because layers won't have any global values
121 // calculated and therefore will not have the dirty flag cleared!
122 if (inChild.type != QSSGRenderNode::Type::Layer)
123 inChild.markDirty(DirtyFlag::GlobalValuesDirty);
124 if (QSSGRenderRoot *rootNode = QSSGRenderRoot::get(rootNodeRef))
125 rootNode->markDirty(QSSGRenderRoot::DirtyFlag::TreeDirty);
126}
127
128void QSSGRenderNode::removeChild(QSSGRenderNode &inChild)
129{
130 if (Q_UNLIKELY(type != QSSGRenderNode::Type::Layer && inChild.parent != this)) {
131 Q_ASSERT(inChild.parent == this);
132 return;
133 }
134
135 inChild.parent = nullptr;
136 if (inChild.type != QSSGRenderNode::Type::Root)
137 inChild.rootNodeRef = nullptr;
138 inChild.h = {};
139 children.remove(inChild);
140 if (QSSGRenderRoot *rootNode = QSSGRenderRoot::get(rootNodeRef))
141 rootNode->markDirty(QSSGRenderRoot::DirtyFlag::TreeDirty);
142 inChild.markDirty(DirtyFlag::GlobalValuesDirty);
143}
144
145void QSSGRenderNode::removeFromGraph()
146{
147 if (parent)
148 parent->removeChild(*this);
149
150 // Orphan all of my children.
151 for (auto it = children.begin(), end = children.end(); it != end;) {
152 auto &removedChild = *it++;
153 children.remove(removedChild);
154 removedChild.parent = nullptr;
155 }
156}
157
158QSSGBounds3 QSSGRenderNode::getBounds(QSSGBufferManager &inManager,
159 bool inIncludeChildren) const
160{
161 QSSGBounds3 retval;
162 if (inIncludeChildren)
163 retval = getChildBounds(inManager);
164
165 if (type == QSSGRenderGraphObject::Type::Model) {
166 auto model = static_cast<const QSSGRenderModel *>(this);
167 retval.include(inManager.getModelBounds(model));
168 }
169 return retval;
170}
171
172QSSGBounds3 QSSGRenderNode::getChildBounds(QSSGBufferManager &inManager) const
173{
174 QSSGBounds3 retval;
175 QSSGBounds3 childBounds;
176 for (auto &child : children) {
177 childBounds = child.getBounds(inManager);
178 if (!childBounds.isEmpty()) {
179 // Transform the bounds into our local space.
180 childBounds.transform(child.localTransform);
181 retval.include(childBounds);
182 }
183 }
184 return retval;
185}
186
187QVector3D QSSGRenderNode::getDirection(const QMatrix4x4 &globalTransform)
188{
189 const float *dataPtr(globalTransform.data());
190 QVector3D retval(dataPtr[8], dataPtr[9], dataPtr[10]);
191 retval.normalize();
192 return retval;
193}
194
195QVector3D QSSGRenderNode::getScalingCorrectDirection(const QMatrix4x4 &globalTransform)
196{
197 QMatrix3x3 theDirMatrix = globalTransform.normalMatrix();
198 QVector3D theOriginalDir(0, 0, -1);
199 QVector3D retval = QSSGUtils::mat33::transform(theDirMatrix, theOriginalDir);
200 // Should already be normalized, but whatever
201 retval.normalize();
202 return retval;
203}
204
205void QSSGRenderNode::calculateMVP(const QMatrix4x4 &globalTransform, const QMatrix4x4 &inViewProjection, QMatrix4x4 &outMVP)
206{
207 outMVP = inViewProjection * globalTransform;
208}
209
210void QSSGRenderNode::calculateNormalMatrix(const QMatrix4x4 &globalTransform, QMatrix3x3 &outNormalMatrix)
211{
212 outNormalMatrix = globalTransform.normalMatrix();
213}
214
215void QSSGRenderNode::calculateMVPAndNormalMatrix(const QMatrix4x4 &globalTransform,
216 const QMatrix4x4 &inViewProjection,
217 QMatrix4x4 &outMVP,
218 QMatrix3x3 &outNormalMatrix)
219{
220 calculateMVP(globalTransform, inViewProjection, outMVP);
221 calculateNormalMatrix(globalTransform, outNormalMatrix);
222}
223
224QT_END_NAMESPACE