HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_PolyCounts.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: GA_PolyCounts.h (GA Library, C++)
7  *
8  * COMMENTS: Implementation of a simple run-length encoded array
9  * intended for storing polygon vertex counts.
10  */
11 
12 #ifndef __GA_PolyCounts__
13 #define __GA_PolyCounts__
14 
15 #include "GA_API.h"
16 
17 #include "GA_Types.h"
18 #include <UT/UT_Array.h>
19 #include <UT/UT_Assert.h>
20 #include <SYS/SYS_Inline.h>
21 #include <SYS/SYS_Types.h>
22 
23 #include <oneapi/tbb/blocked_range.h>
24 
26 
28 {
29 public:
30 
31  class SizeCount
32  {
33  public:
34  SizeCount() {}
35  SizeCount(int sz, int ct)
36  : mySize(sz)
37  , myCount(ct)
38  {}
39  const int &size() const { return mySize; }
40  const int &count() const { return myCount; }
41  int &size() { return mySize; }
42  int &count() { return myCount; }
43  GA_Size product() const { return GA_Size(mySize)*GA_Size(myCount); }
44 
45  typedef int InternalType;
46  private:
47  int mySize;
48  int myCount;
49  };
50 
51  template<typename CLASS,typename ARRAYCLASS>
52  class iteratorT
53  {
54  public:
55  iteratorT() {}
56  iteratorT(CLASS &list)
57  : myArray(&list.array)
58  , myPolygon(0)
59  , myStart(0)
60  , myIndex(0)
61  , myCount(0)
62  {}
63  iteratorT(CLASS &list, GA_Size polygon)
64  : myArray(&list.array)
65  , myPolygon(polygon)
66  {
67  ARRAYCLASS &array = *myArray;
68  UT_ASSERT_P(array.entries() != 0);
69  GA_Size start = 0;
70  GA_Size i;
71  for (i = 0; i < array.entries()
72  && polygon >= array(i).count(); ++i)
73  {
74  start += array(i).product();
75  polygon -= array(i).count();
76  }
77  if (i < array.entries())
78  start += polygon*array(i).size();
79  myStart = start;
80  myIndex = i;
81  myCount = polygon;
82  }
84  : myArray(that.myArray)
85  , myPolygon(that.myPolygon)
86  , myStart(that.myStart)
87  , myIndex(that.myIndex)
88  , myCount(that.myCount)
89  {}
90  iteratorT(ARRAYCLASS *array, GA_Size polygon, GA_Size start, GA_Size index, GA_Size count)
91  : myArray(array)
92  , myPolygon(polygon)
93  , myStart(start)
94  , myIndex(index)
95  , myCount(count)
96  {}
97  SYS_FORCE_INLINE bool atEnd() const
98  {
99  return myIndex == (*myArray).entries();
100  }
102  { return SYSconst_cast(*this); }
104  {
105  ++myPolygon;
106  myStart += nvertices();
107  ++myCount;
108  if (myCount == (*myArray)(myIndex).count())
109  {
110  myCount = 0;
111  ++myIndex;
112  }
113  return *this;
114  }
116  {
117  if (myCount == 0)
118  {
119  --myIndex;
120  myCount = (*myArray)(myIndex).count();
121  }
122  --myCount;
123  myStart -= nvertices();
124  --myPolygon;
125  return *this;
126  }
128  {
129  if (count == 0)
130  return *this;
131 
132  ARRAYCLASS &array = *myArray;
133 
134  GA_Size polygon = myPolygon + count;
135  UT_ASSERT_P(polygon >= 0);
136  GA_Size start = myStart;
137  GA_Size i = myIndex;
138  count += myCount;
139  // If in the same block, just adjust start
140  if (count >= 0 && count < array(i).count())
141  {
142  start += (count - myCount)*array(i).size();
143  }
144  // If past the end of the current block
145  else if (count >= array(i).count())
146  {
147  start += (array(i).count() - myCount)*array(i).size();
148  count -= array(i).count();
149  for (++i; i < array.entries() && count >= array(i).count(); ++i)
150  {
151  start += array(i).product();
152  count -= array(i).count();
153  }
154  if (i < array.entries())
155  start += count*array(i).size();
156  }
157  // If before the beginning of the current block
158  else
159  {
160  if (i < array.entries())
161  start -= myCount*array(i).size();
162  for (--i; -count >= array(i).count(); --i)
163  {
164  start -= array(i).product();
165  count += array(i).count();
166  }
167  start -= (array(i).count() + count)*array(i).size();
168  count += array(i).count();
169  }
170  return iteratorT<CLASS, ARRAYCLASS>(myArray, polygon, start, i, count);
171  }
173  {
174  return (*this)+(-count);
175  }
177  {
178  if (&that!=this)
179  {
180  // NOTE: Cannot assign from an iterator
181  // of a different GA_PolyCounts
182  myArray = that.myArray;
183  myPolygon = that.myPolygon;
184  myStart = that.myStart;
185  myIndex = that.myIndex;
186  myCount = that.myCount;
187  }
188  return *this;
189  }
190  bool operator==(const iteratorT<CLASS, ARRAYCLASS> &that) const
191  {
192  // NOTE: For efficiency, cannot compare with an iterator
193  // of a different GA_PolyCounts
194  return (myPolygon == that.myPolygon);
195  }
196  bool operator!=(const iteratorT<CLASS, ARRAYCLASS> &that) const
197  {
198  // NOTE: For efficiency, cannot compare with an iterator
199  // of a different GA_PolyCounts
200  return (myPolygon != that.myPolygon);
201  }
203  {
204  return (*myArray)(myIndex).size();
205  }
207  {
208  return myPolygon;
209  }
211  {
212  return myStart;
213  }
214 
215  private:
216  ARRAYCLASS *myArray;
217  GA_Size myPolygon;
218  GA_Size myStart;
219  GA_Size myIndex;
220  GA_Size myCount;
221  };
224 
225  /// Range class for multi-threading with TBB
226  class Range
227  {
228  public:
229  Range(const GA_PolyCounts &list)
230  : myIt(list)
231  , myNPolygons(list.getNumPolygons())
232  , myGrainSize(1)
233  {}
234  Range(const GA_PolyCounts &list, GA_Size begin, GA_Size end, GA_Size grainsize = 1)
235  : myIt(list)
236  , myNPolygons(list.getNumPolygons())
237  , myGrainSize(grainsize)
238  {}
240  : myIt(that.myIt + that.myNPolygons/2)
241  , myNPolygons(that.myNPolygons - (that.myNPolygons/2))
242  , myGrainSize(that.myGrainSize)
243  {
244  that.myNPolygons = that.myNPolygons/2;
245  }
246 
247  const_iterator begin() const { return myIt; }
248 
249  // NOTE: DO NOT use the return value from end() as a real iterator;
250  // It is intended for uses like: it != end()
251  // Constructing a full end iterator is expensive, and if
252  // necessary, can be done with: begin() + size()
254  { return const_iterator(NULL, myIt.polygon() + myNPolygons, 0, 0, 0); }
255 
256  GA_Size size() const { return myNPolygons; }
257  GA_Size grainsize() const { return myGrainSize; }
258  bool empty() const { return myNPolygons == 0; }
259  bool is_divisible() const { return myNPolygons >= 2*myGrainSize; }
260  private:
261  const_iterator myIt;
262  GA_Size myNPolygons;
263  const GA_Size myGrainSize;
264  };
265 
267  {}
268 
270  : array(that.array)
271  {}
272 
274  {
275  if (this == &that)
276  return *this;
277 
278  array = that.array;
279  return *this;
280  }
281 
282  iterator begin() { return iterator(*this); }
283  const_iterator begin() const { return const_iterator(*this); }
284 
285  // NOTE: DO NOT use the return value from end() as a real iterator;
286  // It is intended for uses like: it != end()
287  // Constructing a full end iterator is expensive, and if
288  // necessary, can be done with: begin() + size()
289  const_iterator end() const { return const_iterator(NULL, getNumPolygons(), 0, 0, 0); }
290 
291  const_iterator findVertex(GA_Size relativevertex) const
292  {
293  GA_Size start = relativevertex;
294  GA_Size polygon = 0;
295  GA_Size i;
296  for (i = 0; i < array.entries()
297  && relativevertex >= array(i).product(); ++i)
298  {
299  relativevertex -= array(i).product();
300  polygon += array(i).count();
301  }
302  GA_Size count = 0;
303  if (relativevertex)
304  {
305  GA_Size remainder;
306  SYSdivMod(relativevertex, GA_Size(array(i).size()), count, remainder);
307  polygon += count;
308  start -= remainder;
309  }
310  return const_iterator(&array, polygon, start, i, count);
311  }
312 
313  Range range() const { return Range(*this); }
314 
315  UT_Array<SizeCount> &getArray() { return array; }
316  const UT_Array<SizeCount> &getArray() const { return array; }
317 
318  void clear() { array.clear(); }
319 
320  /// Adds "count" polygons with "size" vertices each to the end of the list.
321  /// For example, to add 5000000 triangles, call append(3,5000000).
322  /// Since this is run-length encoded, if the last entry was already
323  /// for polygons with "size" vertices, "count" will just be added to
324  /// the last entry.
326  {
327  if (count == 0)
328  return;
329  if (array.entries() && array.last().size() == size)
330  array.last().count() += count;
331  else
332  array.append(SizeCount(size, count));
333  }
334 
335  void append(const GA_PolyCounts &that)
336  {
337  if (!that.array.entries())
338  return;
339 
340  if (array.entries() && array.last().size() == that.array(0).size())
341  array.last().count() += that.array(0).count();
342  else
343  array.append(that.array(0));
344 
345  for (GA_Size i = 1; i < that.array.entries(); ++i)
346  array.append(that.array(i));
347  }
348 
350  GA_Size sum = 0;
351  for (GA_Size i = 0; i < array.entries(); ++i)
352  sum += array(i).count();
353  return sum;
354  }
355 
357  GA_Size sum = 0;
358  for (GA_Size i = 0; i < array.entries(); ++i)
359  sum += array(i).product();
360  return sum;
361  }
362 
363  /// Simpler than getVertexRange if you just want the polygon size
364  GA_Size getSize(GA_Size polygon) const
365  {
366  UT_ASSERT_P(array.entries() != 0);
367  GA_Size i;
368  for (i = 0; polygon >= array(i).count(); ++i)
369  polygon -= array(i).count();
370  return array(i).size();
371  }
372 
373  void getVertexRange(GA_Size polygon, GA_Size &start, GA_Size &size) const
374  {
375  UT_ASSERT_P(array.entries() != 0);
376  GA_Size index = 0;
377  GA_Size i;
378  for (i = 0; polygon >= array(i).count(); ++i)
379  {
380  index += array(i).product();
381  polygon -= array(i).count();
382  }
383  index += polygon*array(i).size();
384  start = index;
385  size = array(i).size();
386  }
387 
388  int64 getMemoryUsage(bool inclusive) const
389  { return (inclusive ? sizeof(*this) : 0) + array.getMemoryUsage(false); }
390 
391 private:
392  UT_Array<SizeCount> array;
393 };
394 
395 /// This is needed by the tbb wrapper in UT_ParallelUtil
396 /// It returns an upper bound for the actual number of work items
397 /// in the range.
399 {
400  return range.size();
401 }
402 
403 #endif
Range class for multi-threading with TBB.
GA_API size_t UTestimatedNumItems(const GA_PolyCounts::Range &range)
Range(const GA_PolyCounts &list, GA_Size begin, GA_Size end, GA_Size grainsize=1)
const_iterator end() const
GLenum GLint * range
Definition: glcorearb.h:1925
const UT_Array< SizeCount > & getArray() const
UT_Array< SizeCount > & getArray()
iteratorT(CLASS &list, GA_Size polygon)
Definition: GA_PolyCounts.h:63
tbb::split UT_Split
Definition: GA_PolyCounts.h:25
void append(const GA_PolyCounts &that)
GLuint start
Definition: glcorearb.h:475
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
bool is_divisible() const
const int & size() const
Definition: GA_PolyCounts.h:39
GA_PolyCounts & operator=(const GA_PolyCounts &that)
#define GA_API
Definition: GA_API.h:14
SizeCount(int sz, int ct)
Definition: GA_PolyCounts.h:35
GA_Size getNumVertices() const
exint size() const
Definition: UT_Array.h:653
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:236
Range range() const
GA_Size getSize(GA_Size polygon) const
Simpler than getVertexRange if you just want the polygon size.
iteratorT< CLASS, ARRAYCLASS > & operator++()
GA_Size getNumPolygons() const
GA_Size grainsize() const
const_iterator begin() const
iteratorT< CLASS, ARRAYCLASS > operator-(GA_Size count) const
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
bool operator!=(const iteratorT< CLASS, ARRAYCLASS > &that) const
iteratorT< GA_PolyCounts, UT_Array< SizeCount > > iterator
GLuint GLuint end
Definition: glcorearb.h:475
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
const_iterator end() const
long long int64
Definition: SYS_Types.h:116
iterator begin()
int64 getMemoryUsage(bool inclusive) const
iteratorT< const GA_PolyCounts, const UT_Array< SizeCount > > const_iterator
bool empty() const
iteratorT< CLASS, ARRAYCLASS > & operator--()
Range(const GA_PolyCounts &list)
const int & count() const
Definition: GA_PolyCounts.h:40
SYS_FORCE_INLINE bool atEnd() const
Definition: GA_PolyCounts.h:97
exint append()
Definition: UT_Array.h:142
const_iterator findVertex(GA_Size relativevertex) const
SYS_FORCE_INLINE GA_Size start() const
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:655
GLsizeiptr size
Definition: glcorearb.h:664
const_iterator begin() const
iteratorT(const iteratorT< CLASS, ARRAYCLASS > &that)
Definition: GA_PolyCounts.h:83
iteratorT< CLASS, ARRAYCLASS > & operator*() const
void append(GA_Size size, GA_Size count=1)
GLuint index
Definition: glcorearb.h:786
GA_PolyCounts(const GA_PolyCounts &that)
iteratorT(ARRAYCLASS *array, GA_Size polygon, GA_Size start, GA_Size index, GA_Size count)
Definition: GA_PolyCounts.h:90
bool operator==(const iteratorT< CLASS, ARRAYCLASS > &that) const
Range(Range &that, UT_Split)
void getVertexRange(GA_Size polygon, GA_Size &start, GA_Size &size) const
GA_Size size() const
SYS_FORCE_INLINE GA_Size nvertices() const
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
GA_Size product() const
Definition: GA_PolyCounts.h:43
iteratorT< CLASS, ARRAYCLASS > operator+(GA_Size count) const
SYS_FORCE_INLINE GA_Size polygon() const
GLint GLsizei count
Definition: glcorearb.h:405
iteratorT< CLASS, ARRAYCLASS > & operator=(const iteratorT< CLASS, ARRAYCLASS > &that)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566