View Javadoc
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