1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. 35 * All rights reserved. 36 */ 37 38 /* 39 ** License Applicability. Except to the extent portions of this file are 40 ** made subject to an alternative license as permitted in the SGI Free 41 ** Software License B, Version 1.1 (the "License"), the contents of this 42 ** file are subject only to the provisions of the License. You may not use 43 ** this file except in compliance with the License. You may obtain a copy 44 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 45 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: 46 ** 47 ** http://oss.sgi.com/projects/FreeB 48 ** 49 ** Note that, as provided in the License, the Software is distributed on an 50 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS 51 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND 52 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A 53 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. 54 ** 55 ** NOTE: The Original Code (as defined below) has been licensed to Sun 56 ** Microsystems, Inc. ("Sun") under the SGI Free Software License B 57 ** (Version 1.1), shown above ("SGI License"). Pursuant to Section 58 ** 3.2(3) of the SGI License, Sun is distributing the Covered Code to 59 ** you under an alternative license ("Alternative License"). This 60 ** Alternative License includes all of the provisions of the SGI License 61 ** except that Section 2.2 and 11 are omitted. Any differences between 62 ** the Alternative License and the SGI License are offered solely by Sun 63 ** and not by SGI. 64 ** 65 ** Original Code. The Original Code is: OpenGL Sample Implementation, 66 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, 67 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. 68 ** Copyright in any portions created by third parties is as indicated 69 ** elsewhere herein. All Rights Reserved. 70 ** 71 ** Additional Notice Provisions: The application programming interfaces 72 ** established by SGI in conjunction with the Original Code are The 73 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released 74 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version 75 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X 76 ** Window System(R) (Version 1.3), released October 19, 1998. This software 77 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation 78 ** published by SGI, but has not been independently verified as being 79 ** compliant with the OpenGL(R) version 1.2.1 Specification. 80 ** 81 ** Author: Eric Veach, July 1994 82 ** Java Port: Pepijn Van Eeckhoudt, July 2003 83 ** Java Port: Nathan Parker Burg, August 2003 84 */ 85 package org.lwjgl.util.glu.tessellation; 86 87 class Geom { Geom()88 private Geom() { 89 } 90 91 /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), 92 * evaluates the t-coord of the edge uw at the s-coord of the vertex v. 93 * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. 94 * If uw is vertical (and thus passes thru v), the result is zero. 95 * 96 * The calculation is extremely accurate and stable, even when v 97 * is very close to u or w. In particular if we set v->t = 0 and 98 * let r be the negated result (this evaluates (uw)(v->s)), then 99 * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). 100 */ EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w)101 static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) { 102 double gapL, gapR; 103 104 assert (VertLeq(u, v) && VertLeq(v, w)); 105 106 gapL = v.s - u.s; 107 gapR = w.s - v.s; 108 109 if (gapL + gapR > 0) { 110 if (gapL < gapR) { 111 return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)); 112 } else { 113 return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)); 114 } 115 } 116 /* vertical line */ 117 return 0; 118 } 119 EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w)120 static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) { 121 double gapL, gapR; 122 123 assert (VertLeq(u, v) && VertLeq(v, w)); 124 125 gapL = v.s - u.s; 126 gapR = w.s - v.s; 127 128 if (gapL + gapR > 0) { 129 return (v.t - w.t) * gapL + (v.t - u.t) * gapR; 130 } 131 /* vertical line */ 132 return 0; 133 } 134 135 136 /*********************************************************************** 137 * Define versions of EdgeSign, EdgeEval with s and t transposed. 138 */ 139 TransEval(GLUvertex u, GLUvertex v, GLUvertex w)140 static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) { 141 /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), 142 * evaluates the t-coord of the edge uw at the s-coord of the vertex v. 143 * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. 144 * If uw is vertical (and thus passes thru v), the result is zero. 145 * 146 * The calculation is extremely accurate and stable, even when v 147 * is very close to u or w. In particular if we set v->s = 0 and 148 * let r be the negated result (this evaluates (uw)(v->t)), then 149 * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). 150 */ 151 double gapL, gapR; 152 153 assert (TransLeq(u, v) && TransLeq(v, w)); 154 155 gapL = v.t - u.t; 156 gapR = w.t - v.t; 157 158 if (gapL + gapR > 0) { 159 if (gapL < gapR) { 160 return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)); 161 } else { 162 return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)); 163 } 164 } 165 /* vertical line */ 166 return 0; 167 } 168 TransSign(GLUvertex u, GLUvertex v, GLUvertex w)169 static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) { 170 /* Returns a number whose sign matches TransEval(u,v,w) but which 171 * is cheaper to evaluate. Returns > 0, == 0 , or < 0 172 * as v is above, on, or below the edge uw. 173 */ 174 double gapL, gapR; 175 176 assert (TransLeq(u, v) && TransLeq(v, w)); 177 178 gapL = v.t - u.t; 179 gapR = w.t - v.t; 180 181 if (gapL + gapR > 0) { 182 return (v.s - w.s) * gapL + (v.s - u.s) * gapR; 183 } 184 /* vertical line */ 185 return 0; 186 } 187 188 VertCCW(GLUvertex u, GLUvertex v, GLUvertex w)189 static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) { 190 /* For almost-degenerate situations, the results are not reliable. 191 * Unless the floating-point arithmetic can be performed without 192 * rounding errors, *any* implementation will give incorrect results 193 * on some degenerate inputs, so the client must have some way to 194 * handle this situation. 195 */ 196 return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; 197 } 198 199 /* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), 200 * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces 201 * this in the rare case that one argument is slightly negative. 202 * The implementation is extremely stable numerically. 203 * In particular it guarantees that the result r satisfies 204 * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate 205 * even when a and b differ greatly in magnitude. 206 */ Interpolate(double a, double x, double b, double y)207 static double Interpolate(double a, double x, double b, double y) { 208 a = (a < 0) ? 0 : a; 209 b = (b < 0) ? 0 : b; 210 if (a <= b) { 211 if (b == 0) { 212 return (x + y) / 2.0; 213 } else { 214 return (x + (y - x) * (a / (a + b))); 215 } 216 } else { 217 return (y + (x - y) * (b / (a + b))); 218 } 219 } 220 EdgeIntersect(GLUvertex o1, GLUvertex d1, GLUvertex o2, GLUvertex d2, GLUvertex v)221 static void EdgeIntersect(GLUvertex o1, GLUvertex d1, 222 GLUvertex o2, GLUvertex d2, 223 GLUvertex v) 224 /* Given edges (o1,d1) and (o2,d2), compute their point of intersection. 225 * The computed point is guaranteed to lie in the intersection of the 226 * bounding rectangles defined by each edge. 227 */ { 228 double z1, z2; 229 230 /* This is certainly not the most efficient way to find the intersection 231 * of two line segments, but it is very numerically stable. 232 * 233 * Strategy: find the two middle vertices in the VertLeq ordering, 234 * and interpolate the intersection s-value from these. Then repeat 235 * using the TransLeq ordering to find the intersection t-value. 236 */ 237 238 if (!VertLeq(o1, d1)) { 239 GLUvertex temp = o1; 240 o1 = d1; 241 d1 = temp; 242 } 243 if (!VertLeq(o2, d2)) { 244 GLUvertex temp = o2; 245 o2 = d2; 246 d2 = temp; 247 } 248 if (!VertLeq(o1, o2)) { 249 GLUvertex temp = o1; 250 o1 = o2; 251 o2 = temp; 252 temp = d1; 253 d1 = d2; 254 d2 = temp; 255 } 256 257 if (!VertLeq(o2, d1)) { 258 /* Technically, no intersection -- do our best */ 259 v.s = (o2.s + d1.s) / 2.0; 260 } else if (VertLeq(d1, d2)) { 261 /* Interpolate between o2 and d1 */ 262 z1 = EdgeEval(o1, o2, d1); 263 z2 = EdgeEval(o2, d1, d2); 264 if (z1 + z2 < 0) { 265 z1 = -z1; 266 z2 = -z2; 267 } 268 v.s = Interpolate(z1, o2.s, z2, d1.s); 269 } else { 270 /* Interpolate between o2 and d2 */ 271 z1 = EdgeSign(o1, o2, d1); 272 z2 = -EdgeSign(o1, d2, d1); 273 if (z1 + z2 < 0) { 274 z1 = -z1; 275 z2 = -z2; 276 } 277 v.s = Interpolate(z1, o2.s, z2, d2.s); 278 } 279 280 /* Now repeat the process for t */ 281 282 if (!TransLeq(o1, d1)) { 283 GLUvertex temp = o1; 284 o1 = d1; 285 d1 = temp; 286 } 287 if (!TransLeq(o2, d2)) { 288 GLUvertex temp = o2; 289 o2 = d2; 290 d2 = temp; 291 } 292 if (!TransLeq(o1, o2)) { 293 GLUvertex temp = o2; 294 o2 = o1; 295 o1 = temp; 296 temp = d2; 297 d2 = d1; 298 d1 = temp; 299 } 300 301 if (!TransLeq(o2, d1)) { 302 /* Technically, no intersection -- do our best */ 303 v.t = (o2.t + d1.t) / 2.0; 304 } else if (TransLeq(d1, d2)) { 305 /* Interpolate between o2 and d1 */ 306 z1 = TransEval(o1, o2, d1); 307 z2 = TransEval(o2, d1, d2); 308 if (z1 + z2 < 0) { 309 z1 = -z1; 310 z2 = -z2; 311 } 312 v.t = Interpolate(z1, o2.t, z2, d1.t); 313 } else { 314 /* Interpolate between o2 and d2 */ 315 z1 = TransSign(o1, o2, d1); 316 z2 = -TransSign(o1, d2, d1); 317 if (z1 + z2 < 0) { 318 z1 = -z1; 319 z2 = -z2; 320 } 321 v.t = Interpolate(z1, o2.t, z2, d2.t); 322 } 323 } 324 VertEq(GLUvertex u, GLUvertex v)325 static boolean VertEq(GLUvertex u, GLUvertex v) { 326 return u.s == v.s && u.t == v.t; 327 } 328 VertLeq(GLUvertex u, GLUvertex v)329 static boolean VertLeq(GLUvertex u, GLUvertex v) { 330 return u.s < v.s || (u.s == v.s && u.t <= v.t); 331 } 332 333 /* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ 334 TransLeq(GLUvertex u, GLUvertex v)335 static boolean TransLeq(GLUvertex u, GLUvertex v) { 336 return u.t < v.t || (u.t == v.t && u.s <= v.s); 337 } 338 EdgeGoesLeft(GLUhalfEdge e)339 static boolean EdgeGoesLeft(GLUhalfEdge e) { 340 return VertLeq(e.Sym.Org, e.Org); 341 } 342 EdgeGoesRight(GLUhalfEdge e)343 static boolean EdgeGoesRight(GLUhalfEdge e) { 344 return VertLeq(e.Org, e.Sym.Org); 345 } 346 VertL1dist(GLUvertex u, GLUvertex v)347 static double VertL1dist(GLUvertex u, GLUvertex v) { 348 return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); 349 } 350 } 351