001: /*
002: * $RCSfile: Evagation.java,v $
003: *
004: * @(#)Evagation.java 1.31 99/03/01 14:33:18
005: *
006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
007: *
008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
009: * modify and redistribute this software in source and binary code form,
010: * provided that i) this copyright notice and license appear on all copies of
011: * the software; and ii) Licensee does not utilize the software in a manner
012: * which is disparaging to Sun.
013: *
014: * This software is provided "AS IS," without a warranty of any kind. ALL
015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGES.
025: *
026: * This software is not designed or intended for use in on-line control of
027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
028: * the design, construction, operation or maintenance of any nuclear
029: * facility. Licensee represents and warrants that it will not use or
030: * redistribute the Software for such purposes.
031: *
032: * $Revision: 1.2 $
033: * $Date: 2005/02/03 23:06:55 $
034: * $State: Exp $
035: */
036: package org.jdesktop.j3d.loaders.vrml97.impl;
037:
038: import java.applet.Applet;
039: import java.awt.AWTEvent.*;
040: import java.awt.AWTEvent;
041: import java.awt.Cursor;
042: import java.awt.Dimension;
043: import java.awt.Event;
044: import java.awt.Frame;
045: import java.awt.Point;
046: import java.awt.Point;
047: import java.awt.event.*;
048: import java.net.*;
049: import java.util.*;
050: import java.util.Enumeration;
051:
052: import javax.media.j3d.*;
053: import javax.vecmath.*;
054: import vrml.InvalidVRMLSyntaxException;
055:
056: /**
057: * Evagation \Ev`a*ga*tion\, n A wandering about, excursion, a roving.
058: * (Source: Webster's Revised Unbriged Dictionary (1913))
059: *
060: * This is the event controller for the VRML runtime. It dispatches events
061: * from Java3D to the VRML Sensors and handles the walk/fly/examine Viewpoint
062: * animation.
063: */
064: public class Evagation extends Behavior {
065:
066: TransformGroup viewTrans = new TransformGroup();
067: Browser browser;
068: PickRay pickRay;
069: WakeupOnCollisionEntry collisionEnter;
070: WakeupOnCollisionExit collisionExit;
071: WakeupCriterion[] criterion = new WakeupCriterion[7];
072: Matrix3d rot = new Matrix3d();
073: Matrix3d lastFreeRot = new Matrix3d();
074: Matrix3d tmpDirection = new Matrix3d();
075: Matrix3d zComp = new Matrix3d();
076: Vector3d newDirection = new Vector3d();
077: Transform3D positionTrans = new Transform3D();
078: Matrix3d rollRot = new Matrix3d();
079: Matrix3d pitchRot = new Matrix3d();
080: Matrix3d yawRot = new Matrix3d();
081: double rollAngle = 0.0;
082: double pitchAngle = 0.0;
083: double yawAngle = 0.0;
084: double velocity = 0.0;
085: double rollAngleDelta = 0.0;
086: double pitchAngleDelta = 0.0;
087: double yawAngleDelta = 0.0;
088: double directionX;// non destroyed direction vector components
089: double directionY;
090: double directionZ;
091: double acceleration;
092: final static double SPEED = .005;
093: double speed = SPEED;
094: double angularSpeed = SPEED / 420.0;
095: Transform3D currentView;// Orientation and Translation
096: Vector3d currentPosn;// Translation
097: Vector3d lastFreePosn = new Vector3d();
098: Point mousePosn;
099: Point3d eyePosn = new Point3d();
100: double eyeZoffset = 0.0;
101: double startX = 0.0;
102: double startY = 0.0;
103: double startZ = 0.0;
104: double lastT = 0.0;
105: double deltaT = 0.0;
106: static double MAXANG = Math.PI * 2.0;
107: int last_x, last_y;
108: int first_x, first_y;
109: int drag_dx, drag_dy;
110: int eid;
111: boolean initialized;
112: // bug: first time causes null ptr exception
113: boolean firstTime = true;// for resetWakeups
114: boolean collided = false;
115: // store the current dragsensor, so mouse
116: // motion means something even if the mouse isn't over
117: // the sensor until mouse released.
118: String navMode;
119: SphereSensor sceneExaminer = null;
120: DragSensor curDragSensor;
121: boolean dragIsSensor = false;
122:
123: // pick sphere stuff
124: Transform3D tfm = new Transform3D();
125: Transform3D tfmO = new Transform3D();
126: javax.media.j3d.Appearance pickAppear;
127: javax.media.j3d.TransparencyAttributes pickTransat;
128: RGroup pickSphereHandle;
129: TransformGroup pickSphereLocator = new TransformGroup();
130:
131: // Reusable vars
132: Point3d p1 = new Point3d();
133: Point3d p2 = new Point3d();
134:
135: /**
136: *Constructor for the Evagation object
137: *
138: *@param initBrowser Description of the Parameter
139: */
140: public Evagation(Browser initBrowser) {
141: browser = initBrowser;
142: initialized = false;
143: collided = false;
144: currentView = new Transform3D();
145: currentView.setIdentity();
146: pickRay = new PickRay();
147: }
148:
149: /** Description of the Method */
150: public void initialize() {
151: initialize(new BoundingSphere(new Point3d(), 1000.0),
152: new Vector3d(startX, startY, startZ));
153:
154: }
155:
156: /**
157: * Description of the Method
158: *
159: *@param bounds Description of the Parameter
160: *@param currentPosn Description of the Parameter
161: */
162: public void initialize(BoundingSphere bounds, Vector3d currentPosn) {
163:
164: Transform3D initTransform = new Transform3D();
165: setSchedulingBounds(bounds);
166: this .currentPosn = currentPosn;
167:
168: currentView.setTranslation(currentPosn);
169:
170: rollAngle = 0.0;
171: pitchAngle = 0.0;
172: rollAngleDelta = 0.0;
173: pitchAngleDelta = 0.0;
174: yawAngleDelta = 0.0;
175: yawAngleDelta = 0.0;
176: velocity = 0;
177:
178: initialized = true;
179: resetWakeups();
180: }
181:
182: /**
183: * Sets the viewGroup attribute of the Evagation object
184: *
185: *@param newViewTrans The new viewGroup value
186: */
187: public void setViewGroup(TransformGroup newViewTrans) {
188: viewTrans = newViewTrans;
189:
190: // getBounds only works with Morph and Shape now
191: //Bounds b = viewTrans.getBounds();
192: Bounds b = new BoundingSphere();
193: if (browser.curNavInfo == null) {
194: browser.curNavInfo = new NavigationInfo(browser.loader);
195: } else {
196: double sizex = browser.curNavInfo.avatarSize.mfloat[0] / 2.0f;
197: double sizey;
198: if (browser.curNavInfo.avatarSize.mfloat.length > 1) {
199: sizey = browser.curNavInfo.avatarSize.mfloat[1] / 2.0f;
200: } else {
201: sizey = browser.curNavInfo.avatarSize.mfloat[0] / 2.0f;
202: }
203: double sizez;
204: if (browser.curNavInfo.avatarSize.mfloat.length > 2) {
205: sizez = browser.curNavInfo.avatarSize.mfloat[2] / 2.0f;
206: } else {
207: sizez = browser.curNavInfo.avatarSize.mfloat[0] / 2.0f;
208: }
209: b = new BoundingBox(new Point3d(-sizex, -sizey, -sizez),
210: new Point3d(sizex, sizey, sizez));
211: navMode = browser.curNavInfo.type.strings[0];
212: if (!navMode.equals("EXAMINE") && !navMode.equals("WALK")) {
213: navMode = "WALK";
214: }
215: }//else b = new BoundingSphere();
216: speed = browser.curNavInfo.speed.value * SPEED;
217: viewTrans.setCollisionBounds(b);
218: viewTrans.setBounds(b);
219: viewTrans.getTransform(currentView);
220: Vector3d vc = new Vector3d();
221: currentView.get(vc);
222: startX = vc.x;
223: startY = vc.y;
224: startZ = vc.z;
225:
226: if (sceneExaminer != null && navMode.equals("WALK")) {
227: try {
228: browser.deleteRoute(sceneExaminer, "rotation",
229: browser.curSceneT, "rotation");
230: browser.curSceneT.impl.setUserData(null);
231: } catch (Exception e) {
232: e.printStackTrace();
233: }
234: browser.curViewpoint.updateViewTrans();
235: }
236: if (navMode.equals("EXAMINE")) {
237: // bug: it can sometimes happen that in examine mode with
238: // no viewpoint specified that the sceneExaminer is null when
239: // it actually wasn't expected
240: if (browser.sceneExaminer == null) {
241: browser.sceneExaminer = new SphereSensor(browser.loader);
242: try {
243: browser.sceneExaminer
244: .updateParent(browser.curSceneT.impl);
245: } catch (NullPointerException npe) {
246: ;
247: }
248: }
249: sceneExaminer = browser.sceneExaminer;
250: try {
251: browser.addRoute(sceneExaminer, "rotation",
252: browser.curSceneT, "rotation");
253: } catch (Exception e) {
254: e.printStackTrace();
255: }// will null first time
256: }
257: //resetWakeups();
258: }
259:
260: /** Description of the Method */
261: void resetWakeups() {
262: //if ( !firstTime ) {
263: SceneGraphPath viewPath = new SceneGraphPath(browser.locale,
264: viewTrans);
265: //collisionEnter = new WakeupOnCollisionEntry(viewPath);
266: //collisionExit = new WakeupOnCollisionExit(viewPath);
267: //criterion[0] = collisionEnter;
268: //criterion[1] = collisionExit;
269: criterion = new WakeupCriterion[7];
270: criterion[0] = new WakeupOnAWTEvent(MouseEvent.MOUSE_MOVED);
271: criterion[1] = new WakeupOnAWTEvent(MouseEvent.MOUSE_PRESSED);
272: criterion[2] = new WakeupOnAWTEvent(MouseEvent.MOUSE_DRAGGED);
273: criterion[3] = new WakeupOnAWTEvent(MouseEvent.MOUSE_CLICKED);
274: criterion[4] = new WakeupOnAWTEvent(MouseEvent.MOUSE_RELEASED);
275: criterion[5] = new WakeupOnAWTEvent(KeyEvent.KEY_RELEASED);
276: criterion[6] = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
277:
278: wakeupOn(new WakeupOr(criterion));
279: //} else { firstTime = false; }
280: firstTime = false;
281: }
282:
283: /**
284: * Description of the Method
285: *
286: *@param critter Description of the Parameter
287: */
288: public void processStimulus(Enumeration critter) {
289: WakeupCriterion wakeup;
290: while (critter.hasMoreElements()) {
291: wakeup = (WakeupCriterion) critter.nextElement();
292: //if ( wakeup instanceof WakeupOnCollisionEntry ) {
293: //collided = true;
294: //currentView.setRotationScale( lastFreeRot );
295: //currentView.setTranslation( lastFreePosn );
296: //resetWakeups();
297: //System.out.println("collided");
298: //} else if ( wakeup instanceof WakeupOnCollisionExit ) {
299: //collided = false;
300: //System.out.println("exit");
301: //resetWakeups();
302: //} else if ( wakeup instanceof WakeupOnAWTEvent ) {
303: AWTEvent[] awts = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
304: for (int i = 0; i < awts.length; i++) {
305: processEvent(awts[i]);
306: }
307: resetWakeups();
308: //}
309:
310: }
311: }
312:
313: /**
314: * Description of the Method
315: *
316: *@param evt Description of the Parameter
317: */
318: void processEvent(AWTEvent evt) {
319: if (!initialized) {
320: System.out.println("Event before behavior is initialized");
321: return;
322: }
323: if (evt instanceof KeyEvent) {
324: processKeyEvent((KeyEvent) evt);
325: } else if (evt instanceof MouseEvent) {
326: processMouseEvent((MouseEvent) evt);
327: } else if (evt instanceof FocusEvent) {
328: processFocusEvent((FocusEvent) evt);
329: }
330: }
331:
332: /**
333: * Description of the Method
334: *
335: *@param evt Description of the Parameter
336: */
337: public void processMouseEvent(MouseEvent evt) {
338:
339: eid = evt.getID();
340: boolean mmb = ((evt.getModifiers() & MouseEvent.BUTTON2_MASK) > 0);
341: switch (eid) {
342: case MouseEvent.MOUSE_DRAGGED:
343: mousePosn = evt.getPoint();
344:
345: drag_dx = mousePosn.x - first_x;
346: drag_dy = mousePosn.y - first_y;
347: last_x = mousePosn.x;
348: last_y = mousePosn.y;
349:
350: // this must be here, and really want to do this in vworld coords
351: if (drag_dx * drag_dx + drag_dy * drag_dy > 100) {
352: mouseDragged(evt.getWhen(), drag_dx, drag_dy, first_x,
353: first_y, mmb);
354: }
355:
356: if (dragIsSensor) {
357: velocity = 0;
358: } else {
359: pitchAngleDelta = -drag_dx * angularSpeed;
360: if (evt.isShiftDown()) {
361: yawAngleDelta = -drag_dy * angularSpeed;
362: } else {
363: velocity = (drag_dy) * speed;
364: }
365: }
366:
367: break;
368: case MouseEvent.MOUSE_CLICKED:
369: mousePosn = evt.getPoint();
370: first_x = last_x = mousePosn.x;
371: first_y = last_y = mousePosn.y;
372: mouseClicked(evt.getWhen(), last_x, last_y, mmb);
373: break;
374: case MouseEvent.MOUSE_PRESSED:
375: mousePosn = evt.getPoint();
376: first_x = mousePosn.x;
377: first_y = mousePosn.y;
378: break;
379: case MouseEvent.MOUSE_RELEASED:
380: clearDragState();
381: curDragSensor = null;
382: dragIsSensor = false;
383: break;
384: default:
385: break;
386: }
387: update();
388:
389: }
390:
391: /**
392: * Description of the Method
393: *
394: *@param evt Description of the Parameter
395: */
396: private void processKeyEvent(KeyEvent evt) {
397: int key;
398: double ROT_ANGLE = 0.03;
399: double VELOCITY = 5.0;
400: key = evt.getKeyCode();
401: if (evt.getID() == KeyEvent.KEY_RELEASED) {
402: velocity = 0.0;
403: rollAngleDelta = 0.0;
404: pitchAngleDelta = 0.0;
405: yawAngleDelta = 0.0;
406: }
407:
408: // todo: make a switch statement instead
409: if (evt.getID() == KeyEvent.KEY_PRESSED) {
410: if (key == KeyEvent.VK_UP) {
411: velocity = -VELOCITY;
412: } else if (key == KeyEvent.VK_DOWN) {
413: velocity = VELOCITY;
414: } else if (key == KeyEvent.VK_LEFT) {
415: pitchAngleDelta += ROT_ANGLE;
416: } else if (key == KeyEvent.VK_RIGHT) {
417: pitchAngleDelta -= ROT_ANGLE;
418: } else if (key == KeyEvent.VK_S) {
419: resetViewpoint();
420: } else if (key == KeyEvent.VK_C) {
421: pitchAngle = 0.0;
422: pitchAngleDelta = 0.0;
423: rollAngle = 0.0;
424: rollAngleDelta = 0.0;
425: velocity = 0.0;
426: } else if (key == KeyEvent.VK_D) {
427: browser.treePrinter.print(browser.curScene);
428: } else if (key == KeyEvent.VK_SLASH) {
429: browser.outputTiming();
430: } else if (key == KeyEvent.VK_ESCAPE) {
431: browser.outputTiming();
432: browser.shutDown();
433: } else if (key == KeyEvent.VK_PAGE_UP) {
434: yawAngleDelta = 2.0 * SPEED;
435: } else if (key == KeyEvent.VK_PAGE_DOWN) {
436: yawAngleDelta = -2.0 * SPEED;
437: }
438: }
439: calcTransform();
440: viewTrans.setTransform(currentView);
441:
442: }
443:
444: /**
445: * Description of the Method
446: *
447: *@param evt Description of the Parameter
448: */
449: private void processFocusEvent(FocusEvent evt) {
450: if (evt.getID() == FocusEvent.FOCUS_GAINED) {
451: //System.out.println("XAutoRepeatOn(display) ... please ");
452: } else if (evt.getID() == FocusEvent.FOCUS_LOST) {
453: //System.out.println("XAutoRepeatOff(display) ... please ");
454: }
455: }
456:
457: /** Description of the Method */
458: void forceUpDown() {
459: curDragSensor = null;
460: clearDragState();
461: first_x = last_x = mousePosn.x;
462: first_y = last_y = mousePosn.y;
463: mouseDragged(Time.getNow(), drag_dx, drag_dy, first_x, first_y,
464: false);
465:
466: }
467:
468: /** Description of the Method */
469: void clearDragState() {
470: drag_dx = drag_dy = 0;
471: first_x = first_y = -1;
472: rollAngleDelta = pitchAngleDelta = yawAngleDelta = 0.0;
473: velocity = 0.0;
474: if (curDragSensor != null) {
475: curDragSensor.offset();
476: }
477: }
478:
479: /** Description of the Method */
480: private void calcTransform() {
481:
482: //if (!collided) {
483: positionTrans.set(velocity * deltaT);
484: zComp.setIdentity();
485: zComp.setRow(2, 0, 0, 1);
486:
487: rot.setIdentity();
488: rot.mul(rollRot);
489: rot.mul(pitchRot);
490: rot.mul(yawRot);
491:
492: tmpDirection.mul(rot, zComp);
493: newDirection.x = directionX = tmpDirection.m02;
494: newDirection.y = directionY = tmpDirection.m12;
495: newDirection.z = directionZ = tmpDirection.m22;
496:
497: positionTrans.transform(newDirection);
498: currentPosn.add(newDirection);
499:
500: rollAngle = Math.IEEEremainder(rollAngle + rollAngleDelta,
501: Math.PI * 2.0);
502: pitchAngle = Math.IEEEremainder(pitchAngle + pitchAngleDelta,
503: Math.PI * 2.0);
504: yawAngle = Math.IEEEremainder(yawAngle + yawAngleDelta,
505: Math.PI * 2.0);
506:
507: rollRot.rotZ(rollAngle);
508: pitchRot.rotY(pitchAngle);
509: yawRot.rotX(yawAngle);
510:
511: currentView.setRotationScale(rot);
512: currentView.setTranslation(currentPosn);
513: //} else {
514: //currentView.setRotationScale( lastFreeRot );
515: //currentView.setTranslation( lastFreePosn );
516: //}
517: }
518:
519: /**
520: * Description of the Method
521: *
522: *@param now Description of the Parameter
523: */
524: public void simTick(double now) {
525: // it is not specified when the event acutally happens, so
526: // that is why collided gets checked all the time
527: if (!collided) {
528: deltaT = now - lastT;
529: lastFreeRot.set(rot);
530: lastFreePosn.set(currentPosn);
531: } else {
532: if (browser.debug) {
533: System.out.println("collided");
534: }
535: deltaT = 0.0;// this effectively freezes the viewplatfrom
536: // upon collision. it is not entirely the desired effect
537: //deltaT = now-lastT;
538: }
539: lastT = now;
540: update();
541: // This is an experimental drag-n-hold feature. Uncomment to enable
542: // the SphereSensor SFBool autoSpin from within a file
543: //if ( curDragSensor != null )
544: //curDragSensor.simTick(now);
545: }
546:
547: /** Description of the Method */
548: void update() {
549: if (initialized) {
550: calcTransform();
551: // any new collision info should happen after this call
552: if ((currentView.getType() & Transform3D.CONGRUENT) != 0) {
553: viewTrans.setTransform(currentView);
554: }
555: }
556: }
557:
558: /** Description of the Method */
559: public void resetViewpoint() {
560: rollAngle = 0.0;
561: pitchAngle = 0.0;
562: yawAngle = 0.0;
563: rollAngleDelta = 0.0;
564: pitchAngleDelta = 0.0;
565: yawAngleDelta = 0.0;
566: velocity = 0;
567: currentPosn = new Vector3d(startX, startY, startZ);
568: }
569:
570: /**
571: * Gets the pickRay attribute of the Evagation object
572: *
573: *@param xpos Description of the Parameter
574: *@param ypos Description of the Parameter
575: *@return The pickRay value
576: */
577: private PickRay getPickRay(int xpos, int ypos) {
578: Transform3D motion = new Transform3D();
579: Point3d mousePosn = new Point3d();
580: Vector3d mouseVec = new Vector3d();
581:
582: browser.canvas.getCenterEyeInImagePlate(eyePosn);
583: browser.canvas.getPixelLocationInImagePlate(xpos, ypos,
584: mousePosn);
585: browser.canvas.getImagePlateToVworld(motion);
586:
587: //if(navMode.equals("EXAMINE")) eyeZoffset = eyePosn.z;
588: //else eyeZoffset=0.0;
589: eyeZoffset = eyePosn.z;
590:
591: motion.transform(eyePosn);
592: motion.transform(mousePosn);
593: mouseVec.sub(mousePosn, eyePosn);
594: mouseVec.normalize();
595:
596: pickRay.set(eyePosn, mouseVec);
597:
598: return pickRay;
599: }
600:
601: /**
602: * Description of the Method
603: *
604: *@param step Description of the Parameter
605: *@param path Description of the Parameter
606: */
607: private void pickEcho(javax.media.j3d.Node step, SceneGraphPath path) {
608: try {
609: javax.media.j3d.Bounds b = step.getBounds();
610: if (b instanceof javax.media.j3d.BoundingSphere) {
611: Point3d p = new Point3d();
612: ((BoundingSphere) b).getCenter(p);
613: try {
614: step.getLocalToVworld(this .tfm);
615: } catch (IllegalSharingException e) {
616: try {
617: step.getLocalToVworld(path, this .tfm);
618: } catch (Exception f) {
619: /*f.printStackTrace();*/
620: ;
621: }
622: }
623: this .tfmO.set(new Vector3d(p));
624: this .tfm.mul(this .tfmO);
625: com.sun.j3d.utils.geometry.Sphere sp = new com.sun.j3d.utils.geometry.Sphere(
626: (float) ((BoundingSphere) b).getRadius());
627: attachPickSphere(sp);
628: } else {
629: if (browser.debug) {
630: System.out.println("node bounds are not "
631: + "BoundingSphere");
632: }
633: }
634: // node might not have capability to read bounds
635: } catch (Exception ed) {
636: System.out.println("Exception trying to echo pick");
637: ed.printStackTrace();
638: }
639: }
640:
641: /**
642: * Description of the Method
643: *
644: *@param when Description of the Parameter
645: *@param x Description of the Parameter
646: *@param y Description of the Parameter
647: *@param mmb Description of the Parameter
648: */
649: void mouseClicked(double when, int x, int y, boolean mmb) {
650:
651: if (browser.debug) {
652: System.out.println("Evagation.mouseClicked() called");
653: }
654: // all touch events should have the same timestamp. This will
655: // prevent multiple events on the same sensor from the same pick
656: double touchTime = Time.getNow();
657: browser.beginRoute(touchTime);
658:
659: SceneGraphPath[] stuffPicked = browser.curScene
660: .pickAllSorted(getPickRay(x, y));
661: if (stuffPicked != null) {
662: if (browser.debug) {
663: System.out.println("stuffPicked.length="
664: + stuffPicked.length);
665: }
666: for (int i = 0; i < stuffPicked.length; i++) {
667: if (browser.debug) {
668: System.out.println("stuffPicked[" + i + "] is "
669: + stuffPicked[i]);
670: }
671: VrmlSensor vs = (VrmlSensor) null;
672: Vector sv = (Vector) null;
673: javax.media.j3d.Node step = null;
674: if (browser.debug) {
675: System.out.println("stuffPicked[" + i
676: + "].nodeCount() = "
677: + stuffPicked[i].nodeCount());
678: }
679: for (int j = 0; j < stuffPicked[i].nodeCount(); j++) {
680: step = stuffPicked[i].getNode(j);
681: if (browser.debug || browser.pickEcho) {
682: pickEcho(step, stuffPicked[i]);
683: }
684: Object o = step.getUserData();
685: if (browser.debug && j == 0) {
686: System.out.println(i + " " + j
687: + "Picked node is " + step
688: + " user data is " + o);
689: System.out.println(stuffPicked[i].getObject());
690: }
691: if (o instanceof Vector && !((Vector) o).isEmpty()) {
692: // save the bottom most to preserve nesting
693: // note, the userData should be a vector
694: // of sensors for this group.
695: sv = (Vector) o;
696: // rare case
697: } else if (o instanceof SphereSensor) {
698: sv = new Vector();
699: sv.addElement(o);
700: step.setUserData(sv);
701: }
702: }
703:
704: if (sv != null) {
705: Enumeration e = sv.elements();
706: while (e.hasMoreElements()) {
707: vs = (VrmlSensor) (e.nextElement());
708: if (vs instanceof TouchSensor) {
709: TouchSensor ts = (TouchSensor) vs;
710: if (ts.enabled.value == true) {
711: if (browser.debug) {
712: System.out
713: .println("Calling setValue on "
714: + "touchTime for sensor "
715: + ts.toStringId());
716: }
717: ts.touchTime.setValue(touchTime);
718: }
719: } else if (vs instanceof DragSensor && !mmb) {
720: // p1 and p2 are same point, its a click
721: //browser.canvas.getPixelLocationInImagePlate(x,y,p1);
722: //browser.canvas.getPixelLocationInImagePlate(x,y,p2);
723: //((DragSensor)vs).update(p1,p2,step,stuffPicked[i]);
724: //dragIsSensor = true;
725: //curDragSensor = (DragSensor)vs;
726: } else if (vs instanceof Anchor) {
727: String toGoto = ((Anchor) vs).url.strings[0];
728: try {
729: browser.canvas.setCursor(new Cursor(
730: Cursor.WAIT_CURSOR));
731: browser.loadURL(
732: ((Anchor) vs).url.strings,
733: (String[]) null);
734: } catch (java.io.IOException ioe) {
735: System.err
736: .println("IO exception reading URL");
737: } catch (InvalidVRMLSyntaxException ivse) {
738: System.err.println("VRML parse error");
739: }
740: String status = browser.getName() + " : "
741: + browser.getDescription();
742: if (browser.container instanceof Applet) {
743: if (toGoto.endsWith(".wrl")) {
744: ((Applet) (browser.container))
745: .showStatus(status);
746: } else {
747: try {
748: ((Applet) (browser.container))
749: .getAppletContext()
750: .showDocument(
751: new URL(toGoto));
752: } catch (MalformedURLException me) {
753: ((Applet) (browser.container))
754: .showStatus(me
755: .toString());
756: }
757: }
758: } else if (browser.container instanceof Frame) {
759: ((Frame) (browser.container))
760: .setTitle(status);
761: ((org.jdesktop.j3d.loaders.vrml97.Player) (browser.container))
762: .setGotoString(toGoto);
763: }
764: browser.canvas.setCursor(new Cursor(
765: Cursor.HAND_CURSOR));
766: }
767: }
768: }
769: }
770: }
771:
772: browser.endRoute();
773: }
774:
775: /**
776: * Description of the Method
777: *
778: *@param when Description of the Parameter
779: *@param dx Description of the Parameter
780: *@param dy Description of the Parameter
781: *@param x Description of the Parameter
782: *@param y Description of the Parameter
783: *@param mmb Description of the Parameter
784: */
785: void mouseDragged(double when, int dx, int dy, int x, int y,
786: boolean mmb) {
787: // bug: if a click sensor and drag sensor are in same group,
788: // drag never autoRotates.
789: browser.beginRoute(Time.getNow());
790: if (curDragSensor != null && !mmb) {
791: // dragsensors node reference must have already been set
792: browser.canvas.getPixelLocationInImagePlate(x, y, p1);
793: browser.canvas.getPixelLocationInImagePlate(x + dx, y + dy,
794: p2);
795: p1.z = p2.z = eyeZoffset;
796: curDragSensor.update(p1, p2, null, null);
797: } else {
798: SceneGraphPath[] stuffDragged = browser.curScene
799: .pickAllSorted(getPickRay(x, y));
800: if (stuffDragged != null) {
801: for (int i = 0; i < stuffDragged.length; i++) {
802: VrmlSensor vs = (VrmlSensor) null;
803: Vector sv = (Vector) null;
804: javax.media.j3d.Node step = null;
805: for (int j = 0; j < stuffDragged[i].nodeCount(); j++) {
806: try {
807: step = stuffDragged[i].getNode(j);
808: Object o = step.getUserData();
809: if (browser.debug && j == 0) {
810: System.out.println(i + "." + j
811: + ": Picked node is " + step
812: + " user data is " + o);
813: }
814:
815: if (o instanceof Vector
816: && !((Vector) o).isEmpty()) {
817: // save the bottom most to preserve nesting
818: // note, the userData should be a vector
819: // of sensors for this group.
820: sv = (Vector) o;
821: // the scneExaminer should be the exception
822: if (navMode.equals("EXAMINE")) {
823: j = stuffDragged[i].nodeCount();
824: }// break;
825: }
826: // node might not have capability to read bounds
827: } catch (Exception ed) {
828: ed.printStackTrace();
829: }
830: }
831: if (sv != null) {
832: Enumeration e = sv.elements();
833: while (e.hasMoreElements()) {
834: vs = (VrmlSensor) (e.nextElement());
835: if (vs instanceof DragSensor && !mmb) {
836: browser.canvas
837: .getPixelLocationInImagePlate(
838: x, y, p1);
839: browser.canvas
840: .getPixelLocationInImagePlate(x
841: + dx, y + dy, p2);
842: p1.z = p2.z = eyeZoffset;
843: // this is the first drag segment,
844: // The sensor may need to inspect the stuffDragged path
845: // to get the transform above.
846: ((DragSensor) vs).update(p1, p2, step,
847: stuffDragged[i]);
848: dragIsSensor = true;
849: curDragSensor = (DragSensor) vs;
850: } else {
851: curDragSensor = null;
852: }
853: }
854: }
855: }
856: }
857: }
858: browser.endRoute();
859: }
860:
861: /**
862: * Description of the Method
863: *
864: *@param sp Description of the Parameter
865: */
866: void attachPickSphere(com.sun.j3d.utils.geometry.Sphere sp) {
867: if (!pickSphereLocator.isLive()) {
868: try {
869: pickSphereLocator.removeChild(0);
870: } catch (ArrayIndexOutOfBoundsException aioobe) {
871: ;
872: }
873:
874: pickSphereHandle = new RGroup();
875: pickSphereLocator = new TransformGroup();
876: pickSphereHandle.addChild(pickSphereLocator);
877: pickTransat = new javax.media.j3d.TransparencyAttributes(
878: TransparencyAttributes.FASTEST, 0.5f);
879: pickTransat
880: .setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
881: pickTransat
882: .setCapability(TransparencyAttributes.ALLOW_VALUE_READ);
883: pickAppear = new javax.media.j3d.Appearance();
884: pickAppear.setTransparencyAttributes(pickTransat);
885: // sphere should have been already created the right size
886: sp.setAppearance(pickAppear);
887: pickSphereLocator.addChild(sp);
888: pickSphereLocator.addChild(new PickSphereTimer(browser,
889: pickSphereHandle, pickTransat));
890: pickSphereLocator.setTransform(this.tfm);
891: browser.locale.addBranchGraph(pickSphereHandle);
892: }
893: }
894:
895: }
|