Windows NT 4.0 source code leak
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.

173 lines
5.9 KiB

5 years ago
  1. /*
  2. ** Copyright 1994, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. **
  17. ** Author: Eric Veach, July 1994.
  18. */
  19. #include "geom.h"
  20. #include "mesh.h"
  21. #include "tessmono.h"
  22. #include <assert.h>
  23. #define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \
  24. eDst->Sym->winding += eSrc->Sym->winding)
  25. /* __gl_meshTesselateMonoRegion( face ) tesselates a monotone region
  26. * (what else would it do??) The region must consist of a single
  27. * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
  28. * case means that any vertical line intersects the interior of the
  29. * region in a single interval.
  30. *
  31. * Tesselation consists of adding interior edges (actually pairs of
  32. * half-edges), to split the region into non-overlapping triangles.
  33. *
  34. * The basic idea is explained in Preparata and Shamos (which I don''t
  35. * have handy right now), although their implementation is more
  36. * complicated than this one. The are two edge chains, an upper chain
  37. * and a lower chain. We process all vertices from both chains in order,
  38. * from right to left.
  39. *
  40. * The algorithm ensures that the following invariant holds after each
  41. * vertex is processed: the untesselated region consists of two
  42. * chains, where one chain (say the upper) is a single edge, and
  43. * the other chain is concave. The left vertex of the single edge
  44. * is always to the left of all vertices in the concave chain.
  45. *
  46. * Each step consists of adding the rightmost unprocessed vertex to one
  47. * of the two chains, and forming a fan of triangles from the rightmost
  48. * of two chain endpoints. Determining whether we can add each triangle
  49. * to the fan is a simple orientation test. By making the fan as large
  50. * as possible, we restore the invariant (check it yourself).
  51. */
  52. void __gl_meshTesselateMonoRegion( GLUface *face )
  53. {
  54. GLUhalfEdge *up, *lo;
  55. /* All edges are oriented CCW around the boundary of the region.
  56. * First, find the half-edge whose origin vertex is rightmost.
  57. * Since the sweep goes from left to right, face->anEdge should
  58. * be close to the edge we want.
  59. */
  60. up = face->anEdge;
  61. assert( up->Lnext != up && up->Lnext->Lnext != up );
  62. for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev )
  63. ;
  64. for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext )
  65. ;
  66. lo = up->Lprev;
  67. while( up->Lnext != lo ) {
  68. if( VertLeq( up->Dst, lo->Org )) {
  69. /* up->Dst is on the left. It is safe to form triangles from lo->Org.
  70. * The EdgeGoesLeft test guarantees progress even when some triangles
  71. * are CW, given that the upper and lower chains are truly monotone.
  72. */
  73. while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext )
  74. || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) {
  75. lo = __gl_meshConnect( lo->Lnext, lo )->Sym;
  76. }
  77. lo = lo->Lprev;
  78. } else {
  79. /* lo->Org is on the left. We can make CCW triangles from up->Dst. */
  80. while( lo->Lnext != up && (EdgeGoesRight( up->Lprev )
  81. || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) {
  82. up = __gl_meshConnect( up, up->Lprev )->Sym;
  83. }
  84. up = up->Lnext;
  85. }
  86. }
  87. /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region
  88. * can be tesselated in a fan from this leftmost vertex.
  89. */
  90. assert( lo->Lnext != up );
  91. while( lo->Lnext->Lnext != up ) {
  92. lo = __gl_meshConnect( lo->Lnext, lo )->Sym;
  93. }
  94. }
  95. /* __gl_meshTesselateInterior( mesh ) tesselates each region of
  96. * the mesh which is marked "inside" the polygon. Each such region
  97. * must be monotone.
  98. */
  99. void __gl_meshTesselateInterior( GLUmesh *mesh )
  100. {
  101. GLUface *f, *next;
  102. /*LINTED*/
  103. for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
  104. /* Make sure we don''t try to tesselate the new triangles. */
  105. next = f->next;
  106. if( f->inside ) {
  107. __gl_meshTesselateMonoRegion( f );
  108. }
  109. }
  110. }
  111. /* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
  112. * which are not marked "inside" the polygon. Since further mesh operations
  113. * on NULL faces are not allowed, the main purpose is to clean up the
  114. * mesh so that exterior loops are not represented in the data structure.
  115. */
  116. void __gl_meshDiscardExterior( GLUmesh *mesh )
  117. {
  118. GLUface *f, *next;
  119. /*LINTED*/
  120. for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
  121. /* Since f will be destroyed, save its next pointer. */
  122. next = f->next;
  123. if( ! f->inside ) {
  124. __gl_meshZapFace( f );
  125. }
  126. }
  127. }
  128. #define MARKED_FOR_DELETION 0x7fffffff
  129. /* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
  130. * winding numbers on all edges so that regions marked "inside" the
  131. * polygon have a winding number of "value", and regions outside
  132. * have a winding number of 0.
  133. *
  134. * If keepOnlyBoundary is TRUE, it also deletes all edges which do not
  135. * separate an interior region from an exterior one.
  136. */
  137. void __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
  138. GLboolean keepOnlyBoundary )
  139. {
  140. GLUhalfEdge *e, *eNext;
  141. for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
  142. eNext = e->next;
  143. if( e->Rface->inside != e->Lface->inside ) {
  144. /* This is a boundary edge (one side is interior, one is exterior). */
  145. e->winding = (e->Lface->inside) ? value : -value;
  146. } else {
  147. /* Both regions are interior, or both are exterior. */
  148. if( ! keepOnlyBoundary ) {
  149. e->winding = 0;
  150. } else {
  151. __gl_meshDelete( e );
  152. }
  153. }
  154. }
  155. }