Leaked source code of windows server 2003
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.

250 lines
8.1 KiB

  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 <assert.h>
  20. #include "mesh.h"
  21. #include "geom.h"
  22. int __gl_vertLeq( GLUvertex *u, GLUvertex *v )
  23. {
  24. /* Returns TRUE if u is lexicographically <= v. */
  25. return VertLeq( u, v );
  26. }
  27. GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
  28. {
  29. /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
  30. * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
  31. * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
  32. * If uw is vertical (and thus passes thru v), the result is zero.
  33. *
  34. * The calculation is extremely accurate and stable, even when v
  35. * is very close to u or w. In particular if we set v->t = 0 and
  36. * let r be the negated result (this evaluates (uw)(v->s)), then
  37. * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
  38. */
  39. GLdouble gapL, gapR;
  40. assert( VertLeq( u, v ) && VertLeq( v, w ));
  41. gapL = v->s - u->s;
  42. gapR = w->s - v->s;
  43. if( gapL + gapR > 0 ) {
  44. if( gapL < gapR ) {
  45. return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR));
  46. } else {
  47. return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR));
  48. }
  49. }
  50. /* vertical line */
  51. return 0;
  52. }
  53. GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
  54. {
  55. /* Returns a number whose sign matches EdgeEval(u,v,w) but which
  56. * is cheaper to evaluate. Returns > 0, == 0 , or < 0
  57. * as v is above, on, or below the edge uw.
  58. */
  59. GLdouble gapL, gapR;
  60. assert( VertLeq( u, v ) && VertLeq( v, w ));
  61. gapL = v->s - u->s;
  62. gapR = w->s - v->s;
  63. if( gapL + gapR > 0 ) {
  64. return (v->t - w->t) * gapL + (v->t - u->t) * gapR;
  65. }
  66. /* vertical line */
  67. return 0;
  68. }
  69. /***********************************************************************
  70. * Define versions of EdgeSign, EdgeEval with s and t transposed.
  71. */
  72. GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
  73. {
  74. /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
  75. * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
  76. * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v.
  77. * If uw is vertical (and thus passes thru v), the result is zero.
  78. *
  79. * The calculation is extremely accurate and stable, even when v
  80. * is very close to u or w. In particular if we set v->s = 0 and
  81. * let r be the negated result (this evaluates (uw)(v->t)), then
  82. * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s).
  83. */
  84. GLdouble gapL, gapR;
  85. assert( TransLeq( u, v ) && TransLeq( v, w ));
  86. gapL = v->t - u->t;
  87. gapR = w->t - v->t;
  88. if( gapL + gapR > 0 ) {
  89. if( gapL < gapR ) {
  90. return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR));
  91. } else {
  92. return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR));
  93. }
  94. }
  95. /* vertical line */
  96. return 0;
  97. }
  98. GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
  99. {
  100. /* Returns a number whose sign matches TransEval(u,v,w) but which
  101. * is cheaper to evaluate. Returns > 0, == 0 , or < 0
  102. * as v is above, on, or below the edge uw.
  103. */
  104. GLdouble gapL, gapR;
  105. assert( TransLeq( u, v ) && TransLeq( v, w ));
  106. gapL = v->t - u->t;
  107. gapR = w->t - v->t;
  108. if( gapL + gapR > 0 ) {
  109. return (v->s - w->s) * gapL + (v->s - u->s) * gapR;
  110. }
  111. /* vertical line */
  112. return 0;
  113. }
  114. int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w )
  115. {
  116. /* For almost-degenerate situations, the results are not reliable.
  117. * Unless the floating-point arithmetic can be performed without
  118. * rounding errors, *any* implementation will give incorrect results
  119. * on some degenerate inputs, so the client must have some way to
  120. * handle this situation.
  121. */
  122. return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0;
  123. }
  124. /* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b),
  125. * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces
  126. * this in the rare case that one argument is slightly negative.
  127. * The implementation is extremely stable numerically.
  128. * In particular it guarantees that the result r satisfies
  129. * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
  130. * even when a and b differ greatly in magnitude.
  131. */
  132. #define RealInterpolate(a,x,b,y) \
  133. (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \
  134. ((a <= b) ? ((b == 0) ? ((x+y) / 2) \
  135. : (x + (y-x) * (a/(a+b)))) \
  136. : (y + (x-y) * (b/(a+b)))))
  137. #ifndef DEBUG
  138. #define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y)
  139. #else
  140. /* Claim: the ONLY property the sweep algorithm relies on is that
  141. * MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that.
  142. */
  143. #include <stdlib.h>
  144. extern int RandomInterpolate;
  145. GLdouble Interpolate( GLdouble a, GLdouble x, GLdouble b, GLdouble y)
  146. {
  147. #ifndef NT
  148. printf("*********************%d\n",RandomInterpolate);
  149. #endif
  150. if( RandomInterpolate ) {
  151. a = 1.2 * drand48() - 0.1;
  152. a = (a < 0) ? 0 : ((a > 1) ? 1 : a);
  153. b = 1.0 - a;
  154. }
  155. return RealInterpolate(a,x,b,y);
  156. }
  157. #endif
  158. #define Swap(a,b) if (1) { GLUvertex *t = a; a = b; b = t; } else
  159. void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
  160. GLUvertex *o2, GLUvertex *d2,
  161. GLUvertex *v )
  162. /* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
  163. * The computed point is guaranteed to lie in the intersection of the
  164. * bounding rectangles defined by each edge.
  165. */
  166. {
  167. GLdouble z1, z2;
  168. /* This is certainly not the most efficient way to find the intersection
  169. * of two line segments, but it is very numerically stable.
  170. *
  171. * Strategy: find the two middle vertices in the VertLeq ordering,
  172. * and interpolate the intersection s-value from these. Then repeat
  173. * using the TransLeq ordering to find the intersection t-value.
  174. */
  175. if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); }
  176. if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); }
  177. if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
  178. if( ! VertLeq( o2, d1 )) {
  179. /* Technically, no intersection -- do our best */
  180. v->s = (o2->s + d1->s) / 2;
  181. } else if( VertLeq( d1, d2 )) {
  182. /* Interpolate between o2 and d1 */
  183. z1 = EdgeEval( o1, o2, d1 );
  184. z2 = EdgeEval( o2, d1, d2 );
  185. if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
  186. v->s = Interpolate( z1, o2->s, z2, d1->s );
  187. } else {
  188. /* Interpolate between o2 and d2 */
  189. z1 = EdgeSign( o1, o2, d1 );
  190. z2 = -EdgeSign( o1, d2, d1 );
  191. if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
  192. v->s = Interpolate( z1, o2->s, z2, d2->s );
  193. }
  194. /* Now repeat the process for t */
  195. if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); }
  196. if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); }
  197. if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
  198. if( ! TransLeq( o2, d1 )) {
  199. /* Technically, no intersection -- do our best */
  200. v->t = (o2->t + d1->t) / 2;
  201. } else if( TransLeq( d1, d2 )) {
  202. /* Interpolate between o2 and d1 */
  203. z1 = TransEval( o1, o2, d1 );
  204. z2 = TransEval( o2, d1, d2 );
  205. if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
  206. v->t = Interpolate( z1, o2->t, z2, d1->t );
  207. } else {
  208. /* Interpolate between o2 and d2 */
  209. z1 = TransSign( o1, o2, d1 );
  210. z2 = -TransSign( o1, d2, d1 );
  211. if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
  212. v->t = Interpolate( z1, o2->t, z2, d2->t );
  213. }
  214. }