HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
meshUtil.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_IMAGING_HD_MESH_UTIL_H
25 #define PXR_IMAGING_HD_MESH_UTIL_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/imaging/hd/api.h"
29 #include "pxr/imaging/hd/version.h"
30 #include "pxr/imaging/hd/types.h"
32 
33 #include "pxr/usd/sdf/path.h"
34 
35 #include "pxr/base/gf/vec2i.h"
36 #include "pxr/base/gf/vec3i.h"
37 #include "pxr/base/gf/vec4i.h"
38 
39 #include "pxr/base/vt/array.h"
40 #include "pxr/base/vt/value.h"
41 
43 
44 /// \class HdQuadInfo
45 /// A helper class for quadrangulation computation.
46 
47 // v0 v2
48 // +-----e2----+
49 // \ | /
50 // \ __c__ /
51 // e0 e1
52 // \ /
53 // \ /
54 // + v1
55 //
56 //
57 // original points additional center and edge points
58 // +------------ ... ----+--------------------------------+
59 // | v0 v1 v2 vn | e0 e1 e2 c0, e3 e4 e5 c1 ... |
60 // +------------ ... ----+--------------------------------+
61 // ^
62 // pointsOffset
63 // <----- numAdditionalPoints ---->
64 
65 struct HdQuadInfo {
67 
68  /// Returns true if the mesh is all-quads.
69  bool IsAllQuads() const { return numAdditionalPoints == 0; }
70 
74  std::vector<int> numVerts; // num vertices of non-quads
75  std::vector<int> verts; // vertex indices of non-quads
76 };
77 
78 /// \class HdMeshUtil
79 /// A collection of utility algorithms for generating triangulation
80 /// and quadrangulation of an input topology.
81 
83 {
84 public:
86  : _topology(topology), _id(id) {}
87  virtual ~HdMeshUtil() {}
88 
89  // --------------------------------------------------------------------
90  /// \name Triangulation
91  ///
92  /// Produces a mesh where each non-triangle face in the base mesh topology
93  /// is fan-triangulated such that the resulting mesh consists entirely
94  /// of triangles.
95  ///
96  /// In order to access per-face signals (face color, face selection etc)
97  /// we need a mapping from primitiveID to authored face index domain.
98  /// This is encoded in primitiveParams, and computed along with indices.
99  /// See \ref PrimitiveParamEncoding.
100  /// @{
101  /*
102  +--------+-------+
103  /| \ |\ |\
104  / | \ 1 | \ 2 | \
105  / | \ | \ | \
106  / | \ | \ | 2 +
107  / 0 | 1 \ | 2 \ | /
108  / | \ | \ | /
109  / | \| \|/
110  +-------+--------+-------+
111  */
112 
113  /// Return a triangulation of the input topology. indices and
114  /// primitiveParams are output parameters.
115  HD_API
116  void ComputeTriangleIndices(VtVec3iArray *indices,
117  VtIntArray *primitiveParams,
118  VtIntArray *edgeIndices = nullptr) const;
119 
120  /// Return a triangulation of a face-varying primvar. source is
121  /// a buffer of size numElements and type corresponding to dataType
122  /// (e.g. HdTypeFloatVec3); the result is a VtArray<T> of the
123  /// correct type written to the variable "triangulated".
124  /// This function returns false if it can't resolve dataType.
125  HD_API
127  int numElements,
129  VtValue *triangulated) const;
130 
131  /// @}
132 
133  // --------------------------------------------------------------------
134  /// \name Quadrangulation
135  ///
136  /// Produces a mesh where each non-quad face in the base mesh topology
137  /// is quadrangulated such that the resulting mesh consists entirely
138  /// of quads. Additionally, supports splitting each resulting quad
139  /// face into a pair of triangles. This is different than simply
140  /// triangulating the base mesh topology and can be useful for
141  /// maintaining consistency with quad-based subdivision schemes.
142  ///
143  /// In order to access per-face signals (face color, face selection etc)
144  /// we need a mapping from primitiveID to authored face index domain.
145  /// This is encoded in primitiveParams, and computed along with indices.
146  /// See \ref PrimitiveParamEncoding.
147  /// @{
148 
149  /*
150  +--------+-------+
151  /| | | \
152  / | | 2 | 2 /\
153  / | | \ / \
154  / 0 | 1 |------+ 2 +
155  /\ /| | / \ /
156  / \/ | | 2 | 2 \/
157  / 0 | 0| | | /
158  +-------+--------+-------+
159  */
160 
161  /// Generate a quadInfo struct for the input topology.
162  HD_API
163  void ComputeQuadInfo(HdQuadInfo* quadInfo) const;
164 
165  /// Return quadrangulated indices of the input topology. indices and
166  /// primitiveParams are output parameters.
167  HD_API
168  void ComputeQuadIndices(VtIntArray *indices,
169  VtIntArray *primitiveParams,
170  VtVec2iArray *edgeIndices = nullptr) const;
171 
172  /// Return triquad indices (triangulated after quadrangulation) of the
173  /// input topology. indices and primitiveParams are output parameters.
174  HD_API
175  void ComputeTriQuadIndices(VtIntArray *indices,
176  VtIntArray *primitiveParams,
177  VtVec2iArray *edgeIndices = nullptr) const;
178 
179  /// Return a quadrangulation of a per-vertex primvar. source is
180  /// a buffer of size numElements and type corresponding to dataType
181  /// (e.g. HdTypeFloatVec3); the result is a VtArray<T> of the
182  /// correct type written to the variable "quadrangulated".
183  /// This function returns false if it can't resolve dataType.
184  HD_API
186  void const* source,
187  int numElements,
189  VtValue *quadrangulated) const;
190 
191  /// Return a quadrangulation of a face-varying primvar.
192  /// source is a buffer of size numElements and type corresponding
193  /// to dataType (e.g. HdTypeFloatVec3); the result is a VtArray<T> of the
194  /// correct type written to the variable "quadrangulated".
195  /// This function returns false if it can't resolve dataType.
196  HD_API
198  int numElements,
200  VtValue *quadrangulated) const;
201 
202  /// @}
203 
204  /// Return a buffer filled with face vertex index pairs corresponding
205  /// to the sequence in which edges are visited when iterating through
206  /// the mesh topology. The edges of degenerate and hole faces are
207  /// included so that this sequence will correspond with either base
208  /// face triangulation or quadrangulation (which typically skips
209  /// over hole faces) as well as for refined surfaces which take into
210  /// account faces tagged as holes as well as other non-manifold faces.
211  HD_API
212  void EnumerateEdges(std::vector<GfVec2i> * edgeVerticesOut) const;
213 
214  // --------------------------------------------------------------------
215  /// \anchor PrimitiveParamEncoding
216  /// \name Primitive Param bit encoding
217  ///
218  /// This encoding provides information about each sub-face resulting
219  /// from the triangulation or quadrangulation of a base topology face.
220  ///
221  /// The encoded faceIndex is the index of the base topology face
222  /// corresponding to a triangulated or quadrangulated sub-face.
223  ///
224  /// The encoded edge flag identifies where a sub-face occurs in the
225  /// sequence of sub-faces produced for each base topology face.
226  /// This edge flag can be used to determine which edges of a sub-face
227  /// correspond to edges of a base topology face and which are internal
228  /// edges that were introduced by triangulation or quadrangulation:
229  /// - 0 unaffected triangle or quad base topology face
230  /// - 1 first sub-face produced by triangulation or quadrangulation
231  /// - 2 last sub-face produced by triangulation or quadrangulation
232  /// - 3 intermediate sub-face produced by triangulation or quadrangulation
233  /// @{
234 
235  // Per-primitive coarse-face-param encoding/decoding functions
236  static int EncodeCoarseFaceParam(int faceIndex, int edgeFlag) {
237  return ((faceIndex << 2) | (edgeFlag & 3));
238  }
239  static int DecodeFaceIndexFromCoarseFaceParam(int coarseFaceParam) {
240  return (coarseFaceParam >> 2);
241  }
242  static int DecodeEdgeFlagFromCoarseFaceParam(int coarseFaceParam) {
243  return (coarseFaceParam & 3);
244  }
245 
246  /// }@
247 
248 private:
249  /// Return the number of quadrangulated quads.
250  /// If degenerate face is found, sets invalidFaceFound as true.
251  int _ComputeNumQuads(VtIntArray const &numVerts,
252  VtIntArray const &holeIndices,
253  bool *invalidFaceFound = nullptr) const;
254 
255  /// Return quad indices (optionally triangulated after quadrangulation).
256  void _ComputeQuadIndices(
257  VtIntArray *indices,
258  VtIntArray *primitiveParams,
259  VtVec2iArray *edgeIndices,
260  bool triangulate = false) const;
261 
262  HdMeshTopology const* _topology;
263  SdfPath const _id;
264 };
265 
266 /// \class HdMeshEdgeIndexTable
267 ///
268 /// Mesh edges are described as a pair of adjacent vertices encoded
269 /// as GfVec2i.
270 ///
271 /// The encoding of mesh edge indices is derived from the enumeration
272 /// of face vertex index pairs provided by HdMeshUtil::EnumerateEdges().
273 ///
274 /// This encoding is consistent across triangulation or quadrangulation
275 /// of the base mesh faces as well as for non-manifold faces on refined
276 /// subdivision surface meshes.
277 ///
278 /// There can be multiple edge indices associated with each pair of
279 /// topological vertices in the mesh, e.g. one for each face incident
280 /// on the edge.
281 ///
282 /// For example, here is a typical edge index assignment for a mesh
283 /// with 2 quad faces and 6 vertices:
284 ///
285 /// faceVertexCounts: [4, 4]
286 /// faceVertexIndices: [0, 1, 4, 3, 1, 2, 5, 4]
287 ///
288 /// edgeId:(edgeVertex[0], edgeVertex[1])
289 ///
290 /// 2:(3,4) 6:(4,5)
291 /// 3----------------4----------------5
292 /// | | |
293 /// | Face 0 | Face 1 |
294 /// | | |
295 /// |3:(0,3) 1:(1,4)|7:(1,4) 5:(2,5)|
296 /// | | |
297 /// | | |
298 /// | | |
299 /// 0----------------1----------------2
300 /// 0:(0,1) 4:(1,2)
301 ///
302 /// Notice that with this assignment, there are eight edge indices even
303 /// though the mesh has seven topological edges. The mesh edge between
304 /// vertex 1 and vertex 4 is associated with two edgeIds (1 and 7),
305 /// one for each incident face.
306 ///
307 /// This kind of edge index assignment can be implemented efficiently
308 /// on the GPU since it falls out automatically from the primitive
309 /// drawing order and requires minimal additional GPU data.
310 ///
311 ///
313 {
314 public:
315  explicit HdMeshEdgeIndexTable(HdMeshTopology const * topology);
317 
318  bool GetVerticesForEdgeIndex(int edgeId, GfVec2i * edgeVerticesOut) const;
319 
321  std::vector<int> const & edgeIndices,
322  std::vector<GfVec2i> * edgeVerticesOut) const;
323 
324  bool GetEdgeIndices(GfVec2i const & edgeVertices,
325  std::vector<int> * edgeIndicesOut) const;
326 
327 private:
328  struct _Edge{
329  _Edge(GfVec2i const & verts_ = GfVec2i(-1), int index_ = -1)
330  : verts(verts_)
331  , index(index_)
332  {
333  // Simplify sorting and searching by keeping the vertices ordered.
334  if (verts[0] > verts[1]) {
335  std::swap(verts[0], verts[1]);
336  }
337  }
338  GfVec2i verts;
339  int index;
340 
341  };
342 
343  struct _CompareEdgeVertices {
344  bool operator() (_Edge const &lhs, _Edge const & rhs) const {
345  return (lhs.verts[0] < rhs.verts[0] ||
346  (lhs.verts[0] == rhs.verts[0] &&
347  lhs.verts[1] < rhs.verts[1]));
348  }
349  };
350 
351  struct _EdgeVerticesHash {
352  // Use a custom hash so that edges (a,b) and (b,a) are equivalent
353  inline size_t operator()(GfVec2i const& v) const {
354  // Triangular numbers for 2-d hash.
355  int theMin = v[0], theMax = v[1];
356  if (theMin > theMax) {
357  std::swap(theMin, theMax);
358  }
359  size_t x = theMin;
360  size_t y = x + theMax;
361  return x + (y * (y + 1)) / 2;
362  }
363  };
364 
365  std::vector<GfVec2i> _edgeVertices;
366  std::vector<_Edge> _edgesByIndex;
367 };
368 
369 /// \class HdMeshTriQuadBuilder
370 ///
371 /// Helper class for emitting a buffer of quad indices, optionally
372 /// splitting each quad into two triangles.
373 ///
375 {
376 public:
377  static int const NumIndicesPerQuad = 4;
378  static int const NumIndicesPerTriQuad = 6;
379 
380  HdMeshTriQuadBuilder(int * indicesBuffer, bool triangulate)
381  : _outputPtr(indicesBuffer)
382  , _triangulate(triangulate)
383  { }
384 
385  void EmitQuadFace(GfVec4i const & quadIndices) {
386  if (_triangulate) {
387  *_outputPtr++ = quadIndices[0];
388  *_outputPtr++ = quadIndices[1];
389  *_outputPtr++ = quadIndices[2];
390  *_outputPtr++ = quadIndices[2];
391  *_outputPtr++ = quadIndices[3];
392  *_outputPtr++ = quadIndices[0];
393  } else {
394  *_outputPtr++ = quadIndices[0];
395  *_outputPtr++ = quadIndices[1];
396  *_outputPtr++ = quadIndices[2];
397  *_outputPtr++ = quadIndices[3];
398  }
399  }
400 
401 private:
402  int * _outputPtr;
403  bool const _triangulate;
404 };
405 
406 
408 
409 #endif // PXR_IMAGING_HD_MESH_UTIL_H
bool GetVerticesForEdgeIndex(int edgeId, GfVec2i *edgeVerticesOut) const
Definition: vec4i.h:60
HD_API bool ComputeTriangulatedFaceVaryingPrimvar(void const *source, int numElements, HdType dataType, VtValue *triangulated) const
std::vector< int > numVerts
Definition: meshUtil.h:74
GLsizei GLenum const void * indices
Definition: glcorearb.h:406
HD_API void ComputeTriQuadIndices(VtIntArray *indices, VtIntArray *primitiveParams, VtVec2iArray *edgeIndices=nullptr) const
Definition: vec2i.h:60
HD_API void ComputeTriangleIndices(VtVec3iArray *indices, VtIntArray *primitiveParams, VtIntArray *edgeIndices=nullptr) const
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1631
HD_API bool ComputeQuadrangulatedFaceVaryingPrimvar(void const *source, int numElements, HdType dataType, VtValue *quadrangulated) const
const GLdouble * v
Definition: glcorearb.h:837
static int DecodeFaceIndexFromCoarseFaceParam(int coarseFaceParam)
}@
Definition: meshUtil.h:239
bool IsAllQuads() const
Returns true if the mesh is all-quads.
Definition: meshUtil.h:69
#define HD_API
Definition: api.h:40
void EmitQuadFace(GfVec4i const &quadIndices)
Definition: meshUtil.h:385
int maxNumVert
Definition: meshUtil.h:73
GLint y
Definition: glcorearb.h:103
static int DecodeEdgeFlagFromCoarseFaceParam(int coarseFaceParam)
}@
Definition: meshUtil.h:242
bool GetVerticesForEdgeIndices(std::vector< int > const &edgeIndices, std::vector< GfVec2i > *edgeVerticesOut) const
virtual ~HdMeshUtil()
Definition: meshUtil.h:87
HdMeshTriQuadBuilder(int *indicesBuffer, bool triangulate)
Definition: meshUtil.h:380
GT_API const UT_StringHolder topology
int pointsOffset
Definition: meshUtil.h:71
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
static int const NumIndicesPerQuad
Definition: meshUtil.h:377
bool GetEdgeIndices(GfVec2i const &edgeVertices, std::vector< int > *edgeIndicesOut) const
Definition: path.h:291
GLint GLenum GLint x
Definition: glcorearb.h:409
HD_API void ComputeQuadIndices(VtIntArray *indices, VtIntArray *primitiveParams, VtVec2iArray *edgeIndices=nullptr) const
HD_API void EnumerateEdges(std::vector< GfVec2i > *edgeVerticesOut) const
static int const NumIndicesPerTriQuad
Definition: meshUtil.h:378
int numAdditionalPoints
Definition: meshUtil.h:72
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
HdQuadInfo()
Definition: meshUtil.h:66
static int EncodeCoarseFaceParam(int faceIndex, int edgeFlag)
}@
Definition: meshUtil.h:236
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
HD_API bool ComputeQuadrangulatedPrimvar(HdQuadInfo const *qi, void const *source, int numElements, HdType dataType, VtValue *quadrangulated) const
HdMeshUtil(HdMeshTopology const *topology, SdfPath const &id)
Definition: meshUtil.h:85
std::vector< int > verts
Definition: meshUtil.h:75
HdType
Definition: types.h:287
HdMeshEdgeIndexTable(HdMeshTopology const *topology)
HUSD_API const char * dataType()
Definition: value.h:167
HD_API void ComputeQuadInfo(HdQuadInfo *quadInfo) const
Generate a quadInfo struct for the input topology.