HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GQ_Detail.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: Quad Edge Library (C++)
7  *
8  */
9 
10 #ifndef _GQ_Detail_h_
11 #define _GQ_Detail_h_
12 
13 #include "GQ_API.h"
14 #include "GQ_Error.h"
15 #include "GQ_Edge.h"
16 
17 #include <GU/GU_PrimPoly.h>
18 #include <GU/GU_RayIntersect.h>
19 #include <GU/GU_Types.h>
20 #include <GEO/GEO_Primitive.h>
22 #include <GA/GA_AttributeRefMap.h>
23 
24 #include <UT/UT_FloatArray.h>
25 #include <UT/UT_IntArray.h>
26 #include <UT/UT_NonCopyable.h>
27 #include <UT/UT_Plane.h>
28 #include <UT/UT_Array.h>
29 #include <UT/UT_Array.h>
30 #include <UT/UT_Map.h>
31 
32 #include <SYS/SYS_Types.h>
33 
34 #include <iosfwd>
35 
36 class GU_Detail;
37 class GQ_Face;
38 class GQ_Point;
39 class GEO_PrimPoly;
40 class GA_PointWrangler;
41 class GA_PrimitiveGroup;
42 class GA_EdgeGroup;
44 class GQ_StitchParms;
45 class GQ_SubdivideParms;
46 class gq_SubdivideAttribHandler;
47 
48 template<typename T, bool B> class GA_EdgeT;
50 
52 {
59 };
60 
61 /// Quad Edge data structure for topological manipulation of polygonal data.
62 ///
63 /// The Quad Edge data structure was invented by Guibas & Stolfi in their
64 /// 1985 paper, "Primitives for the Manipulation of General Subdivisions and
65 /// the Computation of Voronoi Diagrams", ACM Transactions on Graphics,
66 /// 4(2):74-123, April 1985.
67 ///
68 /// That paper has a good description of the capabilities of the data
69 /// structure, and the definition of its basic operators, makeedge and splice().
71 {
72 public:
73  /// The super_point_tolerance should probably be set to -1 which flags
74  /// for no super points to be generated. Super points often cause
75  /// confusing (for the caller) results.
76  GQ_Detail(GU_Detail *gdp,
77  GA_PrimitiveGroup * = 0,
78  fpreal super_point_tolerance = 1E-6);
79  ~GQ_Detail();
80 
81  void clearAndDestroy();
82  /// Cusp polygons which have adjacent edges larger than angle (in degrees)
83  void cusp(fpreal angle, bool no_cut = false);
84 
85  /// Cusp edges in a group
86  void cusp(const GA_EdgeGroup &edges,
87  bool do_cut = false);
88 
89 
90  /// Both clip() and crease() will invalidate this GQ_Detail. If you wish
91  /// to do another GQ_Detail operation, create a new GQ_Detail. 'norm' and
92  /// 'distance' define a plane with 'distance' being measured from the
93  /// origin.
94  /// {
95  void clip(UT_Vector3 &norm, fpreal distance,
96  int normalize);
97  int crease(UT_Vector3 &norm, fpreal distance,
98  int normalize, int outputGroups,
99  GA_PrimitiveGroup *primitive_above=0,
100  GA_PrimitiveGroup *primitive_below=0);
101  /// }
102 
103  void bricker(fpreal sizex = 1.0, fpreal sizey = 1.0,
104  fpreal sizez = 1.0, fpreal offx = 0.0,
105  fpreal offy = 0.0, fpreal offz = 0.0,
106  fpreal anglex = 0.0, fpreal angley = 0.0,
107  fpreal anglez = 0.0,
108  bool fixsharededges = false);
109  void smooth(int divisions, fpreal relativeSize,
110  fpreal weight);
111 
112  // Adds edge weights to the GQ_Detail. (If not already present)
113  void createEdgeWeights();
114 
115  // This is used to set up the edge weights:
116  // To read edgeweights, use getEdgeWeight
117  // The following method assumes that poly is not in the GQ_Detail. It can
118  // be, but it is not a requirement.
119  void setCreaseWeight(const GEO_PrimPoly &poly,
120  fpreal weight);
121  // With the following method the poly can be in the GQ_Detail or in another
122  // gdp. It requires the creaseweight attribute on the polygon or on the
123  // vertices of the polygon. If either the vtxoff or primoff is >= 0, that
124  // attribute will be used...
125  void setCreaseWeight(const GEO_PrimPoly &poly,
126  GA_ROHandleF vtxattrib,
127  GA_ROHandleF primattrib);
128 
129  // Given a GA_Edge, we can map this to a GQ_Edge and set the corresponding
130  // weight. A GU_Detail is required to look up point indices from the edge
131  // since the GA_Edge may not be from the GQ_Detail.
132  void setCreaseWeight(const GA_Edge &edge,
133  const GU_Detail &edge_gdp,
134  fpreal weight);
135 
136  // This is similar to the setCreaseWeight method for GEO_PrimPoly,
137  // but the edge supplied is the only one affected. This edge must
138  // belong to a poly (so that the attribute can be grabbed).
139  void setCreaseWeight(const GA_Edge &gedge,
140  const GA_Primitive &prim,
141  GA_ROHandleF vtxattrib,
142  GA_ROHandleF primattrib);
143 
144 
145  fpreal getEdgeWeight(const GA_Edge &edge);
146  fpreal getEdgeWeight(exint edge_index) const;
147  bool setEdgeWeight(exint edge_index,
148  fpreal weight);
149  void subdivide(const GQ_SubdivideParms &parms,
150  GA_PrimitiveGroup *nonsubdivprims);
151  void dual(const char *attribs_to_swap=NULL);
152  void stitch(const GQ_StitchParms &parms);
153  int stitchEdges(GEO_PrimPoly &polya,
154  const UT_Array<GEO_PrimPoly *> &facea,
155  GEO_PrimPoly &polyb,
156  const UT_Array<GEO_PrimPoly *> &faceb,
157  GA_PrimitiveGroup &changedpolys,
158  fpreal tol, int clamp, int consolidate);
159  void makeWire(fpreal radius, int doSpheres,
160  int doCaps);
161  void buildGeometry(GA_PrimitiveGroup *output = NULL);
162  void buildCreases(GA_PrimitiveGroup *group = 0);
163  void copyEdgeWeightToVertex();
164  void unHole(int maintain);
165  void boundary();
166  void createCuspGroup(GA_Group *group,
167  bool doMinAngle, fpreal minAngle,
168  bool doMaxAngle, fpreal maxAngle);
169  void createBoundaryGroup(GA_Group *grp);
170  void createBoundaryGroup(GA_PointGroup &grp,
171  UT_IntArray *arr);
172  void createBoundaryGroup(GA_Offset ppt,
173  GA_PointGroup &pointgroup);
174  void createBoundaryGroup(const GA_Edge &edge,
175  GA_PointGroup &grp,
176  GEO_PrimPoly *&poly);
177  /// For each boundary loop a separate UT_IntArray is added to the ptlist.
178  /// These intarrays will contain the point numbers, in order, of the
179  /// points that belong to those boundaries.
180  /// This is preferable to the group based approach becausae it can
181  /// handle duplicate points that show up on the boundary of certain
182  /// degenerate geometry..
183  void createBoundaryList(UT_Array<UT_IntArray> &ptlist);
184 
185 
186 // Creates a point group of those points which are adjacent by the certain
187 // given number of edges.
188  void groupEdgePoints(GA_Offset ptoff,
189  int depth,
190  GA_PointGroup &point_group);
191 
192  int isClose();
193 
194  // deleteAllShareEdges is only for testing deleteShareEdge
195  // which will be used for polygon reduction.
196  // Don't use it for deleting all shared edges (ie. want only the boundary)
197  void deleteAllShareEdges();
198 
199 
200  GQ_Point *appendPoint(const GQ_Point *src=0);
202  {
203  GQ_Edge *Q = new GQ_Edge[4];
204  int idx = myEdges.append(Q);
205  for (int i = 0; i < 4; i++)
206  Q[i].init(i + idx * 4);
207  return Q;
208  }
209  GQ_Face *appendFace(GEO_PrimPoly *poly);
210  void removePoint(GQ_Point *p);
211  void removePoint(int i);
212  void removeEdge(GQ_Edge *e);
213  void removeEdge(int i);
214 
215  // removeFace(GQ_Face* f) ensures that the face f is not in the detail
216  // after the call. It returns whether the face was present before the call.
217  bool removeFace(GQ_Face *f);
218 
219  void removeFace(int i);
220 
221  void collapseEdgeList() { myEdges.collapse(); }
222  void collapseFaceList() { myFaces.collapse(); }
223  UT_Array<GQ_Point *> &getPointList() { return myPoints; }
224  const UT_Array<GQ_Point *> &getPointList() const { return myPoints; }
225  UT_ValArray<GQ_Edge *> &getEdgeList() { return myEdges; }
226  const UT_ValArray<GQ_Edge *>&getEdgeList() const{ return myEdges; }
227  UT_DoubleArray &getEdgeWeights() { return myEdgeWeights; }
228  const UT_DoubleArray &getEdgeWeights() const { return myEdgeWeights; }
229  UT_Array<GQ_Point *> &getEdgePoints() { return myEdgePoints; }
230  const UT_Array<GQ_Point*> &getEdgePoints() const { return myEdgePoints; }
231 
232  UT_ValArray<GQ_Face *> &getFaceList() { return myFaces; }
233  const UT_ValArray<GQ_Face *>&getFaceList() const{ return myFaces; }
234  GU_Detail *getGdp() { return myGdp; }
235  const GU_Detail *getGdp() const { return myGdp; }
236  GU_RayIntersect *getRay() { return myRay; }
237  void buildRay()
238  {
239  if (myRay) delete myRay;
240  myRay = new GU_RayIntersect(myGdp, myGroup);
241  }
242  UT_Array<GA_RWAttributeRef> &getOffsets() { return myOffsets; }
243 
244 
245  /// Split edge will return 0 if t is too close to 0 or 1.
246  GQ_Point *splitEdge(GQ_Edge *edge, fpreal t);
247  GQ_Edge *splitEdge(GQ_Edge *, GQ_Point &pt);
248  void deleteShareEdge(GQ_Edge *edge,
249  GA_PrimitiveGroup *deletePrimGroup=0);
250 
251  void wireEdge(GQ_Edge *edge, fpreal radius,
252  int doCaps);
253  void pointSphere(GQ_Point *pt, fpreal radius);
254 
255  int nEdges() const { return myEdges.entries();}
256  int nFaces() const { return myFaces.entries();}
257  int nPoints() const { return myPoints.entries();}
258  GU_Detail *getDetail() const { return myGdp; }
259  // Only test a point of face
260  int aboveOrBelow(GQ_Face *face);
261 
262  // Methods used by decimation
263  void simpleDecimate(int targetPolys);
264  void decCollapse(GQ_Edge *e, GA_PrimitiveGroup *);
265  void decSplit(GQ_Edge *e);
266  void decSwap(GQ_Edge *e);
267  // End of the decimation methods
268 
269  void save(std::ostream &os) const;
270  friend std::ostream &operator<<(std::ostream &os, const GQ_Detail &d)
271  { d.save(os); return os; }
272 
273  /// Given a GA_Edge, return the equivalent GQ_Edge. Relatively
274  /// efficient: O(degree(org)), not O(nedges)
275  GQ_Edge *findEdge(const GA_Edge *edge,
276  const GU_Detail *edge_gdp);
277  GQ_Edge *findEdge(const GA_Edge *edge)
278  { return findEdge(edge, myGdp); }
279  GQ_Edge *findEdge(const GQ_Point *org, const GQ_Point *dest);
280  GA_Offset stepForwardOffset(const GA_Edge *edge);
281 
282  //Returns the first point encountered connected to the org, otherwise
283  //GA_INVALID_OFFSET
284  GA_Offset pickArbitraryConnectedPointOffset(GA_Offset org);
285 
286  //Rotates the edge around a specified origin and resturns the new
287  //destination point
288  GA_Offset rotateAboutOriginOffset(GA_Edge &edge, int dir);
289 
290  // Returns the face that is adjacent to 'face' on the edge indexed by 'edge'
291  GEO_PrimPoly *adjacentFace(const GEO_Face &face, int edge);
292 
293 private:
294  void snapToPlane(UT_Vector3 &norm, fpreal dist);
295  void buildSuperPoints(fpreal distance,
296  const GA_PointGroup *usedpts);
297  /// NOTE: sp and spd1 must both be superpoints!
298  GQ_Edge *findEdgeToShare(GQ_Point *sp, GQ_Point *spd1);
299  GA_PrimitiveGroup *convertToQuadEdge(GA_PrimitiveGroup *,
300  fpreal sp_tol=0.001F);
301  void cleanEdgeToPt(GQ_Point *p);
302  int buildFace(GQ_Face *face);
303  GA_Size getVertexNum(const GQ_Face *face,
304  GA_Offset prevPt,
305  GA_Offset pt) const;
306  void creaseFace(GQ_Face *face, UT_Vector3 &norm,
307  fpreal dist,
308  int outputGroups,
309  GA_PrimitiveGroup *prim_above = 0,
310  GA_PrimitiveGroup *prim_below = 0);
311  void createCreaseFace(GQ_Edge *edge,
312  UT_Vector3 &norm, fpreal dist,
313  int outputGroups,
314  GA_PrimitiveGroup *prim_above = 0,
315  GA_PrimitiveGroup *prim_below = 0);
316  void addIntersectEdges(GQ_Face *face,
317  UT_Vector3 &normal);
318 
319  /// Follows e->lnext() checking if e->org() has flag set, returns true
320  /// if it does. The nonBridge component means when it hits a bridge
321  /// it doesn't follow it, but runs e->oprev() instead.
322  bool nonBridgeLoopHasFlag(GQ_Edge *e,
323  int flag,
324  bool *ok);
325 
326  /// Removes all the bridges on the face that are no longer necessary
327  /// if we connect together points that are GQ_SELECTED.
328  /// The bridges array is filled with any bridge edges that have
329  /// GQ_INTERSECT flag and weren't deleted. (It is hard to get
330  /// this afterwards since you'll no longer have a single face)
331  void removeAllPossibleBridges(GQ_Face *face,
332  UT_Array<GQ_Edge *> &bridges);
333  GQ_Edge * removePossibleBridge(GQ_Edge *bridgeEdge,
334  bool hasisect,
335  int depth,
336  UT_Array<GQ_Edge *> &bridges,
337  bool *ok);
338  void reBridge(UT_Array<GQ_Edge *> &bridges);
339  void reBridgeForCrease(UT_Array<GQ_Edge *>
340  &intersectBridges);
341  UT_Array<GQ_Face *> *split(UT_Vector3 &normal, fpreal distance,
342  int outputGroups = 0,
343  GA_PrimitiveGroup *prim_above = 0,
344  GA_PrimitiveGroup *prim_below = 0);
345  void expandPoint(GQ_Point *pt);
346  void plugGap(GQ_Edge *edge);
347  void shrinkFace(GQ_Face *face, fpreal a, fpreal b);
348  void unHole(GQ_Face *face, int maintain);
349  GQ_Edge * unBridge(GQ_Edge *bridgeEdge, int maintain);
350  void changeGeoPoint(GQ_Face *face, GA_Offset opt,
351  GA_Offset npt, bool all);
352  void uniqueEdge(GQ_Edge *edge);
353  void uniquePoint(GQ_Point *point);
354  void cleanFace(GQ_Face *face);
355  int twoFacesShareAllEdges(GQ_Edge *edge,
356  GA_PrimitiveGroup *deletePrimGroup);
357 
358  // Semi-smooth Catmull-Clark subdivision:
359  void calcFacePoints(int numfaces);
360  void calcEdgePoints(int numedges,
361  GA_Offset *oldEdgeAttribs,
362  bool smoothvertex);
363  void calcVertexPoints(int numpoints,
364  GA_Offset *oldEdgeAttribs,
365  GA_Offset *newVertex,
366  bool smoothvertex);
367 
368  // This has one vertex attribute per point which will be copied in
369  // to all the edge attributes comeing out of that point.
370  void copyVertexAttributeByPoint(int numpoints,
371  GA_Offset *newVertex,
372  gq_SubdivideAttribHandler &ahandler);
373 
374  void copyEdgeVertexAttributes(int numedge);
375  // This is used after the edge attributes are calculated. It will
376  // then set the GQ_VTXBOUNDARY appropriately for all points.
377  void flagVertexBoundaries();
378  void subdivideEdges(int numedges, bool linear);
379  void subdivideFaces(int numfaces,
380  gq_SubdivideAttribHandler &ahandler);
381 
382  // This copies the myEdgeAttribs into the geometrie's polygons:
383  void copyVertexAttributes(int numedges,
384  gq_SubdivideAttribHandler &);
385 
386  void splitPolysWithMultipleHoles(GA_PrimitiveGroup *,
388  gq_SubdivideAttribHandler &);
389  GEO_PrimPoly *findNonSubDivPolyWithEdge(GA_Offset,
390  GA_Offset, GA_PrimitiveGroup *, int &,
391  int &);
392  GEO_PrimPoly *findNonSubDivPolyWithEdge(GA_Offset,
394  void cacheBoundaryEdges(UT_Map<GA_Offset, UT_ValArray<GQ_Edge*>>& pointToEdges) const;
395  GQ_Edge *findBoundEdge(const GQ_Point *, const GQ_Point *,
396  UT_Vector4 &, UT_Vector4 &, int &,
397  const UT_Map<GA_Offset, UT_ValArray<GQ_Edge*>>* pointToEdges);
398  int addSubDivBoundaryPoints(GQ_Edge *, const GQ_Point *,
399  GA_PointGroup *);
400  void createVirtualEdgePoints(const UT_Vector4 &,
401  const UT_Vector4 &, GA_PointGroup *,
402  UT_Vector4Array &);
403  void createActualEdgePoints(const UT_Vector4 &,
404  const UT_Vector4 &, GA_PointGroup *,
405  GA_PointGroup *, gq_SubdivideAttribHandler &);
406  void triangulateNonSubDivPoly(GEO_PrimPoly *,
409  int, gq_SubdivideAttribHandler &);
410  GEO_PrimPoly *dividePolygonContainingEdge(GA_PointGroup *,
412  GA_PrimitiveGroup *, int,
413  GA_Offset &, GA_Offset &,
414  gq_SubdivideAttribHandler &,
415  GEO_PrimPoly *poly = nullptr);
416  void pullHolesUsingBias(GA_PointGroup *,
418  void stitchHoles(GA_PointGroup *, GA_PointGroup *,
419  GEO_PrimPoly *, int, gq_SubdivideAttribHandler &);
420  void pullToEndPoints(GA_PointGroup *, GA_Offset, GA_Offset);
421  void closeHolesAfterSubdivide(UT_Array<GQ_Point *> &,
423  gq_SubdivideAttribHandler &);
424 
425  // Goes through the edges of p and modifies vertex attributes of edges
426  // with a GQ_CUSP flag to make them cusp'd
427  void cuspPoint(GQ_Point *p, const GA_RWHandleV3 &normal_attrib, int i);
428 
429  // Create a point wrangler just-in-time
430  GA_PointWrangler &pointWrangler();
431 
432  // Create a vertex wrangler just-in-time
433  GA_VertexWrangler &vertexWrangler();
434 
435 private:
436 
437  UT_ValArray<GQ_Edge *> myEdges;
438  UT_DoubleArray myEdgeWeights;
439  UT_Array<GQ_Point *> myEdgePoints;
440  UT_ValArray<GQ_Face *> myFaces;
441  UT_Array<GQ_Point *> myPoints;
442  UT_Array<GA_RWAttributeRef> myOffsets;
443  GA_PrimitiveGroup *myGroup; // Primitive group
444  GU_Detail *myGdp;
445  GU_RayIntersect *myRay;
446 
447  GA_PointWrangler *myPointWrangler;
448  GA_VertexWrangler *myVertexWrangler;
449 
450  // This data is used by subdivide:
451  // For most of subdivide, myEdgeAttribs maps edge indices into vertex data,
452  // but in the edge-closing situation it is reinterpreted to map
453  // point numbers into vertex data.
454  GA_AttributeRefMap myHandles;
455  GA_WorkVertexBuffer *myEdgeVertices;
456  GA_WorkVertexBuffer *myFaceVertices;
457 };
458 
459 #endif
GU_Detail * getDetail() const
Definition: GQ_Detail.h:258
GA_API const UT_StringHolder dist
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
#define GQ_API
Definition: GQ_API.h:10
Unsorted map container.
Definition: UT_Map.h:107
UT_ValArray< GQ_Face * > & getFaceList()
Definition: GQ_Detail.h:232
GLenum clamp
Definition: glcorearb.h:1234
int64 exint
Definition: SYS_Types.h:125
const UT_Array< GQ_Point * > & getEdgePoints() const
Definition: GQ_Detail.h:230
void collapseFaceList()
Definition: GQ_Detail.h:222
GLenum src
Definition: glcorearb.h:1793
4D Vector class.
Definition: UT_Vector4.h:172
void buildRay()
Definition: GQ_Detail.h:237
const UT_ValArray< GQ_Edge * > & getEdgeList() const
Definition: GQ_Detail.h:226
const UT_DoubleArray & getEdgeWeights() const
Definition: GQ_Detail.h:228
GLdouble GLdouble t
Definition: glew.h:1403
const UT_ValArray< GQ_Face * > & getFaceList() const
Definition: GQ_Detail.h:233
void save(std::ostream &os) const
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:234
GU_Detail * getGdp()
Definition: GQ_Detail.h:234
GLuint GLuint GLfloat weight
Definition: glew.h:13892
int nFaces() const
Definition: GQ_Detail.h:256
GA_Size GA_Offset
Definition: GA_Types.h:640
const UT_Array< GQ_Point * > & getPointList() const
Definition: GQ_Detail.h:224
UT_Array< GQ_Point * > & getEdgePoints()
Definition: GQ_Detail.h:229
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glcorearb.h:476
GLsizei GLsizei GLfloat distance
Definition: glew.h:13923
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GQ_Edge * findEdge(const GA_Edge *edge)
Definition: GQ_Detail.h:277
UT_Array< GA_RWAttributeRef > & getOffsets()
Definition: GQ_Detail.h:242
A handle to simplify manipulation of multiple attributes.
GLfloat GLfloat p
Definition: glew.h:16656
void collapseEdgeList()
Definition: GQ_Detail.h:221
int nEdges() const
Definition: GQ_Detail.h:255
GQ_BooleanOpType
Definition: GQ_Detail.h:51
const GU_Detail * getGdp() const
Definition: GQ_Detail.h:235
virtual bool smooth(GA_AttributeOperand &d, GA_AttributeOperand &min, GA_AttributeOperand &max, GA_AttributeOperand &t) const
d = SYSsmooth(min, max, t);
fpreal64 fpreal
Definition: SYS_Types.h:277
GQ_Edge * appendEdge()
Definition: GQ_Detail.h:201
GU_RayIntersect * getRay()
Definition: GQ_Detail.h:236
GLboolean GLuint group
Definition: glew.h:2750
GLfloat f
Definition: glcorearb.h:1926
UT_Array< GQ_Point * > & getPointList()
Definition: GQ_Detail.h:223
GLdouble angle
Definition: glew.h:9177
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
friend std::ostream & operator<<(std::ostream &os, const GQ_Detail &d)
Definition: GQ_Detail.h:270
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:29
bool all(const vbool4 &v)
Definition: simd.h:3467
UT_DoubleArray & getEdgeWeights()
Definition: GQ_Detail.h:227
GLenum GLuint GLint GLenum face
Definition: glew.h:4630
constexpr T normalize(UT_FixedVector< T, D > &a) noexcept
UT_ValArray< GQ_Edge * > & getEdgeList()
Definition: GQ_Detail.h:225
int nPoints() const
Definition: GQ_Detail.h:257