001: /*
002: * $RCSfile: PickObject.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.4 $
041: * $Date: 2007/02/09 17:20:13 $
042: * $State: Exp $
043: */
044:
045: /*
046: New Base level methods:
047:
048: ISSUE :
049: How about PickPoint and PickSegment ?
050:
051: DONE :
052: PickShape generatePickRay(int x, int y)
053:
054: SceneGraphPath[] pickAll(int x, int y)
055: SceneGraphPath[] pickAllSorted(int x, int y)
056: SceneGraphPath pickAny(int x, int y)
057: SceneGraphPath pickClosest(int x, int y)
058:
059: Node getPickedNode(SceneGraphPath, flag)
060: Node getPickedNode(SceneGraphPath, flag, int count)
061: where flag can be any combo of:
062: Group, Morph, Primitive, Shape3D,
063: TransformGroup, Switch
064:
065:
066: TODO :
067: SceneGraphPath[] pickGeomAll(int x, int y)
068: SceneGraphPath[] pickGeomAllSorted(int x, int y)
069: SceneGraphPath pickGeomAny(int x, int y)
070: SceneGraphPath pickGeomClosest(int x, int y)
071:
072: bool intersect(SceneGraphPath, PickShape)
073:
074:
075: Eventually:
076: getClosestVtx(ScenGraphPath, PickShape)
077:
078:
079: Misc:
080: Mouse should stay on top of object it is dragging
081:
082: */
083:
084: package com.sun.j3d.utils.behaviors.picking;
085:
086: import java.awt.*;
087: import java.awt.event.*;
088: import java.util.*;
089: import javax.media.j3d.*;
090: import com.sun.j3d.utils.geometry.Primitive;
091: import javax.vecmath.*;
092:
093: /*
094: * Contains methods to aid in picking. A PickObject is created
095: * for a given Canvas3D and a BranchGroup. SceneGraphObjects
096: * under the specified BranchGroup can then be checked to determine
097: * if they have been picked.
098: */
099:
100: /**
101: * @deprecated As of Java 3D version 1.2, replaced by
102: * <code>com.sun.j3d.utils.picking.PickCanvas</code>
103: *
104: * @see com.sun.j3d.utils.picking.PickCanvas
105: */
106:
107: public class PickObject extends Object {
108:
109: // Have to rethink what to support. Is this complete.
110:
111: /**
112: * A flag to indicate to the pickNode method to return a
113: * <code>Shape3D</code> node from
114: * a given <code>SceneGraphPath</code>.
115: *
116: * @see PickObject#pickNode
117: */
118: public static final int SHAPE3D = 0x1;
119:
120: /**
121: * A flag to indicate to the pickNode method to return a
122: * <code>Morph</code> node from
123: * a given <code>SceneGraphPath</code>.
124: *
125: * @see PickObject#pickNode
126: */
127: public static final int MORPH = 0x2;
128:
129: /**
130: * A flag to indicate to the pickNode method to return a
131: * <code>Primitive</code> node
132: * from a given <code>SceneGraphPath</code>.
133: *
134: * @see PickObject#pickNode
135: */
136: public static final int PRIMITIVE = 0x4;
137:
138: /**
139: * A flag to indicate to the pickNode method to return a
140: * <code>Link</code> node from
141: * a given <code>SceneGraphPath</code>.
142: *
143: * @see PickObject#pickNode
144: */
145: public static final int LINK = 0x8;
146:
147: /**
148: * A flag to indicate to the pickNode method to return a
149: * <code>Group</code> node from
150: * a given <code>SceneGraphPath</code>.
151: *
152: * @see PickObject#pickNode
153: */
154: public static final int GROUP = 0x10;
155:
156: /**
157: * A flag to indicate to the pickNode method to return a
158: * <code>TransformGroup</code>
159: * node from a given <code>SceneGraphPath</code>.
160: *
161: * @see PickObject#pickNode
162: */
163: public static final int TRANSFORM_GROUP = 0x20;
164:
165: /**
166: * A flag to indicate to the pickNode method to return a
167: * <code>BranchGroup</code>
168: * node from a given <code>SceneGraphPath</code>.
169: *
170: * @see PickObject#pickNode
171: */
172: public static final int BRANCH_GROUP = 0x40;
173:
174: /**
175: * A flag to indicate to the pickNode method to return a
176: * <code>Switch</code> node from
177: * a given <code>SceneGraphPath</code>.
178: *
179: * @see PickObject#pickNode
180: */
181: public static final int SWITCH = 0x80;
182:
183: /**
184: * Set this flag if you want to pick by geometry.
185: */
186: public static final int USE_GEOMETRY = 0x100;
187:
188: /**
189: * Set this flag if you want to pick by bounds.
190: */
191: public static final int USE_BOUNDS = 0x200;
192:
193: BranchGroup pickRoot;
194: Canvas3D canvas;
195: Point3d origin = new Point3d();
196: Vector3d direction = new Vector3d();
197: PickRay pickRay = new PickRay();
198: SceneGraphPath sceneGraphPath = null;
199: SceneGraphPath sceneGraphPathArr[] = null;
200: int pickBy; // To pick by Bounds or Geometry.
201:
202: static final boolean debug = false;
203:
204: /**
205: * Creates a PickObject.
206: * @param c Current J3D canvas.
207: * @param root The portion of the scenegraph for which picking is to occur
208: * on. It has to be a <code>BranchGroup</code>.
209: *
210: * @see BranchGroup
211: * @see Canvas3D
212: */
213: public PickObject(Canvas3D c, BranchGroup root) {
214: pickRoot = root;
215: canvas = c;
216: }
217:
218: /**
219: * Creates a PickRay that starts at the viewer position and points into
220: * the scene in the direction of (xpos, ypos) specified in window space.
221: *
222: * @param xpos The value along the x-axis.
223: * @param ypos The value along the y-axis.
224: * @return A PickShape object that is the constructed PickRay.
225: */
226: public PickShape generatePickRay(int xpos, int ypos) {
227:
228: Transform3D motion = new Transform3D();
229: Point3d eyePosn = new Point3d();
230: Point3d mousePosn = new Point3d();
231: Vector3d mouseVec = new Vector3d();
232:
233: canvas.getCenterEyeInImagePlate(eyePosn);
234: canvas.getPixelLocationInImagePlate(xpos, ypos, mousePosn);
235: if (canvas.getView().getProjectionPolicy() == View.PARALLEL_PROJECTION) {
236: // Correct for the parallel projection: keep the eye's z
237: // coordinate, but make x,y be the same as the mouse, this
238: // simulates the eye being at "infinity"
239: eyePosn.x = mousePosn.x;
240: eyePosn.y = mousePosn.y;
241: }
242:
243: canvas.getImagePlateToVworld(motion);
244:
245: if (debug) {
246: System.out.println("mouse position " + xpos + " " + ypos);
247: System.out.println("before, mouse " + mousePosn + " eye "
248: + eyePosn);
249: }
250:
251: motion.transform(eyePosn);
252: motion.transform(mousePosn);
253: mouseVec.sub(mousePosn, eyePosn);
254: mouseVec.normalize();
255:
256: if (debug) {
257: System.out.println(motion + "\n");
258: System.out.println("after, mouse " + mousePosn + " eye "
259: + eyePosn + " mouseVec " + mouseVec);
260: }
261:
262: pickRay.set(eyePosn, mouseVec);
263:
264: return (PickShape) pickRay;
265:
266: }
267:
268: /**
269: * Returns an array referencing all the items that are pickable below the
270: * <code>BranchGroup</code> (specified in the PickObject constructor) that
271: * intersect with a ray that starts at the
272: * viewer position and points into the scene in the direction of (xpos, ypos)
273: * specified in window space. The resultant array is unordered.
274: *
275: * @param xpos The value along the x-axis.
276: * @param ypos The value along the y-axis.
277: * @return The array of SceneGraphPath objects that contain Objects that
278: * were picked
279: * If no pickable object is found <code>null</code> is returned..
280: *
281: * @see SceneGraphPath
282: */
283: public SceneGraphPath[] pickAll(int xpos, int ypos) {
284: pickRay = (PickRay) generatePickRay(xpos, ypos);
285: sceneGraphPathArr = pickRoot.pickAll(pickRay);
286: return sceneGraphPathArr;
287: }
288:
289: /**
290: * Returns a sorted array of references to all the Pickable items below the
291: * <code>BranchGroup</code> (specified in the PickObject constructor) that
292: * intersect with the ray that starts at the viewer
293: * position and points into the scene in the direction of (xpos, ypos)
294: * in the window space.
295: * Element [0] references the item closest to viewer.
296: *
297: * @param xpos The value along the x-axis.
298: * @param ypos The value along the y-axis.
299: * @return A sorted arrayof SceneGraphPath objects that contain Objects that
300: * were picked. The array is sorted from closest to farthest from the
301: * viewer
302: * If no pickable object is found <code>null</code> is returned..
303: *
304: * @see SceneGraphPath
305: */
306: public SceneGraphPath[] pickAllSorted(int xpos, int ypos) {
307: pickRay = (PickRay) generatePickRay(xpos, ypos);
308: sceneGraphPathArr = pickRoot.pickAllSorted(pickRay);
309: return sceneGraphPathArr;
310: }
311:
312: /**
313: * Returns a reference to any item that is Pickable below the specified
314: * <code>BranchGroup</code> (specified in the PickObject constructor) which
315: * intersects with the ray that starts at the viewer
316: * position and points into the scene in the direction of (xpos, ypos) in
317: * window space.
318: *
319: * @param xpos The value along the x-axis.
320: * @param ypos The value along the y-axis.
321: * @return A SceneGraphPath of an object that was picked. This is not
322: * guarenteed to return the same result for multiple picks
323: * If no pickable object is found <code>null</code> is returned..
324: *
325: * @see SceneGraphPath
326: */
327: public SceneGraphPath pickAny(int xpos, int ypos) {
328: pickRay = (PickRay) generatePickRay(xpos, ypos);
329: sceneGraphPath = pickRoot.pickAny(pickRay);
330: return sceneGraphPath;
331: }
332:
333: /**
334: * Returns a reference to the item that is closest to the viewer and is
335: * Pickable below the <code>BranchGroup</code> (specified in the PickObject
336: * constructor) which intersects with the ray that starts at
337: * the viewer position and points into the scene in the direction of
338: * (xpos, ypos) in the window space.
339: *
340: * @param xpos The value along the x-axis.
341: * @param ypos The value along the y-axis.
342: * @return A SceneGraphPath which contains the closest pickable object.
343: * If no pickable object is found, <code>null</code> is returned.
344: *
345: * @see SceneGraphPath
346: */
347: public SceneGraphPath pickClosest(int xpos, int ypos) {
348: pickRay = (PickRay) generatePickRay(xpos, ypos);
349: sceneGraphPath = pickRoot.pickClosest(pickRay);
350: return sceneGraphPath;
351: }
352:
353: /**
354: * Returns an array referencing all the items that are pickable below the
355: * <code>BranchGroup</code> (specified in the PickObject constructor) that
356: * intersect with a ray that starts at the
357: * viewer position and points into the scene in the direction of (xpos, ypos)
358: * specified in window space. The resultant array is unordered.
359: *
360: * @param xpos The value along the x-axis.
361: * @param ypos The value along the y-axis.
362: * @param flag Specifys picking by Geometry or Bounds.
363: * @return The array of SceneGraphPath objects that contain Objects that
364: * were picked
365: * If no pickable object is found <code>null</code> is returned..
366: *
367: * @see SceneGraphPath
368: */
369: public SceneGraphPath[] pickAll(int xpos, int ypos, int flag) {
370:
371: if (flag == USE_BOUNDS) {
372: return pickAll(xpos, ypos);
373: } else if (flag == USE_GEOMETRY) {
374: return pickGeomAll(xpos, ypos);
375: } else
376: return null;
377: }
378:
379: /**
380: * Returns a sorted array of references to all the Pickable items below the
381: * <code>BranchGroup</code> (specified in the PickObject constructor) that
382: * intersect with the ray that starts at the viewer
383: * position and points into the scene in the direction of (xpos, ypos)
384: * in the window space.
385: * Element [0] references the item closest to viewer.
386: *
387: * @param xpos The value along the x-axis.
388: * @param ypos The value along the y-axis.
389: * @param flag Specifys picking by Geometry or Bounds.
390: * @return A sorted arrayof SceneGraphPath objects that contain Objects that
391: * were picked. The array is sorted from closest to farthest from the
392: * viewer
393: * If no pickable object is found <code>null</code> is returned..
394: *
395: * @see SceneGraphPath
396: */
397: public SceneGraphPath[] pickAllSorted(int xpos, int ypos, int flag) {
398:
399: if (flag == USE_BOUNDS) {
400: return pickAllSorted(xpos, ypos);
401: } else if (flag == USE_GEOMETRY) {
402: return pickGeomAllSorted(xpos, ypos);
403: } else
404: return null;
405:
406: }
407:
408: /**
409: * Returns a reference to any item that is Pickable below the specified
410: * <code>BranchGroup</code> (specified in the PickObject constructor) which
411: * intersects with the ray that starts at the viewer
412: * position and points into the scene in the direction of (xpos, ypos) in
413: * window space.
414: *
415: * @param xpos The value along the x-axis.
416: * @param ypos The value along the y-axis.
417: * @param flag Specifys picking by Geometry or Bounds.
418: * @return A SceneGraphPath of an object that was picked. This is not
419: * guarenteed to return the same result for multiple picks
420: * If no pickable object is found <code>null</code> is returned..
421: *
422: * @see SceneGraphPath
423: */
424: public SceneGraphPath pickAny(int xpos, int ypos, int flag) {
425:
426: if (flag == USE_BOUNDS) {
427: return pickAny(xpos, ypos);
428: } else if (flag == USE_GEOMETRY) {
429: return pickGeomAny(xpos, ypos);
430: } else
431: return null;
432: }
433:
434: /**
435: * Returns a reference to the item that is closest to the viewer and is
436: * Pickable below the <code>BranchGroup</code> (specified in the PickObject
437: * constructor) which intersects with the ray that starts at
438: * the viewer position and points into the scene in the direction of
439: * (xpos, ypos) in the window space.
440: *
441: * @param xpos The value along the x-axis.
442: * @param ypos The value along the y-axis.
443: * @param flag Specifys picking by Geometry or Bounds.
444: * @return A SceneGraphPath which contains the closest pickable object.
445: * If no pickable object is found, <code>null</code> is returned.
446: *
447: * @see SceneGraphPath
448: */
449: public SceneGraphPath pickClosest(int xpos, int ypos, int flag) {
450:
451: if (flag == USE_BOUNDS) {
452: return pickClosest(xpos, ypos);
453: } else if (flag == USE_GEOMETRY) {
454: return pickGeomClosest(xpos, ypos);
455: } else
456: return null;
457: }
458:
459: private SceneGraphPath[] pickGeomAll(int xpos, int ypos) {
460: Node obj;
461: int i, cnt = 0;
462:
463: pickRay = (PickRay) generatePickRay(xpos, ypos);
464: sceneGraphPathArr = pickRoot.pickAll(pickRay);
465:
466: if (sceneGraphPathArr == null)
467: return null;
468:
469: boolean found[] = new boolean[sceneGraphPathArr.length];
470:
471: for (i = 0; i < sceneGraphPathArr.length; i++) {
472: obj = sceneGraphPathArr[i].getObject();
473: if (obj instanceof Shape3D) {
474: found[i] = ((Shape3D) obj).intersect(
475: sceneGraphPathArr[i], (PickShape) pickRay);
476: } else if (obj instanceof Morph) {
477: found[i] = ((Morph) obj).intersect(
478: sceneGraphPathArr[i], (PickShape) pickRay);
479: }
480: if (found[i] == true)
481: cnt++;
482: }
483:
484: if (cnt == 0)
485: return null;
486:
487: SceneGraphPath newSceneGraphPathArr[] = new SceneGraphPath[cnt];
488:
489: cnt = 0; // reset for reuse.
490: for (i = 0; i < sceneGraphPathArr.length; i++) {
491: if (found[i] == true)
492: newSceneGraphPathArr[cnt++] = sceneGraphPathArr[i];
493: }
494:
495: return newSceneGraphPathArr;
496: }
497:
498: private double distance[];
499:
500: private SceneGraphPath[] pickGeomAllSorted(int xpos, int ypos) {
501: Node obj;
502: int i, cnt = 0;
503: double dist[] = new double[1];
504:
505: // System.out.print("In pickGeomAllSorted\n");
506: pickRay = (PickRay) generatePickRay(xpos, ypos);
507: sceneGraphPathArr = pickRoot.pickAll(pickRay);
508:
509: if (sceneGraphPathArr == null)
510: return null;
511:
512: boolean found[] = new boolean[sceneGraphPathArr.length];
513: double distArr[] = new double[sceneGraphPathArr.length];
514:
515: for (i = 0; i < sceneGraphPathArr.length; i++) {
516: obj = sceneGraphPathArr[i].getObject();
517: if (obj instanceof Shape3D) {
518: found[i] = ((Shape3D) obj).intersect(
519: sceneGraphPathArr[i], pickRay, dist);
520: distArr[i] = dist[0];
521: } else if (obj instanceof Morph) {
522: found[i] = ((Morph) obj).intersect(
523: sceneGraphPathArr[i], pickRay, dist);
524: distArr[i] = dist[0];
525: }
526: if (found[i] == true)
527: cnt++;
528: }
529:
530: if (cnt == 0)
531: return null;
532:
533: SceneGraphPath newSceneGraphPathArr[] = new SceneGraphPath[cnt];
534: distance = new double[cnt];
535:
536: cnt = 0; // reset for reuse.
537: for (i = 0; i < sceneGraphPathArr.length; i++) {
538: if (found[i] == true) {
539: newSceneGraphPathArr[cnt] = sceneGraphPathArr[i];
540: distance[cnt++] = distArr[i];
541: }
542: }
543:
544: return sort(newSceneGraphPathArr);
545: }
546:
547: private SceneGraphPath pickGeomClosest(int xpos, int ypos) {
548: SceneGraphPath sgpArr[] = pickGeomAllSorted(xpos, ypos);
549:
550: if (sgpArr == null)
551: return null;
552:
553: return sgpArr[0];
554: }
555:
556: private SceneGraphPath pickGeomAny(int xpos, int ypos) {
557: Node obj;
558: int i;
559:
560: pickRay = (PickRay) generatePickRay(xpos, ypos);
561: sceneGraphPathArr = pickRoot.pickAll(pickRay);
562: for (i = 0; i < sceneGraphPathArr.length; i++) {
563: obj = sceneGraphPathArr[i].getObject();
564: if (obj instanceof Shape3D) {
565: if (((Shape3D) obj).intersect(sceneGraphPathArr[i],
566: (PickShape) pickRay))
567: return sceneGraphPathArr[i];
568: } else if (obj instanceof Morph) {
569: if (((Morph) obj).intersect(sceneGraphPathArr[i],
570: (PickShape) pickRay))
571: return sceneGraphPathArr[i];
572: }
573: }
574:
575: return null;
576: }
577:
578: /**
579: * Sort the elements in sgpArr and
580: * return the sorted list in SceneGraphPath
581: *
582: * Sorts on the distance but also adjusts an array of positions
583: * this allows the sort to operate on small data elements rather
584: * than the possibly large SceneGraphPath
585: *
586: * Initial implementation is a Quick Sort
587: */
588:
589: private int position[];
590:
591: private SceneGraphPath[] sort(SceneGraphPath sgpArr[]) {
592:
593: if (sgpArr == null)
594: return null;
595:
596: SceneGraphPath sorted[] = new SceneGraphPath[sgpArr.length];
597: position = new int[sgpArr.length];
598:
599: for (int i = 0; i < sgpArr.length; i++) {
600: position[i] = i;
601: }
602:
603: /*
604: System.out.println("Before Sort :");
605: for(int i=0; i<distance.length; i++) {
606: System.out.println("pos " + position[i] +" dist "+ distance[i] +
607: " sgp "+ sgpArr[i]);
608: }
609: */
610:
611: quicksort(0, distance.length - 1);
612:
613: for (int i = 0; i < distance.length; i++) {
614: sorted[i] = sgpArr[position[i]];
615: }
616:
617: /*
618: System.out.println("\nAfter Sort :");
619: for(int i=0; i<distance.length; i++) {
620: System.out.println("pos " + position[i] +" dist "+ distance[i] +
621: " sorted sgp "+ sorted[i]);
622: }
623: */
624:
625: return sorted;
626: }
627:
628: private final void quicksort(int l, int r) {
629: int p, i, j;
630: double tmp, k;
631:
632: i = l;
633: j = r;
634: k = distance[(l + r) / 2];
635: do {
636: while (distance[i] < k)
637: i++;
638: while (k < distance[j])
639: j--;
640: if (i <= j) {
641: tmp = distance[i];
642: distance[i] = distance[j];
643: distance[j] = tmp;
644:
645: p = position[i];
646: position[i] = position[j];
647: position[j] = p;
648: i++;
649: j--;
650: }
651: } while (i <= j);
652:
653: if (l < j)
654: quicksort(l, j);
655: if (l < r)
656: quicksort(i, r);
657: }
658:
659: /**
660: * Returns a reference to a Pickable Node that
661: * is of the specified type
662: * that is contained in the specified SceneGraphPath.
663: * If more than one node of the same type is encountered, the node
664: * closest to the terminal node of SceneGraphPath will be returned.
665: *
666: * @param sgPath the SceneGraphPath to be traversed.
667: * @param flags the Node types interested in picking.
668: * @return the first occurrence of the specified Node type
669: * starting from the terminal node of SceneGraphPath.
670: * If no pickable object is found of the specifed types,
671: * <code>null</code> is returned.
672: */
673: public Node pickNode(SceneGraphPath sgPath, int flags) {
674:
675: if (sgPath != null) {
676: Node pickedNode = sgPath.getObject();
677:
678: if ((pickedNode instanceof Shape3D)
679: && ((flags & SHAPE3D) != 0)) {
680: if (debug)
681: System.out.println("Shape3D found");
682: return pickedNode;
683: } else if ((pickedNode instanceof Morph)
684: && ((flags & MORPH) != 0)) {
685: if (debug)
686: System.out.println("Morph found");
687: return pickedNode;
688: } else {
689: for (int j = sgPath.nodeCount() - 1; j >= 0; j--) {
690: pickedNode = sgPath.getNode(j);
691: if (debug)
692: System.out.println("looking at node "
693: + pickedNode);
694:
695: if ((pickedNode instanceof Primitive)
696: && ((flags & PRIMITIVE) != 0)) {
697: if (debug)
698: System.out.println("Primitive found");
699: return pickedNode;
700: } else if ((pickedNode instanceof Link)
701: && ((flags & LINK) != 0)) {
702: if (debug)
703: System.out.println("Link found");
704: return pickedNode;
705: } else if ((pickedNode instanceof Switch)
706: && ((flags & SWITCH) != 0)) {
707: if (debug)
708: System.out.println("Switch found");
709: return pickedNode;
710: } else if ((pickedNode instanceof TransformGroup)
711: && ((flags & TRANSFORM_GROUP) != 0)) {
712: if (debug)
713: System.out.println("xform group found");
714: return pickedNode;
715: } else if ((pickedNode instanceof BranchGroup)
716: && ((flags & BRANCH_GROUP) != 0)) {
717: if (debug)
718: System.out.println("Branch group found");
719: return pickedNode;
720: } else if ((pickedNode instanceof Group)
721: && ((flags & GROUP) != 0)) {
722: if (debug)
723: System.out.println("Group found");
724: return pickedNode;
725: }
726: }
727:
728: if (pickedNode == null)
729: if (debug)
730: System.out
731: .println("ERROR: null SceneGraphPath");
732: }
733:
734: }
735:
736: return null;
737:
738: }
739:
740: /**
741: * Returns a reference to a Pickable Node that
742: * is of the specified type
743: * that is contained in the specified SceneGraphPath.
744: * The Node returned is the nth <code>occurrence</code>
745: * of a Node that is of the specified type.
746: *
747: * @param sgPath the SceneGraphPath to be traversed.
748: * @param flags the Node types interested.
749: * @param occurrence the occurrence of a Node that
750: * matches the specified type to return. An <code>occurrence</code> of
751: * 1 means to return the first occurrence of that object type (the object
752: * closest to the Locale).
753: * @return the nth <code>occurrence</code> of a Node
754: * of type <code>flags</code>, starting from the Locale. If no pickable object is
755: * found, <code>null</code> is returned.
756: */
757: public Node pickNode(SceneGraphPath sgPath, int flags,
758: int occurrence) {
759: int curCnt = 0;
760:
761: if (sgPath != null) {
762: Node pickedNode = sgPath.getObject();
763:
764: // Shape3D and Morph are leaf nodes and have no children. It doesn't
765: // make sense to do occurrence check here. We'll just return it for now.
766: if ((pickedNode instanceof Shape3D)
767: && ((flags & SHAPE3D) != 0)) {
768: if (debug)
769: System.out.println("Shape3D found");
770: return pickedNode;
771: } else if ((pickedNode instanceof Morph)
772: && ((flags & MORPH) != 0)) {
773: if (debug)
774: System.out.println("Morph found");
775: return pickedNode;
776: } else {
777: for (int j = 0; j < sgPath.nodeCount(); j++) {
778: pickedNode = sgPath.getNode(j);
779: if (debug)
780: System.out.println("looking at node "
781: + pickedNode);
782:
783: if ((pickedNode instanceof Group)
784: && ((flags & GROUP) != 0)) {
785: if (debug)
786: System.out.println("Group found");
787: curCnt++;
788: if (curCnt == occurrence)
789: return pickedNode;
790: } else if ((pickedNode instanceof BranchGroup)
791: && ((flags & BRANCH_GROUP) != 0)) {
792: if (debug)
793: System.out.println("Branch group found");
794: curCnt++;
795: if (curCnt == occurrence)
796: return pickedNode;
797: } else if ((pickedNode instanceof TransformGroup)
798: && ((flags & TRANSFORM_GROUP) != 0)) {
799: if (debug)
800: System.out.println("xform group found");
801: curCnt++;
802: if (curCnt == occurrence)
803: return pickedNode;
804: } else if ((pickedNode instanceof Primitive)
805: && ((flags & PRIMITIVE) != 0)) {
806: if (debug)
807: System.out.println("Primitive found");
808: curCnt++;
809: if (curCnt == occurrence)
810: return pickedNode;
811: } else if ((pickedNode instanceof Link)
812: && ((flags & LINK) != 0)) {
813: if (debug)
814: System.out.println("Link found");
815: curCnt++;
816: if (curCnt == occurrence)
817: return pickedNode;
818: }
819: }
820:
821: if (pickedNode == null)
822: if (debug)
823: System.out
824: .println("ERROR: null SceneGraphPath");
825: }
826:
827: }
828:
829: return null;
830:
831: }
832:
833: }
|