Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
instancerepeater.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// Qt-Security score:significant reason:default
4
5
7#include <math.h>
8#include <QMatrix4x4>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \qmltype InstanceModel
14 \inherits Object3D
15 \inqmlmodule QtQuick3D.Helpers
16 \since 6.4
17 \brief Defines a data model based on an instance table.
18
19 The InstanceModel QML type is a data model that provides access to the elements of an \l Instancing table.
20
21 The following roles are available:
22 \table
23 \header
24 \li Role name
25 \li Description
26 \row
27 \li \c modelPosition
28 \li The position of the instance as a \l vector3d
29 \row
30 \li \c modelRotation
31 \li The rotation of the instance as a \l quaternion
32 \row
33 \li \c modelScale
34 \li The scale of the instance as a \l vector3d
35 \row
36 \li \c modelColor
37 \li The \l color of the instance
38 \row
39 \li \c modelData
40 \li The custom data of the instance as a \l vector4d
41 \endtable
42
43 \sa InstanceRepeater
44*/
45
46/*!
47 \qmlproperty Instancing InstanceModel::instancingTable
48
49 This property specifies the underlying instance table of the model.
50*/
51
52InstanceModel::InstanceModel(QObject *parent)
53 : QAbstractListModel(parent)
54{
55}
56
57QVariant InstanceModel::data(const QModelIndex &index, int role) const
58{
59 if (!index.isValid())
60 return QVariant();
61 ensureTable();
62
63 int idx = index.row();
64
65 if (idx >= m_count) {
66 qWarning("InstanceModel: index out of range");
67 return QVariant();
68 }
69
70 auto *instanceData = reinterpret_cast<const QQuick3DInstancing::InstanceTableEntry*>(m_instanceData.data()) + idx;
71
72 switch (role) {
73 case ColorRole:
74 return instanceData->getColor();
75 case PositionRole:
76 return instanceData->getPosition();
77 case RotationRole:
78 return instanceData->getRotation();
79 case ScaleRole:
80 return instanceData->getScale();
81 case CustomDataRole:
82 return instanceData->instanceData;
83 }
84 return QVariant();
85}
86
87int InstanceModel::rowCount(const QModelIndex &) const
88{
89 ensureTable();
90 return m_count;
91}
92
93void InstanceModel::setInstancing(QQuick3DInstancing *instancing)
94{
95 if (m_instancing == instancing)
96 return;
97 QObject::disconnect(m_tableConnection);
98 m_instancing = instancing;
99 m_tableConnection = QObject::connect(instancing, &QQuick3DInstancing::instanceTableChanged, this, &InstanceModel::reset);
100 emit instancingChanged();
101}
102
103const QQuick3DInstancing::InstanceTableEntry *InstanceModel::instanceData(int index) const
104{
105 if (index >= m_count)
106 return nullptr;
107 return reinterpret_cast<const QQuick3DInstancing::InstanceTableEntry*>(m_instanceData.constData()) + index;
108}
109
110void InstanceModel::ensureTable() const
111{
112 auto *that = const_cast<InstanceModel*>(this);
113 that->m_instanceData = m_instancing->instanceBuffer(&that->m_count);
114}
115
116void InstanceModel::reset()
117{
118 beginResetModel();
119 m_instanceData.clear();
120 endResetModel();
121}
122
123/*!
124 \qmltype InstanceRepeater
125 \inherits Repeater3D
126 \inqmlmodule QtQuick3D.Helpers
127 \since 6.4
128 \brief Instantiates components based on an instance table.
129
130 The InstanceRepeater type is used to create a number of objects based on an
131 \l Instancing table. It is a \l Repeater3D subtype that takes an Instancing table instead
132 of a data model, and automatically applies \c position, \c scale, and \c rotation.
133
134 One use case is to implement \l {View3D::pick}{picking} by creating invisible dummy objects
135 that match the rendered instances. To improve performance, the dummy objects can be created with a
136 simpler geometry than the instanced models.
137
138 For example:
139 \qml
140 InstanceRepeater {
141 instancingTable: myInstanceTable
142 Model {
143 source: "#Cube"
144 pickable: true
145 property int instanceIndex: index // expose the index, so we can identify the instance
146 opacity: 0
147 }
148 }
149 \endqml
150
151 \sa InstanceModel
152*/
153
154/*!
155 \qmlproperty Instancing InstanceRepeater::instancingTable
156
157 This property specifies the instance table used by the repeater.
158*/
159
160InstanceRepeater::InstanceRepeater(QQuick3DNode *parent)
161 : QQuick3DRepeater(parent)
162{
163}
164
165QQuick3DInstancing *InstanceRepeater::instancing() const
166{
167 return m_model ? m_model->instancing() : nullptr;
168}
169
170void InstanceRepeater::setInstancing(QQuick3DInstancing *instancing)
171{
172 if (m_model && m_model->instancing() == instancing)
173 return;
174 if (!m_model)
175 m_model = new InstanceModel(this);
176 m_model->setInstancing(instancing);
177 setModel(QVariant::fromValue(m_model));
178 emit instancingChanged();
179}
180
181void InstanceRepeater::initDelegate(int index, QQuick3DNode *node)
182{
183 Q_ASSERT(m_model);
184 auto *entry = m_model->instanceData(index);
185 Q_ASSERT(entry);
186 node->setPosition(entry->getPosition());
187 node->setScale(entry->getScale());
188 node->setRotation(entry->getRotation());
189}
190
191QT_END_NAMESPACE