Visualization Library 2.0.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 
38 namespace vl
39 {
40 //-----------------------------------------------------------------------------
41 // TriangleIteratorAbstract
42 //-----------------------------------------------------------------------------
45  {
47 
48  public:
49  virtual bool next() = 0;
50  virtual bool hasNext() const = 0;
51  virtual int a() const = 0;
52  virtual int b() const = 0;
53  virtual int c() const = 0;
54  };
55 //-----------------------------------------------------------------------------
56 // TriangleIteratorIndexed
57 //-----------------------------------------------------------------------------
59  template<class TArray>
61  {
63 
64  public:
65 
67  {
68  VL_DEBUG_SET_OBJECT_NAME()
69  mCurrentIndex = 0;
70  mEnd = 0;
71  mA = mB = mC = -1;
72  mEven = true;
73  mIndex0 = 0;
74  mArray = NULL;
75  mPrimRestartIndex = (unsigned int)-1;
76  mPrimRestartOn = false;
77  mBaseVertex = 0;
78  mPrimType = PT_UNKNOWN;
79  }
80 
81  TriangleIteratorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx)
82  {
83  VL_DEBUG_SET_OBJECT_NAME()
84  mCurrentIndex = 0;
85  mEnd = 0;
86  mA = mB = mC = -1;
87  mEven = true;
88  mIndex0 = 0;
89  mArray = idx_array;
90  mPrimRestartIndex = prim_restart_idx;
91  mPrimRestartOn = prim_restart_on;
92  mBaseVertex = base_vert;
93  mPrimType = prim_type;
94  }
95 
96  bool hasNext() const { return mCurrentIndex != mEnd; }
97 
98  virtual int a() const { return mA; }
99  virtual int b() const { return mB; }
100  virtual int c() const { return mC; }
101 
102  void initialize(int start=0, int end=-1)
103  {
104  VL_CHECK( start >= 0 )
105  VL_CHECK( end <= (int)mArray->size() )
106 
107  if (end == -1)
108  end = (int)mArray->size();
109 
110  mCurrentIndex = end; // end
111  mA = mB = mC = -1;
112  mEven = true;
113  mIndex0 = start;
114  mEnd = end;
115  if (mArray->size())
116  {
117  switch(mPrimType)
118  {
119  case PT_TRIANGLES:
120  mCurrentIndex = start;
121  mA = mArray->at(start+0);
122  mB = mArray->at(start+1);
123  mC = mArray->at(start+2);
124  break;
126  mCurrentIndex = start;
127  mA = mArray->at(start+0);
128  mB = mArray->at(start+2);
129  mC = mArray->at(start+4);
130  break;
131  case PT_TRIANGLE_STRIP:
132  mCurrentIndex = start;
133  mA = mArray->at(start+0);
134  mB = mArray->at(start+1);
135  mC = mArray->at(start+2);
136  break;
137  case PT_TRIANGLE_FAN:
138  case PT_POLYGON:
139  mCurrentIndex = start + 1;
140  mA = mArray->at(start+0);
141  mB = mArray->at(start+1);
142  mC = mArray->at(start+2);
143  break;
144  case PT_QUADS:
145  // VL_CHECK( (end-start) % 4 == 0 ) /* primitive restart might screw up this */
146  mCurrentIndex = start;
147  mA = mArray->at(start+0);
148  mB = mArray->at(start+1);
149  mC = mArray->at(start+2);
150  break;
151  case PT_QUAD_STRIP:
152  // VL_CHECK( (end-start) % 2 == 0 ) /* primitive restart might screw up this */
153  mCurrentIndex = start;
154  mA = mArray->at(start+0);
155  mB = mArray->at(start+1);
156  mC = mArray->at(start+2);
157  break;
158  default:
159  Log::error( Say("TriangleIteratorIndexed::initialize(): unsupported primitive type %n.\n") << mPrimType );
160  VL_TRAP();
161  break;
162  }
163  }
164 
165  // if we are not at the end then add base vertices
166  if ( mCurrentIndex != mEnd )
167  {
168  mA += mBaseVertex;
169  mB += mBaseVertex;
170  mC += mBaseVertex;
171  }
172  else
173  {
174  mA = mB = mC = -1;
175  }
176  }
177 
178  bool next()
179  {
180  // reached the end
181  if ( mCurrentIndex == mEnd )
182  return false;
183 
184  switch(mPrimType)
185  {
186 
187  case PT_TRIANGLES:
188  mCurrentIndex += 3;
189  // check for the end
190  if ( mCurrentIndex >= mEnd )
191  mCurrentIndex = mEnd;
192  else
193  if ( isPrimRestart(mCurrentIndex) )
194  {
195  mCurrentIndex += 1;
196  mA = mArray->at(mCurrentIndex + 0);
197  mB = mArray->at(mCurrentIndex + 1);
198  mC = mArray->at(mCurrentIndex + 2);
199  }
200  else
201  {
202  mA = mArray->at(mCurrentIndex + 0);
203  mB = mArray->at(mCurrentIndex + 1);
204  mC = mArray->at(mCurrentIndex + 2);
205  }
206  break;
207 
209  mCurrentIndex += 6;
210  // check for the end
211  if ( mCurrentIndex >= mEnd )
212  mCurrentIndex = mEnd;
213  else
214  if ( isPrimRestart(mCurrentIndex) )
215  {
216  mCurrentIndex += 1;
217  mA = mArray->at(mCurrentIndex + 0);
218  mB = mArray->at(mCurrentIndex + 2);
219  mC = mArray->at(mCurrentIndex + 4);
220  }
221  else
222  {
223  mA = mArray->at(mCurrentIndex + 0);
224  mB = mArray->at(mCurrentIndex + 2);
225  mC = mArray->at(mCurrentIndex + 4);
226  }
227  break;
228 
229  case PT_QUAD_STRIP:
230  case PT_TRIANGLE_STRIP:
231  mCurrentIndex += 1;
232  if ( mCurrentIndex + 2 >= mEnd )
233  mCurrentIndex = mEnd;
234  else
235  if ( isPrimRestart(mCurrentIndex + 2) )
236  {
237  mCurrentIndex += 3;
238  mEven = true;
239  mA = mArray->at(mCurrentIndex + 0);
240  mB = mArray->at(mCurrentIndex + 1);
241  mC = mArray->at(mCurrentIndex + 2);
242  }
243  else
244  {
245  mEven = !mEven;
246  if (mEven)
247  {
248  mA = mArray->at(mCurrentIndex + 0);
249  mB = mArray->at(mCurrentIndex + 1);
250  mC = mArray->at(mCurrentIndex + 2);
251  }
252  else
253  {
254  mA = mArray->at(mCurrentIndex + 0);
255  mB = mArray->at(mCurrentIndex + 2);
256  mC = mArray->at(mCurrentIndex + 1);
257  }
258  }
259  break;
260 
261  case PT_TRIANGLE_FAN:
262  case PT_POLYGON:
263  mCurrentIndex += 1;
264  if ( mCurrentIndex + 1 >= mEnd )
265  {
266  mCurrentIndex = mEnd;
267  }
268  else
269  if ( isPrimRestart(mCurrentIndex + 1) )
270  {
271  mIndex0 = mCurrentIndex + 2;
272  mCurrentIndex = mIndex0 + 1;
273  mA = mArray->at(mIndex0);
274  mB = mArray->at(mCurrentIndex + 0);
275  mC = mArray->at(mCurrentIndex + 1);
276  }
277  else
278  {
279  mA = mArray->at(mIndex0);
280  mB = mArray->at(mCurrentIndex + 0);
281  mC = mArray->at(mCurrentIndex + 1);
282  }
283  break;
284 
285  case PT_QUADS:
286  mCurrentIndex += 2;
287  if ( mCurrentIndex >= mEnd )
288  {
289  mCurrentIndex = mEnd;
290  }
291  else
292  if ( isPrimRestart(mCurrentIndex) )
293  {
294  mCurrentIndex += 1;
295  mEven = true;
296  mA = mArray->at(mCurrentIndex+0);
297  mB = mArray->at(mCurrentIndex+1);
298  mC = mArray->at(mCurrentIndex+2);
299  }
300  else
301  {
302  mEven = !mEven;
303  if ( mEven )
304  {
305  mA = mArray->at(mCurrentIndex+0);
306  mB = mArray->at(mCurrentIndex+1);
307  mC = mArray->at(mCurrentIndex+2);
308  }
309  else
310  {
311  mA = mArray->at(mCurrentIndex+0);
312  mB = mArray->at(mCurrentIndex+1);
313  mC = mArray->at(mCurrentIndex-2);
314  }
315  }
316  break;
317 
318  default:
319  VL_TRAP();
320  break;
321  }
322 
323  // if we are not at the end then add base vertices
324  if (mCurrentIndex != mEnd)
325  {
326  mA += mBaseVertex;
327  mB += mBaseVertex;
328  mC += mBaseVertex;
329  return true;
330  }
331  else
332  {
333  mA = mB = mC = -1;
334  return false;
335  }
336  }
337 
338  void setBaseVertex(int base_vert) { mBaseVertex = base_vert; }
339  int baseVertex() const { return mBaseVertex; }
340 
341  private:
342  bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; }
343 
344  private:
345  const TArray* mArray;
346  EPrimitiveType mPrimType;
347  int mA, mB, mC;
348  int mCurrentIndex;
349  int mIndex0;
350  int mEnd;
351  int mBaseVertex;
352  unsigned int mPrimRestartIndex;
353  bool mPrimRestartOn;
354  bool mEven;
355  };
356 //-----------------------------------------------------------------------------
357 // TriangleIteratorDirect
358 //-----------------------------------------------------------------------------
361  {
363 
364  public:
366  {
367  VL_DEBUG_SET_OBJECT_NAME()
368  mCurrentIndex = mStart = mEnd = 0;
369  mA = mB = mC = -1;
370  mPrimType = prim_type;
371  mEven = true;
372  }
373 
374  bool hasNext() const { return mCurrentIndex != mEnd; }
375 
376  virtual int a() const { return mA; }
377  virtual int b() const { return mB; }
378  virtual int c() const { return mC; }
379 
380  void initialize(int start, int end)
381  {
382  VL_CHECK(end >= start)
383  mStart = start;
384  mCurrentIndex = mEnd = end;
385  mA = mB = mC = -1;
386  mEven = true;
387  switch(mPrimType)
388  {
389  case PT_TRIANGLES:
390  // VL_CHECK( (end - start) % 3 == 0 ) /* primitive restart might screw up this */
391  mCurrentIndex = start;
392  mA = start + 0;
393  mB = start + 1;
394  mC = start + 2;
395  break;
396  case PT_TRIANGLE_STRIP:
397  mCurrentIndex = start;
398  mA = start + 0;
399  mB = start + 1;
400  mC = start + 2;
401  break;
402  case PT_TRIANGLE_FAN:
403  case PT_POLYGON:
404  mCurrentIndex = start + 1;
405  mA = start + 0;
406  mB = start + 1;
407  mC = start + 2;
408  break;
409  case PT_QUADS:
410  // VL_CHECK( (end - start) % 4 == 0 ) /* primitive restart might screw up this */
411  mCurrentIndex = start;
412  mA = start + 0;
413  mB = start + 1;
414  mC = start + 2;
415  break;
416  case PT_QUAD_STRIP:
417  // VL_CHECK( (end - start) % 2 == 0 ) /* primitive restart might screw up this */
418  mCurrentIndex = start;
419  mA = start + 0;
420  mB = start + 1;
421  mC = start + 2;
422  break;
423  default:
424  break;
425  }
426  }
427 
428  bool next()
429  {
430  // reached the end
431  if ( mCurrentIndex == mEnd )
432  return false;
433 
434  switch(mPrimType)
435  {
436 
437  case PT_TRIANGLES:
438  mCurrentIndex += 3;
439  // check for the end
440  if ( mCurrentIndex >= mEnd )
441  mCurrentIndex = mEnd;
442  else
443  {
444  mA = mCurrentIndex + 0;
445  mB = mCurrentIndex + 1;
446  mC = mCurrentIndex + 2;
447  }
448  break;
449 
450  case PT_QUAD_STRIP:
451  case PT_TRIANGLE_STRIP:
452  mCurrentIndex += 1;
453  if ( mCurrentIndex + 2 >= mEnd )
454  mCurrentIndex = mEnd;
455  else
456  {
457  mEven = !mEven;
458  if (mEven)
459  {
460  mA = mCurrentIndex + 0;
461  mB = mCurrentIndex + 1;
462  mC = mCurrentIndex + 2;
463  }
464  else
465  {
466  mA = mCurrentIndex + 0;
467  mB = mCurrentIndex + 2;
468  mC = mCurrentIndex + 1;
469  }
470  }
471  break;
472 
473  case PT_TRIANGLE_FAN:
474  case PT_POLYGON:
475  mCurrentIndex += 1;
476  if ( mCurrentIndex + 1 >= mEnd )
477  {
478  mCurrentIndex = mEnd;
479  }
480  else
481  {
482  mA = mStart;
483  mB = mCurrentIndex+0;
484  mC = mCurrentIndex+1;
485  }
486  break;
487 
488  case PT_QUADS:
489  mCurrentIndex += 2;
490  if ( mCurrentIndex >= mEnd )
491  {
492  mCurrentIndex = mEnd;
493  }
494  else
495  {
496  mEven = !mEven;
497  if ( mEven )
498  {
499  mA = mCurrentIndex+0;
500  mB = mCurrentIndex+1;
501  mC = mCurrentIndex+2;
502  }
503  else
504  {
505  mA = mCurrentIndex+0;
506  mB = mCurrentIndex+1;
507  mC = mCurrentIndex-2;
508  }
509  }
510  break;
511 
512  default:
513  VL_TRAP();
514  break;
515  }
516 
517  // if we are not at the end then add base vertices
518  if (mCurrentIndex == mEnd)
519  {
520  mA = mB = mC = -1;
521  return false;
522  }
523  else
524  return true;
525  }
526 
527  private:
528  EPrimitiveType mPrimType;
529  int mA, mB, mC;
530  int mCurrentIndex;
531  int mStart;
532  int mEnd;
533  bool mEven;
534  };
535 //-----------------------------------------------------------------------------
536 // TriangleIteratorMulti
537 //-----------------------------------------------------------------------------
539  template<class TArray>
541  {
543 
544  public:
545  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)
546  :TriangleIteratorIndexed<TArray>( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx)
547  {
548  VL_DEBUG_SET_OBJECT_NAME()
549  mpBaseVertices = p_base_vertices;
550  mpCountVector = p_count_vector;
551  mStart = 0;
552  mCurPrim = 0;
553  }
554 
555  void initialize()
556  {
557  VL_CHECK( mpBaseVertices->size() == mpCountVector->size() )
558  if ( (*mpBaseVertices).size() )
559  TriangleIteratorIndexed<TArray>::setBaseVertex( (*mpBaseVertices)[mCurPrim] );
560  int end = mStart + (*mpCountVector)[mCurPrim];
562  // abort if could not initialize (primitive not supported)
564  mCurPrim = (int)(*mpCountVector).size()-1;
565  }
566 
567  bool next()
568  {
570  return true;
571  else
572  if ( mCurPrim < (int)(*mpCountVector).size()-1 )
573  {
574  mStart += (*mpCountVector)[mCurPrim];
575  mCurPrim++;
576  initialize();
577  return true;
578  }
579  else
580  return false;
581  }
582 
583  bool hasNext() const
584  {
585  if ( !TriangleIteratorIndexed<TArray>::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 )
586  return false;
587  else
588  return true;
589  }
590 
591  protected:
592  const std::vector<GLint>* mpBaseVertices;
593  const std::vector<GLsizei>* mpCountVector;
594  int mCurPrim;
595  int mStart;
596  };
597 //-----------------------------------------------------------------------------
598 // TriangleIterator
599 //-----------------------------------------------------------------------------
604  {
605  public:
607 
609  bool next() { return mIterator->next(); }
610 
611  bool operator++() { return next(); }
612 
614  bool hasNext() { return mIterator->hasNext(); }
615 
617  int a() const { return mIterator->a(); }
618 
620  int b() const { return mIterator->b(); }
621 
623  int c() const { return mIterator->c(); }
624 
625  protected:
627  };
628 //-----------------------------------------------------------------------------
629 }
630 
631 #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.