Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
6#include "qssgrendernode_p.h"
7
8#include <QtQuick3DUtils/private/qssgutils_p.h>
9
10#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
11
12#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
13
14#include <QtQuick3DUtils/private/qssgplane_p.h>
15
17
22
28
30 = default;
31
33{
34 if ((flags & FlagT(dirtyFlag)) == 0) { // If not already marked
35 flags |= FlagT(dirtyFlag);
36 const bool markSubtreeDirty = ((FlagT(dirtyFlag) & FlagT(DirtyFlag::GlobalValuesDirty)) != 0);
37 if (markSubtreeDirty) {
38 for (auto &cld : children)
39 cld.markDirty(dirtyFlag);
40 }
41 }
42}
43
45{
46 flags &= ~FlagT(dirtyFlag);
47}
48
50{
51 const bool changed = (getLocalState(state) != on);
52 if (changed) { // Mark state dirty
53 flags = on ? (flags | FlagT(state)) : (flags & ~FlagT(state));
54
55 // Mark state dirty
56 switch (state) {
59 break;
62 break;
63 }
64 }
65
66}
67
68// Calculate global transform and opacity
69// Walks up the graph ensure all parents are not dirty so they have
70// valid global transforms.
71
73{
75 if (retval) {
78
79 if (parent) {
80 retval = parent->calculateGlobalVariables() || retval;
86 // Skip calculating the transform for non-active nodes
87 if (globallyActive && parent->type != QSSGRenderGraphObject::Type::Layer) {
89 if (this == instanceRoot) {
92 } else if (instanceRoot) {
94 //### technically O(n^2) -- we could cache localInstanceTransform if every node in the
95 // tree is guaranteed to have the same instance root. That would require an API change.
97 auto *p = parent;
98 while (p) {
99 if (p == instanceRoot) {
100 localInstanceTransform = p->localInstanceTransform * localInstanceTransform;
101 break;
102 }
104 p = p->parent;
105 }
106 } else {
107 // By default, we do magic: translation is applied to the global instance transform,
108 // while scale/rotation is local
109
111 auto &localInstanceMatrix = *reinterpret_cast<float (*)[4][4]>(localInstanceTransform.data());
112 QVector3D localPos{localInstanceMatrix[3][0], localInstanceMatrix[3][1], localInstanceMatrix[3][2]};
113 localInstanceMatrix[3][0] = 0;
114 localInstanceMatrix[3][1] = 0;
115 localInstanceMatrix[3][2] = 0;
118 }
119 }
120 } else {
121 const bool globallyActive = getLocalState(LocalState::Active);
122 flags = globallyActive ? (flags | FlagT(GlobalState::Active)) : (flags & ~FlagT(GlobalState::Active));
123 const bool globallyPickable = getLocalState(LocalState::Pickable);
127 }
128 // Clear dirty flags
130 }
131 // We always clear dirty in a reasonable manner but if we aren't active
132 // there is no reason to tell the universe if we are dirty or not.
133 return retval && getLocalState(LocalState::Active);
134}
135
137{
139
140 // Offset the origin (this is our pivot point)
141 auto offset = (-pivot * scale);
142
143 // Scale
144 transform(0, 0) = scale[0];
145 transform(1, 1) = scale[1];
146 transform(2, 2) = scale[2];
147
148 // Offset (before rotation)
149 transform(0, 3) = offset[0];
150 transform(1, 3) = offset[1];
151 transform(2, 3) = offset[2];
152
153 // rotate
154 transform = QMatrix4x4{rotation.toRotationMatrix()} * transform;
155
156 // translate
157 transform(0, 3) += position[0];
158 transform(1, 3) += position[1];
159 transform(2, 3) += position[2];
160
161 return transform;
162}
163
165{
166 // Adding children to a layer does not reset parent
167 // because layers can share children over with other layers
168 if (type != QSSGRenderNode::Type::Layer) {
169 if (inChild.parent && inChild.parent != this)
170 inChild.parent->removeChild(inChild);
171 inChild.parent = this;
172 }
173 children.push_back(inChild);
174 inChild.markDirty(DirtyFlag::GlobalValuesDirty);
175}
176
178{
179 if (Q_UNLIKELY(type != QSSGRenderNode::Type::Layer && inChild.parent != this)) {
180 Q_ASSERT(inChild.parent == this);
181 return;
182 }
183
184 inChild.parent = nullptr;
185 children.remove(inChild);
186 inChild.markDirty(DirtyFlag::GlobalValuesDirty);
187}
188
190{
191 if (parent)
192 parent->removeChild(*this);
193
194 // Orphan all of my children.
195 for (auto it = children.begin(), end = children.end(); it != end;) {
196 auto &removedChild = *it++;
197 children.remove(removedChild);
198 removedChild.parent = nullptr;
199 }
200}
201
203 bool inIncludeChildren) const
204{
205 QSSGBounds3 retval;
206 if (inIncludeChildren)
207 retval = getChildBounds(inManager);
208
209 if (type == QSSGRenderGraphObject::Type::Model) {
210 auto model = static_cast<const QSSGRenderModel *>(this);
211 retval.include(inManager.getModelBounds(model));
212 }
213 return retval;
214}
215
217{
218 QSSGBounds3 retval;
219 QSSGBounds3 childBounds;
220 for (auto &child : children) {
221 childBounds = child.getBounds(inManager);
222 if (!childBounds.isEmpty()) {
223 // Transform the bounds into our local space.
224 childBounds.transform(child.localTransform);
225 retval.include(childBounds);
226 }
227 }
228 return retval;
229}
230
232{
233 const float *dataPtr(globalTransform.data());
234 QVector3D retval(dataPtr[8], dataPtr[9], dataPtr[10]);
235 retval.normalize();
236 return retval;
237}
238
240{
241 QMatrix3x3 theDirMatrix = globalTransform.normalMatrix();
242 QVector3D theOriginalDir(0, 0, -1);
243 QVector3D retval = QSSGUtils::mat33::transform(theDirMatrix, theOriginalDir);
244 // Should already be normalized, but whatever
245 retval.normalize();
246 return retval;
247}
248
250{
252 retval.setZ(retval.z() * -1);
253
254 if (parent && parent->type != QSSGRenderGraphObject::Type::Layer) {
255 const QVector4D direction(retval.x(), retval.y(), retval.z(), 1.0f);
257 return QVector3D(result.x(), result.y(), result.z());
258 }
259
260 return retval;
261}
262
263void QSSGRenderNode::calculateMVPAndNormalMatrix(const QMatrix4x4 &inViewProjection, QMatrix4x4 &outMVP, QMatrix3x3 &outNormalMatrix) const
264{
265 outMVP = inViewProjection * globalTransform;
266 outNormalMatrix = calculateNormalMatrix();
267}
268
270 const QMatrix4x4 &inViewProjection,
271 QMatrix4x4 &outMVP,
272 QMatrix3x3 &outNormalMatrix)
273{
274 outMVP = inViewProjection * globalTransform;
275 outNormalMatrix = globalTransform.normalMatrix();
276}
277
279{
280 // NB! QMatrix4x4:normalMatrix() uses double precision for determinant
281 // calculations when inverting the matrix, which is good and is important
282 // in practice e.g. in scenes with with small scale factors.
283
285}
286
Definition lalr.h:136
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
QMatrix3x3 normalMatrix() const
Returns the normal matrix corresponding to this 4x4 transformation.
float * data()
Returns a pointer to the raw data of this matrix.
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
The QQuaternion class represents a quaternion consisting of a vector and scalar.
Class representing 3D range or axis aligned bounding box.
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
QSet< QString >::iterator it
direction
else opt state
[0]
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix3x3 &m, const QVector3D &v)
Definition qssgutils.cpp:43
QVector3D Q_QUICK3DUTILS_EXPORT getPosition(const QMatrix4x4 &m)
Definition qssgutils.cpp:97
Combined button and popup list for selecting options.
#define Q_UNLIKELY(x)
GLuint GLuint end
GLenum type
GLbitfield flags
GLenum GLuint GLintptr offset
GLuint GLenum GLenum transform
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLenum GLenum GLenum GLenum scale
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QSqlQueryModel * model
[16]
QLayoutItem * child
[0]
static constexpr QVector3D initScale
bool calculateGlobalVariables()
void clearDirty(DirtyFlag dirtyFlag)
QVector3D getDirection() const
QMatrix4x4 globalTransform
void addChild(QSSGRenderNode &inChild)
QVector3D getScalingCorrectDirection() const
QMatrix4x4 localInstanceTransform
static QMatrix4x4 calculateTransformMatrix(QVector3D position, QVector3D scale, QVector3D pivot, QQuaternion rotation)
QMatrix4x4 globalInstanceTransform
void setState(LocalState state, bool on=true)
QSSGRenderNode * parent
QSSGBounds3 getChildBounds(QSSGBufferManager &inManager) const
std::underlying_type_t< DirtyFlag > FlagT
QMatrix4x4 localTransform
void removeChild(QSSGRenderNode &inChild)
constexpr bool getLocalState(LocalState stateFlag) const
constexpr bool getGlobalState(GlobalState stateFlag) const
~QSSGRenderNode() override
constexpr bool isDirty(DirtyFlag dirtyFlag=DirtyFlag::DirtyMask) const
QMatrix3x3 calculateNormalMatrix() const
void markDirty(DirtyFlag dirtyFlag)
QVector3D getGlobalPivot() const
QSSGBounds3 getBounds(QSSGBufferManager &inManager, bool inIncludeChildren=true) const
QSSGRenderNode * instanceRoot
void calculateMVPAndNormalMatrix(const QMatrix4x4 &inViewProjection, QMatrix4x4 &outMVP, QMatrix3x3 &outNormalMatrix) const
Definition moc.h:23