render.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
  3. * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice including the dates of first publication and
  13. * either this permission notice or a reference to
  14. * http://oss.sgi.com/projects/FreeB/
  15. * shall be included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
  22. * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. *
  25. * Except as contained in this notice, the name of Silicon Graphics, Inc.
  26. * shall not be used in advertising or otherwise to promote the sale, use or
  27. * other dealings in this Software without prior written authorization from
  28. * Silicon Graphics, Inc.
  29. */
  30. /*
  31. ** Author: Eric Veach, July 1994.
  32. **
  33. */
  34. #include "../prboom/SDL_opengl.h" // JDC
  35. //#include "gluos.h"
  36. #include <assert.h>
  37. #include <stddef.h>
  38. #include "mesh.h"
  39. #include "tess.h"
  40. #include "render.h"
  41. #define TRUE 1
  42. #define FALSE 0
  43. /* This structure remembers the information we need about a primitive
  44. * to be able to render it later, once we have determined which
  45. * primitive is able to use the most triangles.
  46. */
  47. struct FaceCount {
  48. long size; /* number of triangles used */
  49. GLUhalfEdge *eStart; /* edge where this primitive starts */
  50. void (*render)(GLUtesselator *, GLUhalfEdge *, long);
  51. /* routine to render this primitive */
  52. };
  53. static struct FaceCount MaximumFan( GLUhalfEdge *eOrig );
  54. static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig );
  55. static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
  56. static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
  57. static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
  58. long size );
  59. static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
  60. static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
  61. /************************ Strips and Fans decomposition ******************/
  62. /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
  63. * fans, strips, and separate triangles. A substantial effort is made
  64. * to use as few rendering primitives as possible (ie. to make the fans
  65. * and strips as large as possible).
  66. *
  67. * The rendering output is provided as callbacks (see the api).
  68. */
  69. void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
  70. {
  71. GLUface *f;
  72. /* Make a list of separate triangles so we can render them all at once */
  73. tess->lonelyTriList = NULL;
  74. for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
  75. f->marked = FALSE;
  76. }
  77. for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
  78. /* We examine all faces in an arbitrary order. Whenever we find
  79. * an unprocessed face F, we output a group of faces including F
  80. * whose size is maximum.
  81. */
  82. if( f->inside && ! f->marked ) {
  83. RenderMaximumFaceGroup( tess, f );
  84. assert( f->marked );
  85. }
  86. }
  87. if( tess->lonelyTriList != NULL ) {
  88. RenderLonelyTriangles( tess, tess->lonelyTriList );
  89. tess->lonelyTriList = NULL;
  90. }
  91. }
  92. static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
  93. {
  94. /* We want to find the largest triangle fan or strip of unmarked faces
  95. * which includes the given face fOrig. There are 3 possible fans
  96. * passing through fOrig (one centered at each vertex), and 3 possible
  97. * strips (one for each CCW permutation of the vertices). Our strategy
  98. * is to try all of these, and take the primitive which uses the most
  99. * triangles (a greedy approach).
  100. */
  101. GLUhalfEdge *e = fOrig->anEdge;
  102. struct FaceCount max, newFace;
  103. max.size = 1;
  104. max.eStart = e;
  105. max.render = &RenderTriangle;
  106. if( ! tess->flagBoundary ) {
  107. newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
  108. newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
  109. newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
  110. newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
  111. newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
  112. newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
  113. }
  114. (*(max.render))( tess, max.eStart, max.size );
  115. }
  116. /* Macros which keep track of faces we have marked temporarily, and allow
  117. * us to backtrack when necessary. With triangle fans, this is not
  118. * really necessary, since the only awkward case is a loop of triangles
  119. * around a single origin vertex. However with strips the situation is
  120. * more complicated, and we need a general tracking method like the
  121. * one here.
  122. */
  123. #define Marked(f) (! (f)->inside || (f)->marked)
  124. #define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
  125. #define FreeTrail(t) if( 1 ) { \
  126. while( (t) != NULL ) { \
  127. (t)->marked = FALSE; t = (t)->trail; \
  128. } \
  129. } else /* absorb trailing semicolon */
  130. static struct FaceCount MaximumFan( GLUhalfEdge *eOrig )
  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, &RenderFan };
  137. GLUface *trail = NULL;
  138. GLUhalfEdge *e;
  139. for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
  140. AddToTrail( e->Lface, trail );
  141. ++newFace.size;
  142. }
  143. for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
  144. AddToTrail( e->Rface, trail );
  145. ++newFace.size;
  146. }
  147. newFace.eStart = e;
  148. /*LINTED*/
  149. FreeTrail( trail );
  150. return newFace;
  151. }
  152. #define IsEven(n) (((n) & 1) == 0)
  153. static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig )
  154. {
  155. /* Here we are looking for a maximal strip that contains the vertices
  156. * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
  157. * reverse, such that all triangles are oriented CCW).
  158. *
  159. * Again we walk forward and backward as far as possible. However for
  160. * strips there is a twist: to get CCW orientations, there must be
  161. * an *even* number of triangles in the strip on one side of eOrig.
  162. * We walk the strip starting on a side with an even number of triangles;
  163. * if both side have an odd number, we are forced to shorten one side.
  164. */
  165. struct FaceCount newFace = { 0, NULL, &RenderStrip };
  166. long headSize = 0, tailSize = 0;
  167. GLUface *trail = NULL;
  168. GLUhalfEdge *e, *eTail, *eHead;
  169. for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
  170. AddToTrail( e->Lface, trail );
  171. ++tailSize;
  172. e = e->Dprev;
  173. if( Marked( e->Lface )) break;
  174. AddToTrail( e->Lface, trail );
  175. }
  176. eTail = e;
  177. for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
  178. AddToTrail( e->Rface, trail );
  179. ++headSize;
  180. e = e->Oprev;
  181. if( Marked( e->Rface )) break;
  182. AddToTrail( e->Rface, trail );
  183. }
  184. eHead = e;
  185. newFace.size = tailSize + headSize;
  186. if( IsEven( tailSize )) {
  187. newFace.eStart = eTail->Sym;
  188. } else if( IsEven( headSize )) {
  189. newFace.eStart = eHead;
  190. } else {
  191. /* Both sides have odd length, we must shorten one of them. In fact,
  192. * we must start from eHead to guarantee inclusion of eOrig->Lface.
  193. */
  194. --newFace.size;
  195. newFace.eStart = eHead->Onext;
  196. }
  197. /*LINTED*/
  198. FreeTrail( trail );
  199. return newFace;
  200. }
  201. static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size )
  202. {
  203. /* Just add the triangle to a triangle list, so we can render all
  204. * the separate triangles at once.
  205. */
  206. assert( size == 1 );
  207. AddToTrail( e->Lface, tess->lonelyTriList );
  208. }
  209. static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
  210. {
  211. /* Now we render all the separate triangles which could not be
  212. * grouped into a triangle fan or strip.
  213. */
  214. GLUhalfEdge *e;
  215. int newState;
  216. int edgeState = -1; /* force edge state output for first vertex */
  217. CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES );
  218. for( ; f != NULL; f = f->trail ) {
  219. /* Loop once for each edge (there will always be 3 edges) */
  220. e = f->anEdge;
  221. do {
  222. if( tess->flagBoundary ) {
  223. /* Set the "edge state" to TRUE just before we output the
  224. * first vertex of each edge on the polygon boundary.
  225. */
  226. newState = ! e->Rface->inside;
  227. if( edgeState != newState ) {
  228. edgeState = newState;
  229. CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
  230. }
  231. }
  232. CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
  233. e = e->Lnext;
  234. } while( e != f->anEdge );
  235. }
  236. CALL_END_OR_END_DATA();
  237. }
  238. static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size )
  239. {
  240. /* Render as many CCW triangles as possible in a fan starting from
  241. * edge "e". The fan *should* contain exactly "size" triangles
  242. * (otherwise we've goofed up somewhere).
  243. */
  244. CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );
  245. CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
  246. CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
  247. while( ! Marked( e->Lface )) {
  248. e->Lface->marked = TRUE;
  249. --size;
  250. e = e->Onext;
  251. CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
  252. }
  253. assert( size == 0 );
  254. CALL_END_OR_END_DATA();
  255. }
  256. static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size )
  257. {
  258. /* Render as many CCW triangles as possible in a strip starting from
  259. * edge "e". The strip *should* contain exactly "size" triangles
  260. * (otherwise we've goofed up somewhere).
  261. */
  262. CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP );
  263. CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
  264. CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
  265. while( ! Marked( e->Lface )) {
  266. e->Lface->marked = TRUE;
  267. --size;
  268. e = e->Dprev;
  269. CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
  270. if( Marked( e->Lface )) break;
  271. e->Lface->marked = TRUE;
  272. --size;
  273. e = e->Onext;
  274. CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
  275. }
  276. assert( size == 0 );
  277. CALL_END_OR_END_DATA();
  278. }
  279. /************************ Boundary contour decomposition ******************/
  280. /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
  281. * contour for each face marked "inside". The rendering output is
  282. * provided as callbacks (see the api).
  283. */
  284. void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
  285. {
  286. GLUface *f;
  287. GLUhalfEdge *e;
  288. for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
  289. if( f->inside ) {
  290. CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP );
  291. e = f->anEdge;
  292. do {
  293. CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
  294. e = e->Lnext;
  295. } while( e != f->anEdge );
  296. CALL_END_OR_END_DATA();
  297. }
  298. }
  299. }
  300. /************************ Quick-and-dirty decomposition ******************/
  301. #define SIGN_INCONSISTENT 2
  302. static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check )
  303. /*
  304. * If check==FALSE, we compute the polygon normal and place it in norm[].
  305. * If check==TRUE, we check that each triangle in the fan from v0 has a
  306. * consistent orientation with respect to norm[]. If triangles are
  307. * consistently oriented CCW, return 1; if CW, return -1; if all triangles
  308. * are degenerate return 0; otherwise (no consistent orientation) return
  309. * SIGN_INCONSISTENT.
  310. */
  311. {
  312. CachedVertex *v0 = tess->cache;
  313. CachedVertex *vn = v0 + tess->cacheCount;
  314. CachedVertex *vc;
  315. GLdouble dot, xc, yc, zc, xp, yp, zp, n[3];
  316. int sign = 0;
  317. /* Find the polygon normal. It is important to get a reasonable
  318. * normal even when the polygon is self-intersecting (eg. a bowtie).
  319. * Otherwise, the computed normal could be very tiny, but perpendicular
  320. * to the true plane of the polygon due to numerical noise. Then all
  321. * the triangles would appear to be degenerate and we would incorrectly
  322. * decompose the polygon as a fan (or simply not render it at all).
  323. *
  324. * We use a sum-of-triangles normal algorithm rather than the more
  325. * efficient sum-of-trapezoids method (used in CheckOrientation()
  326. * in normal.c). This lets us explicitly reverse the signed area
  327. * of some triangles to get a reasonable normal in the self-intersecting
  328. * case.
  329. */
  330. if( ! check ) {
  331. norm[0] = norm[1] = norm[2] = 0.0;
  332. }
  333. vc = v0 + 1;
  334. xc = vc->coords[0] - v0->coords[0];
  335. yc = vc->coords[1] - v0->coords[1];
  336. zc = vc->coords[2] - v0->coords[2];
  337. while( ++vc < vn ) {
  338. xp = xc; yp = yc; zp = zc;
  339. xc = vc->coords[0] - v0->coords[0];
  340. yc = vc->coords[1] - v0->coords[1];
  341. zc = vc->coords[2] - v0->coords[2];
  342. /* Compute (vp - v0) cross (vc - v0) */
  343. n[0] = yp*zc - zp*yc;
  344. n[1] = zp*xc - xp*zc;
  345. n[2] = xp*yc - yp*xc;
  346. dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
  347. if( ! check ) {
  348. /* Reverse the contribution of back-facing triangles to get
  349. * a reasonable normal for self-intersecting polygons (see above)
  350. */
  351. if( dot >= 0 ) {
  352. norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
  353. } else {
  354. norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
  355. }
  356. } else if( dot != 0 ) {
  357. /* Check the new orientation for consistency with previous triangles */
  358. if( dot > 0 ) {
  359. if( sign < 0 ) return SIGN_INCONSISTENT;
  360. sign = 1;
  361. } else {
  362. if( sign > 0 ) return SIGN_INCONSISTENT;
  363. sign = -1;
  364. }
  365. }
  366. }
  367. return sign;
  368. }
  369. /* __gl_renderCache( tess ) takes a single contour and tries to render it
  370. * as a triangle fan. This handles convex polygons, as well as some
  371. * non-convex polygons if we get lucky.
  372. *
  373. * Returns TRUE if the polygon was successfully rendered. The rendering
  374. * output is provided as callbacks (see the api).
  375. */
  376. GLboolean __gl_renderCache( GLUtesselator *tess )
  377. {
  378. CachedVertex *v0 = tess->cache;
  379. CachedVertex *vn = v0 + tess->cacheCount;
  380. CachedVertex *vc;
  381. GLdouble norm[3];
  382. int sign;
  383. if( tess->cacheCount < 3 ) {
  384. /* Degenerate contour -- no output */
  385. return TRUE;
  386. }
  387. norm[0] = tess->normal[0];
  388. norm[1] = tess->normal[1];
  389. norm[2] = tess->normal[2];
  390. if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
  391. ComputeNormal( tess, norm, FALSE );
  392. }
  393. sign = ComputeNormal( tess, norm, TRUE );
  394. if( sign == SIGN_INCONSISTENT ) {
  395. /* Fan triangles did not have a consistent orientation */
  396. return FALSE;
  397. }
  398. if( sign == 0 ) {
  399. /* All triangles were degenerate */
  400. return TRUE;
  401. }
  402. /* Make sure we do the right thing for each winding rule */
  403. switch( tess->windingRule ) {
  404. case GLU_TESS_WINDING_ODD:
  405. case GLU_TESS_WINDING_NONZERO:
  406. break;
  407. case GLU_TESS_WINDING_POSITIVE:
  408. if( sign < 0 ) return TRUE;
  409. break;
  410. case GLU_TESS_WINDING_NEGATIVE:
  411. if( sign > 0 ) return TRUE;
  412. break;
  413. case GLU_TESS_WINDING_ABS_GEQ_TWO:
  414. return TRUE;
  415. }
  416. CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP
  417. : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN
  418. : GL_TRIANGLES );
  419. CALL_VERTEX_OR_VERTEX_DATA( v0->data );
  420. if( sign > 0 ) {
  421. for( vc = v0+1; vc < vn; ++vc ) {
  422. CALL_VERTEX_OR_VERTEX_DATA( vc->data );
  423. }
  424. } else {
  425. for( vc = vn-1; vc > v0; --vc ) {
  426. CALL_VERTEX_OR_VERTEX_DATA( vc->data );
  427. }
  428. }
  429. CALL_END_OR_END_DATA();
  430. return TRUE;
  431. }