Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
8
#
include
"qssgrendernode_p.h"
9
10
#
include
<
QtQuick3DRuntimeRender
/
private
/
qssglayerrenderdata_p
.
h
>
11
12
#
include
<
QtQuick3DUtils
/
private
/
qssgutils_p
.
h
>
13
14
#
include
"qssgrendermodel_p.h"
15
#
include
"qssgrenderroot_p.h"
16
17
#
include
<
QtQuick3DRuntimeRender
/
private
/
qssgrenderbuffermanager_p
.
h
>
18
19
#
include
<
QtQuick3DUtils
/
private
/
qssgplane_p
.
h
>
20
21
QT_BEGIN_NAMESPACE
22
23
QSSGRenderNode::QSSGRenderNode()
24
: QSSGRenderNode(Type::Node)
25
{
26
}
27
28
QSSGRenderNode::QSSGRenderNode(Type type, QSSGRenderGraphObject::FlagT flags)
29
: QSSGRenderGraphObject(type, flags)
30
{
31
localTransform = calculateTransformMatrix({}, initScale, {}, {});
32
}
33
34
QSSGRenderNode::~QSSGRenderNode()
35
=
default
;
36
37
void
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
49
void
QSSGRenderNode::clearDirty(DirtyFlag dirtyFlag)
50
{
51
flags &= ~FlagT(dirtyFlag);
52
}
53
54
void
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
break
;
65
case
QSSGRenderNode::LocalState::Pickable:
66
markDirty(DirtyFlag::PickableDirty);
67
break
;
68
case
QSSGRenderNode::LocalState::Imported:
69
markDirty(DirtyFlag::ImportDirty);
70
break
;
71
}
72
}
73
74
}
75
76
QMatrix4x4 QSSGRenderNode::calculateTransformMatrix(QVector3D position, QVector3D scale, QVector3D pivot, QQuaternion rotation)
77
{
78
QMatrix4x4 transform;
79
80
// Offset the origin (this is our pivot point)
81
auto
offset = (-pivot * scale);
82
83
// Scale
84
transform(0, 0) = scale[0];
85
transform(1, 1) = scale[1];
86
transform(2, 2) = scale[2];
87
88
// Offset (before rotation)
89
transform(0, 3) = offset[0];
90
transform(1, 3) = offset[1];
91
transform(2, 3) = offset[2];
92
93
// rotate
94
transform = QMatrix4x4{rotation.toRotationMatrix()} * transform;
95
96
// translate
97
transform(0, 3) += position[0];
98
transform(1, 3) += position[1];
99
transform(2, 3) += position[2];
100
101
return
transform;
102
}
103
104
void
QSSGRenderNode::addChild(QSSGRenderNode &inChild)
105
{
106
QSSG_ASSERT_X(inChild.parent !=
this
,
"Already a child of this node!"
,
return
);
107
108
// NOTE: A layer does not set a parent reference on its direct children.
109
// Those children (the View3D scene root, the ImportScene dummy, explicit cameras)
110
// are owned and kept alive by other subsystems, e.g. the scene root by the scene manager,
111
// so leaving their parent unset keeps the layer's lifetime decoupled from theirs (They can outlive the layer).
112
// Sharing of imported scenes is handled by the ImportScene dummy injected in
113
// QSSGRenderLayer::setImportScene().
114
if
(type != QSSGRenderNode::Type::Layer) {
115
if
(inChild.parent && inChild.parent !=
this
)
116
inChild.parent->removeChild(inChild);
117
inChild.parent =
this
;
118
}
119
120
QSSG_ASSERT_X(type != QSSGRenderNode::Type::Root || inChild.type == QSSGRenderNode::Type::Layer,
121
"Only layers can be added to the root!"
,
return
);
122
123
if
(inChild.type != QSSGRenderNode::Type::Root)
124
inChild.rootNodeRef = rootNodeRef;
125
126
// NOTE: We push importScene nodes to the front because this way we'll always index
127
// the imported scene first. This keeps their global index low and stable across
128
// views, so a shared imported scene can be placed at the start of a shared data store.
129
if
(inChild.type != QSSGRenderNode::Type::ImportScene)
130
children.push_back(inChild);
131
else
132
children.push_front(inChild);
133
134
// Don't mark dirty if this is a layer, because layers won't have any global values
135
// calculated and therefore will not have the dirty flag cleared!
136
if
(inChild.type != QSSGRenderNode::Type::Layer)
137
inChild.markDirty(DirtyFlag::GlobalValuesDirty);
138
if
(QSSGRenderRoot *rootNode = QSSGRenderRoot::get(rootNodeRef))
139
rootNode->markDirty(QSSGRenderRoot::DirtyFlag::TreeDirty);
140
}
141
142
static
inline
bool
isChildOfLayer
(
const
QSSGRenderLayer &layer,
const
QSSGRenderNode &node)
143
{
144
// A layer does not set parent on its direct children (see addChild()), so the nodes parent
145
// cannot be used to validate relationship between the layer and the node.
146
// Instead we scan the children list to check if node is actually a child of this layer.
147
// We CANNOT dereference node at all! The renderer caches a raw pointer to the
148
// scene-manager-owned scene root and can call this during teardown after that node has been freed.
149
for
(
const
auto
&child : layer.children) {
150
if
(&child == &node)
151
return
true
;
152
}
153
return
false
;
154
}
155
156
void
QSSGRenderNode::removeChild(QSSGRenderNode &inChild)
157
{
158
if
(type == QSSGRenderNode::Type::Layer) {
159
if
(!isChildOfLayer(
static_cast
<
const
QSSGRenderLayer &>(*
this
), inChild))
160
return
;
161
}
else
if
(Q_UNLIKELY(inChild.parent !=
this
)) {
162
Q_ASSERT(inChild.parent ==
this
);
163
return
;
164
}
165
166
inChild.parent =
nullptr
;
167
if
(inChild.type != QSSGRenderNode::Type::Root)
168
inChild.rootNodeRef =
nullptr
;
169
inChild.h = {};
170
children.remove(inChild);
171
if
(QSSGRenderRoot *rootNode = QSSGRenderRoot::get(rootNodeRef))
172
rootNode->markDirty(QSSGRenderRoot::DirtyFlag::TreeDirty);
173
inChild.markDirty(DirtyFlag::GlobalValuesDirty);
174
}
175
176
void
QSSGRenderNode::removeFromGraph()
177
{
178
if
(parent)
179
parent->removeChild(*
this
);
180
181
// Orphan all of my children.
182
for
(
auto
it = children.begin(), end = children.end(); it != end;) {
183
auto
&removedChild = *it++;
184
children.remove(removedChild);
185
removedChild.parent =
nullptr
;
186
removedChild.rootNodeRef =
nullptr
;
187
}
188
}
189
190
QSSGBounds3 QSSGRenderNode::getBounds(QSSGBufferManager &inManager,
191
bool
inIncludeChildren)
const
192
{
193
QSSGBounds3 retval;
194
if
(inIncludeChildren)
195
retval = getChildBounds(inManager);
196
197
if
(type == QSSGRenderGraphObject::Type::Model) {
198
auto
model =
static_cast
<
const
QSSGRenderModel *>(
this
);
199
retval.include(inManager.getModelBounds(model));
200
}
201
return
retval;
202
}
203
204
QSSGBounds3 QSSGRenderNode::getChildBounds(QSSGBufferManager &inManager)
const
205
{
206
QSSGBounds3 retval;
207
QSSGBounds3 childBounds;
208
for
(
auto
&child : children) {
209
childBounds = child.getBounds(inManager);
210
if
(!childBounds.isEmpty()) {
211
// Transform the bounds into our local space.
212
childBounds.transform(child.localTransform);
213
retval.include(childBounds);
214
}
215
}
216
return
retval;
217
}
218
219
QVector3D QSSGRenderNode::getDirection(
const
QMatrix4x4 &globalTransform)
220
{
221
const
float
*dataPtr(globalTransform.data());
222
QVector3D retval(dataPtr[8], dataPtr[9], dataPtr[10]);
223
retval.normalize();
224
return
retval;
225
}
226
227
QVector3D QSSGRenderNode::getScalingCorrectDirection(
const
QMatrix4x4 &globalTransform)
228
{
229
QMatrix3x3 theDirMatrix = globalTransform.normalMatrix();
230
QVector3D theOriginalDir(0, 0, -1);
231
QVector3D retval = QSSGUtils::mat33::transform(theDirMatrix, theOriginalDir);
232
// Should already be normalized, but whatever
233
retval.normalize();
234
return
retval;
235
}
236
237
void
QSSGRenderNode::calculateMVP(
const
QMatrix4x4 &globalTransform,
const
QMatrix4x4 &inViewProjection, QMatrix4x4 &outMVP)
238
{
239
outMVP = inViewProjection * globalTransform;
240
}
241
242
void
QSSGRenderNode::calculateNormalMatrix(
const
QMatrix4x4 &globalTransform, QMatrix3x3 &outNormalMatrix)
243
{
244
outNormalMatrix = globalTransform.normalMatrix();
245
}
246
247
void
QSSGRenderNode::calculateMVPAndNormalMatrix(
const
QMatrix4x4 &globalTransform,
248
const
QMatrix4x4 &inViewProjection,
249
QMatrix4x4 &outMVP,
250
QMatrix3x3 &outNormalMatrix)
251
{
252
calculateMVP(globalTransform, inViewProjection, outMVP);
253
calculateNormalMatrix(globalTransform, outNormalMatrix);
254
}
255
256
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
isChildOfLayer
static bool isChildOfLayer(const QSSGRenderLayer &layer, const QSSGRenderNode &node)
Definition
qssgrendernode.cpp:142
qtquick3d
src
runtimerender
graphobjects
qssgrendernode.cpp
Generated on
for Qt by
1.18.0