1
2 /*
3 * @(#)KeyNavigator.java 1.9 01/06/21 06:44:27
4 *
5 * Copyright (c) 1996-2001 Sun Microsystems, Inc. All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * - Redistribution in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * Neither the name of Sun Microsystems, Inc. or the names of
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * This software is provided "AS IS," without a warranty of any
24 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
25 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
27 * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
28 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
29 * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
30 * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
31 * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
32 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
33 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
34 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 * You acknowledge that Software is not designed,licensed or intended
37 * for use in the design, construction, operation or maintenance of
38 * any nuclear facility.
39 */
40
41 package camera3d;
42
43 import java.io.*;
44 import java.util.*;
45 import javax.media.j3d.*;
46 import javax.vecmath.*;
47 import java.awt.event.*;
48
49 /***
50 * This is the KeyNavigator class. It accumulates AWT key events (key
51 * press and key release) and computes a new transform based on the
52 * accumulated events and elapsed time.
53 */
54 class VcKeyNavigator {
55
56 private Vector3d navVec;
57 private long time;
58
59 private Vector3d fwdAcc;
60 private Vector3d bwdAcc;
61 private Vector3d leftAcc;
62 private Vector3d rightAcc;
63 private Vector3d upAcc;
64 private Vector3d downAcc;
65
66 private Vector3d fwdDrag;
67 private Vector3d bwdDrag;
68 private Vector3d leftDrag;
69 private Vector3d rightDrag;
70 private Vector3d upDrag;
71 private Vector3d downDrag;
72
73 private double fwdVMax;
74 private double bwdVMax;
75 private double leftVMax;
76 private double rightVMax;
77 private double upVMax;
78 private double downVMax;
79
80 private float leftRotAngle;
81 private float rightRotAngle;
82 private float upRotAngle;
83 private float downRotAngle;
84
85 private double mmx;
86
87 private Vector3d a = new Vector3d();
88 private Vector3d dv = new Vector3d();
89 private Point3d dp = new Point3d();
90 private Quat4d udQuat = new Quat4d();
91 private Quat4d lrQuat = new Quat4d();
92 private Vector3d vpPos = new Vector3d();
93 private double vpScale;
94 private Quat4d vpQuat = new Quat4d();
95 private Matrix4d vpMatrix = new Matrix4d();
96 private Transform3D vpTrans = new Transform3D();
97 private Matrix4d mat = new Matrix4d();
98 private Vector3d nda = new Vector3d();
99 private Vector3d temp = new Vector3d();
100 private Transform3D nominal = new Transform3D();
101 // private TransformGroup targetTG;
102 private VcView targetView;
103 /* Tells whether we should force update of VcView data
104 after setTransform execution */
105 private boolean updateViewData = true;
106 private boolean keyPressed = true;
107 // buffer used to print debug info
108 private StringBuffer message = new StringBuffer();
109
110
111 private static final int UP_ARROW = (1<<0);
112 private static final int DOWN_ARROW = (1<<1);
113 private static final int LEFT_ARROW = (1<<2);
114 private static final int RIGHT_ARROW = (1<<3);
115 private static final int PLUS_SIGN = (1<<4);
116 private static final int MINUS_SIGN = (1<<5);
117 private static final int PAGE_UP = (1<<6);
118 private static final int PAGE_DOWN = (1<<7);
119 private static final int HOME_DIR = (1<<8);
120 private static final int HOME_NOMINAL = (1<<9);
121
122 private static final int SHIFT = (1<<10);
123 private static final int ALT = (1<<11);
124 private static final int META = (1<<12);
125
126 private static final int KEY_UP = (1<<13);
127 private static final int KEY_DOWN = (1<<14);
128
129 private int key_state = 0;
130 private int modifier_key_state = 0;
131
132 private double accumulator = 0.0;
133 private int runCount = 0;
134
135
136
137 /***
138 * Constructs a new key navigator object that operates on the specified
139 * transform group. All parameters are set to their default, idle state.
140 * @param targetView the target VcView
141 */
142 public VcKeyNavigator(VcView targetView) {
143 //this.targetTG = targetTG;
144 //targetTG.getTransform(nominal);
145 this.targetView = targetView;
146 targetView.getTransforms(nominal);
147
148 mmx = 128.0;
149 navVec = new Vector3d(0.0,0.0,0.0);
150
151 fwdAcc = new Vector3d( 0.0, 0.0,-mmx);
152 bwdAcc = new Vector3d( 0.0, 0.0, mmx);
153 leftAcc = new Vector3d(-mmx, 0.0, 0.0);
154 rightAcc = new Vector3d( mmx, 0.0, 0.0);
155 upAcc = new Vector3d( 0.0, mmx, 0.0);
156 downAcc = new Vector3d( 0.0,-mmx, 0.0);
157
158 fwdDrag = new Vector3d( 0.0, 0.0, mmx);
159 bwdDrag = new Vector3d( 0.0, 0.0,-mmx);
160 leftDrag = new Vector3d( mmx, 0.0, 0.0);
161 rightDrag = new Vector3d(-mmx, 0.0, 0.0);
162 upDrag = new Vector3d( 0.0,-mmx, 0.0);
163 downDrag = new Vector3d( 0.0, mmx, 0.0);
164
165 fwdVMax = -mmx;
166 bwdVMax = mmx;
167 leftVMax = -mmx;
168 rightVMax = mmx;
169 upVMax = mmx;
170 downVMax = -mmx;
171
172 leftRotAngle = (float) (-Math.PI*2.0/3.0);
173 rightRotAngle = (float) (Math.PI*2.0/3.0);
174 upRotAngle = (float) (Math.PI*2.0/3.0);
175 downRotAngle = (float) (-Math.PI*2.0/3.0);
176
177 // Create Timer here.
178 time = System.currentTimeMillis();
179
180 }
181
182
183 private long getDeltaTime() {
184 long newTime = System.currentTimeMillis();
185 long deltaTime = newTime - time;
186 time = newTime;
187 /*************************
188 accumulator += deltaTime;
189 runCount++;
190 if(runCount%500==0){
191 System.out.println("Average deltaTime== "+accumulator/runCount);
192 accumulator = 0.0;
193 runCount = 0;
194 }
195 **********************/
196 if (deltaTime > 2000) return 0;
197 else return deltaTime;
198 }
199
200 void updateTime(){
201 long foo = this.getDeltaTime();
202 }
203
204 /* Generate a quaternion as a rotation of radians av about 0/x 1/y 2/z axis */
205 private void genRotQuat(double av, int axis, Quat4d q) {
206 double b;
207
208 q.x = q.y = q.z = 0.0;
209 q.w = Math.cos(av/2.0);
210
211 b = 1.0 - q.w*q.w;
212
213 if (b > 0.0)
214 b = Math.sqrt(b);
215 else
216 return;
217
218 if (av < 0.0)
219 b = -b;
220 if (axis == 0)
221 q.x = b;
222 else if (axis == 1)
223 q.y = b;
224 else
225 q.z = b;
226
227 }
228
229 private void accKeyAdd(Vector3d a, Vector3d da, Vector3d drag, double scaleVel) {
230
231 /* Scaling of acceleration due to modification keys */
232 nda.scale(scaleVel, da);
233 /* Addition of sufficent acceleration to counteract drag */
234 nda.sub(drag);
235
236 /* Summing into overall acceleration */
237 a.add(nda);
238
239 }
240
241
242 /***
243 * Computes a new transform for the next frame based on
244 * the current transform, accumulated keyboard inputs, and
245 * elapsed time. This new transform is written into the target
246 * transform group.
247 * This method should be called once per frame.
248 */
249 void integrateTransformChanges() {
250
251 double deltaTime = (double) getDeltaTime();
252 deltaTime *= 0.001;
253 // empirical value
254 //double deltaTime = 0.017;
255
256
257 //double deltaTime = .01;
258 //System.out.println("delta time: "+deltaTime);
259 //if(deltaTime <100) deltaTime = .01;
260 //else deltaTime *= 0.001;
261 //System.out.println("delta time2: "+deltaTime);
262 //message.append("__sawFrame\n");
263 //if(!keyPressed) return;
264 //System.out.println("____integrating changes");
265 //message.append("___integrating changes\n");
266 //System.out.println(message);
267 //message = new StringBuffer();
268 double scaleVel, scaleRot, scaleScale, pre, clipScale;
269 double udAng, lrAng, r;
270
271 // Get the current View Platform transform into a transform3D object.
272 targetView.getTransforms(vpTrans);
273 // Extract the position, quaterion, and scale from the transform3D.
274 vpScale = vpTrans.get(vpQuat, vpPos);
275
276 /* Calculate scale due to modification keys */
277 if ((modifier_key_state & SHIFT) != 0 &&
278 (modifier_key_state & META) == 0) {
279 scaleVel = 3.0; scaleRot = 2.0; scaleScale = 4.0;
280 }
281 else if ((modifier_key_state & SHIFT) == 0 &&
282 (modifier_key_state & META) != 0) {
283 scaleVel = 0.1; scaleRot = 0.1; scaleScale = 0.1;
284 }
285 else if ((modifier_key_state & SHIFT) != 0 &&
286 (modifier_key_state & META) != 0) {
287 scaleVel = 0.1; scaleRot = 0.5; scaleScale = 0.1;
288 }
289 else {
290 scaleRot = scaleVel = 1.0; scaleScale = 4.0;
291 }
292
293 clipScale = .1;
294 /*
295 * Processing of rectiliear motion keys.
296 */
297
298 a.x = a.y = a.z = 0.0; /* acceleration initially 0 */
299
300 /* Acceleration due to keys being down */
301 if ((key_state & UP_ARROW) != 0 && (key_state & DOWN_ARROW) == 0)
302 accKeyAdd(a, fwdAcc, fwdDrag, scaleVel);
303 else
304 if ((key_state & UP_ARROW) == 0 && (key_state & DOWN_ARROW) != 0)
305 accKeyAdd(a, bwdAcc, bwdDrag, scaleVel);
306
307 if (((modifier_key_state & ALT) != 0) &&
308 (key_state & LEFT_ARROW) != 0 && (key_state & RIGHT_ARROW) == 0) {
309 accKeyAdd(a, leftAcc, leftDrag, scaleVel);
310 } else
311 if (((modifier_key_state & ALT) != 0) &&
312 (key_state & LEFT_ARROW) == 0 && (key_state & RIGHT_ARROW) != 0)
313 accKeyAdd(a, rightAcc, rightDrag, scaleVel);
314
315 if (((modifier_key_state & ALT) != 0) &&
316 (key_state & PAGE_UP) != 0 && (key_state & PAGE_DOWN) == 0)
317 accKeyAdd(a, upAcc, upDrag, scaleVel);
318 else
319 if (((modifier_key_state & ALT) != 0) &&
320 (key_state & PAGE_UP) == 0 && (key_state & PAGE_DOWN) != 0)
321 accKeyAdd(a, downAcc, downDrag, scaleVel);
322
323
324 /*
325 * Drag due to new or existing motion
326 */
327 pre = navVec.z + a.z * deltaTime;
328 if (pre < 0.0) {
329 if (pre + fwdDrag.z * deltaTime < 0.0)
330 a.add(fwdDrag);
331 else
332 a.z -= pre/deltaTime;
333 } else if (pre > 0.0) {
334 if (pre + bwdDrag.z * deltaTime > 0.0)
335 a.add(bwdDrag);
336 else
337 a.z -= pre/deltaTime;
338 }
339
340 pre = navVec.x + a.x * deltaTime;
341 if (pre < 0.0) {
342 if (pre + leftDrag.x * deltaTime < 0.0)
343 a.add(leftDrag);
344 else
345 a.x -= pre/deltaTime;
346 } else if (pre > 0.0) {
347 if (pre + rightDrag.x * deltaTime > 0.0)
348 a.add(rightDrag);
349 else
350 a.x -= pre/deltaTime;
351 }
352
353 pre = navVec.y + a.y * deltaTime;
354 if (pre < 0.0) {
355 if (pre + downDrag.y * deltaTime < 0.0)
356 a.add(downDrag);
357 else
358 a.y -= pre/deltaTime;
359 } else if (pre > 0.0) {
360 if (pre + upDrag.y * deltaTime > 0.0)
361 a.add(upDrag);
362 else
363 a.y -= pre/deltaTime;
364 }
365
366 /* Integration of acceleration to velocity */
367 dv.scale(deltaTime, a);
368 navVec.add(dv);
369
370 /* Speed limits */
371 if (navVec.z < scaleVel * fwdVMax) navVec.z = scaleVel * fwdVMax;
372 if (navVec.z > scaleVel * bwdVMax) navVec.z = scaleVel * bwdVMax;
373 if (navVec.x < scaleVel * leftVMax) navVec.x = scaleVel * leftVMax;
374 if (navVec.x > scaleVel * rightVMax) navVec.x = scaleVel* rightVMax;
375 if (navVec.y > scaleVel * upVMax) navVec.y = scaleVel * upVMax;
376 if (navVec.y < scaleVel * downVMax) navVec.y = scaleVel * downVMax;
377
378 /* Integration of velocity to distance */
379 dp.scale(deltaTime, navVec);
380
381 /* Scale our motion to the current avatar scale */
382 // 1.0 eventually needs to be a more complex value (see hs).
383 // r = workplace_coexistence_to_vworld_ori.scale/
384 // one_to_one_coexistence_to_vworld_ori.scale;
385 r = vpScale/1.0;
386 dp.scale(r, dp);
387
388 /*
389 * Processing of rotation motion keys.
390 */
391 udAng = lrAng = 0.0;
392
393 /* Rotation due to keys being down */
394 if (((modifier_key_state & ALT) == 0) &&
395 (key_state & LEFT_ARROW) != 0 && (key_state & RIGHT_ARROW) == 0)
396 lrAng = (double) leftRotAngle;
397 else if (((modifier_key_state & ALT) == 0) &&
398 (key_state & LEFT_ARROW) == 0 && (key_state & RIGHT_ARROW) != 0)
399 lrAng = (double) rightRotAngle;
400
401 if (((modifier_key_state & ALT) == 0) &&
402 (key_state & PAGE_UP) != 0 && (key_state & PAGE_DOWN) == 0)
403 udAng = (double) upRotAngle;
404 else if (((modifier_key_state & ALT) == 0) &&
405 (key_state & PAGE_UP) == 0 && (key_state & PAGE_DOWN) != 0)
406 udAng = (double) downRotAngle;
407
408 lrAng *= scaleRot;
409 udAng *= scaleRot;
410
411 /* Scaling of angle change to delta time */
412 lrAng *= deltaTime;
413 udAng *= deltaTime;
414
415
416 /* Addition to existing orientation */
417 // vr_quat_inverse(&workplace_coexistence_to_vworld_ori.quat, &vpQuat);
418 // vpQuat gotten at top of method.
419 vpQuat.inverse();
420
421 if(lrAng != 0.0) {
422 genRotQuat(lrAng, 1, lrQuat);
423 vpQuat.mul(lrQuat, vpQuat);
424 }
425
426 if(udAng != 0.0) {
427 genRotQuat(udAng, 0, udQuat);
428 vpQuat.mul(udQuat, vpQuat);
429 }
430
431 /* Rotation of distance vector */
432 vpQuat.inverse();
433 vpQuat.normalize(); /* Improvment over HoloSketch */
434 mat.set(vpQuat);
435 mat.transform(dp);
436
437 /* Formerly, the adjustment of backclip distance was handled by manipulation
438 of the scale of the viewPlatform transform; as VcKeyNavigator was modified to
439 use the setTransform method of VcView, that was no longer possible: now
440 we directly set the backclip distance
441 */
442 if ((key_state & PLUS_SIGN) != 0) {
443 //System.out.println("Navigator: + pressed");
444 targetView.setFrontClipDistance(targetView.getFrontClipDistance()*1.05);
445 targetView.setBackClipDistance(targetView.getBackClipDistance()*1.05);
446 //vpScale *= (1.0 + (scaleScale*deltaTime));
447 //if (vpScale > 10e+14) vpScale = 1.0;
448 } else if ((key_state & MINUS_SIGN) != 0) {
449 //System.out.println("Navigator: - pressed");
450 targetView.setFrontClipDistance(targetView.getFrontClipDistance()*.95);
451 targetView.setBackClipDistance(targetView.getBackClipDistance()*.95);
452 //vpScale /= (1.0 + (scaleScale*deltaTime));
453 //if (vpScale < 10e-14) vpScale = 1.0;
454 }
455
456 // add dp into current vp position.
457 vpPos.add(dp);
458
459 if ((key_state & HOME_NOMINAL) != 0) {
460 resetVelocity();
461 // Extract the position, quaterion, and scale from the nominal
462 // transform
463 vpScale = nominal.get(vpQuat, vpPos);
464 }
465 //if(keyPressed){
466 //keyPressed = false;
467 /* Final update of view platform */
468 // Put the transform back into the transform group.
469 //vpTrans.set(vpQuat, vpPos, vpScale);
470 //targetView.setTransform(vpTrans);
471 // New Method in VcView
472 targetView.setTransform(vpQuat,vpPos,vpScale);
473 //}
474 }
475
476
477 /***
478 * Resets the keyboard navigation velocity to 0.
479 */
480 private void resetVelocity() {
481 navVec.x = navVec.y = navVec.z = 0.0;
482 }
483
484
485 /***
486 * Processed a keyboard event. This routine should be called
487 * every time a KEY_PRESSED or KEY_RELEASED event is received.
488 * @param keyEvent the AWT key event
489 */
490 public void processKeyEvent(KeyEvent keyEvent) {
491 //System.out.println("__processKeyEvent");
492 //message.append("_processKeyEvent\n");
493 int keyCode = keyEvent.getKeyCode();
494 int keyChar = keyEvent.getKeyChar();
495
496 //System.err.println("keyCode " + keyCode + " keyChar " + keyChar);
497
498 if (keyEvent.getID() == KeyEvent.KEY_RELEASED) {
499 // we will only update data when key is released
500 updateViewData = true;
501 if (keyChar == '+') key_state &= ~PLUS_SIGN;
502 else
503 switch (keyCode) {
504 case KeyEvent.VK_UP: key_state &= ~UP_ARROW; break;
505 case KeyEvent.VK_DOWN: key_state &= ~DOWN_ARROW; break;
506 case KeyEvent.VK_LEFT: key_state &= ~LEFT_ARROW; break;
507 case KeyEvent.VK_RIGHT: key_state &= ~RIGHT_ARROW; break;
508 case KeyEvent.VK_PAGE_UP: key_state &= ~PAGE_UP; break;
509 case KeyEvent.VK_PAGE_DOWN: key_state &= ~PAGE_DOWN; break;
510 case KeyEvent.VK_EQUALS: key_state &= ~HOME_NOMINAL;break;
511 default: switch(keyChar) {
512 case '-': key_state &= ~MINUS_SIGN; break;
513 }
514 }
515 } else if (keyEvent.getID() == KeyEvent.KEY_PRESSED) {
516 updateViewData = false;
517 if (keyChar == '+') key_state |= PLUS_SIGN;
518 switch (keyCode) {
519 case KeyEvent.VK_UP: key_state |= UP_ARROW; break;
520 case KeyEvent.VK_DOWN: key_state |= DOWN_ARROW; break;
521 case KeyEvent.VK_LEFT: key_state |= LEFT_ARROW; break;
522 case KeyEvent.VK_RIGHT: key_state |= RIGHT_ARROW; break;
523 case KeyEvent.VK_PAGE_UP: key_state |= PAGE_UP; break;
524 case KeyEvent.VK_PAGE_DOWN: key_state |= PAGE_DOWN; break;
525 case KeyEvent.VK_EQUALS: key_state |= HOME_NOMINAL;break;
526 default: switch(keyChar) {
527 case '-': key_state |= MINUS_SIGN; break;
528 }
529 }
530
531 }
532
533 /* Check modifier keys */
534 if (keyEvent.isShiftDown())
535 modifier_key_state |= SHIFT;
536 else
537 modifier_key_state &= ~SHIFT;
538
539 if (keyEvent.isMetaDown())
540 modifier_key_state |= META;
541 else
542 modifier_key_state &= ~META;
543
544 if (keyEvent.isAltDown())
545 modifier_key_state |= ALT;
546 else
547 modifier_key_state &= ~ALT;
548
549 //System.err.println("keyCode " + keyEvent.getKeyCode() + " modifiers " + keyEvent.getModifiers());
550 //System.err.println("SHIFT_MASK " + keyEvent.SHIFT_MASK);
551 //System.err.println("CTRL_MASK " + keyEvent.CTRL_MASK);
552 //System.err.println("META_MASK " + keyEvent.META_MASK);
553 //System.err.println("ALT_MASK " + keyEvent.ALT_MASK);
554
555 keyPressed =true;
556 }
557 }
This page was automatically generated by Maven