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 <tbb/tbb_stddef.h>
25 
27 {
28 public:
29 
30  class SizeCount
31  {
32  public:
33  SizeCount() {}
34  SizeCount(int sz, int ct)
35  : mySize(sz)
36  , myCount(ct)
37  {}
38  const int &size() const { return mySize; }
39  const int &count() const { return myCount; }
40  int &size() { return mySize; }
41  int &count() { return myCount; }
42  GA_Size product() const { return GA_Size(mySize)*GA_Size(myCount); }
43 
44  typedef int InternalType;
45  private:
46  int mySize;
47  int myCount;
48  };
49 
50  template<typename CLASS,typename ARRAYCLASS>
51  class iteratorT
52  {
53  public:
54  iteratorT() {}
55  iteratorT(CLASS &list)
56  : myArray(&list.array)
57  , myPolygon(0)
58  , myStart(0)
59  , myIndex(0)
60  , myCount(0)
61  {}
62  iteratorT(CLASS &list, GA_Size polygon)
63  : myArray(&list.array)
64  , myPolygon(polygon)
65  {
66  ARRAYCLASS &array = *myArray;
67  UT_ASSERT_P(array.entries() != 0);
68  GA_Size start = 0;
69  GA_Size i;
70  for (i = 0; i < array.entries()
71  && polygon >= array(i).count(); ++i)
72  {
73  start += array(i).product();
74  polygon -= array(i).count();
75  }
76  if (i < array.entries())
77  start += polygon*array(i).size();
78  myStart = start;
79  myIndex = i;
80  myCount = polygon;
81  }
83  : myArray(that.myArray)
84  , myPolygon(that.myPolygon)
85  , myStart(that.myStart)
86  , myIndex(that.myIndex)
87  , myCount(that.myCount)
88  {}
89  iteratorT(ARRAYCLASS *array, GA_Size polygon, GA_Size start, GA_Size index, GA_Size count)
90  : myArray(array)
91  , myPolygon(polygon)
92  , myStart(start)
93  , myIndex(index)
94  , myCount(count)
95  {}
96  SYS_FORCE_INLINE bool atEnd() const
97  {
98  return myIndex == (*myArray).entries();
99  }
101  { return SYSconst_cast(*this); }
103  {
104  ++myPolygon;
105  myStart += nvertices();
106  ++myCount;
107  if (myCount == (*myArray)(myIndex).count())
108  {
109  myCount = 0;
110  ++myIndex;
111  }
112  return *this;
113  }
115  {
116  if (myCount == 0)
117  {
118  --myIndex;
119  myCount = (*myArray)(myIndex).count();
120  }
121  --myCount;
122  myStart -= nvertices();
123  --myPolygon;
124  return *this;
125  }
127  {
128  if (count == 0)
129  return *this;
130 
131  ARRAYCLASS &array = *myArray;
132 
133  GA_Size polygon = myPolygon + count;
134  UT_ASSERT_P(polygon >= 0);
135  GA_Size start = myStart;
136  GA_Size i = myIndex;
137  count += myCount;
138  // If in the same block, just adjust start
139  if (count >= 0 && count < array(i).count())
140  {
141  start += (count - myCount)*array(i).size();
142  }
143  // If past the end of the current block
144  else if (count >= array(i).count())
145  {
146  start += (array(i).count() - myCount)*array(i).size();
147  count -= array(i).count();
148  for (++i; i < array.entries() && count >= array(i).count(); ++i)
149  {
150  start += array(i).product();
151  count -= array(i).count();
152  }
153  if (i < array.entries())
154  start += count*array(i).size();
155  }
156  // If before the beginning of the current block
157  else
158  {
159  if (i < array.entries())
160  start -= myCount*array(i).size();
161  for (--i; -count >= array(i).count(); --i)
162  {
163  start -= array(i).product();
164  count += array(i).count();
165  }
166  start -= (array(i).count() + count)*array(i).size();
167  count += array(i).count();
168  }
169  return iteratorT<CLASS, ARRAYCLASS>(myArray, polygon, start, i, count);
170  }
172  {
173  return (*this)+(-count);
174  }
176  {
177  if (&that!=this)
178  {
179  // NOTE: Cannot assign from an iterator
180  // of a different GA_PolyCounts
181  myArray = that.myArray;
182  myPolygon = that.myPolygon;
183  myStart = that.myStart;
184  myIndex = that.myIndex;
185  myCount = that.myCount;
186  }
187  return *this;
188  }
189  bool operator==(const iteratorT<CLASS, ARRAYCLASS> &that) const
190  {
191  // NOTE: For efficiency, cannot compare with an iterator
192  // of a different GA_PolyCounts
193  return (myPolygon == that.myPolygon);
194  }
195  bool operator!=(const iteratorT<CLASS, ARRAYCLASS> &that) const
196  {
197  // NOTE: For efficiency, cannot compare with an iterator
198  // of a different GA_PolyCounts
199  return (myPolygon != that.myPolygon);
200  }
202  {
203  return (*myArray)(myIndex).size();
204  }
206  {
207  return myPolygon;
208  }
210  {
211  return myStart;
212  }
213 
214  private:
215  ARRAYCLASS *myArray;
216  GA_Size myPolygon;
217  GA_Size myStart;
218  GA_Size myIndex;
219  GA_Size myCount;
220  };
223 
224  /// Range class for multi-threading with TBB
225  class Range
226  {
227  public:
228  Range(const GA_PolyCounts &list)
229  : myIt(list)
230  , myNPolygons(list.getNumPolygons())
231  , myGrainSize(1)
232  {}
233  Range(const GA_PolyCounts &list, GA_Size begin, GA_Size end, GA_Size grainsize = 1)
234  : myIt(list)
235  , myNPolygons(list.getNumPolygons())
236  , myGrainSize(grainsize)
237  {}
239  : myIt(that.myIt + that.myNPolygons/2)
240  , myNPolygons(that.myNPolygons - (that.myNPolygons/2))
241  , myGrainSize(that.myGrainSize)
242  {
243  that.myNPolygons = that.myNPolygons/2;
244  }
245 
246  const_iterator begin() const { return myIt; }
247 
248  // NOTE: DO NOT use the return value from end() as a real iterator;
249  // It is intended for uses like: it != end()
250  // Constructing a full end iterator is expensive, and if
251  // necessary, can be done with: begin() + size()
253  { return const_iterator(NULL, myIt.polygon() + myNPolygons, 0, 0, 0); }
254 
255  GA_Size size() const { return myNPolygons; }
256  GA_Size grainsize() const { return myGrainSize; }
257  bool empty() const { return myNPolygons == 0; }
258  bool is_divisible() const { return myNPolygons >= 2*myGrainSize; }
259  private:
260  const_iterator myIt;
261  GA_Size myNPolygons;
262  const GA_Size myGrainSize;
263  };
264 
266  {}
267 
269  : array(that.array)
270  {}
271 
273  {
274  if (this == &that)
275  return *this;
276 
277  array = that.array;
278  return *this;
279  }
280 
281  iterator begin() { return iterator(*this); }
282  const_iterator begin() const { return const_iterator(*this); }
283 
284  // NOTE: DO NOT use the return value from end() as a real iterator;
285  // It is intended for uses like: it != end()
286  // Constructing a full end iterator is expensive, and if
287  // necessary, can be done with: begin() + size()
288  const_iterator end() const { return const_iterator(NULL, getNumPolygons(), 0, 0, 0); }
289 
290  const_iterator findVertex(GA_Size relativevertex) const
291  {
292  GA_Size start = relativevertex;
293  GA_Size polygon = 0;
294  GA_Size i;
295  for (i = 0; i < array.entries()
296  && relativevertex >= array(i).product(); ++i)
297  {
298  relativevertex -= array(i).product();
299  polygon += array(i).count();
300  }
301  GA_Size count = 0;
302  if (relativevertex)
303  {
304  GA_Size remainder;
305  SYSdivMod(relativevertex, GA_Size(array(i).size()), count, remainder);
306  polygon += count;
307  start -= remainder;
308  }
309  return const_iterator(&array, polygon, start, i, count);
310  }
311 
312  Range range() const { return Range(*this); }
313 
314  UT_Array<SizeCount> &getArray() { return array; }
315  const UT_Array<SizeCount> &getArray() const { return array; }
316 
317  void clear() { array.clear(); }
318 
319  /// Adds "count" polygons with "size" vertices each to the end of the list.
320  /// For example, to add 5000000 triangles, call append(3,5000000).
321  /// Since this is run-length encoded, if the last entry was already
322  /// for polygons with "size" vertices, "count" will just be added to
323  /// the last entry.
325  {
326  if (count == 0)
327  return;
328  if (array.entries() && array.last().size() == size)
329  array.last().count() += count;
330  else
331  array.append(SizeCount(size, count));
332  }
333 
334  void append(const GA_PolyCounts &that)
335  {
336  if (!that.array.entries())
337  return;
338 
339  if (array.entries() && array.last().size() == that.array(0).size())
340  array.last().count() += that.array(0).count();
341  else
342  array.append(that.array(0));
343 
344  for (GA_Size i = 1; i < that.array.entries(); ++i)
345  array.append(that.array(i));
346  }
347 
349  GA_Size sum = 0;
350  for (GA_Size i = 0; i < array.entries(); ++i)
351  sum += array(i).count();
352  return sum;
353  }
354 
356  GA_Size sum = 0;
357  for (GA_Size i = 0; i < array.entries(); ++i)
358  sum += array(i).product();
359  return sum;
360  }
361 
362  /// Simpler than getVertexRange if you just want the polygon size
363  GA_Size getSize(GA_Size polygon) const
364  {
365  UT_ASSERT_P(array.entries() != 0);
366  GA_Size i;
367  for (i = 0; polygon >= array(i).count(); ++i)
368  polygon -= array(i).count();
369  return array(i).size();
370  }
371 
372  void getVertexRange(GA_Size polygon, GA_Size &start, GA_Size &size) const
373  {
374  UT_ASSERT_P(array.entries() != 0);
375  GA_Size index = 0;
376  GA_Size i;
377  for (i = 0; polygon >= array(i).count(); ++i)
378  {
379  index += array(i).product();
380  polygon -= array(i).count();
381  }
382  index += polygon*array(i).size();
383  start = index;
384  size = array(i).size();
385  }
386 
387  int64 getMemoryUsage(bool inclusive) const
388  { return (inclusive ? sizeof(*this) : 0) + array.getMemoryUsage(false); }
389 
390 private:
391  UT_Array<SizeCount> array;
392 };
393 
394 /// This is needed by the tbb wrapper in UT_ParallelUtil
395 /// It returns an upper bound for the actual number of work items
396 /// in the range.
398 {
399  return range.size();
400 }
401 
402 #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:62
tbb::split UT_Split
Definition: GA_PolyCounts.h:24
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:38
GA_PolyCounts & operator=(const GA_PolyCounts &that)
#define GA_API
Definition: GA_API.h:14
SizeCount(int sz, int ct)
Definition: GA_PolyCounts.h:34
GA_Size getNumVertices() const
exint size() const
Definition: UT_Array.h:646
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:39
SYS_FORCE_INLINE bool atEnd() const
Definition: GA_PolyCounts.h:96
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:648
GLsizeiptr size
Definition: glcorearb.h:664
const_iterator begin() const
iteratorT(const iteratorT< CLASS, ARRAYCLASS > &that)
Definition: GA_PolyCounts.h:82
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:89
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:42
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:558