HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GU_SubDivPatch.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_SubDivPatch.h ( GU Library, C++)
7  *
8  * COMMENTS: Patch-based subdivision shared between mantra and the
9  * subdivide SOP
10  */
11 
12 #ifndef __GU_SubDivPatch_h__
13 #define __GU_SubDivPatch_h__
14 
15 #include "GU_API.h"
16 #include "GU_SubDivPacking.h"
17 #include <GA/GA_ElementGroup.h>
18 #include <GA/GA_OffsetList.h>
19 #include <GA/GA_Types.h>
20 #include <UT/UT_Assert.h>
21 #include <UT/UT_Array.h>
22 #include <UT/UT_IntArray.h>
23 #include <SYS/SYS_Types.h>
24 #include <SYS/SYS_Math.h>
25 #include <stddef.h>
26 
27 class GU_Detail;
28 class GU_SubDivVertex;
29 class GU_SubDivPatch;
30 class GEO_Primitive;
31 
32 ///
33 /// A subdivision edge for user-driven subdivision. The edge stores hard
34 /// edge information including weights and per-vertex hard flags. Edges
35 /// are destroyed when either attached vertex is destroyed.
36 ///
37 
38 static const uint8 SUBD_HARD_EDGE = 0x01;
39 static const uint8 SUBD_LINEAR_CREASES = 0x02;
40 
42 {
43 public:
45  const GU_SubDivEdge *parent = 0);
46  ~GU_SubDivEdge();
47 
48  /// Calculate the new subdivision point using the catmull-clark masks.
49  void catclarkChild();
51  {
52  if (!myChild)
53  catclarkChild();
54  return myChild;
55  }
56 
57  /// Return the other vertex
59  {
60  return (vtx == myVertex[0]) ?
61  myVertex[1] : myVertex[0];
62  }
63 
64  void setFlag(uint8 f) { myFlag |= f; }
65  void clearFlag(uint8 f) { myFlag &= ~f; }
66  bool getFlag(uint8 f) const { return myFlag & f; }
67 
68  void setWeight(fpreal weight) { myWeight = weight; }
69  fpreal getWeight() const { return myWeight; }
70  bool isHardVertex() const { return myHardVertex; }
71  void initHardVertex(int size)
72  {
73  if (!myHardVertex)
74  myHardVertex = new uint8[size];
75  }
77  {
78  if (!myHardVertex)
79  {
80  myHardVertex = new uint8[sizes.entries()];
81  for (exint i = 0; i < sizes.entries(); i++)
82  myHardVertex[i] = sizes(i);
83  }
84  }
85  void setHardVertex(int i)
86  { myHardVertex[i] = getHardVertexSize(i) | 0x80; }
87  void clearHardVertex(int i)
88  { myHardVertex[i] = getHardVertexSize(i); }
89  bool getHardVertex(int i) const
90  { return myHardVertex ? myHardVertex[i] & 0x80 : 0; }
91  int getHardVertexSize(int i) const
92  { return myHardVertex ? myHardVertex[i] & 0x7F : 0; }
93  int getHardVertexCount(int vcount) const
94  {
95  int i, off;
96  for (i = 0, off = 0; off < vcount; i++)
97  off += getHardVertexSize(i);
98  return i;
99  }
100 
101 private:
102  GU_SubDivEdge() {}
103 
104 private:
105  GU_SubDivVertex *myChild;
106  GU_SubDivVertex *myVertex[2];
107  uint8 *myHardVertex;
108  fpreal myWeight;
109  uint8 myFlag;
110 };
111 
112 ///
113 /// A subdivision vertex for user-driven subdivision. Vertices hold the
114 /// subdivision data as well as references to edges and faces.
115 ///
116 
117 static const uint8 SUBD_VTX_COMPLETE = 0x01;
118 static const uint8 SUBD_VTX_VTXSET = 0x02;
119 static const uint8 SUBD_VTX_MARK = 0x04;
120 
122 {
123 public:
124  static GU_SubDivVertex *allocVertex(int valence, int datasize,
125  int vertexsize);
126  static GU_SubDivVertex *allocVertex(const GU_SubDivVertex &src);
127  static void freeVertex(GU_SubDivVertex *vtx);
128 
129  void incRefCount() { myRefCount++; }
130  void decRefCount()
131  {
132  myRefCount--;
133  UT_ASSERT(myRefCount >= 0);
134  if (myRefCount <= 0)
135  freeVertex(this);
136  }
137 
138  void setNum(GA_Index num) { myGeoNum = num; }
139  GA_Index getNum() const { return myGeoNum; }
140 
141  /// Adds vtx at the specified position in my edge table. If idx == -1,
142  /// then add vtx to the next available position. Returns the edge.
143  GU_SubDivEdge *setEdge(GU_SubDivVertex *vtx, int idx = -1,
144  GU_SubDivEdge *parent = 0);
145  void setEdge(GU_SubDivEdge *edge, int idx)
146  { myEdges[idx] = edge; }
147  void clearEdge(GU_SubDivEdge *edge);
148 
149  /// Remove an edge from this vertex at the given index. This operation
150  /// may change the valence.
151  void removeEdge(int idx);
152 
153  /// Add the face to the specified position in my face table. If idx ==
154  /// -1, then we'll analyse the edges in the face to decide where to
155  /// put it.
156  void setFace(GU_SubDivPatch *face, int idx = -1);
157  void clearFace(GU_SubDivPatch *face);
158 
159  /// Set and get completion status. We're complete when all our
160  /// neighbouring edges and faces are defined.
161  void setAllIncomplete();
162  void copyIncomplete(const GU_SubDivVertex *vtx);
163  void setComplete(int i) { myFaces[i] = 0; }
164 
165  /// Get subdivision data associated with this vertex
166  float *getData() const { return myData; }
167 
168  /// Get per-face vertex data if it exists. You should use
169  /// getFaceIndex() to retrieve the face index to be passed to this
170  /// operation.
171  float *getVertexData(int fidx) const;
172 
173  /// Set vertex data. The index is a face identifier in the current
174  /// vertex. If a vertex seam is detected, we'll allocate separate
175  /// face vertex data. The offset array is used to isolate individual
176  /// vertex attributes so that we can have an independent hard edge mask
177  /// for each attribute. The offsets are in number of floats and point
178  /// to the start of each attribute.
179  void setVertexData(const float *data, int idx,
180  const UT_IntArray &offsets);
181 
182  /// Resets the vertex data at off to the default values.
183  void defaultVertexData(int low, int high);
184 
185  int getSize() const { return myFloatCount; }
186  int getVertexSize() const { return myVertexCount; }
187 
188  /// Operations used to build new data from subdivision rules
189  void sum(const GU_SubDivVertex *vtx, fpreal scale = 1)
190  {
191  for (int i = 0; i < myFloatCount; i++)
192  myData[i] += vtx->myData[i] * scale;
193  }
194  void sum(const GU_SubDivVertex *vtx,
195  const GU_SubDivPatch *face, fpreal scale = 1);
196  void sumVertex(const GU_SubDivVertex *vtx,
197  const GU_SubDivPatch *face, int idx,
198  int low = 0, int high = -1,
199  fpreal scale = 1);
201  {
202  for (int i = 0; i < myFloatCount; i++)
203  myData[i] *= scale;
204  }
205  void scaleVertex(fpreal scale,
206  int low = 0, int high = -1);
207  void copyVertex(int src, int dest, int low = 0, int high = -1);
208 
209  // Get vertex and face connectivity.
210  void getVertices(UT_Array<GU_SubDivVertex *> &list);
211  void getFaces(UT_Array<GU_SubDivPatch *> &list,
212  const GU_SubDivPatch *face) const;
213 
214  /// Calculate the new subdivision point using the catmull-clark masks.
216  {
217  if (!myChild)
218  catclarkChild(false);
219  return myChild;
220  }
221 
222  /// Calculate the limit subdivision point using the catmull-clark
223  /// masks. If you use this operation, further subdivision using this
224  /// vertex will not produce the correct result.
226  {
227  if (!myChild)
228  catclarkChild(true);
229  return myChild;
230  }
231 
232  int getEdgeIndex(const GU_SubDivVertex *vtx) const;
233  GU_SubDivEdge *getEdge(int idx) const { return myEdges[idx]; }
235  {
236  int idx = getEdgeIndex(vtx);
237  return idx >= 0 ? myEdges[idx] : 0;
238  }
240  { return getEdge(vtx)->getChild(); }
241 
242  int getFaceIndex(const GU_SubDivPatch *face) const;
243  GU_SubDivPatch *getFace(int idx) const { return myFaces[idx]; }
244  bool hasFace(const GU_SubDivPatch *face) const
245  { return getFaceIndex(face) >= 0; }
246 
247  int getValence() const { return myValence; }
248  bool hasHardEdge() const;
249 
250  /// Order the edges using the face set for this vertex
251  void sortEdges();
252  void setWeight(fpreal weight, bool linear,
253  const GU_SubDivPatch *face);
254 
255  void setFlag(uint8 f) { myFlag |= f; }
256  void clearFlag(uint8 f) { myFlag &= ~f; }
257  bool getFlag(uint8 f) const { return myFlag & f; }
258 
259  /// Dump geometry for the vertex as a draw file
260  void dumpGeo(char c, const GU_SubDivPatch *face = 0) const;
261 
262 protected:
263  void catclarkRule(GU_SubDivVertex *dest,
264  int creaseidx[2], int hcount,
265  bool limit);
266  void catclarkRuleVertex(GU_SubDivVertex *dest,
267  int creaseidx[2], int hcount,
268  int low, int high,
269  bool limit);
270 
271 private:
272  GU_SubDivVertex() {}
273  ~GU_SubDivVertex() {}
274 
275  void catclarkChild(bool limit);
276 
277 private:
278  GU_SubDivVertex *myChild;
279  GU_SubDivEdge **myEdges;
280  GU_SubDivPatch **myFaces;
281  float *myData;
282  float *myVertexData; // Optional for vtx boundary
283  int myValence;
284  int myRefCount;
285  int myFloatCount; // myData size
286  int myVertexCount; // myVertexData size
287  GA_Index myGeoNum; // GEO point number
288  uint8 myFlag;
289 };
290 
291 ///
292 /// A subdivision patch for user-driven subdivision. Patches can be
293 /// subdivided in any order, and should be freed by decrementing the
294 /// reference count in the caller. Creation automatically initializes the
295 /// reference count to 1. You should not increment the reference count.
296 ///
297 
298 static const uint8 SUBD_PATCH_LIVE = 0x01;
299 static const uint8 SUBD_PATCH_REVERSE = 0x02;
300 static const uint8 SUBD_PATCH_MARK = 0x04;
301 
303 {
304 public:
305  static GU_SubDivPatch *allocPatch(
306  const UT_Array<GU_SubDivVertex *> &vertices, bool islive);
307  static void freePatch(GU_SubDivPatch *patch);
308 
309  void decRefCount();
310  int getRefCount() { return myRefCount; }
311 
312  ///
313  /// Catmull-clark subdivision
314  ///
315  /// Perform subdivision on this patch, creating a new set of
316  /// subpatches. The caller attains ownership of the patches.
317  ///
318  void catclark(UT_Array<GU_SubDivPatch *> &patches);
319 
320  /// Return the face centroid
322  {
323  if (!myChild)
324  catclarkChild();
325  return myChild;
326  }
327 
328  /// Return the number of edges and vertices bordering this patch.
329  int getValence() const { return myValence; }
330  /// Return the next vertex after vtx
331  GU_SubDivVertex *getNextVertex(GU_SubDivVertex *vtx) const;
332  GU_SubDivVertex *getPrevVertex(GU_SubDivVertex *vtx) const;
333 
334  /// If we're a bezier, returns the bezier hull. The correct vertex
335  /// attribute associations are returned in the vtxdata array. If we're
336  /// not a bezier, false is returned.
337  bool getBezier(UT_Array<GU_SubDivVertex *> &vtx,
338  UT_Array<float *> &vtxdata) const;
339  /// Get internal and external vertices bordering this patch
340  void getVertices(UT_Array<GU_SubDivVertex *> &vtx) const;
341  GU_SubDivVertex *getVertex(int i) const { return myVertex[i]; }
342  void getFaceRing(UT_Array<GU_SubDivPatch *> &list) const;
343 
344  /// Make an independent copy of this patch with new vertices and edges
345  GU_SubDivPatch *copy() const;
346 
347  /// Live patches are allowed to be externally referenced and keep
348  /// additional references to the surrounding ring of patches so that
349  /// all the data required for subdivision is available.
350  void makeLive();
351  bool isLive() const { return myFlag & SUBD_PATCH_LIVE; }
352 
353  /// Reverse the vertex order for this patch. We'll keep a flag to
354  /// determine whether it is flipped relative to the original geometry.
355  void reverse();
356 
357  /// Dump geometry for the patch as a draw file
358  void dumpGeo() const;
359 
360  void setFlag(uint8 f) { myFlag |= f; }
361  void clearFlag(uint8 f) { myFlag &= ~f; }
362  void toggleFlag(uint8 f) { myFlag ^= f; }
363  bool getFlag(uint8 f) const { return myFlag & f; }
364 
365 protected:
367  {
368  myRefCount--;
369  UT_ASSERT(myRefCount >= 0);
370  if (myRefCount == 0)
371  freePatch(this);
372  }
373 
374  /// Creates subpatches within this patch. If a face is supplied, we'll
375  /// only construct subpatches on the boundary with the face.
376  void catclarkPatches(GU_SubDivPatch *face = 0);
377 
378 private:
379  GU_SubDivPatch() {}
380  ~GU_SubDivPatch() {}
381 
382  void incRefCount() { myRefCount++; }
383  void catclarkChild();
384 
385 private:
386  GU_SubDivPatch **mySubPatches;
387  GU_SubDivVertex *myChild;
388  GU_SubDivVertex **myVertex;
389  int myValence;
390  int myRefCount;
391  uint8 myFlag;
392 };
393 
394 /// An interface for constructing a set of patches from geometry
396 {
397 public:
398  /// Given a set of motion blur details, create the subdivision patch
399  /// representation.
400  GU_SubDivPatchSet(const GU_Detail *detail,
401  const GU_SubDivPacking &ptattribs,
402  const GU_SubDivPacking &vtxattribs,
403  bool linearcreases = false,
404  const GA_PrimitiveGroup *primgroup=NULL);
406 
407  void stealPatches(UT_Array<GU_SubDivPatch *> &patches);
408 
409  GU_SubDivPatch *getPatch(exint i) const;
410  const GEO_Primitive *getGEOPrimitive(exint i) const;
411  GA_Size getSoupPolygon(exint i ) const;
412 
413  /// Perform subdivision on the geometry. The @c gdp is modified so the
414  /// original polygons are deleted and replaced with the Catmull-Clark
415  /// subdivision representation.
416  static void catclark(GU_Detail *gdp,
417  int depth,
418  const GA_PrimitiveGroup *group,
419  bool linear_creases,
420  bool build_polysoups);
421 
423  { return myPointPacking; }
425  { return myVertexPacking; }
426 
427 private:
428  void processFace(const GEO_Primitive *prim,
429  const UT_Array<GU_SubDivVertex *> &vertices);
430  void processSoup(const GEO_Primitive *prim,
431  const UT_Array<GU_SubDivVertex *> &vertices);
432  bool addFace(GA_Offset primoff,
433  const UT_Array<GA_Offset> &gfacevtx,
434  const UT_Array<GU_SubDivVertex *> &vertices,
435  GA_Size souppolygon);
436 
437  const GU_Detail *myDetail;
438  UT_Array<GU_SubDivPatch *> myPatches;
439  GA_OffsetList myGEOPrims;
440  GA_ListType<GA_Size,GA_Size> mySoupPolygons;
441  GU_SubDivPacking myPointPacking;
442  GU_SubDivPacking myVertexPacking;
443 };
444 
445 #endif
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
Definition: glcorearb.h:2620
bool getFlag(uint8 f) const
void initHardVertex(int size)
void decRefCountInternal()
void setEdge(GU_SubDivEdge *edge, int idx)
GU_SubDivVertex * getOther(const GU_SubDivVertex *vtx) const
Return the other vertex.
GU_SubDivVertex * getChild()
Calculate the new subdivision point using the catmull-clark masks.
GU_SubDivVertex * getChild()
bool isHardVertex() const
int getValence() const
Return the number of edges and vertices bordering this patch.
void sum(const GU_SubDivVertex *vtx, fpreal scale=1)
Operations used to build new data from subdivision rules.
void setFlag(uint8 f)
int getValence() const
GA_Index getNum() const
bool getFlag(uint8 f) const
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:817
png_uint_32 i
Definition: png.h:2877
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:211
void setFlag(uint8 f)
GLsizeiptr size
Definition: glcorearb.h:663
void setComplete(int i)
GLuint GLsizei const GLuint const GLintptr * offsets
Definition: glcorearb.h:2620
int getVertexSize() const
GA_Size GA_Offset
Definition: GA_Types.h:617
const GU_SubDivPacking & getPointPacking() const
GA_API const UT_StringHolder scale
GLfloat f
Definition: glcorearb.h:1925
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glcorearb.h:475
void setWeight(fpreal weight)
float * getData() const
Get subdivision data associated with this vertex.
void clearFlag(uint8 f)
bool getHardVertex(int i) const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:102
void toggleFlag(uint8 f)
int64 exint
Definition: SYS_Types.h:115
void setFlag(uint8 f)
fpreal getWeight() const
GU_SubDivVertex * getVertex(int i) const
GU_SubDivEdge * getEdge(const GU_SubDivVertex *vtx) const
GU_SubDivVertex * getChild()
Return the face centroid.
void clearFlag(uint8 f)
void setHardVertex(int i)
GU_SubDivVertex * getLimit()
void clearFlag(uint8 f)
#define GU_API
Definition: GU_API.h:11
GLboolean * data
Definition: glcorearb.h:130
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:611
void scale(fpreal scale)
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:446
double fpreal
Definition: SYS_Types.h:269
GU_SubDivEdge * getEdge(int idx) const
int getSize() const
unsigned char uint8
Definition: SYS_Types.h:31
void setNum(GA_Index num)
GLfloat GLfloat v1
Definition: glcorearb.h:816
GU_SubDivPatch * getFace(int idx) const
bool getFlag(uint8 f) const
const GU_SubDivPacking & getVertexPacking() const
bool hasFace(const GU_SubDivPatch *face) const
png_infop png_uint_32 int num
Definition: png.h:2158
void initHardVertex(const UT_IntArray &sizes)
GU_SubDivVertex * getEdgeChild(const GU_SubDivVertex *vtx) const
int getHardVertexSize(int i) const
void clearHardVertex(int i)
int getHardVertexCount(int vcount) const
An interface for constructing a set of patches from geometry.
bool isLive() const
GLenum src
Definition: glcorearb.h:1792