| 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 | #ifndef QSSG_RENDER_NODE_H |
| 6 | #define QSSG_RENDER_NODE_H |
| 7 | |
| 8 | // |
| 9 | // W A R N I N G |
| 10 | // ------------- |
| 11 | // |
| 12 | // This file is not part of the Qt API. It exists purely as an |
| 13 | // implementation detail. This header file may change from version to |
| 14 | // version without notice, or even be removed. |
| 15 | // |
| 16 | // We mean it. |
| 17 | // |
| 18 | |
| 19 | #include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h> |
| 20 | |
| 21 | #include <QtQuick3DUtils/private/qssgutils_p.h> |
| 22 | #include <QtQuick3DUtils/private/qssgbounds3_p.h> |
| 23 | #include <QtQuick3DUtils/private/qssginvasivelinkedlist_p.h> |
| 24 | |
| 25 | #include <QtGui/QMatrix4x4> |
| 26 | #include <QtGui/qquaternion.h> |
| 27 | #include <QtGui/QVector3D> |
| 28 | |
| 29 | QT_BEGIN_NAMESPACE |
| 30 | |
| 31 | struct QSSGRenderModel; |
| 32 | struct QSSGRenderLight; |
| 33 | class QSSGRenderCamera; |
| 34 | struct QSSGRenderText; |
| 35 | struct QSSGRenderNode; |
| 36 | class QSSGBufferManager; |
| 37 | class QSSGLayerRenderData; |
| 38 | class QSSGRenderRoot; |
| 39 | |
| 40 | struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderNode : public QSSGRenderGraphObject |
| 41 | { |
| 42 | enum class LocalState : quint8 |
| 43 | { |
| 44 | Active = 1 << 0, |
| 45 | Pickable = 1 << 1 |
| 46 | }; |
| 47 | |
| 48 | enum class GlobalState : quint8 |
| 49 | { |
| 50 | Active = 1 << 2, |
| 51 | Pickable = 1 << 3 |
| 52 | }; |
| 53 | |
| 54 | enum class DirtyFlag : quint32 |
| 55 | { |
| 56 | TransformDirty = 1 << 4, |
| 57 | OpacityDirty = 1 << 5, |
| 58 | ActiveDirty = 1 << 6, |
| 59 | PickableDirty = 1 << 7, |
| 60 | SubNodeDirty = 1 << 8, // Sub-nodes should set/unest this if they "extend" the dirty flags provided by the node |
| 61 | |
| 62 | GlobalValuesDirty = TransformDirty | OpacityDirty | ActiveDirty | PickableDirty, |
| 63 | DirtyMask = GlobalValuesDirty | SubNodeDirty |
| 64 | }; |
| 65 | using FlagT = std::underlying_type_t<DirtyFlag>; |
| 66 | |
| 67 | static constexpr QVector3D initScale { 1.0f, 1.0f, 1.0f }; |
| 68 | |
| 69 | // changing any one of these means you have to |
| 70 | // set this object dirty |
| 71 | QVector3D pivot; |
| 72 | int staticFlags = 0; |
| 73 | |
| 74 | // This only sets dirty, not transform dirty |
| 75 | // Opacity of 1 means opaque, opacity of zero means transparent. |
| 76 | float localOpacity = 1.0f; |
| 77 | |
| 78 | // Nodes are initially dirty and locally active! |
| 79 | FlagT flags { FlagT(DirtyFlag::GlobalValuesDirty) | FlagT(LocalState::Active) }; |
| 80 | // These end up right handed |
| 81 | QMatrix4x4 localTransform; |
| 82 | |
| 83 | // node graph members. |
| 84 | QSSGRenderRoot **rootNodeRef = nullptr; |
| 85 | QSSGRenderNode *parent = nullptr; |
| 86 | QSSGRenderNode *nextSibling = nullptr; |
| 87 | QSSGRenderNode *previousSibling = nullptr; |
| 88 | QSSGRenderNode *instanceRoot = nullptr; |
| 89 | |
| 90 | // Handle(s) to the render data. |
| 91 | QSSGRenderNodeHandle h; |
| 92 | |
| 93 | using ChildList = QSSGInvasiveLinkedList<QSSGRenderNode, &QSSGRenderNode::previousSibling, &QSSGRenderNode::nextSibling>; |
| 94 | ChildList children; |
| 95 | |
| 96 | QString debugObjectName; |
| 97 | |
| 98 | QSSGRenderNode(); |
| 99 | QSSGRenderNode(Type type, FlagT flags = 0); |
| 100 | ~QSSGRenderNode() override; |
| 101 | |
| 102 | // Sets this object dirty and walks down the graph setting all |
| 103 | // children who are not dirty to be dirty. |
| 104 | void markDirty(DirtyFlag dirtyFlag); |
| 105 | void clearDirty(DirtyFlag dirtyFlag); |
| 106 | [[nodiscard]] inline constexpr bool isDirty(DirtyFlag dirtyFlag = DirtyFlag::DirtyMask) const { return ((flags & FlagT(dirtyFlag)) != 0); } |
| 107 | void setState(LocalState state, bool on = true); |
| 108 | [[nodiscard]] inline constexpr bool getLocalState(LocalState stateFlag) const { return ((flags & FlagT(stateFlag)) != 0); } |
| 109 | [[nodiscard]] inline constexpr bool getGlobalState(GlobalState stateFlag) const { return ((flags & FlagT(stateFlag)) != 0); } |
| 110 | |
| 111 | void addChild(QSSGRenderNode &inChild); |
| 112 | void removeChild(QSSGRenderNode &inChild); |
| 113 | |
| 114 | // Remove this node from the graph. |
| 115 | // It is no longer the the parent's child lists |
| 116 | // and all of its children no longer have a parent |
| 117 | // finally they are no longer siblings of each other. |
| 118 | void removeFromGraph(); |
| 119 | |
| 120 | // Calculates a tranform matrix based on the position, scale, pivot and rotation arguments. |
| 121 | // NOTE!!!: This function does not update or mark any nodes as dirty, if the returned matrix is set on a node then |
| 122 | // markDirty, calculateGlobalVariables etc. needs to be called as needed! |
| 123 | [[nodiscard]] static QMatrix4x4 calculateTransformMatrix(QVector3D position, QVector3D scale, QVector3D pivot, QQuaternion rotation); |
| 124 | |
| 125 | // Get the bounds of us and our children in our local space. |
| 126 | QSSGBounds3 getBounds(QSSGBufferManager &inManager, |
| 127 | bool inIncludeChildren = true) const; |
| 128 | QSSGBounds3 getChildBounds(QSSGBufferManager &inManager) const; |
| 129 | // Assumes CalculateGlobalVariables has already been called. |
| 130 | [[nodiscard]] static QVector3D getGlobalPos(const QMatrix4x4 &globalTransform) { return QVector3D(globalTransform(0, 3), globalTransform(1, 3), globalTransform(2, 3)); } |
| 131 | // Pulls the 3rd column out of the global transform. |
| 132 | [[nodiscard]] static QVector3D getDirection(const QMatrix4x4 &globalTransform); |
| 133 | // Multiplies (0,0,-1) by the inverse transpose of the upper 3x3 of the global transform. |
| 134 | // This is correct w/r/t to scaling and which the above getDirection is not. |
| 135 | [[nodiscard]] static QVector3D getScalingCorrectDirection(const QMatrix4x4 &globalTransform); |
| 136 | |
| 137 | // outMVP and outNormalMatrix are returned ready to upload to openGL, meaning they are |
| 138 | // row-major. |
| 139 | static void calculateMVP(const QMatrix4x4 &globalTransform, |
| 140 | const QMatrix4x4 &inViewProjection, |
| 141 | QMatrix4x4 &outMVP); |
| 142 | static void calculateNormalMatrix(const QMatrix4x4 &globalTransform, |
| 143 | QMatrix3x3 &outNormalMatrix); |
| 144 | static void calculateMVPAndNormalMatrix(const QMatrix4x4 &globalTransfor, |
| 145 | const QMatrix4x4 &inViewProjection, |
| 146 | QMatrix4x4 &outMVP, |
| 147 | QMatrix3x3 &outNormalMatrix); |
| 148 | |
| 149 | // The Squared value of \a val |
| 150 | // This is mainly used for setting the sorting bias on models and particles |
| 151 | // since we're using the squared distance when sorting. |
| 152 | [[nodiscard]] static inline float signedSquared(float val) |
| 153 | { |
| 154 | const float sign = (val >= 0.0f) ? 1.0f : -1.0f; |
| 155 | return sign * val * val; |
| 156 | } |
| 157 | }; |
| 158 | |
| 159 | QT_END_NAMESPACE |
| 160 | |
| 161 | #endif |
| 162 | |