g4tools  5.4.0
Classes | Macros | Functions
render File Reference
#include "mesh"
#include "_tess"
Include dependency graph for render:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  FaceCount
 inlined C code : /////////////////////////////////// More...
 

Macros

#define tools_glutess_render
 
#define Marked(f)   (! (f)->inside || (f)->marked)
 
#define AddToTrail(f, t)   ((f)->trail = (t), (t) = (f), (f)->marked = TOOLS_GLU_TRUE)
 
#define FreeTrail(t)   do { while( (t) != NULL ) { (t)->marked = TOOLS_GLU_FALSE; t = (t)->trail; } } while(false)
 
#define IsEven(n)   (((n) & 1) == 0)
 

Functions

inline struct FaceCount static_MaximumFan (GLUhalfEdge *eOrig)
 
inline struct FaceCount static_MaximumStrip (GLUhalfEdge *eOrig)
 
inline void static_RenderFan (GLUtesselator *tess, GLUhalfEdge *eStart, long size)
 
inline void static_RenderStrip (GLUtesselator *tess, GLUhalfEdge *eStart, long size)
 
inline void static_RenderTriangle (GLUtesselator *tess, GLUhalfEdge *eStart, long size)
 
inline void static_RenderMaximumFaceGroup (GLUtesselator *tess, GLUface *fOrig)
 
inline void static_RenderLonelyTriangles (GLUtesselator *tess, GLUface *head)
 
void __gl_renderMesh (GLUtesselator *tess, GLUmesh *mesh)
 
void __gl_renderBoundary (GLUtesselator *tess, GLUmesh *mesh)
 
int SIGN_INCONSISTENT ()
 
inline int static_ComputeNormal (GLUtesselator *tess, GLUdouble norm[3], int check)
 
GLUboolean __gl_renderCache (GLUtesselator *tess)
 

Macro Definition Documentation

◆ AddToTrail

#define AddToTrail (   f,
 
)    ((f)->trail = (t), (t) = (f), (f)->marked = TOOLS_GLU_TRUE)

Definition at line 125 of file render.

◆ FreeTrail

#define FreeTrail (   t)    do { while( (t) != NULL ) { (t)->marked = TOOLS_GLU_FALSE; t = (t)->trail; } } while(false)

Definition at line 128 of file render.

◆ IsEven

#define IsEven (   n)    (((n) & 1) == 0)

Definition at line 155 of file render.

◆ Marked

#define Marked (   f)    (! (f)->inside || (f)->marked)

Definition at line 123 of file render.

◆ tools_glutess_render

#define tools_glutess_render

Definition at line 4 of file render.

Function Documentation

◆ __gl_renderBoundary()

void __gl_renderBoundary ( GLUtesselator tess,
GLUmesh mesh 
)
inline

Definition at line 312 of file render.

313 {
314  GLUface *f;
315  GLUhalfEdge *e;
316 
317  for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
318  if( f->inside ) {
320  e = f->anEdge;
321  do {
323  e = e->Lnext;
324  } while( e != f->anEdge );
326  }
327  }
328 }

◆ __gl_renderCache()

GLUboolean __gl_renderCache ( GLUtesselator tess)
inline

Definition at line 418 of file render.

419 {
420  CachedVertex *v0 = tess->cache;
421  CachedVertex *vn = v0 + tess->cacheCount;
422  CachedVertex *vc;
423  GLUdouble norm[3];
424  int sign;
425 
426  if( tess->cacheCount < 3 ) {
427  /* Degenerate contour -- no output */
428  return TOOLS_GLU_TRUE;
429  }
430 
431  norm[0] = tess->normal[0];
432  norm[1] = tess->normal[1];
433  norm[2] = tess->normal[2];
434  if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
435  static_ComputeNormal( tess, norm, TOOLS_GLU_FALSE );
436  }
437 
438  sign = static_ComputeNormal( tess, norm, TOOLS_GLU_TRUE );
439  if( sign == SIGN_INCONSISTENT() ) {
440  /* Fan triangles did not have a consistent orientation */
441  return TOOLS_GLU_FALSE;
442  }
443  if( sign == 0 ) {
444  /* All triangles were degenerate */
445  return TOOLS_GLU_TRUE;
446  }
447 
448  /* Make sure we do the right thing for each winding rule */
449  switch( tess->windingRule ) {
452  break;
454  if( sign < 0 ) return TOOLS_GLU_TRUE;
455  break;
457  if( sign > 0 ) return TOOLS_GLU_TRUE;
458  break;
460  return TOOLS_GLU_TRUE;
461  }
462 
464  : (tess->cacheCount > 3) ? GLU_TRIANGLE_FAN
465  : GLU_TRIANGLES );
466 
468  if( sign > 0 ) {
469  for( vc = v0+1; vc < vn; ++vc ) {
471  }
472  } else {
473  for( vc = vn-1; vc > v0; --vc ) {
475  }
476  }
478  return TOOLS_GLU_TRUE;
479 }

◆ __gl_renderMesh()

void __gl_renderMesh ( GLUtesselator tess,
GLUmesh mesh 
)
inline

Definition at line 59 of file render.

60 {
61  GLUface *f;
62 
63  /* Make a list of separate triangles so we can render them all at once */
64  tess->lonelyTriList = NULL;
65 
66  for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
68  }
69  for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
70 
71  /* We examine all faces in an arbitrary order. Whenever we find
72  * an unprocessed face F, we output a group of faces including F
73  * whose size is maximum.
74  */
75  if( f->inside && ! f->marked ) {
77  assert( f->marked );
78  }
79  }
80  if( tess->lonelyTriList != NULL ) {
82  tess->lonelyTriList = NULL;
83  }
84 }

◆ SIGN_INCONSISTENT()

int SIGN_INCONSISTENT ( )
inline

Definition at line 334 of file render.

334  {
335  static const int s_value = 2;
336  return s_value;
337 }

◆ static_ComputeNormal()

inline int static_ComputeNormal ( GLUtesselator tess,
GLUdouble  norm[3],
int  check 
)

Definition at line 339 of file render.

348 {
349  CachedVertex *v0 = tess->cache;
350  CachedVertex *vn = v0 + tess->cacheCount;
351  CachedVertex *vc;
352  GLUdouble dot, xc, yc, zc, xp, yp, zp, n[3];
353  int sign = 0;
354 
355  /* Find the polygon normal. It is important to get a reasonable
356  * normal even when the polygon is self-intersecting (eg. a bowtie).
357  * Otherwise, the computed normal could be very tiny, but perpendicular
358  * to the true plane of the polygon due to numerical noise. Then all
359  * the triangles would appear to be degenerate and we would incorrectly
360  * decompose the polygon as a fan (or simply not render it at all).
361  *
362  * We use a sum-of-triangles normal algorithm rather than the more
363  * efficient sum-of-trapezoids method (used in CheckOrientation()
364  * in normal.c). This lets us explicitly reverse the signed area
365  * of some triangles to get a reasonable normal in the self-intersecting
366  * case.
367  */
368  if( ! check ) {
369  norm[0] = norm[1] = norm[2] = 0.0;
370  }
371 
372  vc = v0 + 1;
373  xc = vc->coords[0] - v0->coords[0];
374  yc = vc->coords[1] - v0->coords[1];
375  zc = vc->coords[2] - v0->coords[2];
376  while( ++vc < vn ) {
377  xp = xc; yp = yc; zp = zc;
378  xc = vc->coords[0] - v0->coords[0];
379  yc = vc->coords[1] - v0->coords[1];
380  zc = vc->coords[2] - v0->coords[2];
381 
382  /* Compute (vp - v0) cross (vc - v0) */
383  n[0] = yp*zc - zp*yc;
384  n[1] = zp*xc - xp*zc;
385  n[2] = xp*yc - yp*xc;
386 
387  dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
388  if( ! check ) {
389  /* Reverse the contribution of back-facing triangles to get
390  * a reasonable normal for self-intersecting polygons (see above)
391  */
392  if( dot >= 0 ) {
393  norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
394  } else {
395  norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
396  }
397  } else if( dot != 0 ) {
398  /* Check the new orientation for consistency with previous triangles */
399  if( dot > 0 ) {
400  if( sign < 0 ) return SIGN_INCONSISTENT();
401  sign = 1;
402  } else {
403  if( sign > 0 ) return SIGN_INCONSISTENT();
404  sign = -1;
405  }
406  }
407  }
408  return sign;
409 }

◆ static_MaximumFan()

struct FaceCount static_MaximumFan ( GLUhalfEdge eOrig)

Definition at line 130 of file render.

131 {
132  /* eOrig->Lface is the face we want to render. We want to find the size
133  * of a maximal fan around eOrig->Org. To do this we just walk around
134  * the origin vertex as far as possible in both directions.
135  */
136  struct FaceCount newFace = { 0, NULL, &static_RenderFan };
137  GLUface *trail = NULL;
138  GLUhalfEdge *e;
139 
140  for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
141  AddToTrail( e->Lface, trail );
142  ++newFace.size;
143  }
144  for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
145  AddToTrail( e->Rface, trail );
146  ++newFace.size;
147  }
148  newFace.eStart = e;
149  /*LINTED*/
150  FreeTrail( trail );
151  return newFace;
152 }

◆ static_MaximumStrip()

struct FaceCount static_MaximumStrip ( GLUhalfEdge eOrig)

Definition at line 157 of file render.

158 {
159  /* Here we are looking for a maximal strip that contains the vertices
160  * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
161  * reverse, such that all triangles are oriented CCW).
162  *
163  * Again we walk forward and backward as far as possible. However for
164  * strips there is a twist: to get CCW orientations, there must be
165  * an *even* number of triangles in the strip on one side of eOrig.
166  * We walk the strip starting on a side with an even number of triangles;
167  * if both side have an odd number, we are forced to shorten one side.
168  */
169  struct FaceCount newFace = { 0, NULL, &static_RenderStrip };
170  long headSize = 0, tailSize = 0;
171  GLUface *trail = NULL;
172  GLUhalfEdge *e, *eTail, *eHead;
173 
174  for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
175  AddToTrail( e->Lface, trail );
176  ++tailSize;
177  e = e->Dprev;
178  if( Marked( e->Lface )) break;
179  AddToTrail( e->Lface, trail );
180  }
181  eTail = e;
182 
183  for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
184  AddToTrail( e->Rface, trail );
185  ++headSize;
186  e = e->Oprev;
187  if( Marked( e->Rface )) break;
188  AddToTrail( e->Rface, trail );
189  }
190  eHead = e;
191 
192  newFace.size = tailSize + headSize;
193  if( IsEven( tailSize )) {
194  newFace.eStart = eTail->Sym;
195  } else if( IsEven( headSize )) {
196  newFace.eStart = eHead;
197  } else {
198  /* Both sides have odd length, we must shorten one of them. In fact,
199  * we must start from eHead to guarantee inclusion of eOrig->Lface.
200  */
201  --newFace.size;
202  newFace.eStart = eHead->Onext;
203  }
204  /*LINTED*/
205  FreeTrail( trail );
206  return newFace;
207 }

◆ static_RenderFan()

void static_RenderFan ( GLUtesselator tess,
GLUhalfEdge eStart,
long  size 
)

Definition at line 256 of file render.

257 {
258  /* Render as many CCW triangles as possible in a fan starting from
259  * edge "e". The fan *should* contain exactly "size" triangles
260  * (otherwise we've goofed up somewhere).
261  */
263  CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
264  CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
265 
266  while( ! Marked( e->Lface )) {
267  e->Lface->marked = TOOLS_GLU_TRUE;
268  --size;
269  e = e->Onext;
270  CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
271  }
272 
273  assert( size == 0 );
275 }

◆ static_RenderLonelyTriangles()

void static_RenderLonelyTriangles ( GLUtesselator tess,
GLUface head 
)

Definition at line 221 of file render.

222 {
223  /* Now we render all the separate triangles which could not be
224  * grouped into a triangle fan or strip.
225  */
226  GLUhalfEdge *e;
227  int newState;
228  int edgeState = -1; /* force edge state output for first vertex */
229 
231 
232  for( ; f != NULL; f = f->trail ) {
233  /* Loop once for each edge (there will always be 3 edges) */
234 
235  e = f->anEdge;
236  do {
237  if( tess->flagBoundary ) {
238  /* Set the "edge state" to TOOLS_GLU_TRUE just before we output the
239  * first vertex of each edge on the polygon boundary.
240  */
241  newState = ! e->Rface->inside;
242  if( edgeState != newState ) {
243  edgeState = newState;
245  }
246  }
248 
249  e = e->Lnext;
250  } while( e != f->anEdge );
251  }
253 }

◆ static_RenderMaximumFaceGroup()

void static_RenderMaximumFaceGroup ( GLUtesselator tess,
GLUface fOrig 
)

Definition at line 87 of file render.

88 {
89  /* We want to find the largest triangle fan or strip of unmarked faces
90  * which includes the given face fOrig. There are 3 possible fans
91  * passing through fOrig (one centered at each vertex), and 3 possible
92  * strips (one for each CCW permutation of the vertices). Our strategy
93  * is to try all of these, and take the primitive which uses the most
94  * triangles (a greedy approach).
95  */
96  GLUhalfEdge *e = fOrig->anEdge;
97  struct FaceCount max, newFace;
98 
99  max.size = 1;
100  max.eStart = e;
101  max.render = &static_RenderTriangle;
102 
103  if( ! tess->flagBoundary ) {
104  newFace = static_MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
105  newFace = static_MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
106  newFace = static_MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
107 
108  newFace = static_MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
109  newFace = static_MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
110  newFace = static_MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
111  }
112  (*(max.render))( tess, max.eStart, max.size );
113 }

◆ static_RenderStrip()

void static_RenderStrip ( GLUtesselator tess,
GLUhalfEdge eStart,
long  size 
)

Definition at line 278 of file render.

279 {
280  /* Render as many CCW triangles as possible in a strip starting from
281  * edge "e". The strip *should* contain exactly "size" triangles
282  * (otherwise we've goofed up somewhere).
283  */
285  CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
286  CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
287 
288  while( ! Marked( e->Lface )) {
289  e->Lface->marked = TOOLS_GLU_TRUE;
290  --size;
291  e = e->Dprev;
292  CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
293  if( Marked( e->Lface )) break;
294 
295  e->Lface->marked = TOOLS_GLU_TRUE;
296  --size;
297  e = e->Onext;
298  CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
299  }
300 
301  assert( size == 0 );
303 }

◆ static_RenderTriangle()

void static_RenderTriangle ( GLUtesselator tess,
GLUhalfEdge eStart,
long  size 
)

Definition at line 210 of file render.

211 {
212  /* Just add the triangle to a triangle list, so we can render all
213  * the separate triangles at once.
214  */
215  assert( size == 1 );
216  AddToTrail( e->Lface, tess->lonelyTriList );
217  (void)size;
218 }
GLUmesh::fHead
GLUface fHead
Definition: mesh:133
GLU_TESS_WINDING_POSITIVE
#define GLU_TESS_WINDING_POSITIVE
Definition: _glu:39
IsEven
#define IsEven(n)
Definition: render:155
GLU_LINE_LOOP
#define GLU_LINE_LOOP
Definition: _glu:85
FaceCount::size
long size
Definition: render:31
static_RenderMaximumFaceGroup
inline void static_RenderMaximumFaceGroup(GLUtesselator *tess, GLUface *fOrig)
Definition: render:87
GLUtesselator::cache
CachedVertex cache[GLU_TESS_MAX_CACHE]
Definition: _tess:76
CALL_END_OR_END_DATA
#define CALL_END_OR_END_DATA()
Definition: _tess:118
CachedVertex
Definition: _tess:22
GLUtesselator::normal
GLUdouble normal[3]
Definition: _tess:41
GLUtesselator::lonelyTriList
GLUface * lonelyTriList
Definition: _tess:62
GLUhalfEdge::Lnext
GLUhalfEdge * Lnext
Definition: mesh:110
GLUtesselator::cacheCount
int cacheCount
Definition: _tess:75
GLUface::marked
GLUboolean marked
Definition: mesh:102
GLUhalfEdge
Definition: mesh:106
static_MaximumFan
inline struct FaceCount static_MaximumFan(GLUhalfEdge *eOrig)
Definition: render:130
GLUvertex::data
void * data
Definition: mesh:86
SIGN_INCONSISTENT
int SIGN_INCONSISTENT()
Definition: render:334
FaceCount
inlined C code : ///////////////////////////////////
Definition: render:30
GLUhalfEdge::Sym
GLUhalfEdge * Sym
Definition: mesh:108
GLU_TESS_WINDING_ABS_GEQ_TWO
#define GLU_TESS_WINDING_ABS_GEQ_TWO
Definition: _glu:138
CachedVertex::coords
GLUdouble coords[3]
Definition: _tess:23
GLUtesselator::boundaryOnly
GLUboolean boundaryOnly
Definition: _tess:61
TOOLS_GLU_TRUE
#define TOOLS_GLU_TRUE
Definition: _glu:82
GLUdouble
double GLUdouble
Definition: _glu:16
static_RenderFan
inline void static_RenderFan(GLUtesselator *tess, GLUhalfEdge *eStart, long size)
Definition: render:256
FaceCount::eStart
GLUhalfEdge * eStart
Definition: render:32
GLU_TRIANGLES
#define GLU_TRIANGLES
Definition: _glu:86
GLU_TESS_WINDING_NEGATIVE
#define GLU_TESS_WINDING_NEGATIVE
Definition: _glu:40
GLUhalfEdge::Onext
GLUhalfEdge * Onext
Definition: mesh:109
FreeTrail
#define FreeTrail(t)
Definition: render:128
TOOLS_GLU_FALSE
#define TOOLS_GLU_FALSE
Definition: _glu:81
GLU_TESS_WINDING_ODD
#define GLU_TESS_WINDING_ODD
Definition: _glu:38
tools::file::size
bool size(const std::string &a_file, long &a_size)
Definition: fsize:13
static_ComputeNormal
inline int static_ComputeNormal(GLUtesselator *tess, GLUdouble norm[3], int check)
Definition: render:339
GLUtesselator::windingRule
GLUenum windingRule
Definition: _tess:48
CALL_VERTEX_OR_VERTEX_DATA
#define CALL_VERTEX_OR_VERTEX_DATA(a)
Definition: _tess:108
CALL_BEGIN_OR_BEGIN_DATA
#define CALL_BEGIN_OR_BEGIN_DATA(a)
Definition: _tess:103
GLU_TRIANGLE_STRIP
#define GLU_TRIANGLE_STRIP
Definition: _glu:87
GLUface::inside
GLUboolean inside
Definition: mesh:103
AddToTrail
#define AddToTrail(f, t)
Definition: render:125
static_MaximumStrip
inline struct FaceCount static_MaximumStrip(GLUhalfEdge *eOrig)
Definition: render:157
GLUhalfEdge::Lface
GLUface * Lface
Definition: mesh:112
GLU_TRIANGLE_FAN
#define GLU_TRIANGLE_FAN
Definition: _glu:88
GLUface
Definition: mesh:94
GLUhalfEdge::Org
GLUvertex * Org
Definition: mesh:111
GLUface::next
GLUface * next
Definition: mesh:95
static_RenderLonelyTriangles
inline void static_RenderLonelyTriangles(GLUtesselator *tess, GLUface *head)
Definition: render:221
GLUtesselator::flagBoundary
GLUboolean flagBoundary
Definition: _tess:60
GLU_TESS_WINDING_NONZERO
#define GLU_TESS_WINDING_NONZERO
Definition: _glu:137
Marked
#define Marked(f)
Definition: render:123
CachedVertex::data
void * data
Definition: _tess:24
static_RenderStrip
inline void static_RenderStrip(GLUtesselator *tess, GLUhalfEdge *eStart, long size)
Definition: render:278
static_RenderTriangle
inline void static_RenderTriangle(GLUtesselator *tess, GLUhalfEdge *eStart, long size)
Definition: render:210
CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA
#define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a)
Definition: _tess:113
GLUface::anEdge
GLUhalfEdge * anEdge
Definition: mesh:97