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>
24 typedef tbb::split UT_Split;
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  SizeCount(const SizeCount &that) = default;
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  {
103  ++myPolygon;
104  myStart += nvertices();
105  ++myCount;
106  if (myCount == (*myArray)(myIndex).count())
107  {
108  myCount = 0;
109  ++myIndex;
110  }
111  return *this;
112  }
114  {
115  if (myCount == 0)
116  {
117  --myIndex;
118  myCount = (*myArray)(myIndex).count();
119  }
120  --myCount;
121  myStart -= nvertices();
122  --myPolygon;
123  return *this;
124  }
126  {
127  if (count == 0)
128  return *this;
129 
130  ARRAYCLASS &array = *myArray;
131 
132  GA_Size polygon = myPolygon + count;
133  UT_ASSERT_P(polygon >= 0);
134  GA_Size start = myStart;
135  GA_Size i = myIndex;
136  count += myCount;
137  // If in the same block, just adjust start
138  if (count >= 0 && count < array(i).count())
139  {
140  start += (count - myCount)*array(i).size();
141  }
142  // If past the end of the current block
143  else if (count >= array(i).count())
144  {
145  start += (array(i).count() - myCount)*array(i).size();
146  count -= array(i).count();
147  for (++i; i < array.entries() && count >= array(i).count(); ++i)
148  {
149  start += array(i).product();
150  count -= array(i).count();
151  }
152  if (i < array.entries())
153  start += count*array(i).size();
154  }
155  // If before the beginning of the current block
156  else
157  {
158  if (i < array.entries())
159  start -= myCount*array(i).size();
160  for (--i; -count >= array(i).count(); --i)
161  {
162  start -= array(i).product();
163  count += array(i).count();
164  }
165  start -= (array(i).count() + count)*array(i).size();
166  count += array(i).count();
167  }
168  return iteratorT<CLASS, ARRAYCLASS>(myArray, polygon, start, i, count);
169  }
171  {
172  return (*this)+(-count);
173  }
175  {
176  if (&that!=this)
177  {
178  // NOTE: Cannot assign from an iterator
179  // of a different GA_PolyCounts
180  myArray = that.myArray;
181  myPolygon = that.myPolygon;
182  myStart = that.myStart;
183  myIndex = that.myIndex;
184  myCount = that.myCount;
185  }
186  return *this;
187  }
188  bool operator==(const iteratorT<CLASS, ARRAYCLASS> &that) const
189  {
190  // NOTE: For efficiency, cannot compare with an iterator
191  // of a different GA_PolyCounts
192  return (myPolygon == that.myPolygon);
193  }
194  bool operator!=(const iteratorT<CLASS, ARRAYCLASS> &that) const
195  {
196  // NOTE: For efficiency, cannot compare with an iterator
197  // of a different GA_PolyCounts
198  return (myPolygon != that.myPolygon);
199  }
201  {
202  return (*myArray)(myIndex).size();
203  }
205  {
206  return myPolygon;
207  }
209  {
210  return myStart;
211  }
212 
213  private:
214  ARRAYCLASS *myArray;
215  GA_Size myPolygon;
216  GA_Size myStart;
217  GA_Size myIndex;
218  GA_Size myCount;
219  };
222 
223  /// Range class for multi-threading with TBB
224  class Range
225  {
226  public:
227  Range(const GA_PolyCounts &list)
228  : myIt(list)
229  , myNPolygons(list.getNumPolygons())
230  , myGrainSize(1)
231  {}
232  Range(const GA_PolyCounts &list, GA_Size begin, GA_Size end, GA_Size grainsize = 1)
233  : myIt(list)
234  , myNPolygons(list.getNumPolygons())
235  , myGrainSize(grainsize)
236  {}
238  : myIt(that.myIt + that.myNPolygons/2)
239  , myNPolygons(that.myNPolygons - (that.myNPolygons/2))
240  , myGrainSize(that.myGrainSize)
241  {
242  that.myNPolygons = that.myNPolygons/2;
243  }
244 
245  const_iterator begin() const { return myIt; }
246 
247  // NOTE: DO NOT use the return value from end() as a real iterator;
248  // It is intended for uses like: it != end()
249  // Constructing a full end iterator is expensive, and if
250  // necessary, can be done with: begin() + size()
252  { return const_iterator(NULL, myIt.polygon() + myNPolygons, 0, 0, 0); }
253 
254  GA_Size size() const { return myNPolygons; }
255  GA_Size grainsize() const { return myGrainSize; }
256  bool empty() const { return myNPolygons == 0; }
257  bool is_divisible() const { return myNPolygons >= 2*myGrainSize; }
258  private:
259  const_iterator myIt;
260  GA_Size myNPolygons;
261  const GA_Size myGrainSize;
262  };
263 
265  {}
266 
268  : array(that.array)
269  {}
270 
272  {
273  if (this == &that)
274  return *this;
275 
276  array = that.array;
277  return *this;
278  }
279 
280  iterator begin() { return iterator(*this); }
281  const_iterator begin() const { return const_iterator(*this); }
282 
283  // NOTE: DO NOT use the return value from end() as a real iterator;
284  // It is intended for uses like: it != end()
285  // Constructing a full end iterator is expensive, and if
286  // necessary, can be done with: begin() + size()
287  const_iterator end() const { return const_iterator(NULL, getNumPolygons(), 0, 0, 0); }
288 
289  const_iterator findVertex(GA_Size relativevertex) const
290  {
291  GA_Size start = relativevertex;
292  GA_Size polygon = 0;
293  GA_Size i;
294  for (i = 0; i < array.entries()
295  && relativevertex >= array(i).product(); ++i)
296  {
297  relativevertex -= array(i).product();
298  polygon += array(i).count();
299  }
300  GA_Size count = 0;
301  if (relativevertex)
302  {
304  SYSdivMod(relativevertex, GA_Size(array(i).size()), count, remainder);
305  polygon += count;
306  start -= remainder;
307  }
308  return const_iterator(&array, polygon, start, i, count);
309  }
310 
311  Range range() const { return Range(*this); }
312 
313  UT_Array<SizeCount> &getArray() { return array; }
314  const UT_Array<SizeCount> &getArray() const { return array; }
315 
316  void clear() { array.clear(); }
317 
318  /// Adds "count" polygons with "size" vertices each to the end of the list.
319  /// For example, to add 5000000 triangles, call append(3,5000000).
320  /// Since this is run-length encoded, if the last entry was already
321  /// for polygons with "size" vertices, "count" will just be added to
322  /// the last entry.
324  {
325  if (count == 0)
326  return;
327  if (array.entries() && array.last().size() == size)
328  array.last().count() += count;
329  else
330  array.append(SizeCount(size, count));
331  }
332 
333  void append(const GA_PolyCounts &that)
334  {
335  if (!that.array.entries())
336  return;
337 
338  if (array.entries() && array.last().size() == that.array(0).size())
339  array.last().count() += that.array(0).count();
340  else
341  array.append(that.array(0));
342 
343  for (GA_Size i = 1; i < that.array.entries(); ++i)
344  array.append(that.array(i));
345  }
346 
348  GA_Size sum = 0;
349  for (GA_Size i = 0; i < array.entries(); ++i)
350  sum += array(i).count();
351  return sum;
352  }
353 
355  GA_Size sum = 0;
356  for (GA_Size i = 0; i < array.entries(); ++i)
357  sum += array(i).product();
358  return sum;
359  }
360 
361  /// Simpler than getVertexRange if you just want the polygon size
362  GA_Size getSize(GA_Size polygon) const
363  {
364  UT_ASSERT_P(array.entries() != 0);
365  GA_Size i;
366  for (i = 0; polygon >= array(i).count(); ++i)
367  polygon -= array(i).count();
368  return array(i).size();
369  }
370 
371  void getVertexRange(GA_Size polygon, GA_Size &start, GA_Size &size) const
372  {
373  UT_ASSERT_P(array.entries() != 0);
374  GA_Size index = 0;
375  GA_Size i;
376  for (i = 0; polygon >= array(i).count(); ++i)
377  {
378  index += array(i).product();
379  polygon -= array(i).count();
380  }
381  index += polygon*array(i).size();
382  start = index;
383  size = array(i).size();
384  }
385 
386  int64 getMemoryUsage(bool inclusive) const
387  { return (inclusive ? sizeof(*this) : 0) + array.getMemoryUsage(false); }
388 
389 private:
390  UT_Array<SizeCount> array;
391 };
392 
393 /// This is needed by the tbb wrapper in UT_ParallelUtil
394 /// It returns an upper bound for the actual number of work items
395 /// in the range.
397 {
398  return range.size();
399 }
400 
401 #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:1924
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:24
void append(const GA_PolyCounts &that)
GLuint start
Definition: glcorearb.h:474
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:12
SizeCount(int sz, int ct)
Definition: GA_PolyCounts.h:34
GA_Size getNumVertices() const
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
Range range() const
GLsizeiptr size
Definition: glcorearb.h:663
size_t remainder
Definition: wrapArray.h:334
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
long long int64
Definition: SYS_Types.h:107
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:125
bool operator!=(const iteratorT< CLASS, ARRAYCLASS > &that) const
iteratorT< GA_PolyCounts, UT_Array< SizeCount > > iterator
GLuint GLuint end
Definition: glcorearb.h:474
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
const_iterator end() const
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
GLint GLsizei count
Definition: glcorearb.h:404
const_iterator findVertex(GA_Size relativevertex) const
SYS_FORCE_INLINE GA_Size start() const
const_iterator begin() const
iteratorT(const iteratorT< CLASS, ARRAYCLASS > &that)
Definition: GA_PolyCounts.h:83
void append(GA_Size size, GA_Size count=1)
GLuint index
Definition: glcorearb.h:785
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
GA_Size product() const
Definition: GA_PolyCounts.h:43
iteratorT< CLASS, ARRAYCLASS > operator+(GA_Size count) const
SYS_FORCE_INLINE GA_Size polygon() const
iteratorT< CLASS, ARRAYCLASS > & operator=(const iteratorT< CLASS, ARRAYCLASS > &that)