8#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
9#include <QtQuick3DRuntimeRender/private/qssgrenderskin_p.h>
11#include <QtQuick3DUtils/private/qssgutils_p.h>
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
46QQuick3DSkin::QQuick3DSkin(QQuick3DObject *parent)
47 : QQuick3DObject(*(
new QQuick3DObjectPrivate(QQuick3DObjectPrivate::Type::Skin)), parent)
51QQuick3DSkin::~QQuick3DSkin()
53 for (
const auto &conn : m_jointsConnections) {
54 disconnect(conn.first);
55 disconnect(conn.second);
60
61
62
63
64
65
66
67
68
69
70
71QQmlListProperty<QQuick3DNode> QQuick3DSkin::joints()
73 return QQmlListProperty<QQuick3DNode>(
this,
75 QQuick3DSkin::qmlAppendJoint,
76 QQuick3DSkin::qmlJointsCount,
77 QQuick3DSkin::qmlJointAt,
78 QQuick3DSkin::qmlClearJoints);
81#define POS4BONETRANS(x) (sizeof(float) * 16
* (x) * 2
)
82#define POS4BONENORM(x) (sizeof(float) * 16
* ((x) * 2
+ 1
))
84void QQuick3DSkin::qmlAppendJoint(QQmlListProperty<QQuick3DNode> *list, QQuick3DNode *joint)
88 QQuick3DSkin *self =
static_cast<QQuick3DSkin *>(list->object);
89 if (!self->m_jointsConnections.contains(joint)) {
90 self->m_jointsConnections[joint] =
93 joint, &QQuick3DNode::sceneTransformChanged,
94 self, [self, joint]() {
95 self->m_dirtyJoints.insert(joint);
99 joint, &QQuick3DNode::destroyed,
100 self, [self, joint]() {
101 self->m_dirtyJoints.remove(joint);
102 self->m_removedJoints.insert(joint);
108 self->m_joints.push_back(joint);
109 self->m_dirtyJoints.insert(joint);
113QQuick3DNode *QQuick3DSkin::qmlJointAt(QQmlListProperty<QQuick3DNode> *list, qsizetype index)
115 QQuick3DSkin *self =
static_cast<QQuick3DSkin *>(list->object);
116 return self->m_joints.at(index);
119qsizetype QQuick3DSkin::qmlJointsCount(QQmlListProperty<QQuick3DNode> *list)
121 QQuick3DSkin *self =
static_cast<QQuick3DSkin *>(list->object);
122 return self->m_joints.size();
125void QQuick3DSkin::qmlClearJoints(QQmlListProperty<QQuick3DNode> *list)
127 QQuick3DSkin *self =
static_cast<QQuick3DSkin *>(list->object);
128 for (
const auto &conn : self->m_jointsConnections) {
129 disconnect(conn.first);
130 disconnect(conn.second);
132 self->m_jointsConnections.clear();
134 self->m_joints.clear();
135 self->m_boneData.clear();
136 self->m_dirtyJoints.clear();
137 self->m_removedJoints.clear();
143
144
145
146
147
148
149
150
151
152
153QList<QMatrix4x4> QQuick3DSkin::inverseBindPoses()
const
155 return m_inverseBindPoses;
158void QQuick3DSkin::setInverseBindPoses(
const QList<QMatrix4x4> &poses)
160 if (m_inverseBindPoses == poses)
163 m_updatedByNewInverseBindPoses = qMax(poses.size(), m_inverseBindPoses.size());
164 m_inverseBindPoses = poses;
166 emit inverseBindPosesChanged();
170QSSGRenderGraphObject *QQuick3DSkin::updateSpatialNode(QSSGRenderGraphObject *node)
174 node =
new QSSGRenderSkin();
176 QQuick3DObject::updateSpatialNode(node);
177 auto skinNode =
static_cast<QSSGRenderSkin *>(node);
179 if (!m_removedJoints.empty()) {
180 for (
int i = m_joints.size() - 1; i >= 0; --i) {
181 const auto &joint = m_joints.at(i);
182 if (m_removedJoints.contains(joint)) {
183 m_joints.removeAt(i);
185 sizeof(
float) * 16 * 2);
188 m_removedJoints.clear();
191 if (skinNode->boneCount != quint32(m_joints.size())) {
192 skinNode->boneCount = quint32(m_joints.size());
193 const int boneTexWidth = qCeil(qSqrt(skinNode->boneCount * 4 * 2));
194 const int textureSizeInBytes = boneTexWidth * boneTexWidth * 16;
195 m_boneData.resize(textureSizeInBytes);
196 skinNode->setSize(QSize(boneTexWidth, boneTexWidth));
199 if (m_updatedByNewInverseBindPoses > 0 || !m_dirtyJoints.empty()) {
200 for (
int i = 0; i < m_joints.size(); ++i) {
201 const auto &joint = m_joints.at(i);
202 if (i < m_updatedByNewInverseBindPoses || m_dirtyJoints.contains(joint)) {
203 QMatrix4x4 jointGlobal = joint->sceneTransform();
204 if (m_inverseBindPoses.size() > i)
205 jointGlobal *= m_inverseBindPoses.at(i);
207 reinterpret_cast<
const void *>(jointGlobal.constData()),
210 reinterpret_cast<
const void *>(QMatrix4x4(jointGlobal.normalMatrix()).constData()),
214 m_dirtyJoints.clear();
215 m_updatedByNewInverseBindPoses = 0;
218 skinNode->setTextureData(m_boneData);