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