View Javadoc
1 /***************************************************************************** 2 * Virtual Mockup for Machine Vision 3 * Copyright (C) 2001-2003 Fabio R. de Miranda, João E. Kogler Jr., 4 * Carlos S. Santos. 5 * Virtual Mockup for Machine Vision Project funded by SENAC-SP 6 * 7 * Permission is granted to redistribute and/or modify this 8 * software under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This software is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License (http://www.gnu.org/copyleft/lesser.html) 16 * for more details. 17 * 18 *****************************************************************************/ 19 20 package camera3d; 21 22 import javax.media.j3d.*; 23 import javax.vecmath.*; 24 import java.util.*; 25 import javax.swing.Icon; 26 import camera3d.event.*; 27 import camera3d.manipulation.RotatableObject; 28 import camera3d.manipulation.TranslatableObject; 29 import camera3d.manipulation.ScalableObject; 30 31 /*** 32 * Abstract superclass to all objects that can be added to the scene graph. 33 * 34 * @author Fábio Roberto de Miranda, Carlos da Silva dos Santos 35 */ 36 public abstract class VcObject implements RotatableObject, 37 TranslatableObject, 38 ScalableObject { 39 40 41 private static final boolean autoComputeBounds = false; 42 43 private boolean debugflag = true; 44 45 String tooltipText; 46 47 /*** Holds rotation angles. */ 48 Vector3f rotAngles; 49 /*** Holds local rotation angles. */ 50 Vector3d localRotAngles; 51 /*** Holds translation values. */ 52 Vector3d transVec; 53 /*** Holds scale values. */ 54 Vector3d scaleVec; 55 56 /*** For local rotation values. */ 57 Quat4d localRotQ4d; 58 /*** For rotation values. */ 59 Quat4d rotQ4d; 60 61 //02-06-2002 Added temporary preallocated variables 62 Point3d tempP3d1 = new Point3d(); 63 Point3d tempP3d2 = new Point3d(); 64 Point3d tempP3d3 = new Point3d(); 65 Vector3f tempVec3f = new Vector3f(); 66 67 private static int instanceCounter = 0; 68 69 /*** Flag signaling if this object is undergoing a transformation. */ 70 private boolean transforming=false; 71 72 // holds BoundingBox diagonal; used to set axis length 73 private double diagonal; 74 // indicates whether Bounding box geometry has already been created 75 private boolean bBoxCreated = false; 76 77 /*** Holds reference to objects which are interested in changes made to this object. */ 78 private Vector changeListeners = new Vector(5, 3); 79 /*** Indicates whether positional components are updated. */ 80 boolean invalidData = true; 81 82 83 // Reserved for future implementation of 84 // a service that calls back any objects 85 // that display any data related to this object 86 Vector propertyChangeListeners; 87 88 /*** Root BranchGroup for this object. */ 89 BranchGroup bg; 90 BranchGroup decoratorsBG; // This branchGroup will hold elements that are not 91 // part of the object but can be used by the system, 92 // such as boundingBoxes and labels showing the object name 93 94 /*** Holds translation components. */ 95 TransformGroup parentTransTG; 96 /*** Holds rotation and scale components. */ 97 TransformGroup parentRotScaleTG; 98 TransformGroup pivotTG; 99 100 /*** Absolute axis system. */ 101 Axis globalAxis; 102 /*** Local (object) axis system. */ 103 Axis localAxis; 104 105 // used in misimported methods from CoreScene 106 Transform3D backupVPTransT3D = new Transform3D(); 107 Transform3D tempTransT3D = new Transform3D(); 108 // 109 110 Quat4d tempQ4d = new Quat4d(); 111 Quat4d tempQ4d2 = new Quat4d(); 112 Quat4d tempQ4d3 = new Quat4d(); 113 114 Transform3D tempT3D = new Transform3D(); 115 Transform3D auxT3D = new Transform3D(); 116 Transform3D auxT3D2 = new Transform3D(); 117 Transform3D backupT3D = new Transform3D(); 118 private Transform3D tempRotT3D = new Transform3D(); 119 private Transform3D tempRotT3D2 = new Transform3D(); 120 Matrix3d tempRot = new Matrix3d(); 121 Vector3d tempTrans = new Vector3d(); 122 123 Vector3d tempVec3d = new Vector3d(); 124 Vector3d tempScaleVec = new Vector3d(); 125 126 127 String label; 128 129 private StringBuffer strBuffer = new StringBuffer(); 130 BoundingBox boundingBox = new BoundingBox(); 131 // the boxAvatarShape will be used to display the bounding box 132 // when necessary 133 Shape3D boxAvatarShape = new Shape3D(); 134 BranchGroup shapeBG; // holds the boxAvatarShape 135 136 Point3d lowerP3d = new Point3d(); 137 Point3d upperP3d = new Point3d(); 138 139 private boolean selected = false; 140 /*** Holds reference to other VcObjects that are added as children to this one. */ 141 List childrenList = new ArrayList(); 142 143 // protected TransformType transformationType; 144 protected TransformMode transformationMode; 145 146 /*** Event that signal changes in this object's transform.*/ 147 VcTransformChangedEvent transformEvent; 148 VcTranslationChangedEvent translationEvent; 149 VcRotationChangedEvent rotationEvent; 150 VcScaleChangedEvent scaleEvent; 151 /*** Event that signal changes in this object's label.*/ 152 VcLabelChangedEvent labelEvent; 153 154 /*** Event that signal generic changes*/ 155 VcObjectEvent genericEvent; 156 157 /*** Event that signals that a Node has been added to this object. */ 158 VcNodeAddedEvent addNodeEvent; 159 160 /*** Event that signals that a Node has been removed from this object. */ 161 VcNodeRemovedEvent removeNodeEvent; 162 163 /*** Event that signals that a VcObject has been added as a child to this object. */ 164 VcChildAddedEvent addChildEvent; 165 166 /*** Event that signals that a VcObject that was a child to this object has been removed. */ 167 VcChildRemovedEvent removeChildEvent; 168 169 /*** Holds most recent event generated by this object. */ 170 VcObjectEvent currentEvent; 171 172 /*** 173 * Default Constructor. 174 */ 175 public VcObject() { 176 this.instanceCounter++; 177 bg = new BranchGroup(); 178 179 assembleSubGraph(bg); 180 181 bg.setCapability(Group.ALLOW_CHILDREN_EXTEND); 182 bg.setCapability(Group.ALLOW_CHILDREN_WRITE); 183 bg.setCapability(Group.ALLOW_CHILDREN_READ); 184 bg.setCapability(BranchGroup.ALLOW_DETACH); 185 bg.setCapability(Node.ALLOW_PICKABLE_READ); 186 bg.setCapability(Node.ALLOW_PICKABLE_WRITE); 187 bg.setCapability(Node.ENABLE_PICK_REPORTING); 188 bg.setCapability(Node.ALLOW_BOUNDS_READ); 189 bg.setCapability(BranchGroup.ALLOW_LOCAL_TO_VWORLD_READ); 190 bg.setCapability(Node.ALLOW_AUTO_COMPUTE_BOUNDS_READ); 191 bg.setCapability(Node.ALLOW_AUTO_COMPUTE_BOUNDS_WRITE); 192 bg.setBoundsAutoCompute(autoComputeBounds); 193 194 rotAngles = new Vector3f(); 195 localRotAngles = new Vector3d(); 196 transVec = new Vector3d(); 197 scaleVec = new Vector3d(); 198 //localScaleVec = new Vector3d(); 199 rotQ4d = new Quat4d(); 200 localRotQ4d = new Quat4d(); 201 updateData(); 202 setInvalidData(true); 203 204 /* Sets this as the user data for picking purposes. */ 205 bg.setUserData(this); 206 boxAvatarShape.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE); 207 boxAvatarShape.setCapability(Shape3D.ALLOW_GEOMETRY_READ); 208 boxAvatarShape.setCapability(Shape3D.ALLOW_APPEARANCE_READ); 209 boxAvatarShape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); 210 211 shapeBG = new BranchGroup(); 212 shapeBG.setCapability(BranchGroup.ALLOW_DETACH); 213 shapeBG.addChild(boxAvatarShape); 214 215 /* When any of the children of this BranchGroup collides, 216 * it is as if this bg collided 217 */ 218 //bg.setAlternateCollisionTarget(true); 219 /* 220 * Allows the autocomputing of bounds for picking 221 */ 222 //bg.setBoundsAutoCompute(true); 223 224 /* Makes this object pickable*/ 225 bg.setPickable(true); 226 227 /* creates event objects; these will be reused any time the corresponding 228 event happens */ 229 transformEvent = new VcTransformChangedEvent(this); 230 translationEvent = new VcTranslationChangedEvent(this); 231 rotationEvent = new VcRotationChangedEvent(this); 232 scaleEvent = new VcScaleChangedEvent(this); 233 labelEvent = new VcLabelChangedEvent(this); 234 genericEvent = new VcObjectEvent(this); 235 currentEvent = genericEvent; 236 } 237 238 /*** Rotates this object around local X axis. 239 * 240 * @param x_angle Rotation to be applied (in degreees). 241 */ 242 public void rotateEulerLocalX(double x_angle){ 243 this.rotateEulerLocal(x_angle, 0.0, 0.0); 244 } 245 246 /*** Rotates this object around local Y axis. 247 * 248 * @param y_angle Rotation to be applied (in degreees). 249 */ 250 public void rotateEulerLocalY(double y_angle){ 251 this.rotateEulerLocal(0.0, y_angle, 0.0); 252 } 253 254 /*** Rotates this object around local Z axis. 255 * 256 * @param z_angle Rotation to be applied (in degreees). 257 */ 258 public void rotateEulerLocalZ(double z_angle){ 259 this.rotateEulerLocal(0.0, 0.0, z_angle); 260 } 261 262 /*** 263 * Rotates objects relative to its local coordinate system. 264 * At the end of execution notifyChangeListeners() is called. 265 * @param x_angle angle of rotation to be applied (X axis) in radians. 266 * @param y_angle angle of rotation to be applied (Y axis) in radians. 267 * @param z_angle angle of rotation to be applied (Z axis) in radians. 268 */ 269 public void rotateEulerLocal(double x_angle, double y_angle, double z_angle){ 270 debugln("rotate euler local: "+x_angle+" "+y_angle+" "+z_angle); 271 // Converted degree input to radians -- when input was in degrees. 272 /* 273 double x = Math.toRadians(x_angle); 274 double y = Math.toRadians(y_angle); 275 double z = Math.toRadians(z_angle); 276 */ 277 278 // Vector with local rotation angles is updated. 279 localRotAngles.x = (float)x_angle; 280 localRotAngles.y = (float)y_angle; 281 localRotAngles.z = (float)z_angle; 282 283 parentRotScaleTG.getTransform(auxT3D); 284 auxT3D.getScale(scaleVec); 285 auxT3D.setScale(1.0); 286 287 tempT3D.setEuler(localRotAngles); 288 289 // local rotation is applied to parentRotScale transform by means of 290 // multiplication; after that we set the new transform. 291 auxT3D.mul(tempT3D); 292 auxT3D.setScale(scaleVec); 293 parentRotScaleTG.setTransform(auxT3D); 294 295 // data is set as invalid because we didn't update rotAngles Vector. 296 setInvalidData(true); 297 currentEvent = rotationEvent; 298 notifyChangeListeners(); 299 } 300 301 /* 302 * Caution: 303 * The following methods cannot be used to perform manipulation by mouse 304 * in absolute mode. 305 * For instance, a call to rotateEulerX(angle) will not have the visual 306 * effect of a rotation around the X axis. 307 */ 308 309 /*** 310 * Sets the value of the rotation around the absolute X axis. Other angles remain 311 * unchanged. Field invalidData is set to false, as rotAngles is updated. Method 312 * notifyChangeListeners() is called at the end of execution. 313 * 314 * @param x_angle new value of X rotation (in degrees). 315 */ 316 public void rotateEulerX(double x_angle){ 317 rotAngles.x = (float)x_angle; 318 MathUtility.eulerToQuat(rotAngles.x, rotAngles.y, rotAngles.z, rotQ4d); 319 rotate(this.rotQ4d); 320 setInvalidData(false); 321 currentEvent = rotationEvent; 322 notifyChangeListeners(); 323 } 324 325 /*** 326 * Sets the value of the rotation around the absolute Y axis. Other angles remain 327 * unchanged. Field invalidData is set to false, as rotAngles is updated. Method 328 * notifyChangeListeners() is called at the end of execution. 329 * 330 * @param y_angle new value of Y rotation (in degrees). 331 */ 332 public void rotateEulerY(double y_angle){ 333 rotAngles.y = (float)y_angle; 334 MathUtility.eulerToQuat(rotAngles.x, rotAngles.y, rotAngles.z, rotQ4d); 335 rotate(this.rotQ4d); 336 setInvalidData(false); 337 currentEvent = rotationEvent; 338 notifyChangeListeners(); 339 } 340 341 /*** 342 * Sets the value of the rotation around the absolute Z axis. Other angles remain 343 * unchanged. Field invalidData is set to false, as rotAngles is updated. Method 344 * notifyChangeListeners() is called at the end of execution. 345 * @param z_angle new value of Z rotation (in degrees). 346 */ 347 public void rotateEulerZ(double z_angle){ 348 rotAngles.z = (float)z_angle; 349 MathUtility.eulerToQuat(rotAngles.x, rotAngles.y, rotAngles.z, rotQ4d); 350 rotate(this.rotQ4d); 351 setInvalidData(false); 352 currentEvent = rotationEvent; 353 notifyChangeListeners(); 354 } 355 356 /*** 357 * Sets the value of the rotation around the absolute X,Y and Z axis. Field invalidData 358 * is set to false, as rotAngles is updated. Method notifyChangeListeners() is called 359 * at the end of execution. 360 * 361 * @param x_angle new value of X rotation (in degrees). 362 * @param y_angle new value of Y rotation (in degrees). 363 * @param z_angle new value of Z rotation (in degrees). 364 */ 365 public void rotateEuler(double x_angle, double y_angle, double z_angle){ 366 debugln("rotate euler: "+x_angle+" "+y_angle+" "+z_angle); 367 /* 368 rotAngles.x = (float)Math.toRadians(x_angle); 369 rotAngles.y = (float)Math.toRadians(y_angle); 370 rotAngles.z = (float)Math.toRadians(z_angle); 371 */ 372 rotAngles.x = (float)x_angle; 373 rotAngles.y = (float)y_angle; 374 rotAngles.z = (float)z_angle; 375 376 377 MathUtility.eulerToQuat(rotAngles.x, rotAngles.y, rotAngles.z, rotQ4d); 378 rotate(this.rotQ4d); 379 380 //following block uses setEuler method instead of quaternions 381 // to achieve the same effect 382 /* 383 parentRotScaleTG.getTransform(backupT3D); 384 tempVec3d.set(rotAngles); 385 tempT3D.setEuler(tempVec3d); 386 backupT3D.getScale(tempVec3d); 387 tempT3D.setScale(tempVec3d); 388 parentRotScaleTG.setTransform(tempT3D); 389 */ 390 391 // as we update value of rotAngles, data remains valid 392 setInvalidData(false); 393 currentEvent = rotationEvent; 394 notifyChangeListeners(); 395 } 396 397 /*** 398 * Sets the rotation to the one described by the input quaternion. 399 * @param rotQ4d quaternion containing the new value of the rotation. 400 */ 401 void rotate(Quat4d rotQ4d){ 402 403 parentRotScaleTG.getTransform(tempT3D); 404 backupT3D.set(tempT3D); 405 tempT3D.getScale(tempVec3d); 406 //debugln("__PRIOR scale: "+tempVec3d.x+" "+tempVec3d.y+" "+tempVec3d.z); 407 //tempT3D.getScale(scaleVec); 408 409 tempRotT3D.set(rotQ4d); 410 tempRotT3D.setScale(tempVec3d); 411 //debugln("__AFTER scale: "+tempVec3d.x+" "+tempVec3d.y+" "+tempVec3d.z); 412 //tempRotT3D.setScale(scaleVec); 413 try { 414 parentRotScaleTG.setTransform(tempRotT3D); 415 } catch (BadTransformException bt){ 416 parentRotScaleTG.setTransform(backupT3D); 417 } 418 // for the moment, it seems to be a better option to delegate to the methods that 419 // called this one the responsibility of notifying listeners 420 //setInvalidData(true); 421 //notifyChangeListeners(); 422 } 423 424 public void rotateLocal(TransformScope axis, double deltaAngle){ 425 if(axis==TransformScope.X) rotateEulerLocalX(deltaAngle); 426 if(axis==TransformScope.Y) rotateEulerLocalY(deltaAngle); 427 if(axis==TransformScope.Z) rotateEulerLocalZ(deltaAngle); 428 } 429 430 /*** 431 * Performs incremental rotation around one of the absolute axis. It is suitable 432 * to be called by manipulators, in order to perform absolute rotation.<br> 433 * Method from RotatableObject interface. 434 * @param axis the axis around which the rotation will be performed. 435 * @param deltaAngle of the increment (in radians). 436 */ 437 public void rotateAbsolute(TransformScope axis, double deltaAngle){ 438 //double angle = Math.toRadians(deltaAngle)/2; 439 /* 440 double angle = deltaAngle/2; 441 double sin = Math.sin(angle); 442 double cos = Math.cos(angle); 443 if(axis==TransformScope.X){ 444 tempQ4d.set(sin,0,0,cos); 445 }else if(axis==TransformScope.Y){ 446 tempQ4d.set(0,sin,0,cos); 447 }else if(axis==TransformScope.Z){ 448 tempQ4d.set(0,0,sin,cos); 449 }else{ 450 // will default to X rotation 451 tempQ4d.set(sin,0,0,cos); 452 }*/ 453 MathUtility.generateRotQuat(axis,deltaAngle,tempQ4d); 454 parentRotScaleTG.getTransform(auxT3D2); 455 auxT3D2.get(tempQ4d2); 456 tempQ4d.mul(tempQ4d2); 457 tempQ4d.normalize(); 458 rotate(tempQ4d); 459 setInvalidData(true); 460 currentEvent = rotationEvent; 461 notifyChangeListeners(); 462 } 463 464 /*** 465 * Adds a node to pivot transform group. 466 * Method notifyChangeListeners() is called by the end of execution. 467 * @param n Node to be added. 468 */ 469 public void addNode(Node n){ 470 this.pivotTG.addChild(n); 471 // genericEvent.setType(VcObjectEvent.NODE_ADDED); 472 if(addNodeEvent==null){ 473 addNodeEvent = new VcNodeAddedEvent(this,n); 474 }else addNodeEvent.setNode(n); 475 476 currentEvent = addNodeEvent; 477 notifyChangeListeners(); 478 } 479 480 481 /*** 482 * Removes a node from pivot transform group. 483 * Method notifyChangeListeners() is called at the end of execution. 484 * @param n Node to be removed. 485 */ 486 public void removeNode(Node n){ 487 this.pivotTG.removeChild(n); 488 //genericEvent.setType(VcObjectEvent.NODE_REMOVED); 489 if(removeNodeEvent==null){ 490 removeNodeEvent = new VcNodeRemovedEvent(this,n); 491 }else removeNodeEvent.setNode(n); 492 493 currentEvent = removeNodeEvent; 494 notifyChangeListeners(); 495 } 496 497 /*** 498 * Removes all nodes currently under pivot transform group. 499 * Method notifyChangeListeners() is called at the end of execution. 500 */ 501 public void removeAllNodes(){ 502 this.pivotTG.removeAllChildren(); 503 genericEvent.setType(VcObjectEvent.ALLNODES_REMOVED); 504 currentEvent = genericEvent; 505 notifyChangeListeners(); 506 } 507 508 509 /*** 510 * Returns root BranchGroup 511 * @return root BG 512 */ 513 public BranchGroup getBranchGroup(){ 514 return this.bg; 515 } 516 517 /*** Returns the label which identifies this object. 518 * @return String containing the label. 519 */ 520 public String getLabel(){ 521 return this.label; 522 } 523 524 /*** Sets the label which identifies this object. Listeners are notified after the change. 525 * @param s String containing new label. 526 */ 527 public void setLabel(String s){ 528 labelEvent.setOldLabel(this.label); 529 this.label = s; 530 labelEvent.setNewLabel(s); 531 currentEvent = labelEvent; 532 notifyChangeListeners(); 533 } 534 535 /*** 536 * Removes the BranchGroup from its parent in Java 3D tree. 537 */ 538 public void detach(){ 539 bg.detach(); 540 genericEvent.setType(VcObjectEvent.OBJECT_DETACHED); 541 currentEvent = genericEvent; 542 // notifyChangeListeners(); 543 } 544 545 /*** 546 * Returns this object's translation into the Vector3d object passed as input. 547 */ 548 public void getTranslation(Point3d transP3d){ 549 transP3d.set(this.transVec); 550 } 551 552 553 // getLocal?Angle methods commented out on 05/08/2003, as they were never used. 554 /*** Returns the value (degrees) of X angle in local coordinate system.*/ 555 /* 556 public double getLocalXAngle(){ 557 //updateData(); 558 return Math.toDegrees(localRotAngles.x); 559 }*/ 560 561 /*** Returns the value (degrees) of Y angle in local coordinate system.*/ 562 /* 563 public double getLocalYAngle(){ 564 //updateData(); 565 return Math.toDegrees(localRotAngles.y); 566 }*/ 567 568 /*** Returns the value (degrees) of Z angle in local coordinate system.*/ 569 /* 570 public double getLocalZAngle(){ 571 //updateData(); 572 return Math.toDegrees(localRotAngles.z); 573 }*/ 574 575 /*** Returns the value (degrees) of X angle in absolute coordinate system. 576 */ 577 public double getXAngleDeg(){ 578 updateData(); 579 return Math.toDegrees(rotAngles.x); 580 } 581 582 /*** Returns the value (degrees) of Y angle in absolute coordinate system. 583 */ 584 public double getYAngleDeg(){ 585 updateData(); 586 return Math.toDegrees(rotAngles.y); 587 } 588 589 /*** Returns the value (degrees) of Z angle in absolute coordinate system. 590 */ 591 public double getZAngleDeg(){ 592 updateData(); 593 return Math.toDegrees(rotAngles.z); 594 } 595 596 597 /*** Returns the value (radians) of X angle in absolute coordinate system. 598 */ 599 public double getXAngleRad(){ 600 updateData(); 601 return rotAngles.x; 602 } 603 604 /*** Returns the value (radians) of Y angle in absolute coordinate system. 605 */ 606 public double getYAngleRad(){ 607 updateData(); 608 return rotAngles.y; 609 } 610 611 /*** Returns the value (radians) of Z angle in absolute coordinate system. 612 */ 613 public double getZAngleRad(){ 614 updateData(); 615 return rotAngles.z; 616 } 617 618 619 /*** Returns the value of translation in X axis direction. 620 */ 621 public double getXTranslation(){ 622 //updateData(); 623 return transVec.x; 624 } 625 626 /*** Returns the value translation in Y axis direction. 627 */ 628 public double getYTranslation(){ 629 //updateData(); 630 return transVec.y; 631 } 632 633 /*** Returns the value of translation in Z axis direction. 634 */ 635 public double getZTranslation(){ 636 //updateData(); 637 return transVec.z; 638 } 639 640 /*** Returns the value of scale in X axis direction. 641 */ 642 public double getXScale(){ 643 // updateData(); 644 return scaleVec.x; 645 } 646 647 /*** Returns the value of scale in Y axis direction. 648 * @return Y scale 649 */ 650 public double getYScale(){ 651 // updateData(); 652 return scaleVec.y; 653 } 654 655 /*** Returns the value of scale in Z axis direction. 656 * @return Z scale 657 */ 658 public double getZScale(){ 659 // updateData(); 660 return scaleVec.z; 661 } 662 663 /*** 664 * Returns a Vector of rotation angles (X,Y,Z), corresponding to the Transform3D 665 * object given as input. 666 * Code derived from the one at Eric Reiss' Homepage, at: 667 * http://jamaica.ee.pitt.edu/Eric/java3d/rotation.htm 668 * Changes due to different order of multiplication of matrices (X.Y.Z in original code, 669 * Z.Y.X in present one). Also changed the name of some variables to use pre-allocated ones 670 * and thus reduce memory usage. 671 */ 672 Vector3f getRotAngle(Transform3D t3D) 673 { 674 //System.out.println("___getRotAngle called"); 675 // Matrix3d m1 = new Matrix3d(); 676 double c,tRx,tRy; 677 //Vector3f Angles = new Vector3f(); 678 679 t3D.get(tempRot); 680 //tempVec3f.y = (float)Math.asin(tempRot.getElement(0,2)); 681 tempVec3f.y = (float)Math.asin(-tempRot.getElement(2,0)); 682 c = Math.cos(tempVec3f.y); 683 if (Math.abs(c) > 0.00001) 684 { 685 tRx = tempRot.getElement(2,2)/c; 686 //tRy = -tempRot.getElement(1,2)/c; 687 tRy = tempRot.getElement(2,1)/c; 688 tempVec3f.x = (float)Math.atan2(tRy,tRx); 689 tRx = tempRot.getElement(0,0)/c; 690 //tRy = -tempRot.getElement(0,1)/c; 691 tRy = tempRot.getElement(1,0)/c; 692 tempVec3f.z = (float)Math.atan2(tRy,tRx); 693 } 694 else 695 { 696 // Gimbal lock has occurred 697 tempVec3f.x = (float)0.0; 698 699 //tRx = tempRot.getElement(1,1)/c; 700 //tRy = tempRot.getElement(1,0)/c; 701 // here we are using the fact that the rotation around X axii 702 // is zero, so cos(X) = 1 and sin(X) = 0, which simplifies some 703 // terms. 704 tRx = tempRot.getElement(1,1); 705 tRy = -tempRot.getElement(0,1); 706 tempVec3f.z = (float)Math.atan2(tRy,tRx); 707 } 708 709 if (tempVec3f.x < 0.0) 710 { 711 tempVec3f.x+=2*Math.PI; 712 } 713 else if (tempVec3f.x > (2*Math.PI)) 714 { 715 tempVec3f.x-=2*Math.PI; 716 } 717 if (tempVec3f.y < 0.0) 718 { 719 tempVec3f.y+=2*Math.PI; 720 } 721 else if (tempVec3f.y > (2*Math.PI)) 722 { 723 tempVec3f.y-=2*Math.PI; 724 } 725 if (tempVec3f.z < 0.0) 726 { 727 tempVec3f.z+=2*Math.PI; 728 } 729 else if (tempVec3f.z > (2*Math.PI)) 730 { 731 tempVec3f.z-=2*Math.PI; 732 } 733 if ( ( tempVec3f.x < 0.001 ) && ( tempVec3f.x > -0.001 ) ) 734 { 735 tempVec3f.x = (float)0.0; 736 } 737 if ( ( tempVec3f.y < 0.001 ) && ( tempVec3f.y > -0.001 ) ) 738 { 739 tempVec3f.y = (float)0.0; 740 } 741 if ( ( tempVec3f.z < 0.001 ) && ( tempVec3f.z > -0.001 ) ) 742 { 743 tempVec3f.z = (float)0.0; 744 } 745 if ( tempVec3f.x == 0.0) 746 { 747 tempVec3f.x = Math.abs(tempVec3f.x); 748 } 749 if ( tempVec3f.y == 0.0) 750 { 751 tempVec3f.y = Math.abs(tempVec3f.y); 752 } 753 if ( tempVec3f.z == 0.0) 754 { 755 tempVec3f.z = Math.abs(tempVec3f.z); 756 } 757 if ( tempVec3f.x == 2*Math.PI) 758 { 759 tempVec3f.x = (float)0.0; 760 } 761 if ( tempVec3f.y == 2*Math.PI) 762 { 763 tempVec3f.y = (float)0.0; 764 } 765 if ( tempVec3f.z == 2*Math.PI) 766 { 767 tempVec3f.z = (float)0.0; 768 } 769 770 return(tempVec3f); 771 } 772 773 public void updateData(){ 774 debugln("VcObject.updateData() called"); 775 if (invalidData){ 776 debugln("VcObject.updateData(): data must be recalculated"); 777 try { 778 parentTransTG.getTransform(tempT3D); 779 } catch (javax.media.j3d.RestrictedAccessException rte){ 780 debugln("VcObject: Restricted access exception happened when trying to update data."); 781 setInvalidData(true); 782 //rte.printStackTrace(); 783 } 784 785 // Finds translation values 786 tempT3D.get(transVec); 787 788 parentRotScaleTG.getTransform(tempT3D); 789 // Code below unnecessary since move to Quaternions. 790 // Finds value of x,y,and z angles 791 rotAngles = getRotAngle(tempT3D); 792 // 793 /// 794 tempT3D.getScale(scaleVec); 795 } 796 setInvalidData(false); 797 } 798 799 public void translateLocal(double x, double y, double z){ 800 tempVec3d.x = x; 801 tempVec3d.y = y; 802 tempVec3d.z = z; 803 804 tempTransT3D.setIdentity(); 805 tempTransT3D.setTranslation(tempVec3d); 806 807 // Extract the transform from local to vworld so that we know 808 // in world coordinates the value of the translation component present at tempT3D matrix 809 pivotTG.getLocalToVworld(auxT3D); 810 811 // Finds out the accumulated result of all transforms from the root of this object down to 812 // parentRotScaleTG 813 auxT3D.mul(tempTransT3D); 814 815 // Finds out the total translation 816 auxT3D.get(tempTrans); 817 818 /////Great place for new approach 819 ///////translate(tempTrans.x, tempTrans.y, tempTrans.z); 820 this.setTransform(auxT3D); 821 822 setInvalidData(true); 823 currentEvent = translationEvent; 824 notifyChangeListeners(); 825 } 826 827 828 public void translate(double x, double y, double z){ 829 transVec.x = x; 830 transVec.y = y; 831 transVec.z = z; 832 833 parentTransTG.getTransform(tempT3D); // copies the transform into tempT3D 834 backupVPTransT3D.set(tempT3D); 835 836 tempT3D.get(tempRot, tempTrans); // extracts rotational and scaling info 837 tempT3D.getScale(tempScaleVec); 838 tempRotT3D.setIdentity(); //resets the rotational transform 839 840 tempRotT3D.setRotation(tempRot); // reapply rotation, but we got rid of scaling component 841 tempT3D.setIdentity(); //resets transform 842 843 /* Assembles translation vector */ 844 tempVec3d.x = x; 845 tempVec3d.y = y; 846 tempVec3d.z = z; 847 848 tempT3D.setTranslation(tempVec3d); //sets translation 849 tempT3D.setScale(tempScaleVec); //sets scaling again 850 tempT3D.mul(tempRotT3D); // restores rotation 851 try { 852 parentTransTG.setTransform(tempT3D); 853 } catch (BadTransformException bt) { 854 strBuffer.append(bt.getMessage()); 855 strBuffer.append("\n\rBefore {"); 856 strBuffer.append(backupVPTransT3D.toString()); 857 strBuffer.append("}\nAfter:{"); 858 strBuffer.append(tempT3D.toString()); 859 strBuffer.append("}"); 860 //canvas3d.enableMessage(strBuffer.toString()); 861 debugln(strBuffer.toString()); 862 parentTransTG.setTransform(backupVPTransT3D); 863 } 864 setInvalidData(true); 865 currentEvent = translationEvent; 866 notifyChangeListeners(); 867 } 868 869 /*** 870 * Sets this objects's absolute scale along (local) X axis. The notifyChangeListeners 871 * method is called at the end of execution. 872 * @param scale new absolute scale 873 */ 874 public void scaleX(double scale){ 875 parentRotScaleTG.getTransform(auxT3D); 876 scaleVec.x = scale; 877 auxT3D.setScale(scaleVec); 878 parentRotScaleTG.setTransform(auxT3D); 879 currentEvent = scaleEvent; 880 notifyChangeListeners(); 881 } 882 883 /*** 884 * Sets this objects's absolute scale along (local) Y axis. The notifyChangeListeners 885 * method is called at the end of execution. 886 * @param scale new absolute scale 887 */ 888 public void scaleY(double scale){ 889 parentRotScaleTG.getTransform(auxT3D); 890 scaleVec.y = scale; 891 auxT3D.setScale(scaleVec); 892 parentRotScaleTG.setTransform(auxT3D); 893 currentEvent = scaleEvent; 894 notifyChangeListeners(); 895 } 896 897 /*** 898 * Sets this objects's absolute scale along (local) Z axis. The notifyChangeListeners 899 * method is called at the end of execution. 900 * @param scale new absolute scale 901 */ 902 public void scaleZ(double scale){ 903 parentRotScaleTG.getTransform(auxT3D); 904 scaleVec.z = scale; 905 auxT3D.setScale(scaleVec); 906 parentRotScaleTG.setTransform(auxT3D); 907 currentEvent = scaleEvent; 908 notifyChangeListeners(); 909 } 910 911 public void scaleXRelative(double scale){ 912 setRelativeScale(scale,1,1); 913 /* 914 parentRotScaleTG.getTransform(auxT3D); 915 tempT3D.setIdentity(); 916 tempVec3d.x = scale; 917 tempVec3d.y = tempVec3d.z = 1.0; 918 tempT3D.setScale(tempVec3d); 919 auxT3D.mul(tempT3D); 920 parentRotScaleTG.setTransform(auxT3D); 921 auxT3D.getScale(scaleVec); 922 currentEvent = scaleEvent; 923 notifyChangeListeners(); 924 */ 925 } 926 927 public void scaleYRelative(double scale){ 928 setRelativeScale(1,scale,1); 929 /* 930 parentRotScaleTG.getTransform(auxT3D); 931 tempT3D.setIdentity(); 932 tempVec3d.y = scale; 933 tempVec3d.x = tempVec3d.z = 1.0; 934 tempT3D.setScale(tempVec3d); 935 auxT3D.mul(tempT3D); 936 parentRotScaleTG.setTransform(auxT3D); 937 auxT3D.getScale(scaleVec); 938 //setInvalidData(true); 939 currentEvent = scaleEvent; 940 notifyChangeListeners(); 941 */ 942 } 943 944 public void scaleZRelative(double scale){ 945 setRelativeScale(1,1,scale); 946 /* 947 parentRotScaleTG.getTransform(auxT3D); 948 tempT3D.setIdentity(); 949 tempVec3d.z = scale; 950 tempVec3d.x = tempVec3d.y = 1.0; 951 tempT3D.setScale(tempVec3d); 952 auxT3D.mul(tempT3D); 953 parentRotScaleTG.setTransform(auxT3D); 954 auxT3D.getScale(scaleVec); 955 //setInvalidData(true); 956 currentEvent = scaleEvent; 957 notifyChangeListeners(); 958 */ 959 } 960 961 /*** 962 * 963 */ 964 public void setRelativeScale(double x, double y, double z){ 965 parentRotScaleTG.getTransform(auxT3D); 966 967 /* Places relative scale in tempT3D */ 968 tempT3D.setIdentity(); 969 tempVec3d.x = x; 970 tempVec3d.y = y; 971 tempVec3d.z = z; 972 tempT3D.setScale(tempVec3d); 973 /* Multiplies former and temporary transformations */ 974 auxT3D.mul(tempT3D); 975 976 /* Retrieves new value of this object's scale. */ 977 auxT3D.getScale(scaleVec); 978 979 parentRotScaleTG.setTransform(auxT3D); 980 currentEvent = scaleEvent; 981 notifyChangeListeners(); 982 } 983 984 /*** 985 * Sets absolute scale for this object. The notifyChangeListeners method is called 986 * at the end of execution. 987 * @param x scale value along local X axis. 988 * @param y scale value along local Y axis. 989 * @param z scale value along local Z axis. 990 */ 991 public void setAbsoluteScale(double x, double y, double z){ 992 parentRotScaleTG.getTransform(auxT3D); 993 scaleVec.x = x; 994 scaleVec.y = y; 995 scaleVec.z = z; 996 auxT3D.setScale(scaleVec); 997 parentRotScaleTG.setTransform(auxT3D); 998 auxT3D.getScale(scaleVec); 999 currentEvent = scaleEvent; 1000 notifyChangeListeners(); 1001 } 1002 1003 /* 1004 * This method must be called inside any other method that changes the state 1005 * of this object. 1006 */ 1007 void notifyChangeListeners(){ 1008 Iterator iter = changeListeners.iterator(); 1009 while (iter.hasNext()){ 1010 ((VcObjectChangeListener)iter.next()).vcObjectChanged(currentEvent); 1011 } 1012 } 1013 1014 /*** 1015 * Removes all objects currently registered as listeners of changes made to this 1016 * object. 1017 */ 1018 public void removeAllChangeListeners(){ 1019 changeListeners.removeAllElements(); 1020 } 1021 1022 /*** 1023 * Removes one object currently registered as a listener of changes made to this 1024 * object. 1025 */ 1026 public void removeChangeListener(VcObjectChangeListener chg){ 1027 changeListeners.remove(chg); 1028 } 1029 1030 /*** 1031 * Adds the specified VcObjectChangeListener to be notified of changes made 1032 * to this object. The updateData method is called prior to the addition. 1033 * @param listener Listener to be added 1034 */ 1035 public void addChangeListener(VcObjectChangeListener listener){ 1036 updateData(); 1037 changeListeners.add(listener); 1038 } 1039 1040 /* 1041 * This method indicates that values previously extracted from 1042 * Transform matrices need to be recomputed 1043 */ 1044 private void setInvalidData(boolean b){ 1045 this.invalidData = b; 1046 } 1047 1048 /*** 1049 * Convenience method for printing debug information 1050 * @param s Debug string to be printed 1051 */ 1052 void debugln(String s){ 1053 if (GUIControl.debugflag){ 1054 //if(debugflag){ 1055 System.out.println(s); 1056 } 1057 } 1058 1059 /*** 1060 * Returns parameters of this object's BoundingBox, in local coordinates. 1061 * The settings of current BoundingBox are copied into returnBB. 1062 */ 1063 public void getBoundingBox(BoundingBox returnBB){ 1064 if(returnBB!=null){ 1065 if(boundingBox!=null){ 1066 boundingBox.getLower(tempP3d1); 1067 returnBB.setLower(tempP3d1); 1068 boundingBox.getUpper(tempP3d1); 1069 returnBB.setUpper(tempP3d1); 1070 } 1071 } 1072 } 1073 1074 void computeBoundingBox(){ 1075 GeometryUtility.computeBoundingBox(this.getBranchGroup(), 1076 this.boundingBox); 1077 1078 } 1079 1080 public void showBoundingBox(){ 1081 //computeBoundingBox(); 1082 //13/05/2002 - prevents multiple execution 1083 if(!bBoxCreated){ 1084 Color3f color = new Color3f(0.0f, 1.0f, 0.4f); 1085 GeometryUtility.createBoxGeometry(boundingBox, boxAvatarShape,color); 1086 // calculates diagonal of BoundingBox 1087 boundingBox.getUpper(tempP3d1); 1088 boundingBox.getLower(tempP3d2); 1089 this.diagonal = tempP3d2.distance(tempP3d1); 1090 bBoxCreated = true; 1091 } 1092 shapeBG.detach(); 1093 this.decoratorsBG.addChild(shapeBG); 1094 } 1095 1096 1097 public void hideBoundingBox(){ 1098 shapeBG.detach(); 1099 //decoratorsBG.detach(); 1100 } 1101 1102 public void removeBoundingBox(){ 1103 if (decoratorsBG!=null){ 1104 decoratorsBG.detach(); 1105 } 1106 } 1107 1108 /*** 1109 * Returns a flag indicating whether the object is part of a live scene graph. 1110 * @return true if object is part of a live scene graph, else false 1111 */ 1112 public boolean isLive(){ 1113 return this.bg.isLive(); 1114 } 1115 1116 /*** 1117 * Returns a flag indicating whether internal data representating state needs updating. 1118 */ 1119 public boolean isInvalidData(){ 1120 return this.invalidData; 1121 } 1122 1123 1124 /*** 1125 * Adds a VcObject as a child to this one. Calling this method will have no effect if the 1126 * object given as parameter is already a live. Method notifyChangeListeners() is called 1127 * by the end of execution if the object could be added. 1128 * @param vcObject object to be added 1129 */ 1130 public void addVcChild(VcObject vcObject){ 1131 if(childrenList.contains(vcObject)){ 1132 debugln("Error: "+this.getLabel()+" already contains "+vcObject.getLabel()); 1133 } 1134 else{ 1135 if(vcObject.bg.isLive()){ 1136 debugln("Error: "+vcObject.label+" is live"); 1137 } 1138 else{ 1139 this.parentRotScaleTG.addChild(vcObject.bg); 1140 childrenList.add(vcObject); 1141 if(addChildEvent==null){ 1142 addChildEvent = new VcChildAddedEvent(this,vcObject); 1143 }else addChildEvent.setChild(vcObject); 1144 currentEvent = addChildEvent; 1145 notifyChangeListeners(); 1146 } 1147 } 1148 } 1149 1150 /*** 1151 * Removes a VcObject from child transform group. 1152 * Method notifyChangeListeners() is called at the end of execution. 1153 * @param vcObject object to be removed 1154 */ 1155 public void removeVcChild(VcObject vcObject){ 1156 if(childrenList.contains(vcObject)){ 1157 childrenList.remove(vcObject); 1158 parentRotScaleTG.removeChild(vcObject.bg); 1159 if(removeChildEvent==null){ 1160 removeChildEvent = new VcChildRemovedEvent(this,vcObject); 1161 }else removeChildEvent.setChild(vcObject); 1162 1163 currentEvent = removeChildEvent; 1164 notifyChangeListeners(); 1165 } else debugln("Error: "+vcObject.label+" was not child of "+this.label); 1166 } 1167 1168 /*** 1169 * Removes a VcObject from child transform group. 1170 * Method notifyChangeListeners() is called at the end of execution. 1171 * @param n index of object to be removed 1172 */ 1173 public void removeVcChild(int n){ 1174 if(n<childrenList.size()){ 1175 VcObject obj = (VcObject) childrenList.get(n); 1176 removeVcChild(obj); 1177 } else debugln("Error: number of children < "+n); 1178 } 1179 1180 /*** 1181 * Returns a List containing all VcObjects kept as children of 1182 * this object 1183 * @return list of children 1184 */ 1185 public List getChildrenList(){ 1186 return this.childrenList; 1187 } 1188 1189 /*** 1190 * Sets this object transform. The Transform3D passed as input is separated 1191 * into a translational component and a rotation-and-scaling component. 1192 */ 1193 public void setTransform(Transform3D transform){ 1194 //printTransform(transform); 1195 //this.parentTransTG.setTransform(transform); 1196 1197 transform.get(tempRot, tempTrans); 1198 tempT3D.setIdentity(); 1199 tempT3D.setTranslation(tempTrans); 1200 parentTransTG.setTransform(tempT3D); 1201 tempT3D.setIdentity(); 1202 tempT3D.setRotationScale(tempRot); 1203 // updates rotation angles 1204 rotAngles = getRotAngle(tempT3D); 1205 //tempT3D.setScale(1.0); 1206 parentRotScaleTG.setTransform(tempT3D); 1207 1208 //this.tg.setTransform(transform); 1209 setInvalidData(true); 1210 //updateData(); 1211 currentEvent = transformEvent; 1212 notifyChangeListeners(); 1213 } 1214 1215 /*** 1216 * Returns parameters of this object's BoundingBox, in virtual world coordinates. 1217 * The settings of current BoundingBox are copied into returnBB. 1218 */ 1219 public void getBoundingBoxInVWorld(BoundingBox returnBB){ 1220 // 1221 pivotTG.getTransform(auxT3D); 1222 try { 1223 pivotTG.getLocalToVworld(tempT3D); 1224 } catch (CapabilityNotSetException ex) { 1225 debugln("Error in:"+this.getLabel()); 1226 ex.printStackTrace(); 1227 } catch (RestrictedAccessException ex){ 1228 debugln("Could not get Local to VWorld for "+this.getLabel()+", exception stack trace"); 1229 ex.printStackTrace(); 1230 } 1231 tempT3D.mul(auxT3D); 1232 boundingBox.getLower(lowerP3d); 1233 boundingBox.getUpper(upperP3d); 1234 tempT3D.transform(lowerP3d); 1235 tempT3D.transform(upperP3d); 1236 returnBB.setLower(lowerP3d); 1237 returnBB.setUpper(upperP3d); 1238 } 1239 1240 /* Shows/Hides an object representing the global axis for this object*/ 1241 public void setGlobalAxisVisible(boolean visible){ 1242 // hides localAxis if we are to show global axis 1243 if(visible) localAxis.setVisible(false); 1244 globalAxis.setVisible(visible); 1245 } 1246 1247 /* Shows/Hides an object representing the local axis for this object*/ 1248 public void setLocalAxisVisible(boolean visible){ 1249 // hides localAxis if we are to show global axis 1250 if(visible) globalAxis.setVisible(false); 1251 localAxis.setVisible(visible); 1252 } 1253 1254 /* 1255 * Assembles internal graph. 1256 * 27/03/2003 - changed methos access from public to private 1257 */ 1258 private void assembleSubGraph(BranchGroup root){ 1259 decoratorsBG = new BranchGroup(); 1260 parentTransTG = new TransformGroup(); 1261 parentRotScaleTG = new TransformGroup(); 1262 pivotTG = new TransformGroup(); 1263 globalAxis = new Axis(); 1264 localAxis = new Axis(); 1265 1266 decoratorsBG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); 1267 decoratorsBG.setCapability(BranchGroup.ALLOW_CHILDREN_READ); 1268 decoratorsBG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 1269 1270 parentTransTG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); 1271 parentTransTG.setCapability(BranchGroup.ALLOW_CHILDREN_READ); 1272 parentTransTG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 1273 parentTransTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); 1274 parentTransTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 1275 parentTransTG.setCapability(TransformGroup.ALLOW_LOCAL_TO_VWORLD_READ); 1276 //parentTransTG.setBoundsAutoCompute(true); 1277 parentTransTG.setBoundsAutoCompute(true); 1278 parentTransTG.setCapability(Node.ENABLE_PICK_REPORTING); 1279 parentTransTG.setPickable(true); 1280 1281 parentRotScaleTG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); 1282 parentRotScaleTG.setCapability(BranchGroup.ALLOW_CHILDREN_READ); 1283 parentRotScaleTG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 1284 parentRotScaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); 1285 parentRotScaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 1286 parentRotScaleTG.setCapability(TransformGroup.ALLOW_LOCAL_TO_VWORLD_READ); 1287 //parentRotScaleTG.setBoundsAutoCompute(true); 1288 parentRotScaleTG.setBoundsAutoCompute(false); 1289 parentRotScaleTG.setCapability(Node.ENABLE_PICK_REPORTING); 1290 parentRotScaleTG.setPickable(true); 1291 1292 1293 pivotTG.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND); 1294 pivotTG.setCapability(BranchGroup.ALLOW_CHILDREN_READ); 1295 pivotTG.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE); 1296 pivotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); 1297 pivotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); 1298 pivotTG.setCapability(TransformGroup.ALLOW_LOCAL_TO_VWORLD_READ); 1299 //pivotTG.setBoundsAutoCompute(true); 1300 pivotTG.setBoundsAutoCompute(false); 1301 pivotTG.setCapability(Node.ENABLE_PICK_REPORTING); 1302 pivotTG.setPickable(true); 1303 1304 // Assemble subtree 1305 root.addChild(parentTransTG); 1306 1307 parentTransTG.addChild(globalAxis.getRootGroup()); 1308 parentTransTG.addChild(parentRotScaleTG); 1309 1310 parentRotScaleTG.addChild(pivotTG); 1311 parentRotScaleTG.addChild(localAxis.getRootGroup()); 1312 parentRotScaleTG.addChild(decoratorsBG); 1313 globalAxis.setVisible(false); 1314 localAxis.setVisible(false); 1315 } 1316 1317 public void printTransform(Transform3D t3d){ 1318 if (GUIControl.debugflag){ 1319 t3d.get(tempRot, tempTrans); 1320 debugln("Rotation: \n"+tempRot.m00+" "+tempRot.m01+" "+tempRot.m02+ " "+ 1321 tempRot.m10+" "+tempRot.m11+" "+tempRot.m12+ " "+ 1322 tempRot.m20+" "+tempRot.m21+" "+tempRot.m22+ " "); 1323 debugln("Translation: "+tempTrans.x+" "+tempTrans.y+" "+tempTrans.z); 1324 } 1325 } 1326 1327 protected void setTransformsToIdentity(){ 1328 auxT3D.setIdentity(); 1329 parentTransTG.setTransform(auxT3D); 1330 parentRotScaleTG.setTransform(auxT3D); 1331 pivotTG.setTransform(auxT3D); 1332 notifyChangeListeners(); 1333 } 1334 1335 1336 public String getInfo(){ 1337 String info = getLabel() +"\nTranslation:\t"+ "X: "+getXTranslation()+ " Y: "+getYTranslation()+ 1338 " Z: "+getZTranslation()+ "\nRotation:\t\t" + "X: "+getXAngleDeg()+ " Y: "+getYAngleDeg()+ 1339 " Z: "+getZAngleDeg() + "\n\n"; 1340 return info; 1341 } 1342 1343 1344 1345 /*** 1346 * By calling this object this object shows himself "selected", what is indicated 1347 * by some visual modifications. 1348 */ 1349 public void select(){ 1350 debugln(this.getLabel()+" selected"); 1351 this.showBoundingBox(); 1352 selected = true; 1353 localAxis.setVisible(true); 1354 // 13-05-2002 1355 // replaced call to DimensionsManager.getDimensionsManager().getAxisSize() 1356 // DimensionsManager keeps the axis size of the last object selected instead 1357 // of the current one; now the axis size is calculated internally (in createBoxGeometry) 1358 localAxis.setSize(this.diagonal); 1359 globalAxis.setSize(this.diagonal); 1360 } 1361 1362 1363 /* 1364 * By calling this method, this object shows itself unselected 1365 * 28-02-2002 1366 */ 1367 public void unselect(){ 1368 debugln(this.getLabel() +" unselect();"); 1369 this.hideBoundingBox(); 1370 globalAxis.setVisible(false); 1371 localAxis.setVisible(false); 1372 selected = false; 1373 } 1374 1375 1376 /*** Método para Luciano utilizar*/ 1377 void lucianify(GeometryArray geometryArray, Transform3D t3D){ 1378 Transform3D tempT3D = new Transform3D(); 1379 Point3d tempP3d = new Point3d(); 1380 tempT3D.set(t3D); 1381 1382 StringBuffer edgesStr = new StringBuffer(4000); 1383 StringBuffer facesStr = new StringBuffer(4000); 1384 1385 System.out.println("object {"); 1386 if (geometryArray instanceof IndexedTriangleArray){ 1387 IndexedTriangleArray tArray = (IndexedTriangleArray) geometryArray; 1388 int indexCount = tArray.getVertexCount(); 1389 int vertexCount = tArray.getVertexCount(); 1390 1391 for (int i=0; i < vertexCount; i++){ 1392 tArray.getCoordinate(i, tempP3d); 1393 tempT3D.transform(tempP3d); 1394 System.out.println("vertex #"+i+"{"+tempP3d.x+","+tempP3d.y+","+tempP3d.z+"}"); 1395 } 1396 1397 int edgeCounter = 0; 1398 int faceCounter = 0; 1399 1400 for (int j=0; j < indexCount - 1; j++){ 1401 int index1 = tArray.getCoordinateIndex(j); 1402 int index2 = tArray.getCoordinateIndex(j+1); 1403 System.out.println("edge #"+(edgeCounter++)+" {"+index1+","+index2+"}"); 1404 } 1405 1406 } else { 1407 System.out.println("Object to Lucianify doesn't have indexed triangles"); 1408 } 1409 } 1410 1411 1412 1413 /*** 1414 * Transforms euler angles into the corresponding rotation quaternion. 1415 * The order in which rotations are applied is: 1416 * roll(X axii)-->pitch(Y axii)-->yaw(Z axii) 1417 * Extracted from Nick Bobick's Gamasutra Code. 1418 * @param roll rotation around x axis 1419 * @param pitch rotation around y axis 1420 * @param yaw rotation around z axis 1421 */ 1422 /* 1423 void eulerToQuat(double roll, double pitch, double yaw, Quat4d quat) 1424 { 1425 double cr, cp, cy, sr, sp, sy, cpcy, spsy; 1426 // 1427 The order in which rotations are applied is: 1428 roll(X axii)-->pitch(Y axii)-->yaw(Z axii) 1429 each rotation can be represented by a quaternion, say qr,qp and qy 1430 qr = cr + sr(1,0,0) 1431 qp = cp + sp(0,1,0) 1432 qy = cy + sy(0,0,1) 1433 Notes: 1434 - the first element of each quaternion is a scalar; 1435 - we use (X,Y,Z) triple to denote a vector; 1436 - the quaternion representing the combined rotations is: 1437 q = qy*qp*qr 1438 1439 if we represent a quaternion as n + v, where n is the scalar part and 1440 v is the vector part, the product between quaternions q1 = n1 + v1 and 1441 q2 = n2 + v2 is given by: 1442 q1*q2 = n1*n2 - v1.v2 + n1*v2 + n2*v1 + v1xv2 1443 where: 1444 * -> product by an scalar 1445 . -> internal product 1446 x -> cross product 1447 1448 thus: 1449 qy*qp = cp*cy + (-sp*sy,cy*sp,cp*sy) 1450 and: 1451 (qy*qp)*qr = cr*cp*cy - sr*sp*sy + 1452 + (sr*cp*cy - cr*sp*sy, 1453 cr*sp*cy + sr*cp*sy, 1454 cr*cp*sy - sr*sp*cy) 1455 // 1456 1457 //calculate trig identities 1458 cr = Math.cos(roll/2); 1459 cp = Math.cos(pitch/2); 1460 cy = Math.cos(yaw/2); 1461 1462 sr = Math.sin(roll/2); 1463 sp = Math.sin(pitch/2); 1464 sy = Math.sin(yaw/2); 1465 1466 cpcy = cp * cy; 1467 spsy = sp * sy; 1468 1469 quat.w = cr * cpcy + sr * spsy; 1470 quat.x = sr * cpcy - cr * spsy; 1471 quat.y = cr * sp * cy + sr * cp * sy; 1472 quat.z = cr * cp * sy - sr * sp * cy; 1473 1474 quat.normalize(); 1475 }*/ 1476 1477 1478 /*** 1479 * Returns the transform 3D which keeps the translation part of this object's transform. 1480 * @param t3D Transform3D which will receive the parent translation transform. 1481 */ 1482 public void getParentTransTG(Transform3D t3D){ 1483 parentTransTG.getTransform(t3D); 1484 } 1485 1486 /*** 1487 * Returns the transform 3D which keeps the rotation and scaling parts of this object's transform. 1488 * @param t3D Transform3D which will receive the parent rotation and scale transform. 1489 */ 1490 public void getParentRotScaleTG(Transform3D t3D){ 1491 parentRotScaleTG.getTransform(t3D); 1492 } 1493 1494 /*** 1495 * Returns all accumulated transforms but pivot transforms. 1496 */ 1497 public void getTransforms(Transform3D transforms){ 1498 parentTransTG.getTransform(auxT3D); 1499 parentRotScaleTG.getTransform(tempT3D); 1500 auxT3D.mul(tempT3D); 1501 transforms.set(auxT3D); 1502 } 1503 1504 /*** 1505 * Returns this objects Local to Vworld transform. Does not include pivot transform. 1506 * @param t3D object into which will be copied the required transform. 1507 */ 1508 public void getLocalToVworld(Transform3D t3D){ 1509 if(!this.isLive()){ 1510 throw new RestrictedAccessException("Cannot get Local to Vworld transform: "+ 1511 this.getLabel()+" is not live"); 1512 } 1513 pivotTG.getLocalToVworld(t3D); 1514 } 1515 1516 /*** 1517 * Sets flag used to indicate whether this object is undergoing a transformation or not. 1518 */ 1519 public void setOngoingTransformation(boolean transforming){ 1520 this.transforming = transforming; 1521 } 1522 1523 /*** 1524 * Returns flag that indicates whether this object is undergoing a transformation or not. 1525 */ 1526 public boolean underOngoingTransformation(){ 1527 return transforming; 1528 } 1529 1530 /*** 1531 * Sets a specific kind of transformation, useful for the displaying of gizmos, etc. 1532 * 1533 */ 1534 public void setOngoingTransformationMode(TransformMode mode){ 1535 //debugln(this.getLabel()+".setOnTransMode called"); 1536 1537 this.transformationMode = mode; 1538 if (transformationMode == TransformMode.ABSOLUTE){ 1539 globalAxis.setVisible(true); 1540 localAxis.setVisible(false); 1541 //debugln(this.getLabel()+" changed to absolute mode."); 1542 } else if (transformationMode == TransformMode.RELATIVE) { 1543 globalAxis.setVisible(false); 1544 localAxis.setVisible(true); 1545 //debugln(this.getLabel()+" changed to relative mode."); 1546 } else { 1547 //debugln(" transform mode set to "+mode.toString()); 1548 } 1549 } 1550 1551 /*** 1552 * Returns a flag indicating whether this object is selected or not 1553 * @return true if object is selected, false otherwise 1554 */ 1555 public boolean isSelected(){ 1556 return this.selected; 1557 } 1558 1559 1560 public void scaleRelative(TransformScope scope, double scale){ 1561 if(scope==TransformScope.X) scaleXRelative(scale); 1562 if(scope==TransformScope.Y) scaleYRelative(scale); 1563 if(scope==TransformScope.Z) scaleZRelative(scale); 1564 if(scope==TransformScope.XYZ) setRelativeScale(scale,scale,scale); 1565 } 1566 1567 1568 /*** 1569 * "Modern" translation method. It is more convenient to call this 1570 * from inside a translationManipulator 1571 */ 1572 public void translate(Vector3d delta){ 1573 //if(mode == TransformMode.ABSOLUTE){ 1574 translate(delta.x, delta.y, delta.z); 1575 //} 1576 } 1577 1578 /* 1579 * Variant of method above 1580 */ 1581 /* 1582 public void translate(double x, double y, double z, TransformMode mode){ 1583 if(mode == TransformMode.ABSOLUTE){ 1584 translate(x, y, z); 1585 } 1586 else if (mode == TransformMode.RELATIVE){ 1587 translateLocal(x, y, z); 1588 } 1589 }*/ 1590 1591 1592 /*** 1593 * Returns a small Icon associated with the type of this object. 1594 */ 1595 public abstract Icon getIcon(); 1596 1597 /*** 1598 * Sets the Icon associated with the type of this object. 1599 */ 1600 public abstract void setIcon(Icon icon); 1601 1602 /*** 1603 * Returns a string describing this object. 1604 * @return the tool tip 1605 */ 1606 public String getTooltipText(){ 1607 return this.tooltipText; 1608 } 1609 1610 /*** 1611 * Returns the number of objects instatiated so far. 1612 */ 1613 public static int getInstanceCounter(){ 1614 return instanceCounter; 1615 } 1616 1617 1618 1619 /*** 1620 * Sets a text string describing this object. 1621 * @param text the tool tip 1622 */ 1623 public void setTooltipText(String text){ 1624 this.tooltipText = text; 1625 } 1626 1627 /*** 1628 * Calculates the normal and a point belonging to a plane. 1629 * Three points are given as input; the method calculates the vector normal 1630 * to the plane which contains the three input points. 1631 * @param planePoint point belonging to the plane (output parameter) 1632 * @param planeNormal vector normal to the plane (output parameter) 1633 * @param p1 input point 1 1634 * @param p2 input point 2 1635 * @param p3 input point 3 1636 */ 1637 void buildPlanePointAndNormal(Point3d planePoint, Vector3d planeNormal, Point3d p1, Point3d p2, Point3d p3){ 1638 planePoint.set(p1); 1639 planePoint.add(p2); 1640 planePoint.add(p3); 1641 // Planepoint averages other 3 points 1642 planePoint.x/=3; 1643 planePoint.y/=3; 1644 planePoint.z/=3; 1645 tempVec3d.sub(p1, p2); 1646 planeNormal.sub(p3, p2); 1647 planeNormal.cross(tempVec3d, planeNormal); 1648 planeNormal.normalize(); 1649 } 1650 1651 1652 }

This page was automatically generated by Maven