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.

285 lines
7.4 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. /* monotonize.c */
  13. /* Derrick Burns - 1989 */
  14. #include <glos.h>
  15. #include <GL/gl.h>
  16. #include <GL/glu.h>
  17. #include "monotone.h"
  18. static Vert * __gl_connectedge( GLUtriangulatorObj *, Vert *, Vert * );
  19. /*----------------------------------------------------------------------------
  20. * monotonize - add edges to a polygon to create monotone pieces
  21. *----------------------------------------------------------------------------
  22. */
  23. void
  24. __gl_monotonize( GLUtriangulatorObj *tobj )
  25. {
  26. Ray *ray, *new_ray1, *new_ray2;
  27. __gl_sort_priorityq( tobj );
  28. while( __gl_more_priorityq( tobj ) ) {
  29. Vert *vert = __gl_remove_priorityq( tobj );
  30. if( vert->vclass == VC_NO_CLASS ) {
  31. ray = __gl_findray_raylist( tobj, vert );
  32. if( ray->orientation == __gl_ccw_vert( vert ) )
  33. __gl_reverse_vert( vert );
  34. (void) __gl_classify_all( vert );
  35. }
  36. switch (vert->vclass) {
  37. case VC_OK_RIGHT: /* two new rays */
  38. assert( vert->ray == 0 );
  39. ray = __gl_findray_raylist( tobj, vert );
  40. if( ray->orientation != 0 )
  41. __gl_in_error( tobj, 3 );
  42. /* compute top ray */
  43. new_ray1 = __gl_new_ray( tobj, 0 );
  44. __gl_recalc_ray(new_ray1, vert, vert->prev);
  45. if( vert->prev->vclass != VC_BAD_RIGHT )
  46. vert->prev->ray = new_ray1;
  47. /* compute middle ray */
  48. new_ray2 = __gl_new_ray( tobj, 1 );
  49. __gl_recalc_ray(new_ray2, vert, vert->next);
  50. if( vert->next->vclass != VC_OK_LEFT )
  51. vert->next->ray = new_ray2;
  52. new_ray2->vertex = vert;
  53. assert( ! ray->mustconnect );
  54. __gl_add2_raylist( ray->prev, new_ray1, new_ray2 );
  55. break;
  56. case VC_BAD_LEFT: /* two new rays */
  57. assert( vert->ray == 0 );
  58. ray = __gl_findray_raylist( tobj, vert );
  59. if( ray->orientation != 1 )
  60. __gl_in_error( tobj, 3 );
  61. /* compute top ray */
  62. new_ray1 = __gl_new_ray( tobj, 1 );
  63. __gl_recalc_ray(new_ray1, vert, vert->next);
  64. if( vert->next->vclass != VC_OK_LEFT )
  65. vert->next->ray = new_ray1;
  66. /* compute middle ray */
  67. new_ray2 = __gl_new_ray( tobj, 0 );
  68. __gl_recalc_ray(new_ray2, vert, vert->prev);
  69. if( vert->prev->vclass != VC_BAD_RIGHT )
  70. vert->prev->ray = new_ray2;
  71. new_ray1->vertex = __gl_connectedge( tobj,vert, ray->vertex);
  72. /* update bottom ray */
  73. ray->mustconnect = 0;
  74. ray->vertex = vert;
  75. __gl_add2_raylist( ray->prev, new_ray1, new_ray2 );
  76. break;
  77. case VC_OK_LEFT: /* two rays disappear */
  78. ray = vert->ray;
  79. if ( ray == NULL )
  80. __gl_in_error( tobj, 4 );
  81. __gl_checkray_vert( tobj, vert, ray->prev, ray->next->next );
  82. /* region above_ray top ray is outside */
  83. assert( ! ray->mustconnect );
  84. assert( ray->next );
  85. /* region above_ray middle ray is inside */
  86. if( ray->next->mustconnect ) {
  87. __gl_triangulateloop( tobj,__gl_connectedge( tobj,vert,ray->next->vertex));
  88. __gl_triangulateloop( tobj, vert );
  89. } else {
  90. __gl_triangulateloop( tobj, vert );
  91. }
  92. /* region above_ray bottom ray is outside */
  93. assert( ray->next->next );
  94. assert( ! ray->next->next->mustconnect );
  95. __gl_remove2_raylist( tobj, ray );
  96. __gl_delete_ray( tobj, ray->next );
  97. __gl_delete_ray( tobj, ray );
  98. break;
  99. case VC_BAD_RIGHT: /* two rays disappear */
  100. ray = vert->ray;
  101. if ( ray == NULL || ray->next == NULL )
  102. __gl_in_error( tobj, 4 );
  103. __gl_checkray_vert( tobj, vert, ray->prev, ray->next->next );
  104. if (ray->mustconnect) {
  105. vert = __gl_connectedge( tobj, vert, ray->vertex );
  106. __gl_triangulateloop( tobj, ray->vertex->next );
  107. }
  108. if ( ray->next->mustconnect ) {
  109. __gl_in_error( tobj, 8 );
  110. }
  111. assert( ray->next );
  112. assert( ray->next->next );
  113. if (ray->next->next->mustconnect)
  114. __gl_triangulateloop( tobj, __gl_connectedge( tobj, vert,
  115. ray->next->next->vertex) );
  116. ray->next->next->vertex = vert;
  117. ray->next->next->mustconnect = 1;
  118. __gl_remove2_raylist( tobj, ray );
  119. __gl_delete_ray( tobj, ray->next );
  120. __gl_delete_ray( tobj, ray );
  121. break;
  122. case VC_OK_TOP: /* one ray changes ends and coords */
  123. ray = vert->ray;
  124. if( ray == NULL || ray->next == NULL )
  125. __gl_in_error( tobj, 4 );
  126. __gl_checkray_vert( tobj, vert, ray->prev, ray->next );
  127. __gl_recalc_ray( ray, vert, vert->next );
  128. if( vert->next->vclass != VC_OK_LEFT )
  129. vert->next->ray = ray;
  130. if (ray->mustconnect) {
  131. ray->vertex = __gl_connectedge( tobj,vert,ray->vertex);
  132. ray->mustconnect = 0;
  133. __gl_triangulateloop( tobj, vert );
  134. } else {
  135. ray->vertex = vert;
  136. }
  137. assert( ray->next );
  138. assert( ! ray->next->mustconnect );
  139. break;
  140. case VC_OK_BOTTOM: /* one ray changes ends and coords */
  141. ray = vert->ray;
  142. if ( ray == NULL || ray->next == NULL )
  143. __gl_in_error( tobj, 4 );
  144. __gl_checkray_vert( tobj, vert, ray->prev, ray->next );
  145. __gl_recalc_ray( ray, vert, vert->prev );
  146. if( vert->prev->vclass != VC_BAD_RIGHT )
  147. vert->prev->ray = ray;
  148. assert( ! ray->mustconnect );
  149. assert( ray->next );
  150. if (ray->next->mustconnect) {
  151. __gl_triangulateloop( tobj,__gl_connectedge( tobj,vert, ray->next->vertex));
  152. ray->next->mustconnect = 0;
  153. ray->next->vertex = vert;
  154. } else {
  155. ray->next->vertex = vert;
  156. }
  157. break;
  158. case VC_BAD_LONE:
  159. break;
  160. case VC_BAD_ERROR:
  161. __gl_in_error( tobj, 4 );
  162. return;
  163. case VC_NO_CLASS:
  164. assert( 0 );
  165. break;
  166. }
  167. }
  168. return;
  169. }
  170. /*----------------------------------------------------------------------------
  171. * connectedge - create two anti-parallel edges splitting a polygon
  172. *----------------------------------------------------------------------------
  173. */
  174. static Vert *
  175. __gl_connectedge( GLUtriangulatorObj *tobj, Vert *x, Vert *y )
  176. {
  177. Vert *newx, *newy;
  178. if( x == 0 || y == 0 || y->prev == 0 || x->next == 0 ) {
  179. __gl_in_error( tobj, 5 );
  180. return 0;
  181. } else {
  182. assert( x->prev->next == x );
  183. assert( x->next->prev == x );
  184. assert( y->prev->next == y );
  185. assert( y->next->prev == y );
  186. assert( x->next != y );
  187. assert( x != y );
  188. newx = (Vert *) __gl_new_vert( tobj );
  189. newx->myid = x->myid;
  190. newx->nextid = x->nextid;
  191. newx->ray = x->ray;
  192. newx->vclass = x->vclass;
  193. #ifdef ADDED
  194. newx->added = x->added;
  195. #endif
  196. newx->s = x->s;
  197. newx->t = x->t;
  198. newx->data = x->data;
  199. newy = (Vert *) __gl_new_vert( tobj );
  200. newy->myid = y->myid;
  201. newy->nextid = y->nextid;
  202. newy->ray = y->ray;
  203. newy->vclass = y->vclass;
  204. #ifdef ADDED
  205. newy->added = 1;
  206. #endif
  207. newy->s = y->s;
  208. newy->t = y->t;
  209. newy->data = y->data;
  210. newx->prev = newy;
  211. newx->next = x->next;
  212. newy->next = newx;
  213. newy->prev = y->prev;
  214. newx->next->prev = newx;
  215. newy->prev->next = newy;
  216. x->next = y;
  217. y->prev = x;
  218. #ifdef ADDED
  219. x->added = 1;
  220. #endif
  221. assert( x->prev->next == x );
  222. assert( x->next->prev == x );
  223. assert( y->prev->next == y );
  224. assert( y->next->prev == y );
  225. assert( newx->prev->next == newx );
  226. assert( newx->next->prev == newx );
  227. assert( newy->prev->next == newy );
  228. assert( newy->next->prev == newy );
  229. return newx;
  230. }
  231. }