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
qquick3dskin.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dskin_p.h"
5#include "qquick3dobject_p.h"
7
8#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrenderskin_p.h>
10
11#include <QtQuick3DUtils/private/qssgutils_p.h>
12
14
50
54
67QQmlListProperty<QQuick3DNode> QQuick3DSkin::joints()
68{
69 return QQmlListProperty<QQuick3DNode>(this,
70 nullptr,
71 QQuick3DSkin::qmlAppendJoint,
72 QQuick3DSkin::qmlJointsCount,
73 QQuick3DSkin::qmlJointAt,
74 QQuick3DSkin::qmlClearJoints);
75}
76
77#define POS4BONETRANS(x) (sizeof(float) * 16 * (x) * 2)
78#define POS4BONENORM(x) (sizeof(float) * 16 * ((x) * 2 + 1))
79
80void QQuick3DSkin::onJointChanged(QQuick3DNode *node)
81{
82 for (int i = 0; i < m_joints.size(); ++i) {
83 if (m_joints.at(i) == node) {
84 QMatrix4x4 jointGlobal = m_joints.at(i)->sceneTransform();
85 if (m_inverseBindPoses.size() > i)
86 jointGlobal *= m_inverseBindPoses.at(i);
87 memcpy(m_boneData.data() + POS4BONETRANS(i),
88 reinterpret_cast<const void *>(jointGlobal.constData()),
89 sizeof(float) * 16);
90 memcpy(m_boneData.data() + POS4BONENORM(i),
91 reinterpret_cast<const void *>(QMatrix4x4(jointGlobal.normalMatrix()).constData()),
92 sizeof(float) * 11);
93 markDirty();
94 }
95 }
96}
97
98void QQuick3DSkin::onJointDestroyed(QObject *object)
99{
100 for (int i = 0; i < m_joints.size(); ++i) {
101 if (m_joints.at(i) == object) {
102 m_joints.removeAt(i);
103 // remove both transform and normal together
104 m_boneData.remove(POS4BONETRANS(i),
105 sizeof(float) * 16 * 2);
106 markDirty();
107 break;
108 }
109 }
110}
111
112void QQuick3DSkin::qmlAppendJoint(QQmlListProperty<QQuick3DNode> *list, QQuick3DNode *joint)
113{
114 if (joint == nullptr)
115 return;
116 QQuick3DSkin *self = static_cast<QQuick3DSkin *>(list->object);
117 int index = self->m_joints.size();
118 self->m_joints.push_back(joint);
119 QMatrix4x4 jointGlobal = joint->sceneTransform();
120 if (index < self->m_inverseBindPoses.size())
121 jointGlobal *= self->m_inverseBindPoses.at(index);
122 self->m_boneData.append(reinterpret_cast<const char *>(jointGlobal.constData()),
123 sizeof(float) * 16);
124 self->m_boneData.append(reinterpret_cast<const char *>(QMatrix4x4(jointGlobal.normalMatrix()).constData()),
125 sizeof(float) * 16);
126 self->markDirty();
127
129 [self, joint]() { self->onJointChanged(joint); });
130 connect(joint, &QQuick3DNode::destroyed, self, &QQuick3DSkin::onJointDestroyed);
131}
132
133QQuick3DNode *QQuick3DSkin::qmlJointAt(QQmlListProperty<QQuick3DNode> *list, qsizetype index)
134{
135 QQuick3DSkin *self = static_cast<QQuick3DSkin *>(list->object);
136 return self->m_joints.at(index);
137}
138
139qsizetype QQuick3DSkin::qmlJointsCount(QQmlListProperty<QQuick3DNode> *list)
140{
141 QQuick3DSkin *self = static_cast<QQuick3DSkin *>(list->object);
142 return self->m_joints.size();
143}
144
145void QQuick3DSkin::qmlClearJoints(QQmlListProperty<QQuick3DNode> *list)
146{
147 QQuick3DSkin *self = static_cast<QQuick3DSkin *>(list->object);
148 for (const auto &joint : std::as_const(self->m_joints)) {
149 joint->disconnect(self, SLOT(onJointDestroyed(QObject*)));
150 }
151 self->m_joints.clear();
152 self->m_boneData.clear();
153 self->markDirty();
154}
155
156
168QList<QMatrix4x4> QQuick3DSkin::inverseBindPoses() const
169{
170 return m_inverseBindPoses;
171}
172
173void QQuick3DSkin::setInverseBindPoses(const QList<QMatrix4x4> &poses)
174{
175 if (m_inverseBindPoses == poses)
176 return;
177
178 m_inverseBindPoses = poses;
179
180 for (int i = 0; i < m_joints.size(); ++i) {
181 QMatrix4x4 jointGlobal = m_joints.at(i)->sceneTransform();
182 if (m_inverseBindPoses.size() > i)
183 jointGlobal *= m_inverseBindPoses.at(i);
184 memcpy(m_boneData.data() + POS4BONETRANS(i),
185 reinterpret_cast<const void *>(jointGlobal.constData()),
186 sizeof(float) * 16);
187 memcpy(m_boneData.data() + POS4BONENORM(i),
188 reinterpret_cast<const void *>(QMatrix4x4(jointGlobal.normalMatrix()).constData()),
189 sizeof(float) * 11);
190 }
191
192 markDirty();
194}
195
196void QQuick3DSkin::markDirty()
197{
198 if (!m_dirty) {
199 m_dirty = true;
200 update();
201 }
202}
203
204
206{
207 m_dirty = true;
209}
210
212{
213 if (!node) {
214 markAllDirty();
215 node = new QSSGRenderSkin();
216 }
218 auto skinNode = static_cast<QSSGRenderSkin *>(node);
219
220 if (m_dirty) {
221 m_dirty = false;
222 const int boneTexWidth = qCeil(qSqrt(m_joints.size() * 4 * 2));
223 const int textureSizeInBytes = boneTexWidth * boneTexWidth * 16; //NB: Assumes RGBA32F set above (16 bytes per color)
224 m_boneData.resize(textureSizeInBytes);
225 skinNode->setSize(QSize(boneTexWidth, boneTexWidth));
226 skinNode->setTextureData(m_boneData);
227 skinNode->boneCount = m_joints.size();
228 }
229
230 return node;
231}
232
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
QByteArray & remove(qsizetype index, qsizetype len)
Removes len bytes from the array, starting at index position pos, and returns a reference to the arra...
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
Definition qmatrix4x4.h:147
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void sceneTransformChanged()
\qmltype Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DObject \inherits QtObject
virtual QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node)
virtual void markAllDirty()
void setInverseBindPoses(const QList< QMatrix4x4 > &poses)
void inverseBindPosesChanged()
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
void markAllDirty() override
QQmlListProperty< QQuick3DNode > joints
\qmlproperty List<QtQuick3D::Node> Skin::joints
QQuick3DSkin(QQuick3DObject *parent=nullptr)
\qmltype Skin \inherits Object3D \inqmlmodule QtQuick3D
~QQuick3DSkin() override
QList< QMatrix4x4 > inverseBindPoses
\inmodule QtCore
Definition qsize.h:25
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.h:957
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QString & append(QChar c)
Definition qstring.cpp:3252
Combined button and popup list for selecting options.
QString self
Definition language.cpp:58
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:289
int qCeil(T v)
Definition qmath.h:36
#define SLOT(a)
Definition qobjectdefs.h:52
GLuint index
[2]
#define POS4BONETRANS(x)
#define POS4BONENORM(x)
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:165
QList< int > list
[14]
Definition moc.h:23