HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_TriangleMesh.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GU Library (C++)
7  *
8  * GU_TriangleMesh is a an implementation of an embedding triangle mesh
9  * (UT_EmbeddedTriangleMesh) built over a subset of polygons of a geometry
10  * detail. It constructs and maintains the means needed for going from the
11  * physical space to the abstract one and vice versa.
12  *
13  * The represented abstract triangle mesh can be seen as a refinement of the
14  * geometry with the added benefit tha all its elements are numbered
15  * consecutively from zero and the supporting methods allow to map between
16  * elements rapidly. Furthermore, one can map between input geometry elements
17  * and mesh element indices, when applicable.
18  *
19  */
20 
21 #ifndef __GU_TriangleMesh_h__
22 #define __GU_TriangleMesh_h__
23 
24 #include "GU_API.h"
25 
26 #include "GU_Detail.h"
27 #include <GA/GA_Handle.h>
28 #include <UT/UT_UniquePtr.h>
29 #include <UT/UT_TriangleMesh.h>
30 
31 class GU_Detail;
33 class GA_EdgeGroup;
34 class GA_Range;
35 class UT_Classifier;
36 
37 // Helper class to attach a triangle mesh to a detail and turn it into an
38 // embedded triangle mesh. This is passed as a template argument to
39 // GU_TriangleMesh and keeps track of auxiliary points and their positions
40 // (needed for tessellations that require additional points), as well as
41 // correspondences between mesh elements and detail ones. Most importantly
42 // it implements `pointPosition()` expected from template argument.
43 
44 template <typename T>
46 {
47 public:
50 
52  const UT_TriangleMesh &mesh,
53  GA_RWHandleI vtx_pt_attr,
54  const GA_Attribute *pos_attr);
55 
56 
58  PointCoords pointPosition(int pt) const;
59 
61  int numPrimaryPoints() const
62  { return myNumPrimaryPoints; }
63 
65  int numAuxiliaryPoints() const
66  { return int(myAuxiliaryPointPos.size()); }
67 
69  int numPoints() const
70  { return numPrimaryPoints() + numAuxiliaryPoints(); }
71 
73  void setNumPrimaryPoints(int num)
74  { myNumPrimaryPoints = num; }
75 
78  { myAuxiliaryPointPos.append(pos);
79  return numPoints() - 1; }
80 
82  { myVertexToDetailVertex.append(vtx); }
83 
86  { return myVertexToDetailVertex(v); }
87 
90  { return myPos.get(myPosFromVertexAttrib ? vtx
91  : myGdp->vertexPoint(vtx)); }
92 
95  { return myDetailVertexToVertex.get(vtx); }
96 
98  bool isEngaged() const
99  { return myVertexToDetailVertex.size() > 0; }
100 
103  { myDetailVertexToVertex.set(vtx, pt); }
104 
107  { return myPosFromVertexAttrib; }
108 
109 private:
110  using PosHandle = GA_ROHandleT<PointCoords>;
111  using PointCoordsArray = UT_Array<PointCoords>;
112 
113  const
114  UT_TriangleMesh &myMesh;
115  const GU_Detail *myGdp;
116 
117  // Number of points in the mesh that arise (and are mapped back) to actual
118  // geometry points. The points with index myNumPrimaryPoints and higher
119  // are expected to be auxiliary points.
120 
121  int myNumPrimaryPoints = 0;
122  PointCoordsArray myAuxiliaryPointPos;
123  GA_OffsetArray myVertexToDetailVertex;
124 
125  GA_RWHandleI myDetailVertexToVertex;
126  GA_AttributeUPtr myDetailVertexToVertexAttrib;
127 
128  PosHandle myPos;
129  bool myPosFromVertexAttrib = false;
130 };
131 
132 template <typename T>
134  public UT_EmbeddedTriangleMesh< GU_TriangleMeshDetailLinkT<T> >
135 {
136 public:
139 
140  // Various possible ways of splitting polygons with 4 or more vertices
142  {
143  TRIANGULATE_ALL = 0, // Triangulate all polygons
144  SPLIT_CONVEX_QUADS // Split convex quads (new point at centroid),
145  // triangulate all other polygons.
146  };
147 
148  // The constructor needs a constant detail as the reference geometry.
149  // Note that no group is specified here. Polygons to be used for the mesh
150  // can either be added using `appendPoly()` or `appendPolys()` methods
151  // before a call to `buildMesh()`. This allows distribution of polygons
152  // into various meshes in a scan.
153  //
154  // The integer handle can be used to pass an integer vertex attribute to
155  // collect the assigned point number to each geometry vertex. If an
156  // invalid handle is passed, the structure creates its own detached
157  // attribute. The purpose of passing the handle is to share the attribute
158  // between multiple meshes.
159  //
160  // The `tessellation` argument can be used to control the type of
161  // refinement. Currently, the only option other than a straightforward
162  // triangulation is to split convex quads into four triangles by inserting
163  // a virtual vertex at the centroid of the quad.
164 
165  explicit GU_TriangleMeshT(const GU_Detail *gdp,
166  GA_RWHandleI vtx_pt_attr = GA_RWHandleI(),
167  Tessellation tessellation = TRIANGULATE_ALL,
168  const GA_Attribute *pos_attr = nullptr);
169 
171  const GU_Detail *getDetail() const { return myGdp; }
172 
173  // List of polygons used in the construction of the mesh.
175  const
176  GA_OffsetArray &polys() const { return myPolys; }
177 
178 
179  // Add a single polygon to those covered by the mesh. Can only be called
180  // before building the mesh.
183  { UT_ASSERT_P(!isBuilt()); myPolys.append(poly); }
184 
185  // Add a range of polygons to those covered by the mesh.
186  // Can only be called before building the mesh.
187  void appendPolys(const GA_Range &polys);
188 
189  // Build the actual mesh. It checks and drops invalid primitives
190  // (non-polygons and polygons that are open or have < 3 vertices).
191  //
192  // `seams` will specify the intended cuts in mesh. Half-edges matching
193  // edges in `seams` won't get identified with anything.
194  //
195  // `shared_vtx_idx_array`, if passed, will be used instead of an internal
196  // array for indexing vertices of the involved polygons. This is only used
197  // internally and is not meant to deliver any information. It's allowed
198  // to be passed here to avoid repeat allocation in cases where multiple
199  // disjoint meshes are built on the same geometry (eg uv islands). Note
200  // that the size of the array must be at least as one plus the largest
201  // vertex offset.
202  //
203  // Note: The half-edge interface `hip` can be passed if available (though
204  // it *must* cover all the added polygons) but is not needed and passing
205  // `nullptr` should be faster than building the interface and passing it.
206  //
207  // If `allow_zero_length_edges` is false, it prevents geometrically
208  // degenerate triangles that occur if consecutive points around polygons
209  // can have identical positions. In this case, all consecutively coincident
210  // vertices of input polygon are identified into the same point in the
211  // output mesh and the mapping from detail vertices to mesh vertices will
212  // take each vertex v on the polygon to the source vertex of the half edge
213  // in the mesh that corresponds to the edge of the polygon of v that has
214  // for its source the last vertex around the polygon (in the winding order)
215  // that consecutively coincides with v.
216 
217  void buildMesh(const HedgeInterface *hip = nullptr,
218  const GA_EdgeGroup *seams = nullptr,
219  UT_IntArray *shared_vtx_idx_array = nullptr,
220  bool allow_zero_length_edges = false);
221 
222  template<typename Func>
223  void forEachPolyVertex(Func func) const
224  {
225  for (GA_Offset poly : myPolys)
226  {
227  auto vtxs = myGdp->getPrimitiveVertexList(poly);
228  for (int i = 0, ie = int(vtxs.size()); i < ie; i++)
229  func(vtxs(i));
230  }
231  }
232 
233  template<typename Func>
234  void forEachDetailVertex(Func func) const
235  { forEachPolyVertex(func); }
236 
239  { return myLink.vertexFromDetailVertex(vtx); }
240 
242  int pointFromDetailVertex(GA_Offset vtx) const;
243 
244 
245  // Map a half-edge of the mesh to a vertex in the detail. This differs
246  // from the vertexToDetailVertex() in that only half-edges that map
247  // exactly to source vertex of half-edges in the detail are mapped and
248  // other half-edges are mapped to invalid offsets.
249 
251  GA_Offset hedgeToDetailVertex(int h) const;
252 
255  { return vertexFromDetailVertex(vtx); }
256 
259  { return myLink.vertexToDetailVertex(v); }
260 
263  {
264  auto v = Base::triangleVertex(t, 0);
265  return myGdp->vertexPrimitive(vertexToDetailVertex(v));
266  }
267 
268  // Return for a mesh point *a* geometry vertex mapped to it.
271  { return vertexToDetailVertex(Base::pointVertex(pt)); }
272 
273  // Return for a mesh point *the* geometry point mapped to it.
275  GA_Offset pointToDetailPoint(int pt) const;
276 
277  Tessellation tessellation() const { return myTessellation; }
278 
279  fpreal area() const { return myArea; }
280  fpreal polyArea(exint poly_idx) const
281  { return myPolyArea(poly_idx); }
282 
284  bool isBuilt() const
285  { return myLink.isEngaged(); }
286 
287  int numPrimaryPoints() const
288  { return myLink.numPrimaryPoints(); }
289 
290 protected:
293  { return myLink.detailVertexPosition(vtx); }
294 
295 private:
297  bool isValidPoly(GA_Offset prim) const;
298 
300  bool coincide(GA_Offset vtx0, GA_Offset vtx1) const;
301 
302  bool verifyPolys();
303  int indexPolyVertices(bool allow_zesro_length_edges,
304  UT_IntArray &vtx_idx, int &ntris);
305 
306  void classifyVertices(const UT_IntArray &vtx_idx,
307  const GA_EdgeGroup *seams,
308  bool allow_zero_length_edges,
309  UT_Classifier &vtx_to_pt_classes,
310  GA_OffsetArray &seam_vtxs);
311 
312  void classifyVertices(const HedgeInterface *hip,
313  const UT_IntArray &vtx_idx,
314  const GA_EdgeGroup *seams,
315  bool full_range,
316  bool allow_zero_length_edges,
317  UT_Classifier &vtx_to_pt_classes,
318  GA_OffsetArray &seam_vtxs);
319 
320  using DetailLink = GU_TriangleMeshDetailLinkT<T>;
321 
322  DetailLink myLink;
323  const GU_Detail *myGdp = nullptr;
324  Tessellation myTessellation;
325  GA_OffsetArray myPolys;
326 
327  UT_FprealArray myPolyArea;
328  fpreal myArea = 0.0;
329 };
330 
331 template <typename T>
334 {
335  // Find an arbitrary mesh vertex number corresponding to pt and
336  // pap it a an input detail vertex.
337  if (pt >= myNumPrimaryPoints)
338  return myAuxiliaryPointPos(pt - myNumPrimaryPoints);
339 
340  auto vtx = myVertexToDetailVertex(myMesh.pointVertex(pt));
341  return detailVertexPosition(vtx);
342 }
343 
344 template <typename T>
345 GA_Offset
347 {
348  auto vtx = vertexToDetailVertex(Base::pointVertex(pt));
349  if (!GAisValid(vtx))
350  return GA_INVALID_OFFSET;
351  return myGdp->vertexPoint(vtx);
352 }
353 
354 template <typename T>
355 GA_Offset
357 {
358  auto vtx = vertexToDetailVertex(Base::srcVertex(h));
359 
360  int h_sym = Base::sym(h);
361  if (h_sym >= 0 && vtx == vertexToDetailVertex(Base::dstVertex(h_sym)))
362  return GA_INVALID_OFFSET;
363 
364  return vtx;
365 }
366 
367 template <typename T>
368 int
370 {
371  auto v = vertexFromDetailVertex(vtx);
372  if (v < 0)
373  return -1;
374  return Base::vertexPoint(v);
375 }
376 
377 template <typename T>
378 bool
380 {
381  return myGdp->getPrimitiveTypeId(prim) == GEO_PRIMPOLY
382  && myGdp->getPrimitiveClosedFlag(prim)
383  && myGdp->getPrimitiveVertexCount(prim) > 2;
384 }
385 
386 template <typename T>
387 bool
389 {
390  return detailVertexPosition(vtx0) == detailVertexPosition(vtx1);
391 }
392 
393 
394 
398 
399 #endif
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
void forEachDetailVertex(Func func) const
const GLdouble * v
Definition: glcorearb.h:837
Tessellation tessellation() const
bool GAisValid(GA_Size v)
Definition: GA_Types.h:649
SYS_FORCE_INLINE UT_Vector3R detailVertexPosition(GA_Offset vtx) const
void forEachPolyVertex(Func func) const
int64 exint
Definition: SYS_Types.h:125
GA_Offset srcVertex(GEO_Hedge)
Definition: GEO_Hedge.h:179
GU_TriangleMeshT< fpreal32 > GU_TriangleMeshF
3D Vector class.
SYS_FORCE_INLINE int vertexFromDetailVertex(GA_Offset vtx) const
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
A range of elements in an index-map.
Definition: GA_Range.h:42
GA_Size GA_Offset
Definition: GA_Types.h:641
fpreal area() const
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
SYS_FORCE_INLINE void appendPoly(GA_Offset poly)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
GU_TriangleMeshT< fpreal64 > GU_TriangleMeshD
#define GU_API
Definition: GU_API.h:14
SYS_FORCE_INLINE bool isBuilt() const
SYS_FORCE_INLINE GA_Offset dstVertex(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:215
SYS_FORCE_INLINE GA_Offset pointToDetailVertex(int pt) const
SYS_FORCE_INLINE const GU_Detail * getDetail() const
fpreal polyArea(exint poly_idx) const
GLdouble t
Definition: glad.h:2397
UT_UniquePtr< GA_Attribute > GA_AttributeUPtr
Definition: GA_Attribute.h:930
SYS_FORCE_INLINE int pointFromDetailVertex(GA_Offset vtx) const
SYS_FORCE_INLINE int hedgeFromDetailVertex(GA_Offset vtx) const
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
SYS_FORCE_INLINE const GA_OffsetArray & polys() const
GLenum func
Definition: glcorearb.h:783
SYS_FORCE_INLINE GA_Offset vertexToDetailVertex(int v) const
fpreal64 fpreal
Definition: SYS_Types.h:277
SYS_FORCE_INLINE GA_Offset hedgeToDetailVertex(int h) const
int numPrimaryPoints() const
const GEO_DetachedHedgeInterface HedgeInterface
Definition: GU_Decompose.h:54
SYS_FORCE_INLINE GA_Offset pointToDetailPoint(int pt) const
GU_TriangleMeshT< fpreal > GU_TriangleMeshR
GA_RWHandleT< int32 > GA_RWHandleI
Definition: GA_Handle.h:1364
SYS_FORCE_INLINE GA_Offset triangleToDetailPoly(int t) const
UT_StringArray JOINTS hip