blob: f1577382ed5946db559cfe96df83ccc2c100bd50 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "instancerepeater_p.h"
#include <math.h>
#include <QMatrix4x4>
QT_BEGIN_NAMESPACE
/*!
\qmltype InstanceModel
\inherits Object3D
\inqmlmodule QtQuick3D.Helpers
\since 6.4
\brief Defines a data model based on an instance table.
The InstanceModel QML type is a data model that provides access to the elements of an \l Instancing table.
The following roles are available:
\table
\header
\li Role name
\li Description
\row
\li \c modelPosition
\li The position of the instance as a \l vector3d
\row
\li \c modelRotation
\li The rotation of the instance as a \l quaternion
\row
\li \c modelScale
\li The scale of the instance as a \l vector3d
\row
\li \c modelColor
\li The \l color of the instance
\row
\li \c modelData
\li The custom data of the instance as a \l vector4d
\endtable
\sa InstanceRepeater
*/
/*
\table
\header
\li Qt Core Feature
\li Brief Description
\row
\li \l {Signal and Slots}
\li Signals and slots are used for communication
between objects.
\row
\li \l {Layout Management}
\li The Qt layout system provides a simple
and powerful way of specifying the layout
of child widgets.
\row
\li \l {Drag and Drop}
\li Drag and drop provides a simple visual
mechanism which users can use to transfer
information between and within applications.
\endtable
*/
/*!
\qmlproperty Instancing InstanceModel::instancingTable
This property specifies the underlying instance table of the model.
*/
InstanceModel::InstanceModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QVariant InstanceModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
ensureTable();
int idx = index.row();
if (idx >= m_count) {
qWarning("That's not supposed to happen...");
return QVariant();
}
auto *instanceData = reinterpret_cast<const QQuick3DInstancing::InstanceTableEntry*>(m_instanceData.data()) + idx;
switch (role) {
case ColorRole:
return instanceData->getColor();
case PositionRole:
return instanceData->getPosition();
case RotationRole:
return instanceData->getRotation();
case ScaleRole:
return instanceData->getScale();
case CustomDataRole:
return instanceData->instanceData;
}
return QVariant();
}
int InstanceModel::rowCount(const QModelIndex &) const
{
ensureTable();
return m_count;
}
void InstanceModel::setInstancing(QQuick3DInstancing *instancing)
{
if (m_instancing == instancing)
return;
QObject::disconnect(m_tableConnection);
m_instancing = instancing;
m_tableConnection = QObject::connect(instancing, &QQuick3DInstancing::instanceTableChanged, this, &InstanceModel::reset);
emit instancingChanged();
}
const QQuick3DInstancing::InstanceTableEntry *InstanceModel::instanceData(int index) const
{
if (index >= m_count)
return nullptr;
return reinterpret_cast<const QQuick3DInstancing::InstanceTableEntry*>(m_instanceData.constData()) + index;
}
void InstanceModel::ensureTable() const
{
auto *that = const_cast<InstanceModel*>(this);
that->m_instanceData = m_instancing->instanceBuffer(&that->m_count);
}
void InstanceModel::reset()
{
m_instanceData.clear();
}
/*!
\qmltype InstanceRepeater
\inherits Repeater3D
\inqmlmodule QtQuick3D.Helpers
\since 6.4
\brief Instantiates components based on an instance table.
The InstanceRepeater type is used to create a number of objects based on an
\l Instancing table. It is a \l Repeater3D subtype that takes an Instancing table instead
of a data model, and automatically applies \c position, \c scale, and \c rotation.
One use case is to implement \l {View3D::pick}{picking} by creating invisible dummy objects
that match the rendered instances. To improve performance, the dummy objects can be created with a
simpler geometry than the instanced models.
For example:
\qml
InstanceRepeater {
instancingTable: myInstanceTable
Model {
source: "#Cube"
pickable: true
property int instanceIndex: index // expose the index, so we can identify the instance
opacity: 0
}
}
\endqml
\sa InstanceModel
*/
/*!
\qmlproperty Instancing InstanceRepeater::instancingTable
This property specifies the instance table used by the repeater.
*/
InstanceRepeater::InstanceRepeater(QQuick3DNode *parent)
: QQuick3DRepeater(parent)
{
}
QQuick3DInstancing *InstanceRepeater::instancing() const
{
return m_model ? m_model->instancing() : nullptr;
}
void InstanceRepeater::setInstancing(QQuick3DInstancing *instancing)
{
if (m_model && m_model->instancing() == instancing)
return;
if (!m_model)
m_model = new InstanceModel(this);
m_model->setInstancing(instancing);
setModel(QVariant::fromValue(m_model));
emit instancingChanged();
}
void InstanceRepeater::initDelegate(int index, QQuick3DNode *node)
{
Q_ASSERT(m_model);
auto *entry = m_model->instanceData(index);
Q_ASSERT(entry);
node->setPosition(entry->getPosition());
node->setScale(entry->getScale());
node->setRotation(entry->getRotation());
}
QT_END_NAMESPACE
|