001: /*
002: * $RCSfile: Shape3DCompileRetained.java,v $
003: *
004: * Copyright 2000-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:30 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.*;
036:
037: /**
038: * A leaf node that holds a merged shapes in compile mode
039: */
040: class Shape3DCompileRetained extends Shape3DRetained {
041:
042: int numShapes = 0;
043:
044: // Each element in the arraylist is an array of geometries for a
045: // particular merged shape
046: ArrayList geometryInfo = null;
047:
048: Object[] srcList = null;
049:
050: Shape3DCompileRetained(Shape3DRetained[] shapes, int nShapes,
051: int compileFlags) {
052: int i, j;
053: Shape3DRetained shape;
054: GeometryArrayRetained geo;
055: Vector list;
056: // Merged list, only merged if geometry is mergeable
057: Object[] mergedList = new Object[GeometryRetained.GEO_TYPE_GEOMETRYARRAY + 1];
058: // Sorted list of separate geometry by geoType
059: Object[] separateList = new Object[GeometryRetained.GEO_TYPE_GEOMETRYARRAY + 1];
060:
061: // Assign the num of shapes
062: numShapes = nShapes;
063:
064: Bounds shapeBounds;
065:
066: srcList = new Object[nShapes];
067:
068: if (nShapes > 0) {
069: boundsAutoCompute = shapes[0].boundsAutoCompute;
070: source = shapes[0].source;
071: }
072:
073: // Remove the null that was added by Shape3DRetained constructor
074: geometryList.remove(0);
075: int geoIndex = 0;
076:
077: // Assign the fields for this compile shape
078: boundsAutoCompute = shapes[0].boundsAutoCompute;
079: isPickable = shapes[0].isPickable;
080: isCollidable = shapes[0].isCollidable;
081: appearanceOverrideEnable = shapes[0].appearanceOverrideEnable;
082: appearance = shapes[0].appearance;
083: collisionBound = shapes[0].collisionBound;
084: localBounds = shapes[0].localBounds;
085:
086: if ((compileFlags & CompileState.GEOMETRY_READ) != 0)
087: geometryInfo = new ArrayList();
088:
089: for (i = 0; i < nShapes; i++) {
090: shape = shapes[i];
091: ((Shape3D) shape.source).id = i;
092: shape.source.retained = this ;
093: srcList[i] = shape.source;
094: // If the transform has been pushd down
095: // to the shape, don't merge its geometry with other shapes
096: // geometry
097: // Put it in a separate list sorted by geo_type
098: // Have to handle shape.isPickable
099:
100: for (j = 0; j < shape.geometryList.size(); j++) {
101: geo = (GeometryArrayRetained) shape.geometryList.get(j);
102: if (geo != null) {
103: if (shape.willRemainOpaque(geo.geoType)
104: && geo.isMergeable()) {
105: if (mergedList[geo.geoType] == null) {
106: mergedList[geo.geoType] = new ArrayList();
107: }
108: ((ArrayList) mergedList[geo.geoType]).add(geo);
109: } else {
110: // Keep a sorted list based on geoType;
111: if (separateList[geo.geoType] == null) {
112: separateList[geo.geoType] = new ArrayList();
113: }
114: // add it to the geometryList separately
115: ((ArrayList) separateList[geo.geoType])
116: .add(geo);
117: }
118: }
119:
120: }
121:
122: // Point to the geometryList's source, so the
123: // retained side will be garbage collected
124: if ((compileFlags & CompileState.GEOMETRY_READ) != 0) {
125: ArrayList sList = new ArrayList();
126: for (j = 0; j < shape.geometryList.size(); j++) {
127: GeometryRetained g = (GeometryRetained) shape.geometryList
128: .get(j);
129: if (g != null)
130: sList.add(g.source);
131: else
132: sList.add(null);
133: }
134: geometryInfo.add(sList);
135: }
136:
137: }
138: // Now, merged the mergelist and separate list based on geoType,
139: // this enables dlist optmization
140: for (i = 1; i <= GeometryRetained.GEO_TYPE_GEOMETRYARRAY; i++) {
141: GeometryArrayRetained cgeo = null;
142: ArrayList curList;
143: switch (i) {
144: case GeometryArrayRetained.GEO_TYPE_QUAD_SET:
145: if (mergedList[i] != null) {
146: cgeo = new QuadArrayRetained();
147: curList = (ArrayList) mergedList[i];
148: cgeo.setCompiled(curList);
149: geometryList.add(cgeo);
150: cgeo.setSource(((SceneGraphObjectRetained) curList
151: .get(0)).source);
152: }
153: if (separateList[i] != null) {
154: ArrayList glist = (ArrayList) separateList[i];
155: for (int k = 0; k < glist.size(); k++) {
156: geometryList.add(glist.get(k));
157: }
158:
159: }
160: break;
161: case GeometryArrayRetained.GEO_TYPE_TRI_SET:
162: if (mergedList[i] != null) {
163: cgeo = new TriangleArrayRetained();
164: curList = (ArrayList) mergedList[i];
165: cgeo.setCompiled(curList);
166: geometryList.add(cgeo);
167: cgeo.setSource(((SceneGraphObjectRetained) curList
168: .get(0)).source);
169: }
170: if (separateList[i] != null) {
171: ArrayList glist = (ArrayList) separateList[i];
172: for (int k = 0; k < glist.size(); k++) {
173: geometryList.add(glist.get(k));
174: }
175:
176: }
177: break;
178: case GeometryArrayRetained.GEO_TYPE_POINT_SET:
179: if (mergedList[i] != null) {
180: cgeo = new PointArrayRetained();
181: curList = (ArrayList) mergedList[i];
182: cgeo.setCompiled(curList);
183: geometryList.add(cgeo);
184: cgeo.setSource(((SceneGraphObjectRetained) curList
185: .get(0)).source);
186: }
187: if (separateList[i] != null) {
188: ArrayList glist = (ArrayList) separateList[i];
189: for (int k = 0; k < glist.size(); k++) {
190: geometryList.add(glist.get(k));
191: }
192:
193: }
194: break;
195: case GeometryArrayRetained.GEO_TYPE_LINE_SET:
196: if (mergedList[i] != null) {
197: cgeo = new LineArrayRetained();
198: curList = (ArrayList) mergedList[i];
199: cgeo.setCompiled(curList);
200: geometryList.add(cgeo);
201: cgeo.setSource(((SceneGraphObjectRetained) curList
202: .get(0)).source);
203: }
204: if (separateList[i] != null) {
205: ArrayList glist = (ArrayList) separateList[i];
206: for (int k = 0; k < glist.size(); k++) {
207: geometryList.add(glist.get(k));
208: }
209:
210: }
211: break;
212: case GeometryArrayRetained.GEO_TYPE_TRI_STRIP_SET:
213: if (mergedList[i] != null) {
214: cgeo = new TriangleStripArrayRetained();
215: curList = (ArrayList) mergedList[i];
216: cgeo.setCompiled(curList);
217: geometryList.add(cgeo);
218: cgeo.setSource(((SceneGraphObjectRetained) curList
219: .get(0)).source);
220: }
221: if (separateList[i] != null) {
222: ArrayList glist = (ArrayList) separateList[i];
223: for (int k = 0; k < glist.size(); k++) {
224: geometryList.add(glist.get(k));
225: }
226:
227: }
228: break;
229: case GeometryArrayRetained.GEO_TYPE_TRI_FAN_SET:
230: if (mergedList[i] != null) {
231: cgeo = new TriangleFanArrayRetained();
232: curList = (ArrayList) mergedList[i];
233: cgeo.setCompiled(curList);
234: geometryList.add(cgeo);
235: cgeo.setSource(((SceneGraphObjectRetained) curList
236: .get(0)).source);
237: }
238: if (separateList[i] != null) {
239: ArrayList glist = (ArrayList) separateList[i];
240: for (int k = 0; k < glist.size(); k++) {
241: geometryList.add(glist.get(k));
242: }
243:
244: }
245: break;
246: case GeometryArrayRetained.GEO_TYPE_LINE_STRIP_SET:
247: if (mergedList[i] != null) {
248: cgeo = new LineStripArrayRetained();
249: curList = (ArrayList) mergedList[i];
250: cgeo.setCompiled(curList);
251: geometryList.add(cgeo);
252: cgeo.setSource(((SceneGraphObjectRetained) curList
253: .get(0)).source);
254: }
255: if (separateList[i] != null) {
256: ArrayList glist = (ArrayList) separateList[i];
257: for (int k = 0; k < glist.size(); k++) {
258: geometryList.add(glist.get(k));
259: }
260:
261: }
262: break;
263: case GeometryArrayRetained.GEO_TYPE_INDEXED_QUAD_SET:
264: if (mergedList[i] != null) {
265: cgeo = new IndexedQuadArrayRetained();
266: curList = (ArrayList) mergedList[i];
267: cgeo.setCompiled(curList);
268: geometryList.add(cgeo);
269: cgeo.setSource(((SceneGraphObjectRetained) curList
270: .get(0)).source);
271: }
272: if (separateList[i] != null) {
273: ArrayList glist = (ArrayList) separateList[i];
274: for (int k = 0; k < glist.size(); k++) {
275: geometryList.add(glist.get(k));
276: }
277:
278: }
279: break;
280: case GeometryArrayRetained.GEO_TYPE_INDEXED_TRI_SET:
281: if (mergedList[i] != null) {
282: cgeo = new IndexedTriangleArrayRetained();
283: curList = (ArrayList) mergedList[i];
284: cgeo.setCompiled(curList);
285: geometryList.add(cgeo);
286: cgeo.setSource(((SceneGraphObjectRetained) curList
287: .get(0)).source);
288: }
289: if (separateList[i] != null) {
290: ArrayList glist = (ArrayList) separateList[i];
291: for (int k = 0; k < glist.size(); k++) {
292: geometryList.add(glist.get(k));
293: }
294:
295: }
296: break;
297: case GeometryArrayRetained.GEO_TYPE_INDEXED_POINT_SET:
298: if (mergedList[i] != null) {
299: cgeo = new IndexedPointArrayRetained();
300: curList = (ArrayList) mergedList[i];
301: cgeo.setCompiled(curList);
302: geometryList.add(cgeo);
303: cgeo.setSource(((SceneGraphObjectRetained) curList
304: .get(0)).source);
305: }
306: if (separateList[i] != null) {
307: ArrayList glist = (ArrayList) separateList[i];
308: for (int k = 0; k < glist.size(); k++) {
309: geometryList.add(glist.get(k));
310: }
311:
312: }
313: break;
314: case GeometryArrayRetained.GEO_TYPE_INDEXED_LINE_SET:
315: if (mergedList[i] != null) {
316: cgeo = new IndexedLineArrayRetained();
317: curList = (ArrayList) mergedList[i];
318: cgeo.setCompiled(curList);
319: geometryList.add(cgeo);
320: cgeo.setSource(((SceneGraphObjectRetained) curList
321: .get(0)).source);
322: }
323: if (separateList[i] != null) {
324: ArrayList glist = (ArrayList) separateList[i];
325: for (int k = 0; k < glist.size(); k++) {
326: geometryList.add(glist.get(k));
327: }
328:
329: }
330: break;
331: case GeometryArrayRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET:
332: if (mergedList[i] != null) {
333: cgeo = new IndexedTriangleStripArrayRetained();
334: curList = (ArrayList) mergedList[i];
335: cgeo.setCompiled(curList);
336: geometryList.add(cgeo);
337: cgeo.setSource(((SceneGraphObjectRetained) curList
338: .get(0)).source);
339: }
340: if (separateList[i] != null) {
341: ArrayList glist = (ArrayList) separateList[i];
342: for (int k = 0; k < glist.size(); k++) {
343: geometryList.add(glist.get(k));
344: }
345:
346: }
347: break;
348: case GeometryArrayRetained.GEO_TYPE_INDEXED_TRI_FAN_SET:
349: if (mergedList[i] != null) {
350: cgeo = new IndexedTriangleFanArrayRetained();
351: curList = (ArrayList) mergedList[i];
352: cgeo.setCompiled(curList);
353: geometryList.add(cgeo);
354: cgeo.setSource(((SceneGraphObjectRetained) curList
355: .get(0)).source);
356: }
357: if (separateList[i] != null) {
358: ArrayList glist = (ArrayList) separateList[i];
359: for (int k = 0; k < glist.size(); k++) {
360: geometryList.add(glist.get(k));
361: }
362:
363: }
364: break;
365: case GeometryArrayRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET:
366: if (mergedList[i] != null) {
367: cgeo = new IndexedLineStripArrayRetained();
368: curList = (ArrayList) mergedList[i];
369: cgeo.setCompiled(curList);
370: geometryList.add(cgeo);
371: cgeo.setSource(((SceneGraphObjectRetained) curList
372: .get(0)).source);
373: }
374: if (separateList[i] != null) {
375: ArrayList glist = (ArrayList) separateList[i];
376: for (int k = 0; k < glist.size(); k++) {
377: geometryList.add(glist.get(k));
378: }
379:
380: }
381: break;
382: }
383: }
384:
385: }
386:
387: Bounds getCollisionBounds(int childIndex) {
388: return collisionBound;
389: }
390:
391: int numGeometries(int childIndex) {
392: ArrayList geo = (ArrayList) geometryInfo.get(childIndex);
393: return geo.size();
394: }
395:
396: Geometry getGeometry(int i, int childIndex) {
397: ArrayList geoInfo = (ArrayList) geometryInfo.get(childIndex);
398: return (Geometry) geoInfo.get(i);
399:
400: }
401:
402: Enumeration getAllGeometries(int childIndex) {
403: ArrayList geoInfo = (ArrayList) geometryInfo.get(childIndex);
404: Vector geomList = new Vector();
405:
406: for (int i = 0; i < geoInfo.size(); i++) {
407: geomList.add(geoInfo.get(i));
408: }
409:
410: return geomList.elements();
411: }
412:
413: Bounds getBounds(int childIndex) {
414: if (boundsAutoCompute) {
415: ArrayList glist = (ArrayList) geometryInfo.get(childIndex);
416:
417: if (glist != null) {
418: BoundingBox bbox = new BoundingBox((Bounds) null);
419: for (int i = 0; i < glist.size(); i++) {
420: Geometry g = (Geometry) glist.get(i);
421: if (g != null) {
422: GeometryRetained geometry = (GeometryRetained) g.retained;
423: if (geometry.geoType != GeometryRetained.GEO_TYPE_NONE) {
424: geometry.computeBoundingBox();
425: synchronized (geometry.geoBounds) {
426: bbox.combine(geometry.geoBounds);
427: }
428: }
429: }
430: }
431:
432: return (Bounds) bbox;
433:
434: } else {
435: return null;
436: }
437:
438: } else {
439: return super .getBounds();
440: }
441: }
442:
443: /**
444: * Check if the geometry component of this shape node under path
445: * intersects with the pickRay.
446: * @return true if intersected else false. If return is true, dist
447: * contains the closest
448: * distance of intersection.
449: * @exception IllegalArgumentException if <code>path</code> is
450: * invalid.
451: */
452: boolean intersect(SceneGraphPath path, PickShape pickShape,
453: double[] dist) {
454:
455: int flags;
456: PickInfo pickInfo = new PickInfo();
457:
458: Transform3D localToVworld = path.getTransform();
459: if (localToVworld == null) {
460: throw new IllegalArgumentException(J3dI18N
461: .getString("Shape3DRetained3"));
462: }
463: pickInfo.setLocalToVWorldRef(localToVworld);
464:
465: Shape3D shape = (Shape3D) path.getObject();
466: // Get the geometries for this shape only, since the compiled
467: // geomtryList contains several shapes
468: ArrayList glist = (ArrayList) geometryInfo.get(shape.id);
469:
470: // System.err.println("Shape3DCompileRetained.intersect() : ");
471: if (dist == null) {
472: // System.err.println(" no dist request ....");
473: return intersect(pickInfo, pickShape, 0, glist);
474: }
475:
476: flags = PickInfo.CLOSEST_DISTANCE;
477: if (intersect(pickInfo, pickShape, flags, glist)) {
478: dist[0] = pickInfo.getClosestDistance();
479: return true;
480: }
481:
482: return false;
483:
484: }
485:
486: boolean intersect(PickInfo pickInfo, PickShape pickShape,
487: int flags, ArrayList geometryList) {
488:
489: Transform3D localToVworld = pickInfo.getLocalToVWorldRef();
490:
491: Transform3D t3d = new Transform3D();
492: t3d.invert(localToVworld);
493: PickShape newPS = pickShape.transform(t3d);
494:
495: int geomListSize = geometryList.size();
496: GeometryRetained geometry;
497:
498: if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0)
499: && ((flags & PickInfo.CLOSEST_DISTANCE) == 0)
500: && ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0)
501: && ((flags & PickInfo.ALL_GEOM_INFO) == 0)) {
502:
503: for (int i = 0; i < geomListSize; i++) {
504: geometry = (GeometryRetained) geometryList.get(i);
505: if (geometry != null) {
506: if (geometry.mirrorGeometry != null) {
507: geometry = geometry.mirrorGeometry;
508: }
509: // Need to modify this method
510: // if (geometry.intersect(newPS, null, null)) {
511: if (geometry.intersect(newPS, null, 0, null, null,
512: 0)) {
513: return true;
514: }
515: }
516: }
517: } else {
518: double distance;
519: double minDist = Double.POSITIVE_INFINITY;
520: Point3d closestIPnt = new Point3d();
521: Point3d iPnt = new Point3d();
522: Point3d iPntVW = new Point3d();
523:
524: for (int i = 0; i < geomListSize; i++) {
525: geometry = (GeometryRetained) geometryList.get(i);
526: if (geometry != null) {
527: if (geometry.mirrorGeometry != null) {
528: geometry = geometry.mirrorGeometry;
529: }
530: if (geometry.intersect(newPS, pickInfo, flags,
531: iPnt, geometry, i)) {
532:
533: iPntVW.set(iPnt);
534: localToVworld.transform(iPntVW);
535: distance = pickShape.distance(iPntVW);
536:
537: if (minDist > distance) {
538: minDist = distance;
539: closestIPnt.set(iPnt);
540: }
541: }
542: }
543: }
544:
545: if (minDist < Double.POSITIVE_INFINITY) {
546: if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) {
547: pickInfo.setClosestDistance(minDist);
548: }
549: if ((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) {
550: pickInfo.setClosestIntersectionPoint(closestIPnt);
551: }
552: return true;
553: }
554: }
555:
556: return false;
557:
558: }
559:
560: }
|