001: /*
002: * $RCSfile: CachedFrustum.java,v $
003: *
004: * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.8 $
028: * $Date: 2008/02/28 20:17:20 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035:
036: /**
037: * The CachedFrustum class is used to pre compute data for a set of view
038: * frustum planes which allows more efficient intersection testing.
039: *
040: * The CachedFrustum caches data for frustums for effecient intersection
041: * testing.
042: */
043:
044: // this class assumes the planes are in the following order:
045: // left plane = frustumPlanes[0]
046: // right plane = frustumPlanes[1]
047: // top plane = frustumPlanes[2]
048: // bottom plane = frustumPlanes[3]
049: // front plane = frustumPlanes[4]
050: // back plane = frustumPlanes[5]
051: class CachedFrustum {
052:
053: static final double EPSILON = 1.0E-8;
054: Vector4d[] clipPlanes;
055: Point3d[] verts;
056: Point3d upper, lower; // bounding box of frustum
057: Point3d center; // center of frustum
058:
059: /**
060: * Constructs and initializes a new CachedFrustum using the values
061: * provided in the argument.
062: * @param planes array specifying the frustum's clip plane position
063: */
064: CachedFrustum(Vector4d[] planes) {
065: int i;
066: if (planes.length < 6) {
067: throw new IllegalArgumentException(J3dI18N
068: .getString("CachedFrustum0"));
069: }
070: clipPlanes = new Vector4d[6];
071: verts = new Point3d[8];
072: upper = new Point3d();
073: lower = new Point3d();
074: center = new Point3d();
075:
076: for (i = 0; i < 8; i++) {
077: verts[i] = new Point3d();
078: }
079:
080: for (i = 0; i < 6; i++) {
081: clipPlanes[i] = new Vector4d(planes[i]);
082: }
083: computeValues(clipPlanes);
084: }
085:
086: /**
087: * Constructs and initializes a new default CachedFrustum
088: * @param planes array specifying the frustum's clip planes
089: */
090: CachedFrustum() {
091: int i;
092: clipPlanes = new Vector4d[6];
093: upper = new Point3d();
094: lower = new Point3d();
095: verts = new Point3d[8];
096: center = new Point3d();
097:
098: for (i = 0; i < 8; i++) {
099: verts[i] = new Point3d();
100: }
101: for (i = 0; i < 6; i++) {
102: clipPlanes[i] = new Vector4d();
103: }
104:
105: }
106:
107: /**
108: * Returns a string containing the values of the CachedFrustum.
109: */
110: public String toString() {
111: return (clipPlanes[0].toString() + "\n"
112: + clipPlanes[1].toString() + "\n"
113: + clipPlanes[2].toString() + "\n"
114: + clipPlanes[3].toString() + "\n"
115: + clipPlanes[4].toString() + "\n"
116: + clipPlanes[5].toString() + "\n" + "corners=" + "\n"
117: + verts[0].toString() + "\n" + verts[1].toString()
118: + "\n" + verts[2].toString() + "\n"
119: + verts[3].toString() + "\n" + verts[4].toString()
120: + "\n" + verts[5].toString() + "\n"
121: + verts[6].toString() + "\n" + verts[7].toString());
122: }
123:
124: /**
125: * Sets the values of the CachedFrustum based on a new set of frustum planes.
126: * @param planes array specifying the frustum's clip planes
127: */
128: void set(Vector4d[] planes) {
129: int i;
130:
131: if (planes.length != 6) {
132: throw new IllegalArgumentException(J3dI18N
133: .getString("CachedFrustum1"));
134: }
135:
136: for (i = 0; i < 6; i++) {
137: clipPlanes[i].set(planes[i]);
138: }
139:
140: computeValues(clipPlanes);
141: }
142:
143: /**
144: * Computes cached values.
145: * @param planes array specifying the frustum's clip planes
146: */
147: private void computeValues(Vector4d[] planes) {
148:
149: int i;
150:
151: // compute verts
152:
153: computeVertex(0, 3, 4, verts[0]); // front-bottom-left
154: computeVertex(0, 2, 4, verts[1]); // front-top-left
155: computeVertex(1, 2, 4, verts[2]); // front-top-right
156: computeVertex(1, 3, 4, verts[3]); // front-bottom-right
157: computeVertex(0, 3, 5, verts[4]); // back-bottom-left
158: computeVertex(0, 2, 5, verts[5]); // back-top-left
159: computeVertex(1, 2, 5, verts[6]); // back-top-right
160: computeVertex(1, 3, 5, verts[7]); // back-bottom-right
161:
162: // compute bounding box
163:
164: upper.x = verts[0].x;
165: upper.y = verts[0].y;
166: upper.z = verts[0].z;
167: lower.x = verts[0].x;
168: lower.y = verts[0].y;
169: lower.z = verts[0].z;
170:
171: center.x = verts[0].x;
172: center.y = verts[0].y;
173: center.z = verts[0].z;
174:
175: // find min and max in x-y-z directions
176:
177: for (i = 1; i < 8; i++) {
178: if (verts[i].x > upper.x)
179: upper.x = verts[i].x; // xmax
180: if (verts[i].x < lower.x)
181: lower.x = verts[i].x; // xmin
182:
183: if (verts[i].y > upper.y)
184: upper.y = verts[i].y; // ymay
185: if (verts[i].y < lower.y)
186: lower.y = verts[i].y; // ymin
187:
188: if (verts[i].z > upper.z)
189: upper.z = verts[i].z; // zmaz
190: if (verts[i].z < lower.z)
191: lower.z = verts[i].z; // zmin
192:
193: center.x += verts[i].x;
194: center.y += verts[i].y;
195: center.z += verts[i].z;
196: }
197:
198: center.x = center.x * 0.125;
199: center.y = center.y * 0.125;
200: center.z = center.z * 0.125;
201:
202: }
203:
204: private void computeVertex(int a, int b, int c, Point3d vert) {
205: double det, x, y, z;
206:
207: det = clipPlanes[a].x * clipPlanes[b].y * clipPlanes[c].z
208: + clipPlanes[a].y * clipPlanes[b].z * clipPlanes[c].x
209: + clipPlanes[a].z * clipPlanes[b].x * clipPlanes[c].y
210: - clipPlanes[a].z * clipPlanes[b].y * clipPlanes[c].x
211: - clipPlanes[a].y * clipPlanes[b].x * clipPlanes[c].z
212: - clipPlanes[a].x * clipPlanes[b].z * clipPlanes[c].y;
213:
214: if (det * det < EPSILON) {
215: // System.err.println("************** Two planes are parallel : det = " + det);
216: return; // two planes are parallel
217: }
218:
219: det = 1.0 / det;
220:
221: vert.x = (clipPlanes[b].y * clipPlanes[c].z - clipPlanes[b].z
222: * clipPlanes[c].y)
223: * -clipPlanes[a].w;
224: vert.y = (clipPlanes[b].z * clipPlanes[c].x - clipPlanes[b].x
225: * clipPlanes[c].z)
226: * -clipPlanes[a].w;
227: vert.z = (clipPlanes[b].x * clipPlanes[c].y - clipPlanes[b].y
228: * clipPlanes[c].x)
229: * -clipPlanes[a].w;
230:
231: vert.x += (clipPlanes[c].y * clipPlanes[a].z - clipPlanes[c].z
232: * clipPlanes[a].y)
233: * -clipPlanes[b].w;
234: vert.y += (clipPlanes[c].z * clipPlanes[a].x - clipPlanes[c].x
235: * clipPlanes[a].z)
236: * -clipPlanes[b].w;
237: vert.z += (clipPlanes[c].x * clipPlanes[a].y - clipPlanes[c].y
238: * clipPlanes[a].x)
239: * -clipPlanes[b].w;
240:
241: vert.x += (clipPlanes[a].y * clipPlanes[b].z - clipPlanes[a].z
242: * clipPlanes[b].y)
243: * -clipPlanes[c].w;
244: vert.y += (clipPlanes[a].z * clipPlanes[b].x - clipPlanes[a].x
245: * clipPlanes[b].z)
246: * -clipPlanes[c].w;
247: vert.z += (clipPlanes[a].x * clipPlanes[b].y - clipPlanes[a].y
248: * clipPlanes[b].x)
249: * -clipPlanes[c].w;
250:
251: vert.x = vert.x * det;
252: vert.y = vert.y * det;
253: vert.z = vert.z * det;
254:
255: }
256:
257: }
|