001: /*
002: * $RCSfile: Project.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.4 $
041: * $Date: 2007/02/09 17:20:20 $
042: * $State: Exp $
043: */
044:
045: // ----------------------------------------------------------------------
046: //
047: // The reference to Fast Industrial Strength Triangulation (FIST) code
048: // in this release by Sun Microsystems is related to Sun's rewrite of
049: // an early version of FIST. FIST was originally created by Martin
050: // Held and Joseph Mitchell at Stony Brook University and is
051: // incorporated by Sun under an agreement with The Research Foundation
052: // of SUNY (RFSUNY). The current version of FIST is available for
053: // commercial use under a license agreement with RFSUNY on behalf of
054: // the authors and Stony Brook University. Please contact the Office
055: // of Technology Licensing at Stony Brook, phone 631-632-9009, for
056: // licensing information.
057: //
058: // ----------------------------------------------------------------------
059: package com.sun.j3d.utils.geometry;
060:
061: import javax.vecmath.*;
062: import java.io.*;
063: import java.util.*;
064:
065: class Project {
066:
067: /**
068: * This function projects the vertices of the polygons referenced by
069: * loops[i1,..,i2-1] to an approximating plane.
070: */
071: static void projectFace(Triangulator triRef, int loopMin,
072: int loopMax) {
073: Vector3f normal, nr;
074: int i, j;
075: double d;
076:
077: normal = new Vector3f();
078: nr = new Vector3f();
079:
080: // determine the normal of the plane onto which the points get projected
081: determineNormal(triRef, triRef.loops[loopMin], normal);
082: j = loopMin + 1;
083: if (j < loopMax) {
084: for (i = j; i < loopMax; ++i) {
085: determineNormal(triRef, triRef.loops[i], nr);
086: if (Basic.dotProduct(normal, nr) < 0.0) {
087: Basic.invertVector(nr);
088: }
089: Basic.vectorAdd(normal, nr, normal);
090: }
091: d = Basic.lengthL2(normal);
092: if (Numerics.gt(d, Triangulator.ZERO)) {
093: Basic.divScalar(d, normal);
094: } else {
095: // System.out.println("*** ProjectFace: zero-length normal vector!? ***\n");
096: normal.x = normal.y = 0.0f;
097: normal.z = 1.0f;
098: }
099: }
100:
101: // project the points onto this plane. the projected points are stored in
102: // the array `points[0,..,numPoints]'
103:
104: // System.out.println("loopMin " + loopMin + " loopMax " + loopMax);
105: projectPoints(triRef, loopMin, loopMax, normal);
106:
107: }
108:
109: /**
110: * This function computes the average of all normals defined by triples of
111: * successive vertices of the polygon. we'll see whether this is a good
112: * heuristic for finding a suitable plane normal...
113: */
114: static void determineNormal(Triangulator triRef, int ind,
115: Vector3f normal) {
116: Vector3f nr, pq, pr;
117: int ind0, ind1, ind2;
118: int i0, i1, i2;
119: double d;
120:
121: ind1 = ind;
122: i1 = triRef.fetchData(ind1);
123: ind0 = triRef.fetchPrevData(ind1);
124: i0 = triRef.fetchData(ind0);
125: ind2 = triRef.fetchNextData(ind1);
126: i2 = triRef.fetchData(ind2);
127: pq = new Vector3f();
128: Basic.vectorSub((Tuple3f) triRef.vertices[i0],
129: (Tuple3f) triRef.vertices[i1], (Vector3f) pq);
130: pr = new Vector3f();
131: Basic.vectorSub((Tuple3f) triRef.vertices[i2],
132: (Tuple3f) triRef.vertices[i1], (Vector3f) pr);
133: nr = new Vector3f();
134: Basic.vectorProduct(pq, pr, nr);
135: d = Basic.lengthL2(nr);
136: if (Numerics.gt(d, Triangulator.ZERO)) {
137: Basic.divScalar(d, nr);
138: normal.set(nr);
139: } else {
140: normal.x = normal.y = normal.z = 0.0f;
141: }
142:
143: pq.set(pr);
144: ind1 = ind2;
145: ind2 = triRef.fetchNextData(ind1);
146: i2 = triRef.fetchData(ind2);
147: while (ind1 != ind) {
148: Basic.vectorSub((Tuple3f) triRef.vertices[i2],
149: (Tuple3f) triRef.vertices[i1], pr);
150: Basic.vectorProduct(pq, pr, nr);
151: d = Basic.lengthL2(nr);
152: if (Numerics.gt(d, Triangulator.ZERO)) {
153: Basic.divScalar(d, nr);
154: if (Basic.dotProduct(normal, nr) < 0.0) {
155: Basic.invertVector(nr);
156: }
157: Basic.vectorAdd(normal, nr, normal);
158: }
159: pq.set(pr);
160: ind1 = ind2;
161: ind2 = triRef.fetchNextData(ind1);
162: i2 = triRef.fetchData(ind2);
163: }
164:
165: d = Basic.lengthL2(normal);
166: if (Numerics.gt(d, Triangulator.ZERO)) {
167: Basic.divScalar(d, normal);
168: } else {
169: //System.out.println("*** DetermineNormal: zero-length normal vector!? ***\n");
170: normal.x = normal.y = 0.0f;
171: normal.z = 1.0f;
172:
173: }
174: }
175:
176: /**
177: * This function maps the vertices of the polygon referenced by `ind' to the
178: * plane n3.x * x + n3.y * y + n3.z * z = 0. every mapped vertex (x,y,z)
179: * is then expressed in terms of (x',y',z'), where z'=0. this is
180: * achieved by transforming the original vertices into a coordinate system
181: * whose z-axis coincides with n3, and whose two other coordinate axes n1
182: * and n2 are orthonormal on n3. note that n3 is supposed to be of unit
183: * length!
184: */
185: static void projectPoints(Triangulator triRef, int i1, int i2,
186: Vector3f n3) {
187: Matrix4f matrix = new Matrix4f();
188: Point3f vtx = new Point3f();
189: Vector3f n1, n2;
190: double d;
191: int ind, ind1;
192: int i, j1;
193:
194: n1 = new Vector3f();
195: n2 = new Vector3f();
196:
197: // choose n1 and n2 appropriately
198: if ((Math.abs(n3.x) > 0.1) || (Math.abs(n3.y) > 0.1)) {
199: n1.x = -n3.y;
200: n1.y = n3.x;
201: n1.z = 0.0f;
202: } else {
203: n1.x = n3.z;
204: n1.z = -n3.x;
205: n1.y = 0.0f;
206: }
207: d = Basic.lengthL2(n1);
208: Basic.divScalar(d, n1);
209: Basic.vectorProduct(n1, n3, n2);
210: d = Basic.lengthL2(n2);
211: Basic.divScalar(d, n2);
212:
213: // initialize the transformation matrix
214: matrix.m00 = n1.x;
215: matrix.m01 = n1.y;
216: matrix.m02 = n1.z;
217: matrix.m03 = 0.0f; // translation of the coordinate system
218: matrix.m10 = n2.x;
219: matrix.m11 = n2.y;
220: matrix.m12 = n2.z;
221: matrix.m13 = 0.0f; // translation of the coordinate system
222: matrix.m20 = n3.x;
223: matrix.m21 = n3.y;
224: matrix.m22 = n3.z;
225: matrix.m23 = 0.0f; // translation of the coordinate system
226: matrix.m30 = 0.0f;
227: matrix.m31 = 0.0f;
228: matrix.m32 = 0.0f;
229: matrix.m33 = 1.0f;
230:
231: // transform the vertices and store the transformed vertices in the array
232: // `points'
233: triRef.initPnts(20);
234: for (i = i1; i < i2; ++i) {
235: ind = triRef.loops[i];
236: ind1 = ind;
237: j1 = triRef.fetchData(ind1);
238: matrix.transform((Point3f) triRef.vertices[j1], vtx);
239: j1 = triRef.storePoint(vtx.x, vtx.y);
240: triRef.updateIndex(ind1, j1);
241: ind1 = triRef.fetchNextData(ind1);
242: j1 = triRef.fetchData(ind1);
243: while (ind1 != ind) {
244: matrix.transform(triRef.vertices[j1], vtx);
245: j1 = triRef.storePoint(vtx.x, vtx.y);
246: triRef.updateIndex(ind1, j1);
247: ind1 = triRef.fetchNextData(ind1);
248: j1 = triRef.fetchData(ind1);
249: }
250: }
251: }
252:
253: }
|