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