/* * $RCSfile: Project.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision: 1.4 $ * $Date: 2007/02/09 17:20:20 $ * $State: Exp $ */ // ---------------------------------------------------------------------- // // The reference to Fast Industrial Strength Triangulation (FIST) code // in this release by Sun Microsystems is related to Sun's rewrite of // an early version of FIST. FIST was originally created by Martin // Held and Joseph Mitchell at Stony Brook University and is // incorporated by Sun under an agreement with The Research Foundation // of SUNY (RFSUNY). The current version of FIST is available for // commercial use under a license agreement with RFSUNY on behalf of // the authors and Stony Brook University. Please contact the Office // of Technology Licensing at Stony Brook, phone 631-632-9009, for // licensing information. // // ---------------------------------------------------------------------- package com.sun.j3d.utils.geometry; import javax.vecmath.*; import java.io.*; import java.util.*; class Project { /** * This function projects the vertices of the polygons referenced by * loops[i1,..,i2-1] to an approximating plane. */ static void projectFace(Triangulator triRef, int loopMin, int loopMax) { Vector3f normal, nr; int i, j; double d; normal = new Vector3f(); nr = new Vector3f(); // determine the normal of the plane onto which the points get projected determineNormal(triRef, triRef.loops[loopMin], normal); j = loopMin + 1; if (j < loopMax) { for (i = j; i < loopMax; ++i) { determineNormal(triRef, triRef.loops[i], nr); if (Basic.dotProduct(normal, nr) < 0.0) { Basic.invertVector(nr); } Basic.vectorAdd(normal, nr, normal); } d = Basic.lengthL2(normal); if (Numerics.gt(d, Triangulator.ZERO)) { Basic.divScalar(d, normal); } else { // System.out.println("*** ProjectFace: zero-length normal vector!? ***\n"); normal.x = normal.y = 0.0f; normal.z = 1.0f; } } // project the points onto this plane. the projected points are stored in // the array `points[0,..,numPoints]' // System.out.println("loopMin " + loopMin + " loopMax " + loopMax); projectPoints(triRef, loopMin, loopMax, normal); } /** * This function computes the average of all normals defined by triples of * successive vertices of the polygon. we'll see whether this is a good * heuristic for finding a suitable plane normal... */ static void determineNormal(Triangulator triRef, int ind, Vector3f normal) { Vector3f nr, pq, pr; int ind0, ind1, ind2; int i0, i1, i2; double d; ind1 = ind; i1 = triRef.fetchData(ind1); ind0 = triRef.fetchPrevData(ind1); i0 = triRef.fetchData(ind0); ind2 = triRef.fetchNextData(ind1); i2 = triRef.fetchData(ind2); pq = new Vector3f(); Basic.vectorSub((Tuple3f) triRef.vertices[i0], (Tuple3f) triRef.vertices[i1], (Vector3f) pq); pr = new Vector3f(); Basic.vectorSub((Tuple3f) triRef.vertices[i2], (Tuple3f) triRef.vertices[i1], (Vector3f) pr); nr = new Vector3f(); Basic.vectorProduct(pq, pr, nr); d = Basic.lengthL2(nr); if (Numerics.gt(d, Triangulator.ZERO)) { Basic.divScalar(d, nr); normal.set(nr); } else { normal.x = normal.y = normal.z = 0.0f; } pq.set(pr); ind1 = ind2; ind2 = triRef.fetchNextData(ind1); i2 = triRef.fetchData(ind2); while (ind1 != ind) { Basic.vectorSub((Tuple3f) triRef.vertices[i2], (Tuple3f) triRef.vertices[i1], pr); Basic.vectorProduct(pq, pr, nr); d = Basic.lengthL2(nr); if (Numerics.gt(d, Triangulator.ZERO)) { Basic.divScalar(d, nr); if (Basic.dotProduct(normal, nr) < 0.0) { Basic.invertVector(nr); } Basic.vectorAdd(normal, nr, normal); } pq.set(pr); ind1 = ind2; ind2 = triRef.fetchNextData(ind1); i2 = triRef.fetchData(ind2); } d = Basic.lengthL2(normal); if (Numerics.gt(d, Triangulator.ZERO)) { Basic.divScalar(d, normal); } else { //System.out.println("*** DetermineNormal: zero-length normal vector!? ***\n"); normal.x = normal.y = 0.0f; normal.z = 1.0f; } } /** * This function maps the vertices of the polygon referenced by `ind' to the * plane n3.x * x + n3.y * y + n3.z * z = 0. every mapped vertex (x,y,z) * is then expressed in terms of (x',y',z'), where z'=0. this is * achieved by transforming the original vertices into a coordinate system * whose z-axis coincides with n3, and whose two other coordinate axes n1 * and n2 are orthonormal on n3. note that n3 is supposed to be of unit * length! */ static void projectPoints(Triangulator triRef, int i1, int i2, Vector3f n3) { Matrix4f matrix = new Matrix4f(); Point3f vtx = new Point3f(); Vector3f n1, n2; double d; int ind, ind1; int i, j1; n1 = new Vector3f(); n2 = new Vector3f(); // choose n1 and n2 appropriately if ((Math.abs(n3.x) > 0.1) || (Math.abs(n3.y) > 0.1)) { n1.x = -n3.y; n1.y = n3.x; n1.z = 0.0f; } else { n1.x = n3.z; n1.z = -n3.x; n1.y = 0.0f; } d = Basic.lengthL2(n1); Basic.divScalar(d, n1); Basic.vectorProduct(n1, n3, n2); d = Basic.lengthL2(n2); Basic.divScalar(d, n2); // initialize the transformation matrix matrix.m00 = n1.x; matrix.m01 = n1.y; matrix.m02 = n1.z; matrix.m03 = 0.0f; // translation of the coordinate system matrix.m10 = n2.x; matrix.m11 = n2.y; matrix.m12 = n2.z; matrix.m13 = 0.0f; // translation of the coordinate system matrix.m20 = n3.x; matrix.m21 = n3.y; matrix.m22 = n3.z; matrix.m23 = 0.0f; // translation of the coordinate system matrix.m30 = 0.0f; matrix.m31 = 0.0f; matrix.m32 = 0.0f; matrix.m33 = 1.0f; // transform the vertices and store the transformed vertices in the array // `points' triRef.initPnts(20); for (i = i1; i < i2; ++i) { ind = triRef.loops[i]; ind1 = ind; j1 = triRef.fetchData(ind1); matrix.transform((Point3f)triRef.vertices[j1], vtx); j1 = triRef.storePoint(vtx.x, vtx.y); triRef.updateIndex(ind1, j1); ind1 = triRef.fetchNextData(ind1); j1 = triRef.fetchData(ind1); while (ind1 != ind) { matrix.transform(triRef.vertices[j1], vtx); j1 = triRef.storePoint(vtx.x, vtx.y); triRef.updateIndex(ind1, j1); ind1 = triRef.fetchNextData(ind1); j1 = triRef.fetchData(ind1); } } } }