001: /*
002: * $RCSfile: TriangleFanArrayRetained.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 TriangleFanArray object draws an array of vertices as a set of
039: * connected triangle fans. An array of per-strip
040: * vertex counts specifies where the separate strips (fans) appear
041: * in the vertex array. For every strip in the set,
042: * each vertex, beginning with the third vertex in the array,
043: * defines a triangle to be drawn using the current vertex,
044: * the previous vertex and the first vertex. This can be thought of
045: * as a collection of convex polygons.
046: */
047:
048: class TriangleFanArrayRetained extends GeometryStripArrayRetained {
049:
050: TriangleFanArrayRetained() {
051: this .geoType = GEO_TYPE_TRI_FAN_SET;
052: }
053:
054: boolean intersect(PickShape pickShape, PickInfo pickInfo,
055: int flags, Point3d iPnt, GeometryRetained geom,
056: int geomIndex) {
057: Point3d pnts[] = new Point3d[3];
058: double sdist[] = new double[1];
059: double minDist = Double.MAX_VALUE;
060: double x = 0, y = 0, z = 0;
061: int i = 0;
062: int j, end;
063: pnts[0] = new Point3d();
064: pnts[1] = new Point3d();
065: pnts[2] = new Point3d();
066: int[] vtxIndexArr = new int[3];
067:
068: switch (pickShape.getPickType()) {
069: case PickShape.PICKRAY:
070: PickRay pickRay = (PickRay) pickShape;
071:
072: while (i < stripVertexCounts.length) {
073: j = stripStartVertexIndices[i];
074: end = j + stripVertexCounts[i++];
075: for (int k = 0; k < 2; k++) {
076: vtxIndexArr[k] = j;
077: getVertexData(j++, pnts[k]);
078: }
079: while (j < end) {
080: vtxIndexArr[2] = j;
081: getVertexData(j++, pnts[2]);
082: if (intersectRay(pnts, pickRay, sdist, iPnt)) {
083: if (flags == 0) {
084: return true;
085: }
086: if (sdist[0] < minDist) {
087: minDist = sdist[0];
088: x = iPnt.x;
089: y = iPnt.y;
090: z = iPnt.z;
091: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
092: storeInterestData(pickInfo, flags,
093: geom, geomIndex, vtxIndexArr,
094: iPnt, sdist[0]);
095: }
096: }
097: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
098: storeInterestData(pickInfo, flags, geom,
099: geomIndex, vtxIndexArr, iPnt,
100: sdist[0]);
101: }
102: }
103: pnts[1].set(pnts[2]);
104: vtxIndexArr[1] = vtxIndexArr[2];
105: }
106: }
107: break;
108: case PickShape.PICKSEGMENT:
109: PickSegment pickSegment = (PickSegment) pickShape;
110:
111: while (i < stripVertexCounts.length) {
112: j = stripStartVertexIndices[i];
113: end = j + stripVertexCounts[i++];
114: for (int k = 0; k < 2; k++) {
115: vtxIndexArr[k] = j;
116: getVertexData(j++, pnts[k]);
117: }
118: while (j < end) {
119: vtxIndexArr[2] = j;
120: getVertexData(j++, pnts[2]);
121: if (intersectSegment(pnts, pickSegment.start,
122: pickSegment.end, sdist, iPnt)) {
123: if (flags == 0) {
124: return true;
125: }
126: if (sdist[0] < minDist) {
127: minDist = sdist[0];
128: x = iPnt.x;
129: y = iPnt.y;
130: z = iPnt.z;
131: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
132: storeInterestData(pickInfo, flags,
133: geom, geomIndex, vtxIndexArr,
134: iPnt, sdist[0]);
135: }
136: }
137: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
138: storeInterestData(pickInfo, flags, geom,
139: geomIndex, vtxIndexArr, iPnt,
140: sdist[0]);
141: }
142: }
143: pnts[1].set(pnts[2]);
144: vtxIndexArr[1] = vtxIndexArr[2];
145: }
146: }
147: break;
148: case PickShape.PICKBOUNDINGBOX:
149: BoundingBox bbox = (BoundingBox) ((PickBounds) pickShape).bounds;
150:
151: while (i < stripVertexCounts.length) {
152: j = stripStartVertexIndices[i];
153: end = j + stripVertexCounts[i++];
154: for (int k = 0; k < 2; k++) {
155: vtxIndexArr[k] = j;
156: getVertexData(j++, pnts[k]);
157: }
158: while (j < end) {
159: vtxIndexArr[2] = j;
160: getVertexData(j++, pnts[2]);
161: if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) {
162: if (flags == 0) {
163: return true;
164: }
165: if (sdist[0] < minDist) {
166: minDist = sdist[0];
167: x = iPnt.x;
168: y = iPnt.y;
169: z = iPnt.z;
170: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
171: storeInterestData(pickInfo, flags,
172: geom, geomIndex, vtxIndexArr,
173: iPnt, sdist[0]);
174: }
175: }
176: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
177: storeInterestData(pickInfo, flags, geom,
178: geomIndex, vtxIndexArr, iPnt,
179: sdist[0]);
180: }
181: }
182: pnts[1].set(pnts[2]);
183: vtxIndexArr[1] = vtxIndexArr[2];
184: }
185: }
186: break;
187: case PickShape.PICKBOUNDINGSPHERE:
188: BoundingSphere bsphere = (BoundingSphere) ((PickBounds) pickShape).bounds;
189:
190: while (i < stripVertexCounts.length) {
191: j = stripStartVertexIndices[i];
192: end = j + stripVertexCounts[i++];
193: for (int k = 0; k < 2; k++) {
194: vtxIndexArr[k] = j;
195: getVertexData(j++, pnts[k]);
196: }
197: while (j < end) {
198: vtxIndexArr[2] = j;
199: getVertexData(j++, pnts[2]);
200: if (intersectBoundingSphere(pnts, bsphere, sdist,
201: iPnt)) {
202: if (flags == 0) {
203: return true;
204: }
205: if (sdist[0] < minDist) {
206: minDist = sdist[0];
207: x = iPnt.x;
208: y = iPnt.y;
209: z = iPnt.z;
210: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
211: storeInterestData(pickInfo, flags,
212: geom, geomIndex, vtxIndexArr,
213: iPnt, sdist[0]);
214: }
215: }
216: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
217: storeInterestData(pickInfo, flags, geom,
218: geomIndex, vtxIndexArr, iPnt,
219: sdist[0]);
220: }
221: }
222: pnts[1].set(pnts[2]);
223: vtxIndexArr[1] = vtxIndexArr[2];
224: }
225: }
226: break;
227: case PickShape.PICKBOUNDINGPOLYTOPE:
228: BoundingPolytope bpolytope = (BoundingPolytope) ((PickBounds) pickShape).bounds;
229:
230: while (i < stripVertexCounts.length) {
231: j = stripStartVertexIndices[i];
232: end = j + stripVertexCounts[i++];
233: for (int k = 0; k < 2; k++) {
234: vtxIndexArr[k] = j;
235: getVertexData(j++, pnts[k]);
236: }
237: while (j < end) {
238: vtxIndexArr[2] = j;
239: getVertexData(j++, pnts[2]);
240: if (intersectBoundingPolytope(pnts, bpolytope,
241: sdist, iPnt)) {
242: if (flags == 0) {
243: return true;
244: }
245: if (sdist[0] < minDist) {
246: minDist = sdist[0];
247: x = iPnt.x;
248: y = iPnt.y;
249: z = iPnt.z;
250: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
251: storeInterestData(pickInfo, flags,
252: geom, geomIndex, vtxIndexArr,
253: iPnt, sdist[0]);
254: }
255: }
256: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
257: storeInterestData(pickInfo, flags, geom,
258: geomIndex, vtxIndexArr, iPnt,
259: sdist[0]);
260: }
261: }
262: pnts[1].set(pnts[2]);
263: vtxIndexArr[1] = vtxIndexArr[2];
264: }
265: }
266: break;
267: case PickShape.PICKCYLINDER:
268: PickCylinder pickCylinder = (PickCylinder) pickShape;
269:
270: while (i < stripVertexCounts.length) {
271: j = stripStartVertexIndices[i];
272: end = j + stripVertexCounts[i++];
273: for (int k = 0; k < 2; k++) {
274: vtxIndexArr[k] = j;
275: getVertexData(j++, pnts[k]);
276: }
277: while (j < end) {
278: vtxIndexArr[2] = j;
279: getVertexData(j++, pnts[2]);
280: if (intersectCylinder(pnts, pickCylinder, sdist,
281: iPnt)) {
282: if (flags == 0) {
283: return true;
284: }
285: if (sdist[0] < minDist) {
286: minDist = sdist[0];
287: x = iPnt.x;
288: y = iPnt.y;
289: z = iPnt.z;
290: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
291: storeInterestData(pickInfo, flags,
292: geom, geomIndex, vtxIndexArr,
293: iPnt, sdist[0]);
294: }
295: }
296: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
297: storeInterestData(pickInfo, flags, geom,
298: geomIndex, vtxIndexArr, iPnt,
299: sdist[0]);
300: }
301: }
302: pnts[1].set(pnts[2]);
303: vtxIndexArr[1] = vtxIndexArr[2];
304: }
305: }
306: break;
307: case PickShape.PICKCONE:
308: PickCone pickCone = (PickCone) pickShape;
309:
310: while (i < stripVertexCounts.length) {
311: j = stripStartVertexIndices[i];
312: end = j + stripVertexCounts[i++];
313: for (int k = 0; k < 2; k++) {
314: vtxIndexArr[k] = j;
315: getVertexData(j++, pnts[k]);
316: }
317: while (j < end) {
318: vtxIndexArr[2] = j;
319: getVertexData(j++, pnts[2]);
320: if (intersectCone(pnts, pickCone, sdist, iPnt)) {
321: if (flags == 0) {
322: return true;
323: }
324: if (sdist[0] < minDist) {
325: minDist = sdist[0];
326: x = iPnt.x;
327: y = iPnt.y;
328: z = iPnt.z;
329: if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) {
330: storeInterestData(pickInfo, flags,
331: geom, geomIndex, vtxIndexArr,
332: iPnt, sdist[0]);
333: }
334: }
335: if ((flags & PickInfo.ALL_GEOM_INFO) != 0) {
336: storeInterestData(pickInfo, flags, geom,
337: geomIndex, vtxIndexArr, iPnt,
338: sdist[0]);
339: }
340: }
341: pnts[1].set(pnts[2]);
342: vtxIndexArr[1] = vtxIndexArr[2];
343: }
344: }
345: break;
346: case PickShape.PICKPOINT:
347: // Should not happen since API already check for this
348: throw new IllegalArgumentException(J3dI18N
349: .getString("TriangleFanArrayRetained0"));
350: default:
351: throw new RuntimeException(
352: "PickShape not supported for intersection");
353: }
354:
355: if (minDist < Double.MAX_VALUE) {
356: iPnt.x = x;
357: iPnt.y = y;
358: iPnt.z = z;
359: return true;
360: }
361: return false;
362: }
363:
364: // intersect pnts[] with every triangle in this object
365: boolean intersect(Point3d[] pnts) {
366: int j, end;
367: Point3d[] points = new Point3d[3];
368: double dist[] = new double[1];
369: int i = 0;
370:
371: points[0] = new Point3d();
372: points[1] = new Point3d();
373: points[2] = new Point3d();
374:
375: switch (pnts.length) {
376: case 3: // Triangle
377: while (i < stripVertexCounts.length) {
378: j = stripStartVertexIndices[i];
379: end = j + stripVertexCounts[i++];
380: getVertexData(j++, points[0]);
381: getVertexData(j++, points[1]);
382: while (j < end) {
383: getVertexData(j++, points[2]);
384: if (intersectTriTri(points[0], points[1],
385: points[2], pnts[0], pnts[1], pnts[2])) {
386: return true;
387: }
388: points[1].set(points[2]);
389: }
390: }
391: break;
392: case 4: // Quad
393: while (i < stripVertexCounts.length) {
394: j = stripStartVertexIndices[i];
395: end = j + stripVertexCounts[i++];
396: getVertexData(j++, points[0]);
397: getVertexData(j++, points[1]);
398: while (j < end) {
399: getVertexData(j++, points[2]);
400: if (intersectTriTri(points[0], points[1],
401: points[2], pnts[0], pnts[1], pnts[2])
402: || intersectTriTri(points[0], points[1],
403: points[2], pnts[0], pnts[2],
404: pnts[3])) {
405: return true;
406: }
407: points[1].set(points[2]);
408: }
409: }
410: break;
411: case 2: // Line
412: while (i < stripVertexCounts.length) {
413: j = stripStartVertexIndices[i];
414: end = j + stripVertexCounts[i++];
415: getVertexData(j++, points[0]);
416: getVertexData(j++, points[1]);
417: while (j < end) {
418: getVertexData(j++, points[2]);
419: if (intersectSegment(points, pnts[0], pnts[1],
420: dist, null)) {
421: return true;
422: }
423: points[1].set(points[2]);
424: }
425: }
426: break;
427: case 1: // Point
428: while (i < stripVertexCounts.length) {
429: j = stripStartVertexIndices[i];
430: end = j + stripVertexCounts[i++];
431: getVertexData(j++, points[0]);
432: getVertexData(j++, points[1]);
433: while (j < end) {
434: getVertexData(j++, points[2]);
435: if (intersectTriPnt(points[0], points[1],
436: points[2], pnts[0])) {
437: return true;
438: }
439: points[1].set(points[2]);
440: }
441: }
442: break;
443: }
444: return false;
445: }
446:
447: boolean intersect(Transform3D this ToOtherVworld,
448: GeometryRetained geom) {
449: int i = 0, j, end;
450: Point3d[] pnts = new Point3d[3];
451: pnts[0] = new Point3d();
452: pnts[1] = new Point3d();
453: pnts[2] = new Point3d();
454:
455: while (i < stripVertexCounts.length) {
456: j = stripStartVertexIndices[i];
457: end = j + stripVertexCounts[i++];
458: getVertexData(j++, pnts[0]);
459: getVertexData(j++, pnts[1]);
460: this ToOtherVworld.transform(pnts[0]);
461: this ToOtherVworld.transform(pnts[1]);
462: while (j < end) {
463: getVertexData(j++, pnts[2]);
464: this ToOtherVworld.transform(pnts[2]);
465: if (geom.intersect(pnts)) {
466: return true;
467: }
468: pnts[1].set(pnts[2]);
469: }
470: }
471: return false;
472: }
473:
474: // the bounds argument is already transformed
475: boolean intersect(Bounds targetBound) {
476: int i = 0;
477: int j, end;
478: Point3d[] pnts = new Point3d[3];
479: pnts[0] = new Point3d();
480: pnts[1] = new Point3d();
481: pnts[2] = new Point3d();
482:
483: switch (targetBound.getPickType()) {
484: case PickShape.PICKBOUNDINGBOX:
485: BoundingBox box = (BoundingBox) targetBound;
486:
487: while (i < stripVertexCounts.length) {
488: j = stripStartVertexIndices[i];
489: getVertexData(j++, pnts[0]);
490: getVertexData(j++, pnts[1]);
491: end = j + stripVertexCounts[i++];
492: while (j < end) {
493: getVertexData(j++, pnts[2]);
494: if (intersectBoundingBox(pnts, box, null, null)) {
495: return true;
496: }
497: pnts[1].set(pnts[2]);
498: }
499: }
500: break;
501: case PickShape.PICKBOUNDINGSPHERE:
502: BoundingSphere bsphere = (BoundingSphere) targetBound;
503:
504: while (i < stripVertexCounts.length) {
505: j = stripStartVertexIndices[i];
506: end = j + stripVertexCounts[i++];
507: getVertexData(j++, pnts[0]);
508: getVertexData(j++, pnts[1]);
509: while (j < end) {
510: getVertexData(j++, pnts[2]);
511: if (intersectBoundingSphere(pnts, bsphere, null,
512: null)) {
513: return true;
514: }
515: pnts[1].set(pnts[2]);
516: }
517: }
518: break;
519: case PickShape.PICKBOUNDINGPOLYTOPE:
520: BoundingPolytope bpolytope = (BoundingPolytope) targetBound;
521:
522: while (i < stripVertexCounts.length) {
523: j = stripStartVertexIndices[i];
524: end = j + stripVertexCounts[i++];
525: getVertexData(j++, pnts[0]);
526: getVertexData(j++, pnts[1]);
527: while (j < end) {
528: getVertexData(j++, pnts[2]);
529: if (intersectBoundingPolytope(pnts, bpolytope,
530: null, null)) {
531: return true;
532: }
533: pnts[1].set(pnts[2]);
534: }
535: }
536: break;
537: default:
538: throw new RuntimeException(
539: "Bounds not supported for intersection "
540: + targetBound);
541: }
542: return false;
543: }
544:
545: // From Graphics Gems IV (pg5) and Graphics Gems II, Pg170
546: void computeCentroid() {
547: Vector3d vec = new Vector3d();
548: Vector3d normal = new Vector3d();
549: Vector3d tmpvec = new Vector3d();
550: Point3d pnt0 = new Point3d();
551: Point3d pnt1 = new Point3d();
552: Point3d pnt2 = new Point3d();
553: double area, totalarea = 0;
554: int end, replaceIndex, j, i = 0;
555: centroid.x = 0;
556: centroid.y = 0;
557: centroid.z = 0;
558:
559: while (i < stripVertexCounts.length) {
560: j = stripStartVertexIndices[i];
561: end = j + stripVertexCounts[i++];
562: getVertexData(j++, pnt0);
563: getVertexData(j++, pnt1);
564: replaceIndex = 2;
565: while (j < end) {
566: area = 0;
567: if (replaceIndex == 2) {
568: getVertexData(j++, pnt2);
569: replaceIndex = 1;
570: } else {
571: getVertexData(j++, pnt1);
572: replaceIndex = 2;
573: }
574:
575: // Determine the normal
576: vec.sub(pnt0, pnt1);
577: tmpvec.sub(pnt1, pnt2);
578:
579: // Do the cross product
580: normal.cross(vec, tmpvec);
581: normal.normalize();
582: // If a degenerate triangle, don't include
583: if (Double.isNaN(normal.x + normal.y + normal.z))
584: continue;
585:
586: tmpvec.set(0, 0, 0);
587:
588: // compute the area
589: getCrossValue(pnt0, pnt1, tmpvec);
590: getCrossValue(pnt1, pnt2, tmpvec);
591: getCrossValue(pnt2, pnt0, tmpvec);
592: area = normal.dot(tmpvec);
593: totalarea += area;
594: centroid.x += (pnt0.x + pnt1.x + pnt2.x) * area;
595: centroid.y += (pnt0.y + pnt1.y + pnt2.y) * area;
596: centroid.z += (pnt0.z + pnt1.z + pnt2.z) * area;
597:
598: }
599: }
600:
601: if (totalarea != 0.0) {
602: area = 1.0 / (3.0 * totalarea);
603: centroid.x *= area;
604: centroid.y *= area;
605: centroid.z *= area;
606: }
607: }
608:
609: int getClassType() {
610: return TRIANGLE_TYPE;
611: }
612: }
|