1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qgeometry.h" |
41 | #include "qgeometryfactory.h" |
42 | #include "qgeometry_p.h" |
43 | #include <private/qnode_p.h> |
44 | #include <Qt3DRender/qattribute.h> |
45 | #include <Qt3DCore/qpropertyupdatedchange.h> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | using namespace Qt3DCore; |
50 | |
51 | namespace Qt3DRender { |
52 | |
53 | QGeometryFactory::~QGeometryFactory() |
54 | { |
55 | } |
56 | |
57 | QGeometryPrivate::QGeometryPrivate() |
58 | : QNodePrivate(), |
59 | m_boundingVolumePositionAttribute(nullptr) |
60 | { |
61 | } |
62 | |
63 | QGeometryPrivate::~QGeometryPrivate() |
64 | { |
65 | } |
66 | |
67 | /*! |
68 | \qmltype Geometry |
69 | \instantiates Qt3DRender::QGeometry |
70 | \inqmlmodule Qt3D.Render |
71 | \inherits Node |
72 | \since 5.7 |
73 | \brief Encapsulates geometry. |
74 | |
75 | A Geometry type is used to group a list of Attribute objects together |
76 | to form a geometric shape Qt3D is able to render using GeometryRenderer. |
77 | Special attribute can be set in order to calculate bounding volume of the shape. |
78 | */ |
79 | |
80 | /*! |
81 | \class Qt3DRender::QGeometry |
82 | \inmodule Qt3DRender |
83 | \since 5.7 |
84 | \brief Encapsulates geometry. |
85 | |
86 | A Qt3DRender::QGeometry class is used to group a list of Qt3DRender::QAttribute |
87 | objects together to form a geometric shape Qt3D is able to render using |
88 | Qt3DRender::QGeometryRenderer. Special attribute can be set in order to calculate |
89 | bounding volume of the shape. |
90 | */ |
91 | |
92 | /*! |
93 | \qmlproperty Attribute Geometry::boundingVolumePositionAttribute |
94 | |
95 | Holds the attribute used to compute the bounding volume. The bounding volume is used internally |
96 | for picking and view frustum culling. |
97 | |
98 | If unspecified, the system will look for the attribute using the name returned by |
99 | QAttribute::defaultPositionAttributeName. |
100 | |
101 | \sa Attribute |
102 | */ |
103 | /*! |
104 | \qmlproperty list<Attribute> Geometry::attributes |
105 | |
106 | Holds the list of attributes the geometry comprises of. |
107 | */ |
108 | |
109 | /*! |
110 | \property QGeometry::boundingVolumePositionAttribute |
111 | |
112 | Holds the attribute used to compute the bounding volume. The bounding volume is used internally |
113 | for picking and view frustum culling. |
114 | |
115 | If unspecified, the system will look for the attribute using the name returned by |
116 | QAttribute::defaultPositionAttributeName. |
117 | |
118 | \sa Qt3DRender::QAttribute |
119 | */ |
120 | |
121 | |
122 | /*! |
123 | Constructs a new QGeometry with \a parent. |
124 | */ |
125 | QGeometry::QGeometry(QNode *parent) |
126 | : QGeometry(*new QGeometryPrivate(), parent) {} |
127 | |
128 | /*! |
129 | \fn Qt3DRender::QGeometryFactory::operator()() |
130 | |
131 | Returns the generated geometry. |
132 | */ |
133 | /*! |
134 | \fn bool Qt3DRender::QGeometryFactory::operator==(const QGeometryFactory &other) const = 0 |
135 | |
136 | Compares the factory with the factory specified in \a other. |
137 | Returns true if they are equal. |
138 | */ |
139 | /*! |
140 | \internal |
141 | */ |
142 | QGeometry::~QGeometry() |
143 | { |
144 | } |
145 | |
146 | /*! |
147 | \internal |
148 | */ |
149 | QGeometry::QGeometry(QGeometryPrivate &dd, QNode *parent) |
150 | : QNode(dd, parent) |
151 | { |
152 | } |
153 | |
154 | void QGeometry::sceneChangeEvent(const QSceneChangePtr &change) |
155 | { |
156 | Q_D(QGeometry); |
157 | QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(src: change); |
158 | if (e->type() == PropertyUpdated) { |
159 | const bool blocked = blockNotifications(block: true); |
160 | if (e->propertyName() == QByteArrayLiteral("extent" )) { |
161 | const QPair<QVector3D, QVector3D> extent = e->value().value<QPair<QVector3D, QVector3D>>(); |
162 | |
163 | if (extent.first != d->m_minExtent) { |
164 | d->m_minExtent = extent.first; |
165 | emit minExtentChanged(minExtent: extent.first); |
166 | } |
167 | if (extent.second != d->m_maxExtent) { |
168 | d->m_maxExtent = extent.second; |
169 | emit maxExtentChanged(maxExtent: d->m_maxExtent); |
170 | } |
171 | } |
172 | blockNotifications(block: blocked); |
173 | } |
174 | } |
175 | |
176 | /*! |
177 | \fn void Qt3DRender::QGeometry::addAttribute(Qt3DRender::QAttribute *attribute) |
178 | Adds an \a attribute to this geometry. |
179 | */ |
180 | void QGeometry::addAttribute(QAttribute *attribute) |
181 | { |
182 | Q_ASSERT(attribute); |
183 | Q_D(QGeometry); |
184 | if (!d->m_attributes.contains(t: attribute)) { |
185 | d->m_attributes.append(t: attribute); |
186 | |
187 | // Ensures proper bookkeeping |
188 | d->registerDestructionHelper(node: attribute, func: &QGeometry::removeAttribute, d->m_attributes); |
189 | |
190 | // We need to add it as a child of the current node if it has been declared inline |
191 | // Or not previously added as a child of the current node so that |
192 | // 1) The backend gets notified about it's creation |
193 | // 2) When the current node is destroyed, it gets destroyed as well |
194 | if (!attribute->parent()) |
195 | attribute->setParent(this); |
196 | |
197 | d->updateNode(node: attribute, property: "attribute" , change: Qt3DCore::PropertyValueAdded); |
198 | } |
199 | } |
200 | |
201 | /*! |
202 | \fn void Qt3DRender::QGeometry::removeAttribute(Qt3DRender::QAttribute *attribute) |
203 | Removes the given \a attribute from this geometry. |
204 | */ |
205 | void QGeometry::removeAttribute(QAttribute *attribute) |
206 | { |
207 | Q_ASSERT(attribute); |
208 | Q_D(QGeometry); |
209 | if (!d->m_attributes.removeOne(t: attribute)) |
210 | return; |
211 | // Remove bookkeeping connection |
212 | d->unregisterDestructionHelper(node: attribute); |
213 | d->updateNode(node: attribute, property: "attribute" , change: Qt3DCore::PropertyValueRemoved); |
214 | } |
215 | |
216 | void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute) |
217 | { |
218 | Q_D(QGeometry); |
219 | if (d->m_boundingVolumePositionAttribute != boundingVolumePositionAttribute) { |
220 | d->m_boundingVolumePositionAttribute = boundingVolumePositionAttribute; |
221 | emit boundingVolumePositionAttributeChanged(boundingVolumePositionAttribute); |
222 | } |
223 | } |
224 | |
225 | QAttribute *QGeometry::boundingVolumePositionAttribute() const |
226 | { |
227 | Q_D(const QGeometry); |
228 | return d->m_boundingVolumePositionAttribute; |
229 | } |
230 | |
231 | /*! |
232 | \qmlproperty vector3d Geometry::minExtent |
233 | |
234 | Holds the vertex with the lowest x, y, z position values. |
235 | */ |
236 | |
237 | /*! |
238 | \property QGeometry::minExtent |
239 | |
240 | Holds the vertex with the lowest x, y, z position values. |
241 | */ |
242 | QVector3D QGeometry::minExtent() const |
243 | { |
244 | Q_D(const QGeometry); |
245 | return d->m_minExtent; |
246 | } |
247 | |
248 | /*! |
249 | \qmlproperty vector3d Geometry::maxExtent |
250 | |
251 | Holds the vertex with the highest x, y, z position values. |
252 | */ |
253 | |
254 | /*! |
255 | \property QGeometry::maxExtent |
256 | |
257 | Holds the vertex with the highest x, y, z position values. |
258 | */ |
259 | QVector3D QGeometry::maxExtent() const |
260 | { |
261 | Q_D(const QGeometry); |
262 | return d->m_maxExtent; |
263 | } |
264 | |
265 | /*! |
266 | Returns the list of attributes in this geometry. |
267 | */ |
268 | QVector<QAttribute *> QGeometry::attributes() const |
269 | { |
270 | Q_D(const QGeometry); |
271 | return d->m_attributes; |
272 | } |
273 | |
274 | Qt3DCore::QNodeCreatedChangeBasePtr QGeometry::createNodeCreationChange() const |
275 | { |
276 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QGeometryData>::create(arguments: this); |
277 | auto &data = creationChange->data; |
278 | Q_D(const QGeometry); |
279 | data.attributeIds = qIdsForNodes(nodes: d->m_attributes); |
280 | data.boundingVolumePositionAttributeId = qIdForNode(node: d->m_boundingVolumePositionAttribute); |
281 | return creationChange; |
282 | } |
283 | |
284 | } // namespace Qt3DRender |
285 | |
286 | QT_END_NAMESPACE |
287 | |
288 | #include "moc_qgeometry.cpp" |
289 | |