Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
14 KiB

  1. /**************************************************************************
  2. * *
  3. * Copyright (C) 1989, Silicon Graphics, Inc. *
  4. * *
  5. * These coded instructions, statements, and computer programs contain *
  6. * unpublished proprietary information of Silicon Graphics, Inc., and *
  7. * are protected by Federal copyright law. They may not be disclosed *
  8. * to third parties or copied or duplicated in any form, in whole or *
  9. * in part, without the prior written consent of Silicon Graphics, Inc. *
  10. * *
  11. **************************************************************************/
  12. /* triangulate.c */
  13. /* Derrick Burns - 1989 */
  14. #include <glos.h>
  15. #include <stdlib.h>
  16. #include <GL/gl.h>
  17. #include <GL/glu.h>
  18. #include "monotone.h"
  19. #define do_out_vert(x,y) do_out_vertex(x, y)
  20. #define EPSILON 0.0
  21. static void do_out_begin( GLUtriangulatorObj *, GLenum );
  22. static void do_out_edgeflag( GLUtriangulatorObj *, GLboolean );
  23. static void do_out_vertex( GLUtriangulatorObj *, Vert * );
  24. static void do_out_end( GLUtriangulatorObj * );
  25. static void do_out_triangle( GLUtriangulatorObj *, Vert *, Vert *,
  26. Vert * );
  27. static void checkabove( GLUtriangulatorObj *, Vert *, Vert *, Vert *);
  28. /*----------------------------------------------------------------------------
  29. * init_triangulate - reinitialize triangulation data structures
  30. *----------------------------------------------------------------------------
  31. */
  32. void
  33. __gl_init_triangulate( GLUtriangulatorObj *tobj, long nverts )
  34. {
  35. if( tobj->init ) {
  36. if( nverts > tobj->vcount ) {
  37. myfree( (char *)tobj->vdata );
  38. tobj->vcount = nverts * 2;
  39. tobj->vdata = (Vert **)
  40. mymalloc( (unsigned int) tobj->vcount * sizeof(Vert *) );
  41. }
  42. } else {
  43. tobj->init = 1;
  44. tobj->vcount = nverts;
  45. tobj->vdata = (Vert **)
  46. mymalloc( (unsigned int) tobj->vcount * sizeof(Vert *) );
  47. }
  48. }
  49. /*----------------------------------------------------------------------------
  50. * clear_triangulate - free triangulation data structures
  51. *----------------------------------------------------------------------------
  52. */
  53. void
  54. __gl_clear_triangulate( GLUtriangulatorObj *tobj )
  55. {
  56. if( tobj->init == 1 ) {
  57. myfree( (char *) tobj->vdata );
  58. tobj->init = 0;
  59. }
  60. }
  61. /*----------------------------------------------------------------------------
  62. * nextuppervert - find next vertex on upper chain
  63. *----------------------------------------------------------------------------
  64. */
  65. static Vert *
  66. __gl_nextuppervert( GLUtriangulatorObj *tobj )
  67. {
  68. return (tobj->vtop == tobj->vlast || tobj->vbottom == tobj->vtop->prev)
  69. ? 0 : tobj->vtop->prev;
  70. }
  71. /*----------------------------------------------------------------------------
  72. * nextlowervert - find next vertex on lower chain
  73. *----------------------------------------------------------------------------
  74. */
  75. static Vert *
  76. __gl_nextlowervert( GLUtriangulatorObj *tobj )
  77. {
  78. return (tobj->vbottom == tobj->vlast || tobj->vtop == tobj->vbottom->next)
  79. ? 0 : tobj->vbottom->next;
  80. }
  81. /*----------------------------------------------------------------------------
  82. * testccw - test if top three verts on stack make ccw_vert turn
  83. *----------------------------------------------------------------------------
  84. */
  85. static int
  86. testccw( GLUtriangulatorObj *tobj ) /* tobj->lastedge == 1 */
  87. {
  88. float s0, t0, s1, t1, s2, t2;
  89. float area;
  90. s0 = tobj->vdata[tobj->vdatalast]->s;
  91. t0 = tobj->vdata[tobj->vdatalast]->t;
  92. s1 = tobj->vdata[tobj->vdatatop-1]->s;
  93. t1 = tobj->vdata[tobj->vdatatop-1]->t;
  94. s2 = tobj->vdata[tobj->vdatatop-2]->s;
  95. t2 = tobj->vdata[tobj->vdatatop-2]->t;
  96. area = s0*(t1-t2) - s1*(t0-t2) + s2*(t0-t1);
  97. return (area < (float)-EPSILON) ? 0 : 1;
  98. }
  99. /*----------------------------------------------------------------------------
  100. * testcw - test if top three verts on stack make cw turn
  101. *----------------------------------------------------------------------------
  102. */
  103. static int
  104. testcw( GLUtriangulatorObj *tobj ) /* tobj->lastedge == 0 */
  105. {
  106. float s0, t0, s1, t1, s2, t2;
  107. float area;
  108. s0 = tobj->vdata[tobj->vdatalast]->s;
  109. t0 = tobj->vdata[tobj->vdatalast]->t;
  110. s1 = tobj->vdata[tobj->vdatatop-1]->s;
  111. t1 = tobj->vdata[tobj->vdatatop-1]->t;
  112. s2 = tobj->vdata[tobj->vdatatop-2]->s;
  113. t2 = tobj->vdata[tobj->vdatatop-2]->t;
  114. area = s0*(t1-t2) - s1*(t0-t2) + s2*(t0-t1);
  115. return (area > (float)EPSILON) ? 0 : 1;
  116. }
  117. /*----------------------------------------------------------------------------
  118. * pushvert - place vertex on stack
  119. *----------------------------------------------------------------------------
  120. */
  121. static void
  122. pushvert( GLUtriangulatorObj *tobj, Vert *v )
  123. {
  124. ++tobj->vdatatop;
  125. assert( tobj->vdatatop < tobj->vcount );
  126. tobj->vdata[tobj->vdatatop] = v;
  127. }
  128. /*----------------------------------------------------------------------------
  129. * addedge - process new vertex
  130. *----------------------------------------------------------------------------
  131. */
  132. static void
  133. addedge( GLUtriangulatorObj *tobj, Vert *v, long edge )
  134. {
  135. long i;
  136. pushvert( tobj, v );
  137. if( tobj->vdatatop < 2 ) {
  138. tobj->lastedge = edge;
  139. return;
  140. }
  141. tobj->vdatalast = tobj->vdatatop;
  142. if( tobj->lastedge != edge ) {
  143. if( tobj->lastedge == 1 ) {
  144. if ( tobj->vdatalast-1 == 1 ) {
  145. do_out_begin( tobj, GL_TRIANGLES );
  146. } else {
  147. do_out_begin( tobj, GL_TRIANGLE_FAN );
  148. }
  149. do_out_vert( tobj, tobj->vdata[tobj->vdatalast] );
  150. for( i = tobj->vdatalast-1; i >= 1; i-- ) {
  151. do_out_vert( tobj, tobj->vdata[i] );
  152. }
  153. tobj->vdatatop = tobj->vdatalast;
  154. do_out_vert( tobj, tobj->vdata[0] );
  155. do_out_end( tobj );
  156. tobj->lastedge = 0;
  157. } else {
  158. if ( tobj->vdatalast-1 == 1 ) {
  159. do_out_begin( tobj, GL_TRIANGLES );
  160. } else {
  161. do_out_begin( tobj, GL_TRIANGLE_FAN );
  162. }
  163. do_out_vert( tobj, tobj->vdata[tobj->vdatalast] );
  164. do_out_vert( tobj, tobj->vdata[0]);
  165. for( i = 1; i < tobj->vdatalast; i++ ) {
  166. do_out_vert( tobj, tobj->vdata[i] );
  167. }
  168. tobj->vdatatop = tobj->vdatalast;
  169. do_out_end( tobj );
  170. tobj->lastedge = 1;
  171. }
  172. tobj->vdata[0] = tobj->vdata[tobj->vdatalast-1];
  173. tobj->vdata[1] = tobj->vdata[tobj->vdatalast];
  174. tobj->vdatatop = 1;
  175. } else {
  176. if( tobj->lastedge == 1 ) {
  177. if( ! testccw( tobj ) ) return;
  178. do {
  179. tobj->vdatatop--;
  180. } while( (tobj->vdatatop > 1) && testccw( tobj ) );
  181. if ( tobj->vdatalast - tobj->vdatatop == 1 ) {
  182. do_out_begin( tobj, GL_TRIANGLES );
  183. } else {
  184. do_out_begin( tobj, GL_TRIANGLE_FAN );
  185. }
  186. do_out_vert( tobj, tobj->vdata[tobj->vdatalast] );
  187. do_out_vert( tobj, tobj->vdata[tobj->vdatalast-1] );
  188. for( i = tobj->vdatalast-2; i >= tobj->vdatatop-1; i-- ) {
  189. do_out_vert( tobj, tobj->vdata[i] );
  190. }
  191. do_out_end( tobj );
  192. } else {
  193. if( ! testcw( tobj ) ) return;
  194. do {
  195. tobj->vdatatop--;
  196. } while( (tobj->vdatatop > 1) && testcw( tobj ) );
  197. if ( tobj->vdatalast - tobj->vdatatop == 1 ) {
  198. do_out_begin( tobj, GL_TRIANGLES );
  199. } else {
  200. do_out_begin( tobj, GL_TRIANGLE_FAN );
  201. }
  202. do_out_vert( tobj, tobj->vdata[tobj->vdatalast] );
  203. for( i = tobj->vdatatop-1; i <= tobj->vdatalast-2; i++ ) {
  204. do_out_vert( tobj, tobj->vdata[i] );
  205. }
  206. do_out_vert( tobj, tobj->vdata[tobj->vdatalast-1] );
  207. do_out_end( tobj );
  208. }
  209. tobj->vdata[tobj->vdatatop] = tobj->vdata[tobj->vdatalast];
  210. }
  211. }
  212. /*----------------------------------------------------------------------------
  213. * triangulate - triangulate a monotone loop of vertices
  214. *----------------------------------------------------------------------------
  215. */
  216. void
  217. __gl_triangulate( GLUtriangulatorObj *tobj, Vert *v, long count )
  218. {
  219. Vert *vnext;
  220. __gl_init_triangulate( tobj, count );
  221. tobj->vlast = __gl_last_vert( v );
  222. tobj->vdatatop = -1;
  223. pushvert( tobj, tobj->vbottom = tobj->vtop = __gl_first_vert( v ) );
  224. tobj->vtop = __gl_nextuppervert( tobj );
  225. tobj->vbottom = __gl_nextlowervert( tobj );
  226. assert( tobj->vtop && tobj->vbottom );
  227. while ( 1 ) {
  228. if (tobj->vtop->s < tobj->vbottom->s) {
  229. addedge( tobj, tobj->vtop, 1);
  230. tobj->vtop = __gl_nextuppervert( tobj );
  231. if (tobj->vtop == 0) {
  232. while (tobj->vbottom) {
  233. vnext = __gl_nextlowervert( tobj );
  234. addedge( tobj, tobj->vbottom, (vnext ? 0 : 2 ) );
  235. tobj->vbottom = vnext;
  236. }
  237. break;
  238. }
  239. } else {
  240. addedge( tobj, tobj->vbottom, 0);
  241. tobj->vbottom = __gl_nextlowervert( tobj );
  242. if (tobj->vbottom == 0) {
  243. while (tobj->vtop) {
  244. vnext = __gl_nextuppervert( tobj );
  245. addedge( tobj, tobj->vtop, (vnext ? 1 : 2 ) );
  246. tobj->vtop = vnext;
  247. }
  248. break;
  249. }
  250. }
  251. }
  252. assert( tobj->vdatatop < 2 );
  253. }
  254. /*----------------------------------------------------------------------------
  255. * triangulateloop - count vertices in loop and split into triangle meshes
  256. *----------------------------------------------------------------------------
  257. */
  258. void
  259. __gl_triangulateloop( GLUtriangulatorObj *tobj, Vert *v )
  260. {
  261. short count = 0;
  262. Vert *vl = v;
  263. do {
  264. count++;
  265. v = v->next;
  266. } while( v != vl );
  267. __gl_triangulate( tobj, v, count );
  268. }
  269. static void
  270. do_out_begin( GLUtriangulatorObj *tobj, GLenum what )
  271. {
  272. switch( what ) {
  273. case GL_TRIANGLES:
  274. tobj->tritype = GL_TRIANGLES;
  275. tobj->saveCount = 0;
  276. if (tobj->doingTriangles) return;
  277. tobj->doingTriangles = 1;
  278. break;
  279. case GL_TRIANGLE_FAN:
  280. case GL_TRIANGLE_STRIP:
  281. if (tobj->edgeflag) {
  282. /* We convert fans and strips into independent triangles because
  283. ** we can't set edge flags for fans and strips.
  284. */
  285. tobj->tritype = what;
  286. tobj->saveCount = 0;
  287. tobj->reverse = GL_FALSE;
  288. if (tobj->doingTriangles) return;
  289. tobj->doingTriangles = 1;
  290. /* Change "what" so we tell user we are doing GL_TRIANGLES */
  291. what = GL_TRIANGLES;
  292. } else {
  293. /* So do_out_vertex() doesn't try to interpret anything */
  294. tobj->tritype = -1;
  295. if (tobj->doingTriangles) {
  296. tobj->doingTriangles = 0;
  297. do_out_end( tobj );
  298. }
  299. }
  300. break;
  301. }
  302. if (*tobj->begin) {
  303. (*tobj->begin)( what );
  304. tobj->inBegin = GL_TRUE;
  305. }
  306. }
  307. static void
  308. do_out_vertex( GLUtriangulatorObj *tobj, Vert *vertex )
  309. {
  310. /*
  311. ** tobj->tritype is set to GL_TRIANGLE_FAN or GL_TRIANGLE_STRIP if this
  312. ** routine needs to interpret incoming vertices from these
  313. ** primitives and convert them into independent triangles.
  314. ** Otherwise, tobj->tritype is GL_TRIANGLES, and we just ship the
  315. ** vertex to the dispatcher.
  316. */
  317. switch(tobj->tritype) {
  318. case GL_TRIANGLE_FAN:
  319. if (tobj->saveCount < 2) {
  320. tobj->saved[tobj->saveCount] = vertex;
  321. tobj->saveCount++;
  322. return;
  323. } else {
  324. if (tobj->vertex) {
  325. do_out_triangle( tobj, tobj->saved[0], tobj->saved[1], vertex);
  326. tobj->saved[1] = vertex;
  327. }
  328. }
  329. break;
  330. case GL_TRIANGLE_STRIP:
  331. if (tobj->saveCount < 2) {
  332. tobj->saved[tobj->saveCount] = vertex;
  333. tobj->saveCount++;
  334. return;
  335. } else {
  336. if (!tobj->reverse) {
  337. if (tobj->vertex) {
  338. do_out_triangle( tobj, tobj->saved[0], tobj->saved[1],
  339. vertex);
  340. }
  341. tobj->reverse = GL_TRUE;
  342. } else {
  343. if (tobj->vertex) {
  344. do_out_triangle( tobj, tobj->saved[1], tobj->saved[0],
  345. vertex);
  346. }
  347. tobj->reverse = GL_FALSE;
  348. }
  349. tobj->saved[0] = tobj->saved[1];
  350. tobj->saved[1] = vertex;
  351. }
  352. break;
  353. case GL_TRIANGLES:
  354. if (tobj->saveCount < 2) {
  355. tobj->saved[tobj->saveCount] = vertex;
  356. tobj->saveCount++;
  357. return;
  358. } else {
  359. do_out_triangle( tobj, tobj->saved[0], tobj->saved[1], vertex);
  360. tobj->saveCount=0;
  361. }
  362. break;
  363. default:
  364. /* Pass it along, no interpretation */
  365. if (tobj->vertex) {
  366. (*tobj->vertex)( vertex->data );
  367. }
  368. break;
  369. }
  370. }
  371. static void
  372. do_out_triangle( GLUtriangulatorObj *tobj, Vert *v1, Vert *v2, Vert *v3 )
  373. {
  374. if (v1->nextid == v2->myid) {
  375. do_out_edgeflag( tobj, GL_TRUE );
  376. } else {
  377. do_out_edgeflag( tobj, GL_FALSE );
  378. }
  379. if (tobj->vertex) {
  380. (*tobj->vertex)( v1->data );
  381. }
  382. if (v2->nextid == v3->myid) {
  383. do_out_edgeflag( tobj, GL_TRUE );
  384. } else {
  385. do_out_edgeflag( tobj, GL_FALSE );
  386. }
  387. if (tobj->vertex) {
  388. (*tobj->vertex)( v2->data );
  389. }
  390. if (v3->nextid == v1->myid) {
  391. do_out_edgeflag( tobj, GL_TRUE );
  392. } else {
  393. do_out_edgeflag( tobj, GL_FALSE );
  394. }
  395. if (tobj->vertex) {
  396. (*tobj->vertex)( v3->data );
  397. }
  398. }
  399. static void
  400. do_out_edgeflag( GLUtriangulatorObj *tobj, GLboolean value )
  401. {
  402. if (value == tobj->currentEdgeFlag) return;
  403. tobj->currentEdgeFlag = value;
  404. if (tobj->edgeflag) {
  405. (*tobj->edgeflag)(tobj->currentEdgeFlag);
  406. }
  407. }
  408. static void
  409. do_out_end( GLUtriangulatorObj *tobj )
  410. {
  411. if (tobj->doingTriangles) return;
  412. if (tobj->end) {
  413. (*tobj->end)();
  414. tobj->inBegin = GL_FALSE;
  415. }
  416. }
  417. void
  418. __gl_cleanup( GLUtriangulatorObj *tobj )
  419. {
  420. if (tobj->inBegin) {
  421. (*tobj->end)();
  422. tobj->inBegin = GL_FALSE;
  423. tobj->doingTriangles = 0;
  424. }
  425. }
  426. void
  427. __gl_checktriangulate( GLUtriangulatorObj *tobj, Vert *v )
  428. {
  429. Vert *vb, *vt, *vl;
  430. vl = __gl_last_vert( v );
  431. vb = vt = __gl_first_vert( v );
  432. vb = vb->next;
  433. vt = vt->prev;
  434. if( vb == vt ) return;
  435. while( 1 ) {
  436. if( vt->s < vb->s ) {
  437. checkabove( tobj, vt, vb->prev, vb );
  438. vt = vt->prev;
  439. if( vt == vl ) {
  440. for( ; vb != vl; vb=vb->next )
  441. checkabove( tobj, vb, vl, vl->next );
  442. break;
  443. }
  444. } else {
  445. checkabove( tobj, vb, vt, vt->next );
  446. vb = vb->next;
  447. if( vb == vl ) {
  448. for( ; vt != vl; vt=vt->prev )
  449. checkabove( tobj, vt, vl->prev, vl );
  450. break;
  451. }
  452. }
  453. }
  454. }
  455. static void
  456. checkabove( GLUtriangulatorObj *tobj, Vert *v0, Vert *v1, Vert *v2 )
  457. {
  458. float area;
  459. area = v0->s*(v1->t-v2->t) - v1->s*(v0->t-v2->t) + v2->s*(v0->t-v1->t);
  460. if( area < (float)0 )
  461. __gl_in_error( tobj, 8 );
  462. }