001: /*
002: * $RCSfile: TriangleArrayRetained.java,v $
003: *
004: * Copyright 1997-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:32 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.lang.Math;
036:
037: /**
038: * The TriangleArray object draws the array of vertices as individual
039: * triangles. Each group
040: * of three vertices defines a triangle to be drawn.
041: */
042:
043: class TriangleArrayRetained extends GeometryArrayRetained {
044:
045: TriangleArrayRetained() {
046: this .geoType = GEO_TYPE_TRI_SET;
047: }
048:
049: boolean intersect(PickShape pickShape, PickInfo pickInfo,
050: int flags, Point3d iPnt, GeometryRetained geom,
051: int geomIndex) {
052: Point3d pnts[] = new Point3d[3];
053: double sdist[] = new double[1];
054: double minDist = Double.MAX_VALUE;
055: double x = 0, y = 0, z = 0;
056: int[] vtxIndexArr = new int[3];
057:
058: int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex
059: : initialCoordIndex);
060: pnts[0] = new Point3d();
061: pnts[1] = new Point3d();
062: pnts[2] = new Point3d();
063:
064: switch (pickShape.getPickType()) {
065: case PickShape.PICKRAY:
066: PickRay pickRay = (PickRay) pickShape;
067:
068: while (i < validVertexCount) {
069: for (int j = 0; j < 3; j++) {
070: vtxIndexArr[j] = i;
071: getVertexData(i++, pnts[j]);
072: }
073: if (intersectRay(pnts, pickRay, sdist, iPnt)) {
074: if (flags == 0) {
075: return true;
076: }
077: if (sdist[0] < minDist) {
078: minDist = sdist[0];
079: x = iPnt.x;
080: y = iPnt.y;
081: z = iPnt.z;
082: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
083: storeInterestData(pickInfo, flags, geom,
084: geomIndex, vtxIndexArr, iPnt,
085: sdist[0]);
086: }
087: }
088: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
089: storeInterestData(pickInfo, flags, geom,
090: geomIndex, vtxIndexArr, iPnt, sdist[0]);
091: }
092: }
093: }
094: break;
095: case PickShape.PICKSEGMENT:
096: PickSegment pickSegment = (PickSegment) pickShape;
097:
098: while (i < validVertexCount) {
099: for (int j = 0; j < 3; j++) {
100: vtxIndexArr[j] = i;
101: getVertexData(i++, pnts[j]);
102: }
103: if (intersectSegment(pnts, pickSegment.start,
104: pickSegment.end, sdist, iPnt)) {
105: if (flags == 0) {
106: return true;
107: }
108: if (sdist[0] < minDist) {
109: minDist = sdist[0];
110: x = iPnt.x;
111: y = iPnt.y;
112: z = iPnt.z;
113: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
114: storeInterestData(pickInfo, flags, geom,
115: geomIndex, vtxIndexArr, iPnt,
116: sdist[0]);
117: }
118: }
119: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
120: storeInterestData(pickInfo, flags, geom,
121: geomIndex, vtxIndexArr, iPnt, sdist[0]);
122: }
123: }
124: }
125: break;
126: case PickShape.PICKBOUNDINGBOX:
127: BoundingBox bbox = (BoundingBox) ((PickBounds) pickShape).bounds;
128:
129: while (i < validVertexCount) {
130: for (int j = 0; j < 3; j++) {
131: vtxIndexArr[j] = i;
132: getVertexData(i++, pnts[j]);
133: }
134: if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) {
135: if (flags == 0) {
136: return true;
137: }
138: if (sdist[0] < minDist) {
139: minDist = sdist[0];
140: x = iPnt.x;
141: y = iPnt.y;
142: z = iPnt.z;
143: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
144: storeInterestData(pickInfo, flags, geom,
145: geomIndex, vtxIndexArr, iPnt,
146: sdist[0]);
147: }
148: }
149: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
150: storeInterestData(pickInfo, flags, geom,
151: geomIndex, vtxIndexArr, iPnt, sdist[0]);
152: }
153: }
154: }
155: break;
156: case PickShape.PICKBOUNDINGSPHERE:
157: BoundingSphere bsphere = (BoundingSphere) ((PickBounds) pickShape).bounds;
158:
159: while (i < validVertexCount) {
160: for (int j = 0; j < 3; j++) {
161: vtxIndexArr[j] = i;
162: getVertexData(i++, pnts[j]);
163: }
164: if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) {
165: if (flags == 0) {
166: return true;
167: }
168: if (sdist[0] < minDist) {
169: minDist = sdist[0];
170: x = iPnt.x;
171: y = iPnt.y;
172: z = iPnt.z;
173: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
174: storeInterestData(pickInfo, flags, geom,
175: geomIndex, vtxIndexArr, iPnt,
176: sdist[0]);
177: }
178: }
179: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
180: storeInterestData(pickInfo, flags, geom,
181: geomIndex, vtxIndexArr, iPnt, sdist[0]);
182: }
183: }
184: }
185: break;
186: case PickShape.PICKBOUNDINGPOLYTOPE:
187: BoundingPolytope bpolytope = (BoundingPolytope) ((PickBounds) pickShape).bounds;
188:
189: while (i < validVertexCount) {
190: for (int j = 0; j < 3; j++) {
191: vtxIndexArr[j] = i;
192: getVertexData(i++, pnts[j]);
193: }
194: if (intersectBoundingPolytope(pnts, bpolytope, sdist,
195: iPnt)) {
196: if (flags == 0) {
197: return true;
198: }
199: if (sdist[0] < minDist) {
200: minDist = sdist[0];
201: x = iPnt.x;
202: y = iPnt.y;
203: z = iPnt.z;
204: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
205: storeInterestData(pickInfo, flags, geom,
206: geomIndex, vtxIndexArr, iPnt,
207: sdist[0]);
208: }
209: }
210: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
211: storeInterestData(pickInfo, flags, geom,
212: geomIndex, vtxIndexArr, iPnt, sdist[0]);
213: }
214: }
215: }
216: break;
217: case PickShape.PICKCYLINDER:
218: PickCylinder pickCylinder = (PickCylinder) pickShape;
219: while (i < validVertexCount) {
220: for (int j = 0; j < 3; j++) {
221: vtxIndexArr[j] = i;
222: getVertexData(i++, pnts[j]);
223: }
224: if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) {
225: if (flags == 0) {
226: return true;
227: }
228: if (sdist[0] < minDist) {
229: minDist = sdist[0];
230: x = iPnt.x;
231: y = iPnt.y;
232: z = iPnt.z;
233: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
234: storeInterestData(pickInfo, flags, geom,
235: geomIndex, vtxIndexArr, iPnt,
236: sdist[0]);
237: }
238: }
239: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
240: storeInterestData(pickInfo, flags, geom,
241: geomIndex, vtxIndexArr, iPnt, sdist[0]);
242: }
243: }
244: }
245: break;
246: case PickShape.PICKCONE:
247: PickCone pickCone = (PickCone) pickShape;
248:
249: while (i < validVertexCount) {
250: for (int j = 0; j < 3; j++) {
251: vtxIndexArr[j] = i;
252: getVertexData(i++, pnts[j]);
253: }
254: if (intersectCone(pnts, pickCone, sdist, iPnt)) {
255: if (flags == 0) {
256: return true;
257: }
258: if (sdist[0] < minDist) {
259: minDist = sdist[0];
260: x = iPnt.x;
261: y = iPnt.y;
262: z = iPnt.z;
263: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
264: storeInterestData(pickInfo, flags, geom,
265: geomIndex, vtxIndexArr, iPnt,
266: sdist[0]);
267: }
268: }
269: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
270: storeInterestData(pickInfo, flags, geom,
271: geomIndex, vtxIndexArr, iPnt, sdist[0]);
272: }
273: }
274: }
275: break;
276: case PickShape.PICKPOINT:
277: // Should not happen since API already check for this
278: throw new IllegalArgumentException(J3dI18N
279: .getString("TriangleArrayRetained0"));
280: default:
281: throw new RuntimeException(
282: "PickShape not supported for intersection");
283: }
284:
285: if (minDist < Double.MAX_VALUE) {
286: iPnt.x = x;
287: iPnt.y = y;
288: iPnt.z = z;
289: return true;
290: }
291: return false;
292: }
293:
294: boolean intersect(Point3d[] pnts) {
295: Point3d[] points = new Point3d[3];
296: double dist[] = new double[1];
297: int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex
298: : initialCoordIndex);
299:
300: points[0] = new Point3d();
301: points[1] = new Point3d();
302: points[2] = new Point3d();
303:
304: switch (pnts.length) {
305: case 3: // Triangle
306: while (i < validVertexCount) {
307: getVertexData(i++, points[0]);
308: getVertexData(i++, points[1]);
309: getVertexData(i++, points[2]);
310: if (intersectTriTri(points[0], points[1], points[2],
311: pnts[0], pnts[1], pnts[2])) {
312: return true;
313: }
314: }
315: break;
316: case 4: // Quad
317: while (i < validVertexCount) {
318: getVertexData(i++, points[0]);
319: getVertexData(i++, points[1]);
320: getVertexData(i++, points[2]);
321: if (intersectTriTri(points[0], points[1], points[2],
322: pnts[0], pnts[1], pnts[2])
323: || intersectTriTri(points[0], points[1],
324: points[2], pnts[0], pnts[2], pnts[3])) {
325: return true;
326: }
327: }
328: break;
329: case 2: // Line
330: while (i < validVertexCount) {
331: getVertexData(i++, points[0]);
332: getVertexData(i++, points[1]);
333: getVertexData(i++, points[2]);
334: if (intersectSegment(points, pnts[0], pnts[1], dist,
335: null)) {
336: return true;
337: }
338: }
339: break;
340: case 1: // Point
341: while (i < validVertexCount) {
342: getVertexData(i++, points[0]);
343: getVertexData(i++, points[1]);
344: getVertexData(i++, points[2]);
345: if (intersectTriPnt(points[0], points[1], points[2],
346: pnts[0])) {
347: return true;
348: }
349: }
350: break;
351: }
352: return false;
353: }
354:
355: boolean intersect(Transform3D this ToOtherVworld,
356: GeometryRetained geom) {
357:
358: Point3d[] pnts = new Point3d[3];
359: int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex
360: : initialCoordIndex);
361: pnts[0] = new Point3d();
362: pnts[1] = new Point3d();
363: pnts[2] = new Point3d();
364:
365: while (i < validVertexCount) {
366: getVertexData(i++, pnts[0]);
367: getVertexData(i++, pnts[1]);
368: getVertexData(i++, pnts[2]);
369: this ToOtherVworld.transform(pnts[0]);
370: this ToOtherVworld.transform(pnts[1]);
371: this ToOtherVworld.transform(pnts[2]);
372: if (geom.intersect(pnts)) {
373: return true;
374: }
375: }
376: return false;
377: }
378:
379: // the bounds argument is already transformed
380: boolean intersect(Bounds targetBound) {
381: Point3d[] pnts = new Point3d[3];
382: int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex
383: : initialCoordIndex);
384: pnts[0] = new Point3d();
385: pnts[1] = new Point3d();
386: pnts[2] = new Point3d();
387:
388: switch (targetBound.getPickType()) {
389: case PickShape.PICKBOUNDINGBOX:
390: BoundingBox box = (BoundingBox) targetBound;
391:
392: while (i < validVertexCount) {
393: getVertexData(i++, pnts[0]);
394: getVertexData(i++, pnts[1]);
395: getVertexData(i++, pnts[2]);
396: if (intersectBoundingBox(pnts, box, null, null)) {
397: return true;
398: }
399: }
400: break;
401: case PickShape.PICKBOUNDINGSPHERE:
402: BoundingSphere bsphere = (BoundingSphere) targetBound;
403:
404: while (i < validVertexCount) {
405: getVertexData(i++, pnts[0]);
406: getVertexData(i++, pnts[1]);
407: getVertexData(i++, pnts[1]);
408: if (intersectBoundingSphere(pnts, bsphere, null, null)) {
409: return true;
410: }
411: }
412: break;
413: case PickShape.PICKBOUNDINGPOLYTOPE:
414: BoundingPolytope bpolytope = (BoundingPolytope) targetBound;
415:
416: while (i < validVertexCount) {
417: getVertexData(i++, pnts[0]);
418: getVertexData(i++, pnts[1]);
419: getVertexData(i++, pnts[2]);
420: if (intersectBoundingPolytope(pnts, bpolytope, null,
421: null)) {
422: return true;
423: }
424: }
425: break;
426: default:
427: throw new RuntimeException(
428: "Bounds not supported for intersection "
429: + targetBound);
430: }
431:
432: return false;
433: }
434:
435: // From Graphics Gems IV (pg5) and Graphics Gems II, Pg170
436: void computeCentroid() {
437: int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex
438: : initialCoordIndex);
439:
440: Point3d pnt0 = new Point3d();
441: Point3d pnt1 = new Point3d();
442: Point3d pnt2 = new Point3d();
443: Vector3d vec = new Vector3d();
444: Vector3d normal = new Vector3d();
445: Vector3d tmpvec = new Vector3d();
446:
447: double area;
448: double totalarea = 0;
449:
450: centroid.x = 0;
451: centroid.y = 0;
452: centroid.z = 0;
453:
454: while (i < validVertexCount) {
455: getVertexData(i++, pnt0);
456: getVertexData(i++, pnt1);
457: getVertexData(i++, pnt2);
458:
459: // Determine the normal
460: vec.sub(pnt0, pnt1);
461: tmpvec.sub(pnt1, pnt2);
462:
463: // Do the cross product
464: normal.cross(vec, tmpvec);
465: normal.normalize();
466:
467: // If a degenerate triangle, don't include
468: if (Double.isNaN(normal.x + normal.y + normal.z))
469: continue;
470:
471: // compute the area
472: getCrossValue(pnt0, pnt1, tmpvec);
473: getCrossValue(pnt1, pnt2, tmpvec);
474: getCrossValue(pnt2, pnt0, tmpvec);
475: area = normal.dot(tmpvec);
476: centroid.x += (pnt0.x + pnt1.x + pnt2.x) * area;
477: centroid.y += (pnt0.y + pnt1.y + pnt2.y) * area;
478: centroid.z += (pnt0.z + pnt1.z + pnt2.z) * area;
479: totalarea += area;
480:
481: }
482: if (totalarea != 0.0) {
483: area = 1.0 / (3.0 * totalarea);
484: centroid.x *= area;
485: centroid.y *= area;
486: centroid.z *= area;
487: }
488: }
489:
490: int getClassType() {
491: return TRIANGLE_TYPE;
492: }
493: }
|