Overte C++ Documentation
ScriptableMeshPart.h
1 //
2 // Copyright 2018 High Fidelity, Inc.
3 // Copyright 2023 Overte e.V.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 // SPDX-License-Identifier: Apache-2.0
8 //
9 
10 #pragma once
11 
12 #include "ScriptableMesh.h"
13 #include <Scriptable.h>
14 
15 class ScriptValue;
16 
17 namespace scriptable {
18  /*@jsdoc
19  * A handle to in-memory mesh part data in a {@link GraphicsModel}.
20  *
21  * <p>Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or
22  * {@link GraphicsMeshPart.cloneMeshPart}.</p>
23  *
24  * @class GraphicsMeshPart
25  * @hideconstructor
26  *
27  * @hifi-interface
28  * @hifi-client-entity
29  * @hifi-avatar
30  *
31  * @property {boolean} valid - <code>true</code> if the mesh part is valid, <code>false</code> if it isn't.
32  * <em>Read-only.</em>
33  * @property {number} partIndex - The index of the part within the <em>whole</em> mesh (i.e., parent and mesh parts).
34  * <em>Read-only.</em>
35  * @property {number} firstVertexIndex - The index of the first vertex.
36  * @property {number} baseVertexIndex - The index of the base vertex.
37  * @property {number} lastVertexIndex - The index of the last vertex.
38  * @property {Graphics.MeshTopology} topology - The element interpretation. <em>Currently only triangles is supported.</em>
39  * @property {number} numIndices - The number of vertex indices in the mesh part.
40  * @property {number} numVertices - The number of vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
41  * <em>Read-only.</em>
42  * @property {number} numVerticesPerFace - The number of vertices per face, per the <code>topology</code> (e.g., 3 for
43  * triangles).
44  * <em>Read-only.</em>
45  * @property {number} numFaces - The number of faces represented by the mesh part.
46  * <em>Read-only.</em>
47  * @property {number} numAttributes - The number of vertex attributes in the <em>whole</em> mesh (i.e., parent and mesh
48  * parts).
49  * <em>Read-only.</em>
50  * @property {Graphics.BufferTypeName[]} attributeNames - The names of the vertex attributes in the <em>whole</em> mesh
51  * (i.e., parent and mesh parts).
52  * <em>Read-only.</em>
53  * @property {Graphics.MeshExtents} extents - The mesh part extents, in model coordinates.
54  * <em>Read-only.</em>
55  * @property {Object<Graphics.BufferTypeName, Graphics.BufferFormat>} bufferFormats - Details of the buffers used for the
56  * <em>whole</em> mesh (i.e., parent and mesh parts).
57  * <em>Read-only.</em>
58 
59  * @borrows GraphicsMesh.addAttribute as addAttribute
60  * @borrows GraphicsMesh.getVertexAttributes as getVertextAttributes
61  * @borrows GraphicsMesh.setVertexAttributes as setVertextAttributes
62  */
63  class ScriptableMeshPart : public QObject, Scriptable {
64  Q_OBJECT
65  Q_PROPERTY(bool valid READ isValid)
66  Q_PROPERTY(glm::uint32 partIndex MEMBER partIndex CONSTANT)
67  Q_PROPERTY(glm::uint32 firstVertexIndex READ getFirstVertexIndex WRITE setFirstVertexIndex)
68  Q_PROPERTY(glm::uint32 baseVertexIndex READ getBaseVertexIndex WRITE setBaseVertexIndex)
69  Q_PROPERTY(glm::uint32 lastVertexIndex READ getLastVertexIndex WRITE setLastVertexIndex)
70  Q_PROPERTY(int numVerticesPerFace READ getTopologyLength)
71  // NOTE: making read-only for now (see also GraphicsScriptingInterface::newMesh and MeshPartPayload::drawCall)
72  Q_PROPERTY(graphics::Mesh::Topology topology READ getTopology)
73 
74  Q_PROPERTY(glm::uint32 numFaces READ getNumFaces)
75  Q_PROPERTY(glm::uint32 numAttributes READ getNumAttributes)
76  Q_PROPERTY(glm::uint32 numVertices READ getNumVertices)
77  Q_PROPERTY(glm::uint32 numIndices READ getNumIndices WRITE setNumIndices)
78 
79  Q_PROPERTY(QVariantMap extents READ getPartExtents)
80  Q_PROPERTY(QVector<QString> attributeNames READ getAttributeNames)
81  Q_PROPERTY(QVariantMap bufferFormats READ getBufferFormats)
82 
83  public:
84  ScriptableMeshPart(scriptable::ScriptableMeshPointer parentMesh, int partIndex);
85  ScriptableMeshPart& operator=(const ScriptableMeshPart& view) { parentMesh=view.parentMesh; return *this; };
86  ScriptableMeshPart(const ScriptableMeshPart& other) : QObject(other.parent()), Scriptable(), parentMesh(other.parentMesh), partIndex(other.partIndex) {}
87  bool isValid() const { auto mesh = getMeshPointer(); return mesh && partIndex < mesh->getNumParts(); }
88 
89  public slots:
90 
91  /*@jsdoc
92  * Gets the vertex indices.
93  * @function GraphicsMeshPart.getIndices
94  * @returns {number[]} The vertex indices.
95  */
96  QVector<glm::uint32> getIndices() const;
97 
98  /*@jsdoc
99  * Sets the vertex indices.
100  * @function GraphicsMeshPart.setIndices
101  * @param {number[]} indices - The vertex indices.
102  * @returns {boolean} <code>true</code> if successful, <code>false</code> if not.
103  * @throws Throws an error if the number of indices isn't the same, or an index is invalid.
104  */
105  bool setIndices(const QVector<glm::uint32>& indices);
106 
107  /*@jsdoc
108  * Gets the indices of nearby vertices in the mesh part.
109  * @function GraphicsMeshPart.findNearbyPartVertexIndices
110  * @param {Vec3} origin - The search position, in model coordinates.
111  * @param {number} [epsilon=1e-6] - The search distance. If a vertex is within this distance from the
112  * <code>origin</code> it is considered to be "nearby".
113  * @returns {number[]} The indices of nearby vertices.
114  */
115  QVector<glm::uint32> findNearbyPartVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const;
116 
117  /*@jsdoc
118  * Gets the value of an attribute for all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
119  * @function GraphicsMeshPArt.queryVertexAttributes
120  * @param {Graphics.BufferTypeName} name - The name of the attribute to get the vertex values of.
121  * @throws Throws an error if the <code>name</code> is invalid or isn't used in the mesh.
122  * @returns {Graphics.BufferType[]} The attribute values for all vertices.
123  */
124  QVariantList queryVertexAttributes(QVariant selector) const;
125 
126  // @borrows jsdoc from GraphicsMesh.
127  QVariantMap getVertexAttributes(glm::uint32 vertexIndex) const;
128 
129  // @borrows jsdoc from GraphicsMesh.
130  bool setVertexAttributes(glm::uint32 vertexIndex, const QVariantMap& attributeValues);
131 
132  /*@jsdoc
133  * Gets the value of a vertex's attribute.
134  * @function GraphicsMeshPart.getVertexProperty
135  * @param {number} index - The vertex index.
136  * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to get.
137  * @returns {Graphics.BufferType} The value of the vertex attribute.
138  * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the
139  * mesh.
140  */
141  QVariant getVertexProperty(glm::uint32 vertexIndex, const QString& attributeName) const;
142 
143  /*@jsdoc
144  * Sets the value of a vertex's attribute.
145  * @function GraphicsMeshPart.setVertexProperty
146  * @param {number} index - The vertex index.
147  * @param {Graphics.BufferTypeName} name - The name of the vertex attribute to set.
148  * @param {Graphics.BufferType} value - The vertex attribute value to set.
149  * @returns {boolean} <code>true</code> if the vertex attribute value was set, <code>false</code> if it wasn't.
150  * @throws Throws an error if the <code>index</code> is invalid or <code>name</code> is invalid or isn't used in the
151  * mesh.
152  */
153  bool setVertexProperty(glm::uint32 vertexIndex, const QString& attributeName, const QVariant& attributeValues);
154 
155  /*@jsdoc
156  * Gets the vertex indices that make up a face.
157  * @function GraphicsMeshPart.getFace
158  * @param {number} index - The index of the face.
159  * @returns {number[]} The vertex indices that make up the face, of number per the mesh <code>topology</code>.
160  */
161  QVector<glm::uint32> getFace(glm::uint32 faceIndex) const;
162 
163  /*@jsdoc
164  * Scales the mesh to so that it's maximum model coordinate dimension is a specified length.
165  * @function GraphicsMeshPart.scaleToFit
166  * @param {number} scale - The target dimension.
167  * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
168  */
169  QVariantMap scaleToFit(float unitScale);
170 
171  /*@jsdoc
172  * Translates the mesh part.
173  * @function GraphicsMeshPart.translate
174  * @param {Vec3} translation - The translation to apply, in model coordinates.
175  * @returns {Graphics.MeshExtents} The rseulting mesh extents, in model coordinates.
176  */
177  QVariantMap translate(const glm::vec3& translation);
178 
179  /*@jsdoc
180  * Scales the mesh part.
181  * @function GraphicsMeshPart.scale
182  * @param {Vec3} scale - The scale to apply in each model coordinate direction.
183  * @param {Vec3} [origin] - The origin to scale about. If not specified, the center of the mesh part is used.
184  * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
185  */
186  QVariantMap scale(const glm::vec3& scale, const glm::vec3& origin = glm::vec3(NAN));
187 
188  /*@jsdoc
189  * Rotates the mesh part, using Euler angles.
190  * @function GraphicsMeshPart.rotateDegrees
191  * @param {Vec3} eulerAngles - The rotation to perform, in mesh coordinates, as Euler angles in degrees.
192  * @param {Vec3} [origin] - The point about which to rotate, in model coordinates.
193  * <p><strong>Warning:</strong> Currently doesn't work as expected.</p>
194  * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
195  */
196  QVariantMap rotateDegrees(const glm::vec3& eulerAngles, const glm::vec3& origin = glm::vec3(NAN));
197 
198  /*@jsdoc
199  * Rotates the mesh part, using a quaternion.
200  * @function GraphicsMeshPart.rotate
201  * @param {Quat} rotation - The rotation to perform, in model coordinates.
202  * @param {Vec3} [origin] - The point about which to rotate, in model coordinates.
203  * <p><strong>Warning:</strong> Currently doesn't work as expected.</p>
204  * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
205  */
206  QVariantMap rotate(const glm::quat& rotation, const glm::vec3& origin = glm::vec3(NAN));
207 
208  /*@jsdoc
209  * Scales, rotates, and translates the mesh.
210  * @function GraphicsMeshPart.transform
211  * @param {Mat4} transform - The scale, rotate, and translate transform to apply.
212  * @returns {Graphics.MeshExtents} The resulting mesh extents, in model coordinates.
213  */
214  QVariantMap transform(const glm::mat4& transform);
215 
216  // @borrows jsdoc from GraphicsMesh.
217  glm::uint32 addAttribute(const QString& attributeName, const QVariant& defaultValue = QVariant());
218 
219  /*@jsdoc
220  * Sets the value of an attribute for all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
221  * @function GraphicsMeshPart.fillAttribute
222  * @param {Graphics.BufferTypeName} name - The name of the attribute. The attribute is added to the vertices if not
223  * already present.
224  * @param {Graphics.BufferType} value - The value to give the attributes.
225  * @returns {number} <code>1</code> if the attribute name was valid and the attribute values were set, <code>0</code>
226  * otherwise.
227  */
228  glm::uint32 fillAttribute(const QString& attributeName, const QVariant& value);
229 
230  /*@jsdoc
231  * Removes an attribute from all vertices in the <em>whole</em> mesh (i.e., parent and mesh parts).
232  * <p>Note: The <code>"position"</code> attribute cannot be removed.</p>
233  * @function GraphicsMeshPArt.removeAttribute
234  * @param {Graphics.BufferTypeName} name - The name of the attribute to remove.
235  * @returns {boolean} <code>true</code> if the attribute existed and was removed, <code>false</code> otherwise.
236  */
237  bool removeAttribute(const QString& attributeName);
238 
239  /*@jsdoc
240  * Deduplicates vertices.
241  * @function GraphicsMeshPart.dedupeVertices
242  * @param {number} [epsilon=1e-6] - The deduplicadtion distance. If a pair of vertices is within this distance of each
243  * other they are combined into a single vertex.
244  * @returns {boolean} <code>true</code> if the deduplication succeeded, <code>false</code> if it didn't.
245  */
246  bool dedupeVertices(float epsilon = 1e-6);
247 
248  /*@jsdoc
249  * Gets the parent mesh.
250  * @function GraphicsMeshPart.getParentMesh
251  * @returns {GraphicsMesh} The parent mesh.
252  */
253  scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; }
254 
255  /*@jsdoc
256  * Replaces a mesh part with a copy of another mesh part.
257  * @function GraphicsMeshPart.replaceMeshPartData
258  * @param {GrphicsMeshPart} source - The mesh part to copy.
259  * @param {Graphics.BufferTypeName[]} [attributes] - The attributes to copy. If not specified, all attributes are
260  * copied from the source.
261  * @throws Throws an error if the mesh part of source mesh part aren't valid.
262  * @returns {boolean} <code>true</code> if the mesh part was successfully replaced, <code>false</code> if it wasn't.
263  */
264  bool replaceMeshPartData(scriptable::ScriptableMeshPartPointer source, const QVector<QString>& attributeNames = QVector<QString>());
265 
266  /*@jsdoc
267  * Makes a copy of the mesh part.
268  * @function GraphicsMeshPart.cloneMeshPart
269  * @returns {GraphicsMeshPart} A copy of the mesh part.
270  */
271  scriptable::ScriptableMeshPartPointer cloneMeshPart();
272 
273  /*@jsdoc
274  * Exports the mesh part to OBJ format.
275  * @function GraphicsMeshPart.toOBJ
276  * @returns {string} The OBJ format representation of the mesh part.
277  */
278  QString toOBJ();
279 
280 
281  // ScriptEngine-specific wrappers
282 
283  /*@jsdoc
284  * Updates vertex attributes by calling a function for each vertex in the <em>whole</em> mesh (i.e., the parent and
285  * mesh parts). The function can return modified attributes to update the vertex with.
286  * @function GraphicsMeshPart.updateVertexAttributes
287  * @param {GraphicsMesh~updateVertexAttributesCallback} callback - The function to call for each vertex.
288  * @returns {number} The number of vertices the callback was called for.
289  */
290  glm::uint32 updateVertexAttributes(const ScriptValue& callback);
291 
292  /*@jsdoc
293  * Calls a function for each vertex in the <em>whole</em> mesh (i.e., parent and mesh parts).
294  * @function GraphicsMeshPArt.forEachVertex
295  * @param {GraphicsMesh~forEachVertexCallback} callback - The function to call for each vertex.
296  * @returns {number} The number of vertices the callback was called for.
297  */
298  glm::uint32 forEachVertex(const ScriptValue& callback);
299 
300  /*@jsdoc
301  * Checks if an index is valid and, optionally, that vertex has a particular attribute.
302  * @function GraphicsMeshPart.isValidIndex
303  * @param {number} index - The index to check.
304  * @param {Graphics.BufferTypeName} [attribute] - The attribute to check.
305  * @returns {boolean} <code>true</code> if the index is valid and that vertex has the attribute if specified.
306  * @throws Throws an error if the <code>index</code> if invalid or <code>name</code> is invalid or isn't used in the
307  * mesh.
308  */
309  // FIXME: Should return false rather than throw an error.
310  bool isValidIndex(glm::uint32 vertexIndex, const QString& attributeName = QString()) const;
311 
312  public:
313  scriptable::ScriptableMeshPointer parentMesh;
314  glm::uint32 partIndex;
315 
316  protected:
317  const graphics::Mesh::Part& getMeshPart() const;
318  scriptable::MeshPointer getMeshPointer() const { return parentMesh ? parentMesh->getMeshPointer() : nullptr; }
319  QVariantMap getBufferFormats() { return isValid() ? parentMesh->getBufferFormats() : QVariantMap(); }
320  glm::uint32 getNumAttributes() const { return isValid() ? parentMesh->getNumAttributes() : 0; }
321 
322  bool setTopology(graphics::Mesh::Topology topology);
323  graphics::Mesh::Topology getTopology() const { return isValid() ? getMeshPart()._topology : graphics::Mesh::Topology(); }
324  glm::uint32 getTopologyLength() const;
325  glm::uint32 getNumIndices() const { return isValid() ? getMeshPart()._numIndices : 0; }
326  bool setNumIndices(glm::uint32 numIndices) { return setLastVertexIndex(getFirstVertexIndex() + numIndices); }
327  glm::uint32 getNumVertices() const { return isValid() ? parentMesh->getNumVertices() : 0; }
328 
329  bool setFirstVertexIndex(glm::uint32 vertexIndex);
330  glm::uint32 getFirstVertexIndex() const { return isValid() ? getMeshPart()._startIndex : 0; }
331  bool setLastVertexIndex(glm::uint32 vertexIndex);
332  glm::uint32 getLastVertexIndex() const { return isValid() ? getFirstVertexIndex() + getNumIndices() - 1 : 0; }
333  bool setBaseVertexIndex(glm::uint32 vertexIndex);
334  glm::uint32 getBaseVertexIndex() const { return isValid() ? getMeshPart()._baseVertex : 0; }
335 
336  glm::uint32 getNumFaces() const { return getNumIndices() / getTopologyLength(); }
337  QVector<QString> getAttributeNames() const { return isValid() ? parentMesh->getAttributeNames() : QVector<QString>(); }
338  QVariantMap getPartExtents() const;
339  };
340 }
341 
342 Q_DECLARE_METATYPE(scriptable::ScriptableMeshPartPointer)
343 Q_DECLARE_METATYPE(QVector<scriptable::ScriptableMeshPartPointer>)
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40
[ScriptInterface] Provides an engine-independent interface for QScriptable
Definition: Scriptable.h:29