HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_Grid.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_Grid.h
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #pragma once
13 
14 #ifndef __GU_GRID__
15 #define __GU_GRID__
16 
17 #include "GU_API.h"
18 #include "GU_Types.h"
19 #include <GEO/GEO_SurfaceType.h>
20 #include <GA/GA_Types.h>
21 #include <UT/UT_Assert.h>
22 #include <UT/UT_UniquePtr.h>
23 #include <SYS/SYS_Types.h>
24 
26 {
27 public:
28  GU_GridParms();
29 
30  int rows, cols;
31  float xsize, ysize;
32  float xcenter, ycenter, zcenter;
35  int interpEndsU, interpEndsV;
36  int orderU, orderV;
37 };
38 
39 
40 template<typename INT_TYPE=GA_Offset>
41 struct GU_GridT
42 {
43  /// These are the number of edge rows and edge columns.
44  /// @{
47  /// @}
48 
49  /// These members specify the points of the grid
50  /// @{
51  INT_TYPE myCorners[4];
52  INT_TYPE myRow0Start;
53  union {
54  INT_TYPE myRow0Step;
55  INT_TYPE *myRow0Array;
56  };
57  INT_TYPE myRow1Start;
58  union {
59  INT_TYPE myRow1Step;
60  INT_TYPE *myRow1Array;
61  };
62  INT_TYPE myCol0Start;
63  union {
64  INT_TYPE myCol0Step;
65  INT_TYPE *myCol0Array;
66  };
67  INT_TYPE myCol1Start;
68  union {
69  INT_TYPE myCol1Step;
70  INT_TYPE *myCol1Array;
71  };
72  INT_TYPE myMiddleStart;
73  INT_TYPE myMiddleColStep;
74  INT_TYPE myMiddleRowStep;
75  /// @}
76 
78 
79  enum class PrimitiveType : unsigned char {
80  POLYGON,
81  MESH,
82  NURBS,
83  BEZIER,
84  POLYSOUP,
85  POINTS
86  };
87 
89 
90  /// NOTE: Basis orders for NURBS and Bezier surfaces must be in the range
91  /// [2,GA_MAX_ORDER], which fits in 4 bits, since GA_MAX_ORDER==11.
92  unsigned char myBasisOrderU:4;
93  unsigned char myBasisOrderV:4;
95 
96  /// If mySurfaceType is rows, cols, or rows and cols, and a particular
97  /// row or column wraps around (row0[col]==row1[col] or col0[row]==col1[row]),
98  /// This indicates to create an open curve with an extra vertex (if true),
99  /// instead of a closed polygon (if false).
101 
102  /// If mySurfaceType is rows or rows and cols, and columns aren't wrapped,
103  /// if this is true, the first row is present (the usual), else it's not
104  /// (e.g. the grid might be connected to an existing mesh).
106 
107  /// If mySurfaceType is rows or rows and cols, and columns aren't wrapped,
108  /// if this is true, the final row is present (the usual), else it's not
109  /// (e.g. the grid might be connected to an existing mesh).
111 
112  /// If mySurfaceType is cols or rows and cols, and rows aren't wrapped,
113  /// if this is true, the first col is present (the usual), else it's not
114  /// (e.g. the grid might be connected to an existing mesh).
116 
117  /// If mySurfaceType is cols or rows and cols, and rows aren't wrapped,
118  /// if this is true, the final col is present (the usual), else it's not
119  /// (e.g. the grid might be connected to an existing mesh).
121 
122  /// If adjacent points on the boundary are equal, and mySurfaceType is
123  /// one of the triangle options or quads, the appropriate polygons
124  /// will be simple triangles, instead of quads or pairs of triangles.
125  /// If a boundary quad becomes fully degenerate, no polygon will be output
126  /// for it.
128 
129  /// If myPrimitiveType is NURBS or BEZIER, and mySurfaceType is
130  /// GEO_PATCH_ROWS or GEO_PATCH_COLS or GEO_PATCH_ROWCOL, this
131  /// indicates whether to create separate curve primitives (true),
132  /// or a surface primitive with its surface type set correspondingly.
134 
135  /// NOTE: The following members are cached values computed from the members
136  /// above, not used for input.
137  /// After setting the other members, either precompute() must be
138  /// called or these members must be manually set, before any other
139  /// functions can be called.
140  /// @{
141  bool myAllWrapU:1;
142  bool myAllWrapV:1;
143  bool myNoWrapU:1;
144  bool myNoWrapV:1;
147  /// @}
148 
149  /// NOTE: The bools can't be in-class initialized, since they're bitfields,
150  /// and the C++ standard evidently missed the case of bitfields.
151  /// NOTE: The row and col starts are non-negative, so that destructing
152  /// a default constructed grid won't crash.
154  : myRow0Start(0)
155  , myRow1Start(0)
156  , myCol0Start(0)
157  , myCol1Start(0)
159  , myPrimitiveType(PrimitiveType::POLYGON)
160  , myUnrollCurves(false)
161  , myFirstRowIfNotWrapped(true)
162  , myLastRowIfNotWrapped(true)
163  , myFirstColIfNotWrapped(true)
164  , myLastColIfNotWrapped(true)
165  , myTriangularPoles(false)
166  , myCurvesIfBasisRowCol(false)
167  {}
168  ~GU_GridT() { clear(); }
169 
170  /// This computes myAllWrapU, myAllWrapV, myNoWrapU, and myNoWrapV
171  /// after everything else is set.
172  void precompute();
173 
174  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
175  /// myFirstRowIfNotWrapped, myLastRowIfNotWrapped, myFirstColIfNotWrapped,
176  /// and myLastColIfNotWrapped if rows/cols/rowcol.
177  /// NOTE: You don't need to call precompute() after this.
178  void initSingleGrid(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0));
179 
180  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
181  /// myFirstRowIfNotWrapped, myLastRowIfNotWrapped,
182  /// and myUnrollCurves if rows/cols/rowcol.
183  /// NOTE: You don't need to call precompute() after this.
184  void initColTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0));
185 
186  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
187  /// myFirstColIfNotWrapped, myLastColIfNotWrapped,
188  /// and myUnrollCurves if rows/cols/rowcol.
189  /// NOTE: You don't need to call precompute() after this.
190  void initRowTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0));
191 
192  /// This is the sphere most people expect, with north and south poles (row=0/nedgerows).
193  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
194  /// myFirstRowIfNotWrapped, myLastRowIfNotWrapped,
195  /// and myUnrollCurves if rows/cols/rowcol, or
196  /// myTriangularPoles if quads/tris.
197  /// NOTE: You'll probably want to set myFirstRowIfNotWrapped and
198  /// myLastRowIfNotWrapped to false, to match the Sphere SOP.
199  /// NOTE: You don't need to call precompute() after this.
200  void initColSphere(exint nedgerows, exint nedgecols,
201  INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1),
202  INT_TYPE start_mid_pt=INT_TYPE(2));
203 
204  /// This is the sphere most people DON'T expect, with east and west poles (col=0/nedgecols).
205  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
206  /// myFirstColIfNotWrapped, myLastColIfNotWrapped,
207  /// and myUnrollCurves if rows/cols/rowcol, or
208  /// myTriangularPoles if quads/tris.
209  /// NOTE: You'll probably want to set myFirstColIfNotWrapped and
210  /// myLastColIfNotWrapped to false, to match the Sphere SOP.
211  /// NOTE: You don't need to call precompute() after this.
212  void initRowSphere(exint nedgerows, exint nedgecols,
213  INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1),
214  INT_TYPE start_mid_pt=INT_TYPE(2));
215 
216  /// This is effectively a slice of a col sphere, with north and south poles (row=0/nedgerows).
217  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
218  /// myFirstRowIfNotWrapped, myLastRowIfNotWrapped,
219  /// and myUnrollCurves if rows/cols/rowcol, or
220  /// myTriangularPoles if quads/tris.
221  /// NOTE: You'll probably want to set myFirstRowIfNotWrapped and
222  /// myLastRowIfNotWrapped to false, to match the Sphere SOP.
223  /// NOTE: You don't need to call precompute() after this.
224  void initSplitColSphere(exint nedgerows, exint nedgecols,
225  INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1),
226  INT_TYPE start_mid_pt=INT_TYPE(2));
227 
228  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
229  /// myUnrollCurves if rows/cols/rowcol.
230  /// NOTE: You don't need to call precompute() after this.
231  void initTorus(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0));
232 
233  /// NOTE: mySurfaceType & myPrimitiveType must be set before calling, and so should
234  /// myFirstRowIfNotWrapped, myLastRowIfNotWrapped,
235  /// and myUnrollCurves if rows/cols/rowcol, or
236  /// myTriangularPoles if quads/tris.
237  /// NOTE: You'll probably want to set myFirstRowIfNotWrapped or
238  /// myLastRowIfNotWrapped to false, depending on row0_pole.
239  /// NOTE: You don't need to call precompute() after this.
240  void initColCone(exint nedgerows, exint nedgecols, bool row0_pole=true,
241  INT_TYPE start_pt=INT_TYPE(0), INT_TYPE start_mid_pt=INT_TYPE(1));
242 
243  /// Free memory allocations owned by this.
244  /// NOTE: This intentionally does not clear myPrimitiveType,
245  /// mySurfaceType, myBasisOrderU, myBasisOrderV, or myUnrollCurves.
246  void clear()
247  {
248  if (myRow0Start < INT_TYPE(0))
249  {
250  delete [] myRow0Array;
251  myRow0Start = INT_TYPE(0);
252  }
253  if (myRow1Start < INT_TYPE(0))
254  {
255  delete [] myRow1Array;
256  myRow1Start = INT_TYPE(0);
257  }
258  if (myCol0Start < INT_TYPE(0))
259  {
260  delete [] myCol0Array;
261  myCol0Start = INT_TYPE(0);
262  }
263  if (myCol1Start < INT_TYPE(0))
264  {
265  delete [] myCol1Array;
266  myCol1Start = INT_TYPE(0);
267  }
268  }
269 
270  INT_TYPE getPoint(exint row, exint col) const
271  {
272  UT_ASSERT_P(row >= 0 && row <= myNumEdgeRows);
273  UT_ASSERT_P(col >= 0 && col <= myNumEdgeCols);
274  if (row == 0)
275  {
276  if (col == 0)
277  return myCorners[0];
278  if (col == myNumEdgeCols)
279  return myCorners[1];
280  --col;
281  return (myRow0Start < INT_TYPE(0)) ? myRow0Array[col] : (myRow0Start + myRow0Step*col);
282  }
283  if (row == myNumEdgeRows)
284  {
285  if (col == 0)
286  return myCorners[2];
287  if (col == myNumEdgeCols)
288  return myCorners[3];
289  --col;
290  return (myRow1Start < INT_TYPE(0)) ? myRow1Array[col] : (myRow1Start + myRow1Step*col);
291  }
292  --row;
293  if (col == 0)
294  return (myCol0Start < INT_TYPE(0)) ? myCol0Array[row] : (myCol0Start + myCol0Step*row);
295  if (col == myNumEdgeCols)
296  return (myCol1Start < INT_TYPE(0)) ? myCol1Array[row] : (myCol1Start + myCol1Step*row);
297  --col;
298  return myMiddleStart + myMiddleRowStep*row + myMiddleColStep*col;
299  }
300 
301  bool doesRowWrap(exint row) const
302  {
303  if (row == 0)
304  return myCorners[0] == myCorners[1];
305  if (row == myNumEdgeRows)
306  return myCorners[2] == myCorners[3];
307  UT_ASSERT_P(row > 0 && row < myNumEdgeRows);
308  --row;
309  INT_TYPE pt0 = (myCol0Start < INT_TYPE(0)) ? myCol0Array[row] : (myCol0Start + myCol0Step*row);
310  INT_TYPE pt1 = (myCol1Start < INT_TYPE(0)) ? myCol1Array[row] : (myCol1Start + myCol1Step*row);
311  return pt0 == pt1;
312  }
313  bool doesColWrap(exint col) const
314  {
315  if (col == 0)
316  return myCorners[0] == myCorners[2];
317  if (col == myNumEdgeCols)
318  return myCorners[1] == myCorners[3];
319  UT_ASSERT_P(col > 0 && col < myNumEdgeCols);
320  --col;
321  INT_TYPE pt0 = (myRow0Start < INT_TYPE(0)) ? myRow0Array[col] : (myRow0Start + myRow0Step*col);
322  INT_TYPE pt1 = (myRow1Start < INT_TYPE(0)) ? myRow1Array[col] : (myRow1Start + myRow1Step*col);
323  return pt0 == pt1;
324  }
325 
326  // Adjusts the points of the grid such that the effective starting point is different.
327  void shiftPoints(INT_TYPE shift)
328  {
329  for (int i = 0; i < 4; ++i)
330  myCorners[i] += shift;
331 
332  if (myRow0Start >= INT_TYPE(0))
333  myRow0Start += shift;
334  else
335  {
336  for (exint col = 1; col < myNumEdgeCols; ++col)
337  myRow0Array[col-1] += shift;
338  }
339  if (myRow1Start >= INT_TYPE(0))
340  myRow1Start += shift;
341  else
342  {
343  for (exint col = 1; col < myNumEdgeCols; ++col)
344  myRow1Array[col-1] += shift;
345  }
346  if (myCol0Start >= INT_TYPE(0))
347  myCol0Start += shift;
348  else
349  {
350  for (exint row = 1; row < myNumEdgeRows; ++row)
351  myCol0Array[row-1] += shift;
352  }
353  if (myCol1Start >= INT_TYPE(0))
354  myCol1Start += shift;
355  else
356  {
357  for (exint row = 1; row < myNumEdgeRows; ++row)
358  myCol1Array[row-1] += shift;
359  }
360  myMiddleStart += shift;
361  }
362 
363  bool isInvalidTPSurf() const
364  {
365  const bool is_nurbs = (myPrimitiveType == PrimitiveType::NURBS);
366  const bool is_bezier = (myPrimitiveType == PrimitiveType::BEZIER);
367 
368  if (!is_nurbs && !is_bezier)
369  return false;
370 
371  // If number of row vertices or col vertices is smaller than
372  // the corresponding basis order, reject this grid.
374  exint nvtxcols = myNumEdgeCols + exint(myNoWrapU || myUnrollCurves);
375  if (nvtxrows < myBasisOrderV || nvtxcols < myBasisOrderU)
376  return true;
377  // Beziers need the edge count along an axis to be a multiple of (order-1)
378  if (is_bezier && ((myNumEdgeRows % (myBasisOrderV-1)) != 0 || (myNumEdgeCols % (myBasisOrderU-1)) != 0))
379  return true;
380  return false;
381  }
382 
383  void fixTPSurf()
384  {
385  const bool is_nurbs = (myPrimitiveType == PrimitiveType::NURBS);
386  const bool is_bezier = (myPrimitiveType == PrimitiveType::BEZIER);
387  if (!is_nurbs && !is_bezier)
388  return;
389 
390  // Order must be between 2 and GA_MAX_ORDER (inclusive).
393 
394  // If number of row vertices or col vertices is smaller than
395  // the corresponding basis order, increase it.
396  const exint nvtxrows = myNumEdgeRows + exint(myNoWrapV || myUnrollCurves);
397  const exint nvtxcols = myNumEdgeCols + exint(myNoWrapU || myUnrollCurves);
398  if (nvtxrows < myBasisOrderV)
399  myNumEdgeRows += myBasisOrderV-nvtxrows;
400  if (nvtxcols < myBasisOrderU)
401  myNumEdgeCols += myBasisOrderU-nvtxcols;
402  if (is_bezier)
403  {
404  // Beziers need the edge count along an axis to be a multiple of (order-1)
405  const exint row_excess = myNumEdgeRows % (myBasisOrderV-1);
406  const exint col_excess = myNumEdgeCols % (myBasisOrderU-1);
407  if (row_excess != 0)
408  myNumEdgeRows += (myBasisOrderV-1) - row_excess;
409  if (col_excess != 0)
410  myNumEdgeCols += (myBasisOrderU-1) - col_excess;
411  }
412  }
413 };
414 
416 
417 #endif
void initColTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
Definition: GU_GridImpl.h:1184
INT_TYPE myMiddleRowStep
Definition: GU_Grid.h:74
INT_TYPE myCol0Step
Definition: GU_Grid.h:64
GU_GridT()
Definition: GU_Grid.h:153
unsigned char myBasisOrderU
Definition: GU_Grid.h:92
#define GA_MAX_ORDER
Definition: GA_Types.h:185
INT_TYPE myRow1Start
Definition: GU_Grid.h:57
bool myNoWrapU
Definition: GU_Grid.h:143
bool myFirstRowIfNotWrapped
Definition: GU_Grid.h:105
int64 exint
Definition: SYS_Types.h:125
bool myCurvesIfBasisRowCol
Definition: GU_Grid.h:133
INT_TYPE myRow0Step
Definition: GU_Grid.h:54
INT_TYPE * myCol1Array
Definition: GU_Grid.h:70
bool myFirstColIfNotWrapped
Definition: GU_Grid.h:115
void initColCone(exint nedgerows, exint nedgecols, bool row0_pole=true, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE start_mid_pt=INT_TYPE(1))
exint myNumEdgeCols
Definition: GU_Grid.h:46
GEO_SurfaceType type
Definition: GU_Grid.h:34
INT_TYPE * myCol0Array
Definition: GU_Grid.h:65
int interpEndsV
Definition: GU_Grid.h:35
INT_TYPE * myRow0Array
Definition: GU_Grid.h:55
INT_TYPE myRow0Start
Definition: GU_Grid.h:52
bool myTriangularPoles
Definition: GU_Grid.h:127
INT_TYPE myCorners[4]
Definition: GU_Grid.h:51
INT_TYPE myCol1Step
Definition: GU_Grid.h:69
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:134
bool myAllWrapU
Definition: GU_Grid.h:141
GU_OrientationType plane
Definition: GU_Grid.h:33
UT_Vector3T< T > SYSclamp(const UT_Vector3T< T > &v, const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
Definition: UT_Vector3.h:836
void clear()
Definition: GU_Grid.h:246
bool myUnrollCurves
Definition: GU_Grid.h:100
bool isInvalidTPSurf() const
Definition: GU_Grid.h:363
INT_TYPE * myRow1Array
Definition: GU_Grid.h:60
void precompute()
Definition: GU_GridImpl.h:1006
#define GU_API
Definition: GU_API.h:14
INT_TYPE myRow1Step
Definition: GU_Grid.h:59
void initColSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
Definition: GU_GridImpl.h:1363
GEO_SurfaceType mySurfaceType
Definition: GU_Grid.h:77
void shiftPoints(INT_TYPE shift)
Definition: GU_Grid.h:327
GU_OrientationType
Definition: GU_Types.h:32
bool myLastRowIfNotWrapped
Definition: GU_Grid.h:110
exint myNumVertices
Definition: GU_Grid.h:146
INT_TYPE myCol0Start
Definition: GU_Grid.h:62
INT_TYPE getPoint(exint row, exint col) const
Definition: GU_Grid.h:270
INT_TYPE myMiddleStart
Definition: GU_Grid.h:72
bool myLastColIfNotWrapped
Definition: GU_Grid.h:120
~GU_GridT()
Definition: GU_Grid.h:168
void fixTPSurf()
Definition: GU_Grid.h:383
bool myNoWrapV
Definition: GU_Grid.h:144
exint myNumEdgeRows
Definition: GU_Grid.h:45
bool doesRowWrap(exint row) const
Definition: GU_Grid.h:301
int orderV
Definition: GU_Grid.h:36
INT_TYPE myCol1Start
Definition: GU_Grid.h:67
GEO_SurfaceType
float ysize
Definition: GU_Grid.h:31
bool myAllWrapV
Definition: GU_Grid.h:142
bool doesColWrap(exint col) const
Definition: GU_Grid.h:313
exint myNumPrimitives
Definition: GU_Grid.h:145
PrimitiveType
Definition: GU_Grid.h:79
float zcenter
Definition: GU_Grid.h:32
void initRowSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
Definition: GU_GridImpl.h:1454
GLenum GLenum void * row
Definition: glew.h:4965
INT_TYPE myMiddleColStep
Definition: GU_Grid.h:73
PrimitiveType myPrimitiveType
Definition: GU_Grid.h:88
void initRowTube(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
Definition: GU_GridImpl.h:1273
void initTorus(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
Definition: GU_GridImpl.h:1636
int rows
Definition: GU_Grid.h:30
unsigned char myBasisOrderV
Definition: GU_Grid.h:93
void initSingleGrid(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0))
Definition: GU_GridImpl.h:1094
SYS_STATIC_ASSERT(GA_MAX_ORDER< 16)
void initSplitColSphere(exint nedgerows, exint nedgecols, INT_TYPE start_pt=INT_TYPE(0), INT_TYPE end_pt=INT_TYPE(1), INT_TYPE start_mid_pt=INT_TYPE(2))
Definition: GU_GridImpl.h:1545