001: /*
002: * $RCSfile: WalkBehavior.java,v $
003: *
004: * Copyright 1996-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.1 $
041: * $Date: 2007/09/25 20:01:19 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.behaviors;
046:
047: import javax.media.j3d.*;
048: import java.util.*;
049: import java.awt.Event;
050: import java.awt.Point;
051: import java.awt.AWTEvent;
052: import java.awt.event.KeyEvent;
053: import java.awt.event.MouseEvent;
054: import javax.vecmath.*;
055:
056: /**
057: * WalkBehavior is similar to the doomkeys except it can take
058: * input from the mouse for smoother motion
059: *
060: * Key S centers the mouse and sets coordinates to start position
061: * Key C levels the view and sets velocity to zero
062: *
063: * Holding down the shift key and moving the mouse up and down pitches
064: * the viewer
065: */
066:
067: public class WalkBehavior extends Behavior {
068:
069: TransformGroup tgroup;
070:
071: WakeupCondition condition;
072:
073: static final double MOUSE_MOVEMENT = 300;
074: static final double MAX_ANGLE = (Math.PI / 4) / MOUSE_MOVEMENT;
075: static final double ACCELERATION_FACTOR = 0.05;
076:
077: double rollAngle = 0.0;
078: double pitchAngle = 0.0;
079: double yawAngle = 0.0;
080: double velocity = 0.0;
081: double rollAngleDelta = 0.0;
082: double pitchAngleDelta = 0.0;
083: double yawAngleDelta = 0.0;
084: double acceleration;
085:
086: double rollAngleDefault = 0.0;
087: double pitchAngleDefault = 0.0;
088: double yawAngleDefault = 0.0;
089:
090: Transform3D currentView; // Orientation and Translation
091: Transform3D currentOrient; // Orientation
092: Vector3d currentPosn; // Translation
093:
094: Point mousePosn;
095: Point mouseCenter;
096:
097: double startX;
098: double startY;
099: double startZ;
100:
101: public WalkBehavior(TransformGroup tg) {
102: this (0.0, 0.0, 0.0, tg);
103: }
104:
105: public WalkBehavior(double x, double y, double z,
106: TransformGroup tg, double ra, double pa, double ya) {
107: super ();
108: this .tgroup = tg;
109: startX = x;
110: startY = y;
111: startZ = z;
112: rollAngleDefault = ra;
113: pitchAngleDefault = pa;
114: yawAngleDefault = ya;
115: }
116:
117: public WalkBehavior(double x, double y, double z, TransformGroup tg) {
118: this (x, y, z, tg, 0.0, 0.0, 0.0);
119: }
120:
121: public void initialize() {
122: initialize(new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
123: Double.MAX_VALUE), new Vector3d(startX, startY, startZ));
124: }
125:
126: public void initialize(BoundingSphere bounds, Vector3d currentPosn) {
127:
128: Transform3D initTransform = new Transform3D();
129: Vector3d startPosn = new Vector3d();
130: WakeupCriterion[] conditions;
131:
132: conditions = new WakeupCriterion[3];
133: conditions[0] = new WakeupOnAWTEvent(Event.KEY_PRESS);
134: conditions[1] = new WakeupOnAWTEvent(Event.MOUSE_MOVE);
135: conditions[2] = new WakeupOnElapsedTime(50);
136:
137: condition = new WakeupOr(conditions);
138:
139: wakeupOn(condition);
140: setSchedulingBounds(bounds);
141:
142: this .currentPosn = currentPosn;
143:
144: // Setup initial Orientation of View
145: Matrix4d tmp = new Matrix4d();
146: tmp.set(new AxisAngle4d(0, 0, 1, 0));
147: currentOrient = new Transform3D(tmp);
148:
149: currentView = new Transform3D();
150: currentView.setTranslation(currentPosn);
151:
152: mouseCenter = new Point(100, 100);
153:
154: rollAngle = rollAngleDefault;
155: pitchAngle = pitchAngleDefault;
156: yawAngle = yawAngleDefault;
157: rollAngleDelta = 0.0;
158: pitchAngleDelta = 0.0;
159: yawAngleDelta = 0.0;
160: velocity = 0;
161: currentPosn = new Vector3d(startX, startY, startZ);
162: currentOrient.setIdentity();
163: }
164:
165: public void processStimulus(Enumeration criteria) {
166:
167: Transform3D orig = new Transform3D();
168: WakeupCriterion wakeup;
169: boolean AWT = false;
170: AWTEvent[] evt = null;
171: boolean timer = false;
172:
173: while (criteria.hasMoreElements()) {
174: wakeup = (WakeupCriterion) criteria.nextElement();
175: if (wakeup instanceof WakeupOnAWTEvent)
176: evt = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
177: if (wakeup instanceof WakeupOnElapsedTime)
178: timer = true;
179: }
180:
181: if (evt != null && evt[0] instanceof KeyEvent)
182: processKeyEvent((KeyEvent) evt[0]);
183: if (evt != null && evt[0] instanceof MouseEvent) {
184: processMouseEvent((MouseEvent) evt[0]);
185: timer = true;
186: }
187:
188: if (timer) { // If the timer has not expired don't draw
189: calcTransform();
190: tgroup.setTransform(currentView);
191: }
192: wakeupOn(condition);
193: }
194:
195: public void processMouseEvent(MouseEvent evt) {
196: double x, y;
197:
198: if (evt.getID() != MouseEvent.MOUSE_MOVED)
199: return;
200:
201: mousePosn = evt.getPoint();
202:
203: x = mousePosn.x - mouseCenter.x;
204: y = mousePosn.y - mouseCenter.y;
205:
206: yawAngleDelta = -x / MOUSE_MOVEMENT * MAX_ANGLE * Math.abs(x);
207:
208: if (evt.isShiftDown())
209: pitchAngleDelta = -y / MOUSE_MOVEMENT * MAX_ANGLE
210: * Math.abs(y);
211: else
212: velocity = y / MOUSE_MOVEMENT * ACCELERATION_FACTOR
213: * Math.abs(y);
214:
215: }
216:
217: private void processKeyEvent(KeyEvent evt) {
218:
219: int key;
220: double ROT_ANGLE = 0.01;
221: double ACCELERATION = 0.5;
222:
223: key = evt.getKeyCode();
224:
225: if (key == KeyEvent.VK_UP) {
226: velocity -= ACCELERATION;
227: } else if (key == KeyEvent.VK_DOWN) {
228: velocity += ACCELERATION;
229: } else if (key == KeyEvent.VK_LEFT) {
230: yawAngleDelta += ROT_ANGLE;
231: } else if (key == KeyEvent.VK_RIGHT) {
232: yawAngleDelta -= ROT_ANGLE;
233: } else if (key == KeyEvent.VK_S) {
234: mouseCenter = mousePosn;
235: rollAngle = rollAngleDefault;
236: pitchAngle = pitchAngleDefault;
237: yawAngle = yawAngleDefault;
238: rollAngleDelta = 0.0;
239: pitchAngleDelta = 0.0;
240: yawAngleDelta = 0.0;
241: velocity = 0;
242: currentPosn = new Vector3d(startX, startY, startZ);
243: currentOrient.setIdentity();
244: } else if (key == KeyEvent.VK_C) {
245: pitchAngle = 0.0;
246: pitchAngleDelta = 0.0;
247: rollAngle = 0.0;
248: rollAngleDelta = 0.0;
249: currentOrient.setIdentity();
250: velocity = 0.0;
251: }
252:
253: }
254:
255: private void calcTransform() {
256:
257: Matrix3d rot = new Matrix3d();
258: Matrix3d tmpDirection = new Matrix3d();
259: Matrix3d zComp = new Matrix3d(); // Should be a vector but mul not implemented yet
260: Vector3d newDirection = new Vector3d();
261: Transform3D velocityTrans = new Transform3D();
262: Matrix3d rollRot = new Matrix3d();
263: Matrix3d pitchRot = new Matrix3d();
264: Matrix3d yawRot = new Matrix3d();
265:
266: velocityTrans.set(velocity);
267:
268: zComp.setRow(2, 0, 0, 1);
269:
270: pitchAngle += pitchAngleDelta;
271: rollAngle += rollAngleDelta;
272: yawAngle += yawAngleDelta;
273:
274: currentOrient.getRotationScale(rot);
275: tmpDirection.mul(rot, zComp);
276: newDirection.x = tmpDirection.m02;
277: newDirection.y = tmpDirection.m12;
278: newDirection.z = tmpDirection.m22;
279:
280: velocityTrans.transform(newDirection);
281:
282: currentPosn.add(newDirection);
283:
284: rollRot.rotZ(rollAngleDelta);
285: pitchRot.rotX(pitchAngleDelta);
286: yawRot.rotY(yawAngleDelta);
287:
288: rot.mul(rollRot);
289: rot.mul(pitchRot);
290: rot.mul(yawRot);
291:
292: currentOrient.setRotationScale(rot);
293:
294: currentView.setRotationScale(rot);
295: currentView.setTranslation(currentPosn);
296:
297: //System.out.println("Roll="+rollAngle+" Pitch="+pitchAngle+" Velocity="+velocity+" RollDelta="+rollAngleDelta+" PitchDelta="+pitchAngleDelta+" Coords="+currentPosn);
298:
299: }
300:
301: /*
302: * @deprecated Replaced by WalkBehavior( TransformGroup tg )
303: */
304: public void setTransform(TransformGroup t) {
305: this.tgroup = t;
306: t.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
307: t.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
308: }
309: }
|