Visualization Library 2.1.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
TriangleIterator.hpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #ifndef TriangleIterator_INCLUDE_ONCE
33 #define TriangleIterator_INCLUDE_ONCE
34 
35 #include <vlGraphics/Array.hpp>
36 #include <vlCore/vlnamespace.hpp>
37 #include <vlCore/Say.hpp>
38 
39 namespace vl
40 {
41 //-----------------------------------------------------------------------------
42 // TriangleIteratorAbstract
43 //-----------------------------------------------------------------------------
46  {
48 
49  public:
50  virtual bool next() = 0;
51  virtual bool hasNext() const = 0;
52  virtual int a() const = 0;
53  virtual int b() const = 0;
54  virtual int c() const = 0;
55  };
56 //-----------------------------------------------------------------------------
57 // TriangleIteratorIndexed
58 //-----------------------------------------------------------------------------
60  template<class TArray>
62  {
64 
65  public:
66 
68  {
69  VL_DEBUG_SET_OBJECT_NAME()
70  mCurrentIndex = 0;
71  mEnd = 0;
72  mA = mB = mC = -1;
73  mEven = true;
74  mIndex0 = 0;
75  mArray = NULL;
76  mPrimRestartIndex = (unsigned int)-1;
77  mPrimRestartOn = false;
78  mBaseVertex = 0;
79  mPrimType = PT_UNKNOWN;
80  }
81 
82  TriangleIteratorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx)
83  {
84  VL_DEBUG_SET_OBJECT_NAME()
85  mCurrentIndex = 0;
86  mEnd = 0;
87  mA = mB = mC = -1;
88  mEven = true;
89  mIndex0 = 0;
90  mArray = idx_array;
91  mPrimRestartIndex = prim_restart_idx;
92  mPrimRestartOn = prim_restart_on;
93  mBaseVertex = base_vert;
94  mPrimType = prim_type;
95  }
96 
97  bool hasNext() const { return mCurrentIndex != mEnd; }
98 
99  virtual int a() const { return mA; }
100  virtual int b() const { return mB; }
101  virtual int c() const { return mC; }
102 
103  void initialize(int start=0, int end=-1)
104  {
105  VL_CHECK( start >= 0 )
106  VL_CHECK( end <= (int)mArray->size() )
107 
108  if (end == -1)
109  end = (int)mArray->size();
110 
111  mCurrentIndex = end; // end
112  mA = mB = mC = -1;
113  mEven = true;
114  mIndex0 = start;
115  mEnd = end;
116  if (mArray->size())
117  {
118  switch(mPrimType)
119  {
120  case PT_TRIANGLES:
121  mCurrentIndex = start;
122  mA = mArray->at(start+0);
123  mB = mArray->at(start+1);
124  mC = mArray->at(start+2);
125  break;
127  mCurrentIndex = start;
128  mA = mArray->at(start+0);
129  mB = mArray->at(start+2);
130  mC = mArray->at(start+4);
131  break;
132  case PT_TRIANGLE_STRIP:
133  mCurrentIndex = start;
134  mA = mArray->at(start+0);
135  mB = mArray->at(start+1);
136  mC = mArray->at(start+2);
137  break;
138  case PT_TRIANGLE_FAN:
139  case PT_POLYGON:
140  mCurrentIndex = start + 1;
141  mA = mArray->at(start+0);
142  mB = mArray->at(start+1);
143  mC = mArray->at(start+2);
144  break;
145  case PT_QUADS:
146  // VL_CHECK( (end-start) % 4 == 0 ) /* primitive restart might screw up this */
147  mCurrentIndex = start;
148  mA = mArray->at(start+0);
149  mB = mArray->at(start+1);
150  mC = mArray->at(start+2);
151  break;
152  case PT_QUAD_STRIP:
153  // VL_CHECK( (end-start) % 2 == 0 ) /* primitive restart might screw up this */
154  mCurrentIndex = start;
155  mA = mArray->at(start+0);
156  mB = mArray->at(start+1);
157  mC = mArray->at(start+2);
158  break;
159  default:
160  Log::error( Say("TriangleIteratorIndexed::initialize(): unsupported primitive type %n.\n") << mPrimType );
161  VL_TRAP();
162  break;
163  }
164  }
165 
166  // if we are not at the end then add base vertices
167  if ( mCurrentIndex != mEnd )
168  {
169  mA += mBaseVertex;
170  mB += mBaseVertex;
171  mC += mBaseVertex;
172  }
173  else
174  {
175  mA = mB = mC = -1;
176  }
177  }
178 
179  bool next()
180  {
181  // reached the end
182  if ( mCurrentIndex == mEnd )
183  return false;
184 
185  switch(mPrimType)
186  {
187 
188  case PT_TRIANGLES:
189  mCurrentIndex += 3;
190  // check for the end
191  if ( mCurrentIndex >= mEnd )
192  mCurrentIndex = mEnd;
193  else
194  if ( isPrimRestart(mCurrentIndex) )
195  {
196  mCurrentIndex += 1;
197  mA = mArray->at(mCurrentIndex + 0);
198  mB = mArray->at(mCurrentIndex + 1);
199  mC = mArray->at(mCurrentIndex + 2);
200  }
201  else
202  {
203  mA = mArray->at(mCurrentIndex + 0);
204  mB = mArray->at(mCurrentIndex + 1);
205  mC = mArray->at(mCurrentIndex + 2);
206  }
207  break;
208 
210  mCurrentIndex += 6;
211  // check for the end
212  if ( mCurrentIndex >= mEnd )
213  mCurrentIndex = mEnd;
214  else
215  if ( isPrimRestart(mCurrentIndex) )
216  {
217  mCurrentIndex += 1;
218  mA = mArray->at(mCurrentIndex + 0);
219  mB = mArray->at(mCurrentIndex + 2);
220  mC = mArray->at(mCurrentIndex + 4);
221  }
222  else
223  {
224  mA = mArray->at(mCurrentIndex + 0);
225  mB = mArray->at(mCurrentIndex + 2);
226  mC = mArray->at(mCurrentIndex + 4);
227  }
228  break;
229 
230  case PT_QUAD_STRIP:
231  case PT_TRIANGLE_STRIP:
232  mCurrentIndex += 1;
233  if ( mCurrentIndex + 2 >= mEnd )
234  mCurrentIndex = mEnd;
235  else
236  if ( isPrimRestart(mCurrentIndex + 2) )
237  {
238  mCurrentIndex += 3;
239  mEven = true;
240  mA = mArray->at(mCurrentIndex + 0);
241  mB = mArray->at(mCurrentIndex + 1);
242  mC = mArray->at(mCurrentIndex + 2);
243  }
244  else
245  {
246  mEven = !mEven;
247  if (mEven)
248  {
249  mA = mArray->at(mCurrentIndex + 0);
250  mB = mArray->at(mCurrentIndex + 1);
251  mC = mArray->at(mCurrentIndex + 2);
252  }
253  else
254  {
255  mA = mArray->at(mCurrentIndex + 0);
256  mB = mArray->at(mCurrentIndex + 2);
257  mC = mArray->at(mCurrentIndex + 1);
258  }
259  }
260  break;
261 
262  case PT_TRIANGLE_FAN:
263  case PT_POLYGON:
264  mCurrentIndex += 1;
265  if ( mCurrentIndex + 1 >= mEnd )
266  {
267  mCurrentIndex = mEnd;
268  }
269  else
270  if ( isPrimRestart(mCurrentIndex + 1) )
271  {
272  mIndex0 = mCurrentIndex + 2;
273  mCurrentIndex = mIndex0 + 1;
274  mA = mArray->at(mIndex0);
275  mB = mArray->at(mCurrentIndex + 0);
276  mC = mArray->at(mCurrentIndex + 1);
277  }
278  else
279  {
280  mA = mArray->at(mIndex0);
281  mB = mArray->at(mCurrentIndex + 0);
282  mC = mArray->at(mCurrentIndex + 1);
283  }
284  break;
285 
286  case PT_QUADS:
287  mCurrentIndex += 2;
288  if ( mCurrentIndex >= mEnd )
289  {
290  mCurrentIndex = mEnd;
291  }
292  else
293  if ( isPrimRestart(mCurrentIndex) )
294  {
295  mCurrentIndex += 1;
296  mEven = true;
297  mA = mArray->at(mCurrentIndex+0);
298  mB = mArray->at(mCurrentIndex+1);
299  mC = mArray->at(mCurrentIndex+2);
300  }
301  else
302  {
303  mEven = !mEven;
304  if ( mEven )
305  {
306  mA = mArray->at(mCurrentIndex+0);
307  mB = mArray->at(mCurrentIndex+1);
308  mC = mArray->at(mCurrentIndex+2);
309  }
310  else
311  {
312  mA = mArray->at(mCurrentIndex+0);
313  mB = mArray->at(mCurrentIndex+1);
314  mC = mArray->at(mCurrentIndex-2);
315  }
316  }
317  break;
318 
319  default:
320  VL_TRAP();
321  break;
322  }
323 
324  // if we are not at the end then add base vertices
325  if (mCurrentIndex != mEnd)
326  {
327  mA += mBaseVertex;
328  mB += mBaseVertex;
329  mC += mBaseVertex;
330  return true;
331  }
332  else
333  {
334  mA = mB = mC = -1;
335  return false;
336  }
337  }
338 
339  void setBaseVertex(int base_vert) { mBaseVertex = base_vert; }
340  int baseVertex() const { return mBaseVertex; }
341 
342  private:
343  bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; }
344 
345  private:
346  const TArray* mArray;
347  EPrimitiveType mPrimType;
348  int mA, mB, mC;
349  int mCurrentIndex;
350  int mIndex0;
351  int mEnd;
352  int mBaseVertex;
353  unsigned int mPrimRestartIndex;
354  bool mPrimRestartOn;
355  bool mEven;
356  };
357 //-----------------------------------------------------------------------------
358 // TriangleIteratorDirect
359 //-----------------------------------------------------------------------------
362  {
364 
365  public:
367  {
368  VL_DEBUG_SET_OBJECT_NAME()
369  mCurrentIndex = mStart = mEnd = 0;
370  mA = mB = mC = -1;
371  mPrimType = prim_type;
372  mEven = true;
373  }
374 
375  bool hasNext() const { return mCurrentIndex != mEnd; }
376 
377  virtual int a() const { return mA; }
378  virtual int b() const { return mB; }
379  virtual int c() const { return mC; }
380 
381  void initialize(int start, int end)
382  {
383  VL_CHECK(end >= start)
384  mStart = start;
385  mCurrentIndex = mEnd = end;
386  mA = mB = mC = -1;
387  mEven = true;
388  switch(mPrimType)
389  {
390  case PT_TRIANGLES:
391  // VL_CHECK( (end - start) % 3 == 0 ) /* primitive restart might screw up this */
392  mCurrentIndex = start;
393  mA = start + 0;
394  mB = start + 1;
395  mC = start + 2;
396  break;
397  case PT_TRIANGLE_STRIP:
398  mCurrentIndex = start;
399  mA = start + 0;
400  mB = start + 1;
401  mC = start + 2;
402  break;
403  case PT_TRIANGLE_FAN:
404  case PT_POLYGON:
405  mCurrentIndex = start + 1;
406  mA = start + 0;
407  mB = start + 1;
408  mC = start + 2;
409  break;
410  case PT_QUADS:
411  // VL_CHECK( (end - start) % 4 == 0 ) /* primitive restart might screw up this */
412  mCurrentIndex = start;
413  mA = start + 0;
414  mB = start + 1;
415  mC = start + 2;
416  break;
417  case PT_QUAD_STRIP:
418  // VL_CHECK( (end - start) % 2 == 0 ) /* primitive restart might screw up this */
419  mCurrentIndex = start;
420  mA = start + 0;
421  mB = start + 1;
422  mC = start + 2;
423  break;
424  default:
425  break;
426  }
427  }
428 
429  bool next()
430  {
431  // reached the end
432  if ( mCurrentIndex == mEnd )
433  return false;
434 
435  switch(mPrimType)
436  {
437 
438  case PT_TRIANGLES:
439  mCurrentIndex += 3;
440  // check for the end
441  if ( mCurrentIndex >= mEnd )
442  mCurrentIndex = mEnd;
443  else
444  {
445  mA = mCurrentIndex + 0;
446  mB = mCurrentIndex + 1;
447  mC = mCurrentIndex + 2;
448  }
449  break;
450 
451  case PT_QUAD_STRIP:
452  case PT_TRIANGLE_STRIP:
453  mCurrentIndex += 1;
454  if ( mCurrentIndex + 2 >= mEnd )
455  mCurrentIndex = mEnd;
456  else
457  {
458  mEven = !mEven;
459  if (mEven)
460  {
461  mA = mCurrentIndex + 0;
462  mB = mCurrentIndex + 1;
463  mC = mCurrentIndex + 2;
464  }
465  else
466  {
467  mA = mCurrentIndex + 0;
468  mB = mCurrentIndex + 2;
469  mC = mCurrentIndex + 1;
470  }
471  }
472  break;
473 
474  case PT_TRIANGLE_FAN:
475  case PT_POLYGON:
476  mCurrentIndex += 1;
477  if ( mCurrentIndex + 1 >= mEnd )
478  {
479  mCurrentIndex = mEnd;
480  }
481  else
482  {
483  mA = mStart;
484  mB = mCurrentIndex+0;
485  mC = mCurrentIndex+1;
486  }
487  break;
488 
489  case PT_QUADS:
490  mCurrentIndex += 2;
491  if ( mCurrentIndex >= mEnd )
492  {
493  mCurrentIndex = mEnd;
494  }
495  else
496  {
497  mEven = !mEven;
498  if ( mEven )
499  {
500  mA = mCurrentIndex+0;
501  mB = mCurrentIndex+1;
502  mC = mCurrentIndex+2;
503  }
504  else
505  {
506  mA = mCurrentIndex+0;
507  mB = mCurrentIndex+1;
508  mC = mCurrentIndex-2;
509  }
510  }
511  break;
512 
513  default:
514  VL_TRAP();
515  break;
516  }
517 
518  // if we are not at the end then add base vertices
519  if (mCurrentIndex == mEnd)
520  {
521  mA = mB = mC = -1;
522  return false;
523  }
524  else
525  return true;
526  }
527 
528  private:
529  EPrimitiveType mPrimType;
530  int mA, mB, mC;
531  int mCurrentIndex;
532  int mStart;
533  int mEnd;
534  bool mEven;
535  };
536 //-----------------------------------------------------------------------------
537 // TriangleIteratorMulti
538 //-----------------------------------------------------------------------------
540  template<class TArray>
542  {
544 
545  public:
546  TriangleIteratorMulti( const std::vector<GLint>* p_base_vertices, const std::vector<GLsizei>* p_count_vector, const TArray* idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx)
547  :TriangleIteratorIndexed<TArray>( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx)
548  {
549  VL_DEBUG_SET_OBJECT_NAME()
550  mpBaseVertices = p_base_vertices;
551  mpCountVector = p_count_vector;
552  mStart = 0;
553  mCurPrim = 0;
554  }
555 
556  void initialize()
557  {
558  VL_CHECK( mpBaseVertices->size() == mpCountVector->size() )
559  if ( (*mpBaseVertices).size() )
560  TriangleIteratorIndexed<TArray>::setBaseVertex( (*mpBaseVertices)[mCurPrim] );
561  int end = mStart + (*mpCountVector)[mCurPrim];
563  // abort if could not initialize (primitive not supported)
565  mCurPrim = (int)(*mpCountVector).size()-1;
566  }
567 
568  bool next()
569  {
571  return true;
572  else
573  if ( mCurPrim < (int)(*mpCountVector).size()-1 )
574  {
575  mStart += (*mpCountVector)[mCurPrim];
576  mCurPrim++;
577  initialize();
578  return true;
579  }
580  else
581  return false;
582  }
583 
584  bool hasNext() const
585  {
586  if ( !TriangleIteratorIndexed<TArray>::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 )
587  return false;
588  else
589  return true;
590  }
591 
592  protected:
593  const std::vector<GLint>* mpBaseVertices;
594  const std::vector<GLsizei>* mpCountVector;
595  int mCurPrim;
596  int mStart;
597  };
598 //-----------------------------------------------------------------------------
599 // TriangleIterator
600 //-----------------------------------------------------------------------------
605  {
606  public:
608 
610  bool next() { return mIterator->next(); }
611 
612  bool operator++() { return next(); }
613 
615  bool hasNext() { return mIterator->hasNext(); }
616 
618  int a() const { return mIterator->a(); }
619 
621  int b() const { return mIterator->b(); }
622 
624  int c() const { return mIterator->c(); }
625 
626  protected:
628  };
629 //-----------------------------------------------------------------------------
630 }
631 
632 #endif
bool hasNext()
Returns false if the iterator has reached the end of the triangle list.
const std::vector< GLint > * mpBaseVertices
virtual int b() const =0
For internal use only.
virtual int a() const =0
A simple String formatting class.
Definition: Say.hpp:124
virtual int c() const =0
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
For internal use only.
TriangleIteratorMulti(const std::vector< GLint > *p_base_vertices, const std::vector< GLsizei > *p_count_vector, const TArray *idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx)
#define VL_INSTRUMENT_CLASS(ClassName, BaseClass)
Definition: TypeInfo.hpp:122
ref< TriangleIteratorAbstract > mIterator
EPrimitiveType
Visualization Library main namespace.
For internal use only.
#define VL_TRAP()
Definition: checks.hpp:70
For internal use only.
The base class for all the reference counted objects.
Definition: Object.hpp:158
bool next()
Requires the next triangle.
Iterator used to extract the indices of every single triangle of a DrawCall regardless of the primiti...
TriangleIteratorIndexed(const TArray *idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx)
virtual bool hasNext() const =0
#define NULL
Definition: OpenGLDefs.hpp:81
void setBaseVertex(int base_vert)
void initialize(int start, int end)
#define VL_INSTRUMENT_ABSTRACT_CLASS(ClassName, BaseClass)
Definition: TypeInfo.hpp:145
void initialize(int start=0, int end=-1)
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
int c() const
First index of the triangle.
int a() const
First index of the triangle.
TriangleIterator(TriangleIteratorAbstract *it)
#define VL_CHECK(expr)
Definition: checks.hpp:73
TriangleIteratorDirect(EPrimitiveType prim_type=PT_UNKNOWN)
Visualization Library&#39;s enums in the &#39;vl&#39; namespace.
const std::vector< GLsizei > * mpCountVector
int b() const
First index of the triangle.