1 /* 2 * $RCSfile: MorphRetained.java,v $ 3 * 4 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Sun designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Sun in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 24 * CA 95054 USA or visit www.sun.com if you need additional information or 25 * have any questions. 26 * 27 * $Revision: 1.10 $ 28 * $Date: 2008/02/28 20:17:26 $ 29 * $State: Exp $ 30 */ 31 32 package javax.media.j3d; 33 34 import javax.vecmath.*; 35 import java.util.ArrayList; 36 import java.util.Vector; 37 38 /** 39 * A morph leaf node consisting of geometery and appearance properties. 40 */ 41 42 class MorphRetained extends LeafRetained implements GeometryUpdater { 43 44 // These bits should match the Shape3D bits ...(Since the mirrors for 45 // both are Shape3DRetained 46 static final int GEOMETRY_CHANGED = 0x00001; 47 static final int APPEARANCE_CHANGED = 0x00002; 48 static final int COLLISION_CHANGED = 0x00004; 49 static final int BOUNDS_CHANGED = 0x00008; 50 static final int APPEARANCEOVERRIDE_CHANGED = 0x00010; 51 static final int UPDATE_MORPH = 0x00020; 52 53 private static final double TOLERANCE = 1.0e-4; 54 55 56 /** 57 * The mirror Shape3DRetained nodes for this object. There is one 58 * mirror for each instance of this Shape3D node. If it is not in 59 * a SharedGroup, only index 0 is valid. 60 */ 61 ArrayList mirrorShape3D = new ArrayList(); 62 63 64 // Target threads to be notified when morph changes 65 final static int targetThreads = (J3dThread.UPDATE_RENDER | 66 J3dThread.UPDATE_GEOMETRY); 67 68 /** 69 * The appearance component of the morph node. 70 */ 71 AppearanceRetained appearance = null; 72 73 /** 74 * The Geosets associated with the morph node. 75 */ 76 GeometryArrayRetained geometryArrays[]; 77 78 private int numGeometryArrays = 0; 79 80 /** 81 * The weight vector the morph node. 82 */ 83 double weights[]; 84 85 /** 86 * Reference to the BranchGroup path of this mirror shape 87 * This is used for picking only. 88 */ 89 BranchGroupRetained branchGroupPath[]; 90 91 92 // cache value for picking in mirror shape. 93 // True if all the node of the path from this to root are all pickable 94 boolean isPickable = true; 95 96 97 // cache value for collidable in mirror shape. 98 // True if all the node of the path from this to root are all collidable 99 boolean isCollidable = true; 100 101 102 // closest switch parent 103 SwitchRetained closestSwitchParent = null; 104 105 // the child index from the closest switch parent 106 int closestSwitchIndex = -1; 107 108 // Is this Morph visible ? The default is true. 109 boolean visible = true; 110 111 // geometry Bounds in local coordinate 112 Bounds bounds = null; 113 114 // geometry Bounds in virtual world coordinate 115 BoundingBox vwcBounds = new BoundingBox(); 116 117 // collision Bound in local coordinate 118 Bounds collisionBound = null; 119 120 // collision Bounds in virtual world coordinate 121 Bounds collisionVwcBound = null; 122 123 124 GeometryArray morphedGeometryArray = null; 125 126 // Morph data 127 float[] Mcoord = null; 128 float[] Mcolor = null; 129 float[] Mnormal = null; 130 // First dimension is the coordSet, second dimenension is the vertex index 131 // each vertex has 2 or 3floats 132 float[][]MtexCoord = null; 133 134 // Whether the normal appearance is overrided by the alternate app 135 boolean appearanceOverrideEnable = false; 136 137 int changedFrequent = 0; 138 139 MorphRetained()140 MorphRetained() { 141 this.nodeType = NodeRetained.MORPH; 142 localBounds = new BoundingBox(); 143 ((BoundingBox)localBounds).setLower( 1.0, 1.0, 1.0); 144 ((BoundingBox)localBounds).setUpper(-1.0,-1.0,-1.0); 145 } 146 147 /** 148 * Sets the collision bounds of a node. 149 * @param bounds the bounding object for the node 150 */ setCollisionBounds(Bounds bounds)151 void setCollisionBounds(Bounds bounds) { 152 if (bounds != null) { 153 collisionBound = (Bounds)bounds.clone(); 154 } else { 155 collisionBound = null; 156 } 157 if (source.isLive()) { 158 // Notify Geometry Structure to set mirror shape collision 159 // bound and check for collision 160 J3dMessage message = new J3dMessage(); 161 message.type = J3dMessage.COLLISION_BOUND_CHANGED; 162 message.threads = J3dThread.UPDATE_TRANSFORM; 163 message.universe = universe; 164 message.args[1] = collisionBound; 165 VirtualUniverse.mc.processMessage(message); 166 } 167 } 168 169 /** 170 * Sets the geometric bounds of a node. 171 * @param bounds the bounding object for the node 172 */ setBounds(Bounds bounds)173 void setBounds(Bounds bounds) { 174 super.setBounds(bounds); 175 if (source.isLive() && !boundsAutoCompute) { 176 J3dMessage message = new J3dMessage(); 177 message.type = J3dMessage.REGION_BOUND_CHANGED; 178 message.threads = J3dThread.UPDATE_TRANSFORM | 179 targetThreads; 180 message.universe = universe; 181 message.args[0] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 182 message.args[1] = localBounds; 183 VirtualUniverse.mc.processMessage(message); 184 } 185 } 186 187 /** 188 * Gets the collision bounds of a node. 189 * @return the node's bounding object 190 */ getCollisionBounds()191 Bounds getCollisionBounds() { 192 return (collisionBound == null? null : (Bounds)collisionBound.clone()); 193 } 194 195 /** 196 * Sets the geometryArrays component of the Morph node. 197 * @param geometryArrays the new vector of geometryArrays for the morph node 198 */ setGeometryArrays(GeometryArray geometryArrays[])199 void setGeometryArrays(GeometryArray geometryArrays[]) { 200 int i; 201 202 if ((geometryArrays == null || geometryArrays.length == 0) && numGeometryArrays == 0) 203 return; 204 205 GeometryArrayRetained geo, prevGeo; 206 207 if (numGeometryArrays != 0 && (geometryArrays == null || numGeometryArrays != geometryArrays.length)) 208 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained0")); 209 210 211 for (i=1;i < geometryArrays.length;i++) { 212 if (geometryArrays[i] == null || geometryArrays[i-1] == null) 213 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 214 geo = (GeometryArrayRetained)geometryArrays[i].retained; 215 prevGeo = (GeometryArrayRetained)geometryArrays[i-1].retained; 216 if (prevGeo == null || geo == null) { 217 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 218 219 } 220 doErrorCheck(prevGeo, geo); 221 } 222 223 // Check the first one for vertex attributes 224 geo = (GeometryArrayRetained)geometryArrays[0].retained; 225 if ((geo.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { 226 throw new UnsupportedOperationException(J3dI18N.getString("MorphRetained9")); 227 } 228 229 // Check if the first one is in Immediate context 230 if (geometryArrays[0] != null) { 231 geo = (GeometryArrayRetained)geometryArrays[0].retained; 232 } 233 234 if (numGeometryArrays == 0) { 235 this.geometryArrays = new GeometryArrayRetained[geometryArrays.length]; 236 numGeometryArrays = geometryArrays.length; 237 } 238 239 for (i=0;i < numGeometryArrays;i++) { 240 geo = (GeometryArrayRetained)geometryArrays[i].retained; 241 if (((Morph)this.source).isLive()) { 242 if (this.geometryArrays[i] != null) { 243 this.geometryArrays[i].clearLive(refCount); 244 this.geometryArrays[i].removeMorphUser(this); 245 } 246 if (geo != null) { 247 geo.setLive(inBackgroundGroup, refCount); 248 geo.addMorphUser(this); 249 } 250 } 251 252 this.geometryArrays[i] = geo; 253 } 254 if (this.geometryArrays[0] == null) 255 return; 256 257 258 if (weights == null) { 259 weights = new double[numGeometryArrays]; 260 weights[0] = 1.0; 261 int vFormat = this.geometryArrays[0].vertexFormat; 262 // default is zero when new array 263 //for (i=1; i < numGeometryArrays;i++) weights[i] = 0.0; 264 265 int texCoordSetCount = this.geometryArrays[0].getTexCoordSetCount(); 266 if (this.geometryArrays[0] instanceof IndexedGeometryArrayRetained) { 267 Mcoord = new float[this.geometryArrays[0].getNumCoordCount()* 3]; 268 269 if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) 270 Mcolor = new float[this.geometryArrays[0].getNumColorCount()* 3]; 271 else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) 272 Mcolor = new float[this.geometryArrays[0].getNumColorCount()* 4]; 273 274 MtexCoord = new float[texCoordSetCount][]; 275 if ((vFormat & GeometryArray.NORMALS) != 0) 276 Mnormal = new float[this.geometryArrays[0].getNumNormalCount() *3]; 277 for (int k = 0; k < texCoordSetCount; k++) { 278 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) 279 MtexCoord[k] = new float[this.geometryArrays[0].getNumTexCoordCount(k) * 2]; 280 else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)) 281 MtexCoord[k] = new float[this.geometryArrays[0].getNumTexCoordCount(k) * 3]; 282 else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)) 283 MtexCoord[k] = new float[this.geometryArrays[0].getNumTexCoordCount(k) * 4]; 284 } 285 } 286 else { 287 Mcoord = new float[this.geometryArrays[0].validVertexCount* 3]; 288 289 if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) { 290 Mcolor = new float[this.geometryArrays[0].validVertexCount* 3]; 291 } else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) { 292 Mcolor = new float[this.geometryArrays[0].validVertexCount* 4]; 293 } 294 MtexCoord = new float[texCoordSetCount][]; 295 if ((vFormat & GeometryArray.NORMALS) != 0) { 296 Mnormal = new float[this.geometryArrays[0].validVertexCount *3]; 297 } 298 for (int k = 0; k < texCoordSetCount; k++) { 299 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) 300 MtexCoord[k] = new float[this.geometryArrays[0].validVertexCount * 2]; 301 else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)) 302 MtexCoord[k] = new float[this.geometryArrays[0].validVertexCount * 3]; 303 else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)) 304 MtexCoord[k] = new float[this.geometryArrays[0].validVertexCount * 4]; 305 } 306 } 307 } 308 309 // create a new morphedGeometryArray 310 initMorphedGeometry(); 311 312 if (source.isLive()) { 313 314 Shape3DRetained shape = (Shape3DRetained)mirrorShape3D.get(0); 315 316 shape.setMorphGeometry(morphedGeometryArray, mirrorShape3D); 317 318 J3dMessage mChangeMessage = null; 319 mChangeMessage = new J3dMessage(); 320 mChangeMessage.type = J3dMessage.MORPH_CHANGED; 321 mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | 322 J3dThread.UPDATE_TRANSFORM); 323 // If its a indexed geometry array, unindexify in renderBin 324 if (this.geometryArrays[0] instanceof IndexedGeometryArrayRetained) 325 mChangeMessage.threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES; 326 mChangeMessage.args[0] = this; 327 mChangeMessage.args[1]= new Integer(GEOMETRY_CHANGED); 328 // a shadow copy of this ArrayList instance. (The elements themselves are not copied.) 329 mChangeMessage.args[3] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 330 mChangeMessage.universe = universe; 331 VirtualUniverse.mc.processMessage(mChangeMessage); 332 333 if (boundsAutoCompute) { 334 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 335 // Compute the bounds once 336 mga.incrComputeGeoBounds();// This compute the bbox if dirty 337 mga.decrComputeGeoBounds(); 338 } 339 } 340 341 342 343 } 344 345 /** 346 * Retrieves the geometryArrays component of this Morph node. 347 * @param index the index of GeometryArray to be returned 348 * @return the geometryArray component of this morph node 349 */ getGeometryArray(int index)350 GeometryArray getGeometryArray(int index) { 351 return (GeometryArray)this.geometryArrays[index].source; 352 } 353 354 /** 355 * Sets the appearance component of this Morph node. 356 * @param appearance the new apearance component for this morph node 357 */ setAppearance(Appearance newAppearance)358 void setAppearance(Appearance newAppearance) { 359 boolean visibleIsDirty = false; 360 361 if (((Morph)this.source).isLive()) { 362 363 if (appearance != null) { 364 this.appearance.clearLive(refCount); 365 for (int i=mirrorShape3D.size()-1; i>=0; i--) { 366 this.appearance.removeAMirrorUser( 367 (Shape3DRetained)mirrorShape3D.get(i)); 368 } 369 } 370 371 if (newAppearance != null) { 372 ((AppearanceRetained)newAppearance.retained).setLive(inBackgroundGroup, refCount); 373 appearance = ((AppearanceRetained)newAppearance.retained); 374 int size= mirrorShape3D.size(); 375 for (int i=0; i<size; i++) { 376 appearance.addAMirrorUser((Shape3DRetained)mirrorShape3D.get(i)); 377 } 378 if((appearance.renderingAttributes != null) && 379 (visible != appearance.renderingAttributes.visible)) { 380 visible = appearance.renderingAttributes.visible; 381 visibleIsDirty = true; 382 } 383 } 384 else { 385 if(visible == false) { 386 visible = true; 387 visibleIsDirty = true; 388 } 389 } 390 391 // Send a message 392 int size = 0; 393 394 if (visibleIsDirty) 395 size = 2; 396 else 397 size = 1; 398 J3dMessage[] createMessage = new J3dMessage[size]; 399 createMessage[0] = new J3dMessage(); 400 createMessage[0].threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | 401 J3dThread.UPDATE_RENDER; 402 createMessage[0].type = J3dMessage.MORPH_CHANGED; 403 createMessage[0].universe = universe; 404 createMessage[0].args[0] = this; 405 createMessage[0].args[1]= new Integer(APPEARANCE_CHANGED); 406 Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D.size()]; 407 mirrorShape3D.toArray(s3dArr); 408 createMessage[0].args[2] = s3dArr; 409 Object[] obj = new Object[2]; 410 if (newAppearance == null) { 411 obj[0] = null; 412 } 413 else { 414 obj[0] = appearance.mirror; 415 } 416 obj[1] = new Integer(changedFrequent); 417 createMessage[0].args[3] = obj; 418 createMessage[0].args[4] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 419 if(visibleIsDirty) { 420 createMessage[1] = new J3dMessage(); 421 createMessage[1].threads = J3dThread.UPDATE_GEOMETRY; 422 createMessage[1].type = J3dMessage.SHAPE3D_CHANGED; 423 createMessage[1].universe = universe; 424 createMessage[1].args[0] = this; 425 createMessage[1].args[1]= new Integer(APPEARANCE_CHANGED); 426 createMessage[1].args[2]= visible?Boolean.TRUE:Boolean.FALSE; 427 createMessage[1].args[3]= createMessage[0].args[4]; 428 } 429 VirtualUniverse.mc.processMessage(createMessage); 430 } 431 else { 432 if (newAppearance == null) { 433 appearance = null; 434 } else { 435 appearance = (AppearanceRetained) newAppearance.retained; 436 } 437 } 438 } 439 440 /** 441 * Retrieves the morph node's appearance component. 442 * @return the morph node's appearance 443 */ getAppearance()444 Appearance getAppearance() { 445 return (appearance == null ? null : 446 (Appearance) this.appearance.source); 447 } 448 setAppearanceOverrideEnable(boolean flag)449 void setAppearanceOverrideEnable(boolean flag) { 450 if (((Morph)this.source).isLive()) { 451 452 // Send a message 453 J3dMessage createMessage = new J3dMessage(); 454 createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | 455 J3dThread.UPDATE_RENDER;; 456 createMessage.type = J3dMessage.MORPH_CHANGED; 457 createMessage.universe = universe; 458 createMessage.args[0] = this; 459 createMessage.args[1]= new Integer(APPEARANCEOVERRIDE_CHANGED); 460 Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D.size()]; 461 mirrorShape3D.toArray(s3dArr); 462 createMessage.args[2] = s3dArr; 463 Object[] obj = new Object[2]; 464 if (flag) { 465 obj[0] = Boolean.TRUE; 466 } 467 else { 468 obj[0] = Boolean.FALSE; 469 } 470 obj[1] = new Integer(changedFrequent); 471 createMessage.args[3] = obj; 472 createMessage.args[4] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 473 VirtualUniverse.mc.processMessage(createMessage); 474 } 475 appearanceOverrideEnable = flag; 476 } 477 getAppearanceOverrideEnable()478 boolean getAppearanceOverrideEnable() { 479 return appearanceOverrideEnable; 480 } 481 intersect(PickInfo pickInfo, PickShape pickShape, int flags )482 boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags ) { 483 484 Transform3D localToVworld = pickInfo.getLocalToVWorldRef(); 485 486 Transform3D vworldToLocal = new Transform3D(); 487 vworldToLocal.invert(localToVworld); 488 PickShape newPS = pickShape.transform(vworldToLocal); 489 490 GeometryRetained geo = (GeometryRetained) (morphedGeometryArray.retained); 491 492 if (geo.mirrorGeometry != null) { 493 geo = geo.mirrorGeometry; 494 } 495 496 if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0) && 497 ((flags & PickInfo.CLOSEST_DISTANCE) == 0) && 498 ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0) && 499 ((flags & PickInfo.ALL_GEOM_INFO) == 0)) { 500 return geo.intersect(newPS, null, 0, null, null, 0); 501 } else { 502 Point3d closestIPnt = new Point3d(); 503 Point3d iPnt = new Point3d(); 504 Point3d iPntVW = new Point3d(); 505 506 if (geo.intersect(newPS, pickInfo, flags, iPnt, geo, 0)) { 507 508 iPntVW.set(iPnt); 509 localToVworld.transform(iPntVW); 510 double distance = pickShape.distance(iPntVW); 511 512 if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) { 513 pickInfo.setClosestDistance(distance); 514 } 515 if((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) { 516 pickInfo.setClosestIntersectionPoint(iPnt); 517 } 518 return true; 519 } 520 } 521 return false; 522 } 523 524 525 /** 526 * Check if the geometry component of this shape node under path 527 * intersects with the pickShape. 528 * @return true if intersected else false. If return is true, dist 529 * contains the closest distance of intersection if it is not 530 * equal to null. 531 */ intersect(SceneGraphPath path, PickShape pickShape, double[] dist)532 boolean intersect(SceneGraphPath path, 533 PickShape pickShape, double[] dist) { 534 535 // This method will not do bound intersect check, as it assume caller 536 // has already done that. ( For performance and code simplification 537 // reasons. ) 538 539 int flags; 540 PickInfo pickInfo = new PickInfo(); 541 542 Transform3D localToVworld = path.getTransform(); 543 if (localToVworld == null) { 544 throw new RuntimeException(J3dI18N.getString("MorphRetained5")); 545 } 546 547 pickInfo.setLocalToVWorldRef( localToVworld); 548 //System.err.println("MorphRetained.intersect() : "); 549 if (dist == null) { 550 //System.err.println(" no dist request ...."); 551 return intersect(pickInfo, pickShape, 0); 552 } 553 554 flags = PickInfo.CLOSEST_DISTANCE; 555 if (intersect(pickInfo, pickShape, flags)) { 556 dist[0] = pickInfo.getClosestDistance(); 557 return true; 558 } 559 560 return false; 561 562 } 563 564 /** 565 * Sets the Morph node's weight vector 566 * @param wieghts the new vector of weights for the morph node 567 */ setWeights(double weights[])568 void setWeights(double weights[]) { 569 int i; 570 double sum= 0.0; 571 572 if (weights.length != numGeometryArrays) 573 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained7")); 574 575 for (i=weights.length-1; i>=0; i--) { 576 sum += weights[i]; 577 } 578 579 if (Math.abs(sum - 1.0) > TOLERANCE) 580 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained8")); 581 582 // Weights array is ALWAYS malloced in setGeometryArrays method 583 for (i=numGeometryArrays-1; i>=0; i--) 584 this.weights[i] = weights[i]; 585 586 587 if (source.isLive()) { 588 ((GeometryArrayRetained)morphedGeometryArray.retained).updateData(this); 589 J3dMessage mChangeMessage = null; 590 mChangeMessage = new J3dMessage(); 591 mChangeMessage.type = J3dMessage.MORPH_CHANGED; 592 mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | 593 J3dThread.UPDATE_TRANSFORM); 594 // If its a indexed geometry array, unindexify in renderBin 595 if (this.geometryArrays[0] instanceof IndexedGeometryArrayRetained) 596 mChangeMessage.threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES; 597 mChangeMessage.args[0] = this; 598 mChangeMessage.args[1]= new Integer(GEOMETRY_CHANGED); 599 mChangeMessage.args[3] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 600 mChangeMessage.universe = universe; 601 VirtualUniverse.mc.processMessage(mChangeMessage); 602 } 603 604 } 605 606 /** 607 * Retrieves the Morph node's weight vector 608 * @return the morph node's weight vector. 609 */ getWeights()610 double[] getWeights() { 611 return (double[]) weights.clone(); 612 } 613 614 /** 615 * Gets the bounding object of a node. 616 * @return the node's bounding object 617 */ getBounds()618 Bounds getBounds() { 619 if(boundsAutoCompute) { 620 GeometryArrayRetained mga = 621 (GeometryArrayRetained)morphedGeometryArray.retained; 622 if (mga != null) { 623 synchronized(mga.geoBounds) { 624 return (Bounds) mga.geoBounds.clone(); 625 } 626 } else { 627 return null; 628 } 629 } else { 630 return super.getBounds(); 631 } 632 } 633 getEffectiveBounds()634 Bounds getEffectiveBounds() { 635 if(boundsAutoCompute) { 636 return getBounds(); 637 } 638 else { 639 return super.getEffectiveBounds(); 640 } 641 } 642 643 /** 644 * ONLY needed for SHAPE, MORPH, and LINK node type. 645 * Compute the combine bounds of bounds and its localBounds. 646 */ computeCombineBounds(Bounds bounds)647 void computeCombineBounds(Bounds bounds) { 648 649 if(boundsAutoCompute) { 650 GeometryArrayRetained mga = 651 (GeometryArrayRetained)morphedGeometryArray.retained; 652 if (mga != null) { 653 synchronized(mga.geoBounds) { 654 bounds.combine((Bounds) mga.geoBounds); 655 } 656 } 657 } else { 658 // Should this be lock too ? ( MT safe ? ) 659 synchronized(localBounds) { 660 bounds.combine((Bounds) localBounds); 661 } 662 } 663 } 664 665 // Return the number of geometry arrays in this MorphRetained object. getNumGeometryArrays()666 int getNumGeometryArrays() { 667 return numGeometryArrays; 668 } 669 670 // If the geometry of a morph changes, make sure that the 671 // validVertexCount has not changed updateMorphedGeometryArray(GeometryArrayRetained geo, boolean coordinatesChanged)672 void updateMorphedGeometryArray(GeometryArrayRetained geo, boolean coordinatesChanged) { 673 if (numGeometryArrays > 0) { 674 // check if not the first geo, then compare with the first geometry 675 if (geometryArrays[0] != geo) { 676 doErrorCheck(geo, geometryArrays[0]); 677 } 678 else { 679 // if first geo, compare with the second geo 680 if (numGeometryArrays > 1) { 681 doErrorCheck(geo, geometryArrays[1]); 682 } 683 684 } 685 } 686 687 688 ((GeometryArrayRetained)morphedGeometryArray.retained).updateData(this); 689 // Compute the bounds once 690 if (boundsAutoCompute && coordinatesChanged) { 691 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 692 mga.incrComputeGeoBounds(); // This compute the bbox if dirty 693 mga.decrComputeGeoBounds(); 694 } 695 } 696 697 /** 698 * Update GeometryArray computed by morphing input GeometryArrays 699 * with weights 700 */ updateData(Geometry mga)701 public void updateData(Geometry mga) { 702 703 int i,j,k, vFormat, geoType, stripVCount[]; 704 int iCount = 0; 705 int numStrips = 0; 706 int texCoordSetCount = 0; 707 float coord[] = new float[3], color[] = new float[4], 708 normal[] = new float[3], texCoord[] = new float[3]; 709 710 vFormat = geometryArrays[0].vertexFormat; 711 geoType = ((GeometryArrayRetained)geometryArrays[0]).geoType; 712 texCoordSetCount = geometryArrays[0].getTexCoordSetCount(); 713 714 715 716 int vc = 0, nc = 0, cc = 0, n = 0; 717 int count = 0; 718 if (geometryArrays[0] instanceof IndexedGeometryArrayRetained){ 719 count = geometryArrays[0].getNumCoordCount(); 720 } else { 721 count = geometryArrays[0].validVertexCount; 722 } 723 724 for (i=0; i < count; i++) { 725 Mcoord[vc++] = Mcoord[vc++] = Mcoord[vc++] = 0.0f; 726 } 727 728 729 if ((vFormat & GeometryArray.COLOR) != 0) { 730 if (geometryArrays[0] instanceof IndexedGeometryArrayRetained){ 731 count = geometryArrays[0].getNumColorCount(); 732 } else { 733 count = geometryArrays[0].validVertexCount; 734 } 735 for (i=0; i < count; i++) { 736 if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) 737 Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = 0.0f; 738 739 else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) 740 Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = 0.0f; 741 } 742 } 743 744 745 if ((vFormat & GeometryArray.NORMALS) != 0) { 746 if (geometryArrays[0] instanceof IndexedGeometryArrayRetained){ 747 count = geometryArrays[0].getNumNormalCount(); 748 } else { 749 count = geometryArrays[0].validVertexCount; 750 } 751 for (i=0; i < count; i++) { 752 Mnormal[nc++] = Mnormal[nc++] = Mnormal[nc++] = 0.0f; 753 } 754 } 755 756 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 757 for (k = 0; k < texCoordSetCount; k++) { 758 if (geometryArrays[0] instanceof IndexedGeometryArrayRetained){ 759 count = geometryArrays[0].getNumTexCoordCount(k); 760 } else { 761 count = geometryArrays[0].validVertexCount; 762 } 763 int tcount = 0; 764 for (i=0; i < count; i++) { 765 MtexCoord[k][tcount++] = MtexCoord[k][tcount++] = 0.0f; 766 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { 767 MtexCoord[k][tcount++] = 0.0f; 768 } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { 769 MtexCoord[k][tcount++] = 0.0f; 770 MtexCoord[k][tcount++] = 0.0f; 771 } 772 } 773 } 774 } 775 // If by copy, then ... 776 if ((vFormat & GeometryArray.BY_REFERENCE) == 0) { 777 count = 0; 778 for (j=0;j < numGeometryArrays;j++) { 779 double w = weights[j]; 780 if (w != 0) { 781 vc = 0; nc = 0; cc = 0; 782 int initialVertex = 0; 783 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 784 initialVertex = 0; 785 count = geometryArrays[j].getNumCoordCount(); 786 } 787 else { 788 initialVertex = geometryArrays[j].getInitialVertexIndex(); 789 count = geometryArrays[j].validVertexCount; 790 } 791 int endVertex = initialVertex + count; 792 for (i=initialVertex; i< endVertex; i++) { 793 geometryArrays[j].getCoordinate(i, coord); 794 Mcoord[vc++] += coord[0]*w; 795 Mcoord[vc++] += coord[1]*w; 796 Mcoord[vc++] += coord[2]*w; 797 } 798 799 if ((vFormat & GeometryArray.COLOR) != 0) { 800 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 801 count = geometryArrays[j].getNumColorCount(); 802 } 803 endVertex = initialVertex + count; 804 for (i=initialVertex; i< endVertex; i++) { 805 geometryArrays[j].getColor(i, color); 806 Mcolor[cc++] += color[0]*w; 807 Mcolor[cc++] += color[1]*w; 808 Mcolor[cc++] += color[2]*w; 809 if ((vFormat & GeometryArray.WITH_ALPHA) != 0) 810 Mcolor[cc++] += color[3]*w; 811 } 812 } 813 if ((vFormat & GeometryArray.NORMALS) != 0) { 814 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 815 count = geometryArrays[j].getNumNormalCount(); 816 } 817 endVertex = initialVertex + count; 818 for (i=initialVertex; i< endVertex; i++) { 819 geometryArrays[j].getNormal(i, normal); 820 Mnormal[nc++] += normal[0]*w; 821 Mnormal[nc++] += normal[1]*w; 822 Mnormal[nc++] += normal[2]*w; 823 } 824 } 825 826 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 827 for (k = 0; k < texCoordSetCount; k++) { 828 int tcount = 0; 829 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 830 count = geometryArrays[j].getNumTexCoordCount(i); 831 } 832 endVertex = initialVertex + count; 833 for (i=initialVertex; i< endVertex; i++) { 834 geometryArrays[j].getTextureCoordinate(k, i, texCoord); 835 MtexCoord[k][tcount++] += texCoord[0]*w; 836 MtexCoord[k][tcount++] += texCoord[1]*w; 837 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { 838 MtexCoord[k][tcount++] += texCoord[2]*w; 839 } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { 840 MtexCoord[k][tcount++] += texCoord[2]*w; 841 MtexCoord[k][tcount++] += texCoord[3]*w; 842 } 843 } 844 } 845 } 846 } 847 } 848 } 849 else { 850 int vIndex, tIndex, cIndex, nIndex, tstride = 0, cstride = 0; 851 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 852 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { 853 tstride = 2; 854 } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { 855 tstride = 3; 856 } else { 857 tstride = 4; 858 } 859 } 860 861 if ((vFormat & GeometryArray.COLOR) != 0) { 862 cstride = 3; 863 if ((vFormat & GeometryArray.WITH_ALPHA) != 0) 864 cstride = 4; 865 } 866 867 if ((vFormat & GeometryArray.INTERLEAVED) != 0) { 868 float[] vdata; 869 int stride; 870 871 stride = geometryArrays[0].stride(); 872 int coffset = geometryArrays[0].colorOffset(); 873 int noffset = geometryArrays[0].normalOffset(); 874 int voffset = geometryArrays[0].coordinateOffset(); 875 int offset = 0; 876 877 int initialVertex = 0; 878 for (j=0;j < numGeometryArrays;j++) { 879 double w = weights[j]; 880 if (w != 0) { 881 vc = 0; nc = 0; cc = 0; n = 0; 882 vdata = geometryArrays[j].getInterleavedVertices(); 883 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 884 for (k = 0; k < texCoordSetCount; k++) { 885 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 886 tIndex = 0; 887 count = geometryArrays[j].getNumCoordCount(); 888 } 889 else { 890 tIndex = geometryArrays[j].getInitialVertexIndex(); 891 count = geometryArrays[j].validVertexCount; 892 } 893 offset = (tIndex * stride)+k*tstride; 894 int tcount = 0; 895 for (i = 0; i < count; i++, offset += stride) { 896 MtexCoord[k][tcount++] += vdata[offset] * w; 897 MtexCoord[k][tcount++] += vdata[offset+1] * w; 898 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { 899 MtexCoord[k][tcount++] += vdata[offset+2]*w; 900 } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { 901 MtexCoord[k][tcount++] += vdata[offset+2]*w; 902 MtexCoord[k][tcount++] += vdata[offset+3]*w; 903 } 904 } 905 } 906 907 } 908 if ((vFormat & GeometryArray.COLOR) != 0) { 909 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 910 cIndex = 0; 911 count = geometryArrays[j].getNumCoordCount(); 912 } 913 else { 914 cIndex = geometryArrays[j].getInitialVertexIndex(); 915 count = geometryArrays[j].validVertexCount; 916 } 917 offset = (cIndex * stride)+coffset; 918 for (i = 0; i < count; i++, offset += stride) { 919 Mcolor[cc++] += vdata[offset]*w; 920 Mcolor[cc++] += vdata[offset+1]*w; 921 Mcolor[cc++] += vdata[offset+2]*w; 922 if ((vFormat & GeometryArray.WITH_ALPHA)!= 0) 923 Mcolor[cc++] += vdata[offset+3]*w; 924 925 } 926 } 927 928 if ((vFormat & GeometryArray.NORMALS) != 0) { 929 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 930 nIndex = 0; 931 count = geometryArrays[j].getNumCoordCount(); 932 } 933 else { 934 nIndex = geometryArrays[j].getInitialVertexIndex(); 935 count = geometryArrays[j].validVertexCount; 936 } 937 offset = (nIndex * stride)+noffset; 938 for (i = 0; i < count; i++, offset += stride) { 939 Mnormal[nc++] += vdata[offset]*w; 940 Mnormal[nc++] += vdata[offset+1]*w; 941 Mnormal[nc++] += vdata[offset+2]*w; 942 } 943 } 944 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 945 vIndex = 0; 946 count = geometryArrays[j].getNumCoordCount(); 947 } 948 else { 949 vIndex = geometryArrays[j].getInitialVertexIndex(); 950 count = geometryArrays[j].validVertexCount; 951 } 952 offset = (vIndex * stride)+voffset; 953 for (i = 0; i < count; i++, offset += stride) { 954 Mcoord[vc++] += vdata[offset]*w; 955 Mcoord[vc++] += vdata[offset+1]*w; 956 Mcoord[vc++] += vdata[offset+2]*w; 957 958 } 959 } 960 } 961 } 962 else { 963 float byteToFloatScale = 1.0f/255.0f; 964 for (j=0;j < numGeometryArrays;j++) { 965 double w = weights[j]; 966 if (w != 0) { 967 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 968 switch ((geometryArrays[j].vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) { 969 case GeometryArrayRetained.TF: 970 for (k = 0; k < texCoordSetCount; k++) { 971 float[] tf = geometryArrays[j].getTexCoordRefFloat(k); 972 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 973 tIndex = 0; 974 count = geometryArrays[j].getNumTexCoordCount(k); 975 } 976 else { 977 tIndex = geometryArrays[j].getInitialTexCoordIndex(k); 978 count = geometryArrays[j].validVertexCount; 979 } 980 tIndex *= tstride; 981 int tcount = 0; 982 for (i=0; i< count; i++) { 983 MtexCoord[k][tcount++] += tf[tIndex++]*w; 984 MtexCoord[k][tcount++] += tf[tIndex++]*w; 985 if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) 986 MtexCoord[k][tcount++] += tf[tIndex++]*w; 987 } 988 } 989 break; 990 case GeometryArrayRetained.T2F: 991 for (k = 0; k < texCoordSetCount; k++) { 992 int tcount = 0; 993 float[] tf = geometryArrays[j].getTexCoordRefFloat(k); 994 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 995 tIndex = 0; 996 count = geometryArrays[j].getNumTexCoordCount(k); 997 } 998 else { 999 tIndex = geometryArrays[j].getInitialTexCoordIndex(k); 1000 count = geometryArrays[j].validVertexCount; 1001 } 1002 TexCoord2f[] t2f = geometryArrays[j].getTexCoordRef2f(k); 1003 for (i=0; i< count; i++, tIndex++) { 1004 MtexCoord[k][tcount++] += t2f[tIndex].x*w; 1005 MtexCoord[k][tcount++] += t2f[tIndex].y*w; 1006 } 1007 } 1008 break; 1009 case GeometryArrayRetained.T3F: 1010 for (k = 0; k < texCoordSetCount; k++) { 1011 int tcount = 0; 1012 TexCoord3f[] t3f = geometryArrays[j].getTexCoordRef3f(k); 1013 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 1014 tIndex = 0; 1015 count = geometryArrays[j].getNumTexCoordCount(k); 1016 } 1017 else { 1018 tIndex = geometryArrays[j].getInitialTexCoordIndex(k); 1019 count = geometryArrays[j].validVertexCount; 1020 } 1021 for (i=0; i< count; i++, tIndex++) { 1022 MtexCoord[k][tcount++] += t3f[tIndex].x*w; 1023 MtexCoord[k][tcount++] += t3f[tIndex].y*w; 1024 MtexCoord[k][tcount++] += t3f[tIndex].z*w; 1025 } 1026 } 1027 break; 1028 1029 } 1030 } 1031 if ((vFormat & GeometryArray.COLOR) != 0) { 1032 double val = byteToFloatScale * w; 1033 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 1034 cIndex = 0; 1035 count = geometryArrays[j].getNumColorCount(); 1036 } 1037 else { 1038 cIndex = geometryArrays[j].getInitialColorIndex(); 1039 count = geometryArrays[j].validVertexCount; 1040 } 1041 1042 switch ((geometryArrays[j].vertexType & GeometryArrayRetained.COLOR_DEFINED)) { 1043 case GeometryArrayRetained.CF: 1044 float[] cf = geometryArrays[j].getColorRefFloat(); 1045 cc = 0; 1046 cIndex *= cstride; 1047 for (i=0; i< count; i++) { 1048 Mcolor[cc++] += cf[cIndex++]*w; 1049 Mcolor[cc++] += cf[cIndex++]*w; 1050 Mcolor[cc++] += cf[cIndex++]*w; 1051 if ((vFormat & GeometryArray.WITH_ALPHA)!= 0) 1052 Mcolor[cc++] += cf[cIndex++]*w; 1053 } 1054 break; 1055 case GeometryArrayRetained.CUB: 1056 byte[] cub = geometryArrays[j].getColorRefByte(); 1057 cc = 0; 1058 cIndex *= cstride; 1059 for (i=0; i< count; i++) { 1060 Mcolor[cc++] += (cub[cIndex++] & 0xff) * val; 1061 Mcolor[cc++] += (cub[cIndex++] & 0xff) *val; 1062 Mcolor[cc++] += (cub[cIndex++] & 0xff) *val; 1063 if ((vFormat & GeometryArray.WITH_ALPHA)!= 0) 1064 Mcolor[cc++] += (cub[cIndex++] & 0xff) *val; 1065 } 1066 1067 break; 1068 case GeometryArrayRetained.C3F: 1069 Color3f[] c3f = geometryArrays[j].getColorRef3f(); 1070 cc = 0; 1071 for (i=0; i< count; i++, cIndex++) { 1072 Mcolor[cc++] += c3f[cIndex].x * w; 1073 Mcolor[cc++] += c3f[cIndex].y * w; 1074 Mcolor[cc++] += c3f[cIndex].z * w; 1075 } 1076 break; 1077 case GeometryArrayRetained.C4F: 1078 Color4f[] c4f = geometryArrays[j].getColorRef4f(); 1079 cc = 0; 1080 for (i=0; i< count; i++, cIndex++) { 1081 Mcolor[cc++] += c4f[cIndex].x * w; 1082 Mcolor[cc++] += c4f[cIndex].y * w; 1083 Mcolor[cc++] += c4f[cIndex].z * w; 1084 Mcolor[cc++] += c4f[cIndex].w * w; 1085 } 1086 break; 1087 case GeometryArrayRetained.C3UB: 1088 Color3b[] c3b = geometryArrays[j].getColorRef3b(); 1089 cc = 0; 1090 for (i=0; i< count; i++, cIndex++) { 1091 Mcolor[cc++] += (c3b[cIndex].x & 0xff)* val; 1092 Mcolor[cc++] += (c3b[cIndex].y & 0xff) * val; 1093 Mcolor[cc++] += (c3b[cIndex].z & 0xff) * val; 1094 } 1095 break; 1096 case GeometryArrayRetained.C4UB: 1097 Color4b[] c4b = geometryArrays[j].getColorRef4b(); 1098 cc = 0; 1099 for (i=0; i< count; i++, cIndex++) { 1100 Mcolor[cc++] += (c4b[cIndex].x & 0xff)* val; 1101 Mcolor[cc++] += (c4b[cIndex].y & 0xff) * val; 1102 Mcolor[cc++] += (c4b[cIndex].z & 0xff) * val; 1103 Mcolor[cc++] += (c4b[cIndex].w & 0xff) * val; 1104 } 1105 break; 1106 1107 } 1108 } 1109 if ((vFormat & GeometryArray.NORMALS) != 0) { 1110 nc = 0; 1111 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 1112 nIndex = 0; 1113 count = geometryArrays[j].getNumNormalCount(); 1114 } 1115 else { 1116 nIndex = geometryArrays[j].getInitialNormalIndex(); 1117 count = geometryArrays[j].validVertexCount; 1118 } 1119 switch ((geometryArrays[j].vertexType & GeometryArrayRetained.NORMAL_DEFINED)) { 1120 case GeometryArrayRetained.NF: 1121 float[] nf = geometryArrays[j].getNormalRefFloat(); 1122 nIndex *= 3; 1123 for (i=0; i< count; i++) { 1124 Mnormal[nc++] += nf[nIndex++]*w; 1125 Mnormal[nc++] += nf[nIndex++]*w; 1126 Mnormal[nc++] += nf[nIndex++]*w; 1127 } 1128 break; 1129 case GeometryArrayRetained.N3F: 1130 Vector3f[] n3f = geometryArrays[j].getNormalRef3f(); 1131 for (i=0; i< count; i++, nIndex++) { 1132 Mnormal[nc++] += n3f[nIndex].x*w; 1133 Mnormal[nc++] += n3f[nIndex].y*w; 1134 Mnormal[nc++] += n3f[nIndex].z*w; 1135 } 1136 break; 1137 } 1138 } 1139 // Handle vertices .. 1140 vc = 0; 1141 if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) { 1142 vIndex = 0; 1143 count = geometryArrays[j].getNumCoordCount(); 1144 } 1145 else { 1146 vIndex = geometryArrays[j].getInitialCoordIndex(); 1147 count = geometryArrays[j].validVertexCount; 1148 } 1149 switch ((geometryArrays[j].vertexType & GeometryArrayRetained.VERTEX_DEFINED)) { 1150 case GeometryArrayRetained.PF: 1151 float[] pf = geometryArrays[j].getCoordRefFloat(); 1152 vIndex *= 3; 1153 for (i=0; i< count; i++) { 1154 Mcoord[vc++] += pf[vIndex++]*w; 1155 Mcoord[vc++] += pf[vIndex++]*w; 1156 Mcoord[vc++] += pf[vIndex++]*w; 1157 } 1158 break; 1159 case GeometryArrayRetained.PD: 1160 double[] pd = geometryArrays[j].getCoordRefDouble(); 1161 vIndex *= 3; 1162 for (i=0; i< count; i++) { 1163 Mcoord[vc++] += (float)pd[vIndex++]*w; 1164 Mcoord[vc++] += (float)pd[vIndex++]*w; 1165 Mcoord[vc++] += (float)pd[vIndex++]*w; 1166 } 1167 break; 1168 case GeometryArrayRetained.P3F: 1169 Point3f[] p3f = geometryArrays[j].getCoordRef3f(); 1170 for (i=0; i< count; i++, vIndex++) { 1171 Mcoord[vc++] += p3f[vIndex].x*w; 1172 Mcoord[vc++] += p3f[vIndex].y*w; 1173 Mcoord[vc++] += p3f[vIndex].z*w; 1174 } 1175 break; 1176 case GeometryArrayRetained.P3D: 1177 Point3d[] p3d = geometryArrays[j].getCoordRef3d(); 1178 for (i=0; i< count; i++, vIndex++) { 1179 Mcoord[vc++] += (float)p3d[vIndex].x*w; 1180 Mcoord[vc++] += (float)p3d[vIndex].y*w; 1181 Mcoord[vc++] += (float)p3d[vIndex].z*w; 1182 } 1183 break; 1184 1185 } 1186 1187 } 1188 } 1189 } 1190 } 1191 1192 GeometryArrayRetained mgaR = 1193 (GeometryArrayRetained)mga.retained; 1194 1195 mgaR.setCoordRefFloat(Mcoord); 1196 1197 if ((vFormat & GeometryArray.COLOR) != 0) 1198 mgaR.setColorRefFloat(Mcolor); 1199 1200 // *******Need to normalize normals 1201 if ((vFormat & GeometryArray.NORMALS) != 0) 1202 mgaR.setNormalRefFloat(Mnormal); 1203 1204 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 1205 for (k = 0; k < texCoordSetCount; k++) { 1206 mgaR.setTexCoordRefFloat(k, MtexCoord[k]); 1207 } 1208 } 1209 } 1210 updateImmediateMirrorObject(Object[] objs)1211 void updateImmediateMirrorObject(Object[] objs) { 1212 int i; 1213 1214 int component = ((Integer)objs[1]).intValue(); 1215 Shape3DRetained[] msArr = (Shape3DRetained[]) objs[2]; 1216 if ((component & APPEARANCE_CHANGED) != 0) { 1217 Object[] arg = (Object[])objs[3]; 1218 int val = ((Integer)arg[1]).intValue(); 1219 for ( i = msArr.length-1; i >=0; i--) { 1220 msArr[i].appearance = (AppearanceRetained)arg[0]; 1221 msArr[i].changedFrequent = val; 1222 } 1223 } 1224 if ((component & APPEARANCEOVERRIDE_CHANGED) != 0) { 1225 Object[] arg = (Object[])objs[3]; 1226 int val = ((Integer)arg[1]).intValue(); 1227 System.err.println("ChangedFrequent = "+changedFrequent); 1228 for ( i = msArr.length-1; i >=0; i--) { 1229 msArr[i].appearanceOverrideEnable = ((Boolean)arg[0]).booleanValue(); 1230 msArr[i].changedFrequent = val; 1231 } 1232 } 1233 } 1234 1235 /** 1236 * assign a name to this node when it is made live. 1237 */ setLive(SetLiveState s)1238 void setLive(SetLiveState s) { 1239 int i, j; 1240 Shape3DRetained shape; 1241 ArrayList msList = new ArrayList(); 1242 GeometryAtom ga; 1243 int oldrefCount = refCount; 1244 1245 super.doSetLive(s); 1246 nodeId = universe.getNodeId(); 1247 1248 1249 for (i = 0; i < numGeometryArrays; i++) { 1250 synchronized(geometryArrays[i].liveStateLock) { 1251 geometryArrays[i].setLive(inBackgroundGroup, s.refCount); 1252 // Add this morph object as user the first time 1253 if (oldrefCount <= 0) { 1254 geometryArrays[i].addMorphUser(this); 1255 } 1256 } 1257 } 1258 1259 if (this.morphedGeometryArray == null){ 1260 initMorphedGeometry(); 1261 1262 } 1263 ((GeometryArrayRetained)(morphedGeometryArray.retained)).setLive(inBackgroundGroup, s.refCount); 1264 1265 if (boundsAutoCompute) { 1266 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 1267 // Compute the bounds once 1268 mga.incrComputeGeoBounds(); // This compute the bbox if dirty 1269 mga.decrComputeGeoBounds(); 1270 localBounds.setWithLock(mga.geoBounds); 1271 } 1272 1273 1274 if (inSharedGroup) { 1275 for (i=0; i<s.keys.length; i++) { 1276 shape = new Shape3DRetained(); 1277 shape.key = s.keys[i]; 1278 shape.localToVworld = new Transform3D[1][]; 1279 shape.localToVworldIndex = new int[1][]; 1280 1281 1282 j = s.keys[i].equals(localToVworldKeys, 0, 1283 localToVworldKeys.length); 1284 if(j < 0) { 1285 System.err.println("MorphRetained : Can't find hashKey"); 1286 } 1287 1288 shape.localToVworld[0] = localToVworld[j]; 1289 shape.localToVworldIndex[0] = localToVworldIndex[j]; 1290 shape.branchGroupPath = (BranchGroupRetained []) branchGroupPaths.get(j); 1291 shape.isPickable = s.pickable[i]; 1292 shape.isCollidable = s.collidable[i]; 1293 1294 shape.initMirrorShape3D(s, this, j); 1295 mirrorShape3D.add(j, shape); 1296 1297 msList.add(shape); 1298 // Add any scoped lights to the mirror shape 1299 if (s.lights != null) { 1300 ArrayList l = (ArrayList)s.lights.get(j); 1301 if (l != null) { 1302 for (int m = 0; m < l.size(); m++) { 1303 shape.addLight((LightRetained)l.get(m)); 1304 } 1305 } 1306 } 1307 1308 // Add any scoped fog 1309 if (s.fogs != null) { 1310 ArrayList l = (ArrayList)s.fogs.get(j); 1311 if (l != null) { 1312 for (int m = 0; m < l.size(); m++) { 1313 shape.addFog((FogRetained)l.get(m)); 1314 } 1315 } 1316 } 1317 1318 // Add any scoped modelClip 1319 if (s.modelClips != null) { 1320 ArrayList l = (ArrayList)s.modelClips.get(j); 1321 if (l != null) { 1322 for (int m = 0; m < l.size(); m++) { 1323 shape.addModelClip((ModelClipRetained)l.get(m)); 1324 } 1325 } 1326 } 1327 1328 // Add any scoped alt app 1329 if (s.altAppearances != null) { 1330 ArrayList l = (ArrayList)s.altAppearances.get(j); 1331 if (l != null) { 1332 for (int m = 0; m < l.size(); m++) { 1333 shape.addAltApp((AlternateAppearanceRetained)l.get(m)); 1334 } 1335 } 1336 } 1337 1338 if (s.viewLists != null) 1339 shape.viewList = (ArrayList)s.viewLists.get(i); 1340 else 1341 shape.viewList = null; 1342 1343 // ((GeometryArrayRetained)(morphedGeometryArray.retained)).addUser(shape); 1344 1345 1346 ga = Shape3DRetained.getGeomAtom(shape); 1347 1348 // Add the geometry atom for this shape to the Targets 1349 s.nodeList.add(ga); 1350 1351 if (s.transformTargets != null && 1352 s.transformTargets[i] != null) { 1353 s.transformTargets[i].addNode(ga, Targets.GEO_TARGETS); 1354 } 1355 if (s.switchTargets != null && 1356 s.switchTargets[i] != null) { 1357 s.switchTargets[i].addNode(shape, Targets.GEO_TARGETS); 1358 shape.closestSwitchParent = s.closestSwitchParents[i]; 1359 shape.closestSwitchIndex = s.closestSwitchIndices[i]; 1360 } 1361 shape.switchState = (SwitchState)s.switchStates.get(j); 1362 1363 } 1364 } else { 1365 shape = new Shape3DRetained(); 1366 shape.localToVworld = new Transform3D[1][]; 1367 shape.localToVworldIndex = new int[1][]; 1368 shape.localToVworld[0] = this.localToVworld[0]; 1369 shape.localToVworldIndex[0] = this.localToVworldIndex[0]; 1370 shape.branchGroupPath = (BranchGroupRetained []) branchGroupPaths.get(0); 1371 shape.isPickable = s.pickable[0]; 1372 shape.isCollidable = s.collidable[0]; 1373 shape.initMirrorShape3D(s, this, 0); 1374 mirrorShape3D.add(shape); 1375 1376 msList.add(shape); 1377 // Add any scoped lights to the mirror shape 1378 if (s.lights != null) { 1379 ArrayList l = (ArrayList)s.lights.get(0); 1380 if (l != null) { 1381 for (int m = 0; m < l.size(); m++) { 1382 shape.addLight((LightRetained)l.get(m)); 1383 } 1384 } 1385 } 1386 1387 // Add any scoped fog 1388 if (s.fogs != null) { 1389 ArrayList l = (ArrayList)s.fogs.get(0); 1390 if (l != null) { 1391 for (int m = 0; m < l.size(); m++) { 1392 shape.addFog((FogRetained)l.get(m)); 1393 } 1394 } 1395 } 1396 1397 // Add any scoped modelClip 1398 if (s.modelClips != null) { 1399 ArrayList l = (ArrayList)s.modelClips.get(0); 1400 if (l != null) { 1401 for (int m = 0; m < l.size(); m++) { 1402 shape.addModelClip((ModelClipRetained)l.get(m)); 1403 } 1404 } 1405 } 1406 1407 // Add any scoped alt app 1408 if (s.altAppearances != null) { 1409 ArrayList l = (ArrayList)s.altAppearances.get(0); 1410 if (l != null) { 1411 for (int m = 0; m < l.size(); m++) { 1412 shape.addAltApp((AlternateAppearanceRetained)l.get(m)); 1413 } 1414 } 1415 } 1416 1417 if (s.viewLists != null) 1418 shape.viewList = (ArrayList)s.viewLists.get(0); 1419 else 1420 shape.viewList = null; 1421 1422 // ((GeometryArrayRetained)(morphedGeometryArray.retained)).addUser(shape); 1423 1424 ga = Shape3DRetained.getGeomAtom(shape); 1425 1426 // Add the geometry atom for this shape to the Targets 1427 s.nodeList.add(ga); 1428 1429 if (s.transformTargets != null && 1430 s.transformTargets[0] != null) { 1431 s.transformTargets[0].addNode(ga, Targets.GEO_TARGETS); 1432 } 1433 if (s.switchTargets != null && 1434 s.switchTargets[0] != null) { 1435 s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS); 1436 shape.closestSwitchParent = s.closestSwitchParents[0]; 1437 shape.closestSwitchIndex = s.closestSwitchIndices[0]; 1438 } 1439 shape.switchState = (SwitchState)s.switchStates.get(0); 1440 } 1441 if (appearance != null) { 1442 synchronized(appearance.liveStateLock) { 1443 appearance.setLive(inBackgroundGroup, s.refCount); 1444 appearance.initMirrorObject(); 1445 if (appearance.renderingAttributes != null) 1446 visible = appearance.renderingAttributes.visible; 1447 for (int k = 0; k < msList.size(); k++) { 1448 Shape3DRetained sh = (Shape3DRetained)msList.get(k); 1449 sh.appearance = (AppearanceRetained)appearance.mirror; 1450 appearance.addAMirrorUser(sh); 1451 } 1452 } 1453 1454 } 1455 else { 1456 for (int k = 0; k < msList.size(); k++) { 1457 Shape3DRetained sh = (Shape3DRetained)msList.get(k); 1458 sh.appearance = null; 1459 } 1460 } 1461 1462 s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY | 1463 J3dThread.UPDATE_TRANSFORM | 1464 J3dThread.UPDATE_RENDER | 1465 J3dThread.UPDATE_RENDERING_ATTRIBUTES); 1466 1467 // Need to clone the geometry , if its indexed ... 1468 if (refCount == 1 && this.geometryArrays[0] instanceof IndexedGeometryArrayRetained) { 1469 J3dMessage mChangeMessage = new J3dMessage(); 1470 mChangeMessage.type = J3dMessage.MORPH_CHANGED; 1471 mChangeMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; 1472 mChangeMessage.args[0] = this; 1473 mChangeMessage.args[1]= new Integer(GEOMETRY_CHANGED); 1474 mChangeMessage.universe = universe; 1475 VirtualUniverse.mc.processMessage(mChangeMessage); 1476 } 1477 super.markAsLive(); 1478 1479 } 1480 1481 1482 /** 1483 * assign a name to this node when it is made live. 1484 */ clearLive(SetLiveState s)1485 void clearLive(SetLiveState s) { 1486 int i, j; 1487 Shape3DRetained shape; 1488 Object[] shapes; 1489 ArrayList appList = new ArrayList(); 1490 GeometryAtom ga; 1491 1492 super.clearLive(s); 1493 1494 for (i = 0; i < numGeometryArrays; i++) { 1495 synchronized(geometryArrays[i].liveStateLock) { 1496 geometryArrays[i].clearLive(s.refCount); 1497 // Remove this morph object as user, when the last branch 1498 // is clearlived 1499 if (refCount <= 0) { 1500 geometryArrays[i].removeMorphUser(this); 1501 } 1502 } 1503 } 1504 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 1505 1506 mga.clearLive( s.refCount); 1507 1508 if (inSharedGroup) { 1509 shapes = mirrorShape3D.toArray(); 1510 for (i=0; i<s.keys.length; i++) { 1511 for (j=0; j<shapes.length; j++) { 1512 shape = (Shape3DRetained)shapes[j]; 1513 if (shape.key.equals(s.keys[i])) { 1514 // clearMirrorShape(shape); 1515 mirrorShape3D.remove(j); 1516 if (s.switchTargets != null && 1517 s.switchTargets[i] != null) { 1518 s.switchTargets[i].addNode(shape, 1519 Targets.GEO_TARGETS); 1520 } 1521 if (appearance != null) 1522 appList.add(shape); 1523 1524 // ((GeometryArrayRetained)(morphedGeometryArray.retained)).removeUser(shape); 1525 ga = Shape3DRetained.getGeomAtom(shape); 1526 1527 // Add the geometry atoms for this shape to the Targets 1528 s.nodeList.add(ga); 1529 if (s.transformTargets != null && 1530 s.transformTargets[i] != null) { 1531 s.transformTargets[i].addNode(ga, 1532 Targets.GEO_TARGETS); 1533 } 1534 } 1535 } 1536 } 1537 } else { 1538 // Only entry 0 is valid 1539 shape = (Shape3DRetained)mirrorShape3D.get(0); 1540 // clearMirrorShape(shape); 1541 mirrorShape3D.remove(0); 1542 if (s.switchTargets != null && 1543 s.switchTargets[0] != null) { 1544 s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS); 1545 } 1546 if (appearance != null) 1547 appList.add(shape); 1548 1549 // ((GeometryArrayRetained)(morphedGeometryArray.retained)).removeUser(shape); 1550 ga = Shape3DRetained.getGeomAtom(shape); 1551 1552 // Add the geometry atom for this shape to the Targets 1553 s.nodeList.add(ga); 1554 if (s.transformTargets != null && 1555 s.transformTargets[0] != null) { 1556 s.transformTargets[0].addNode(ga, Targets.GEO_TARGETS); 1557 } 1558 } 1559 if (appearance != null) { 1560 synchronized(appearance.liveStateLock) { 1561 appearance.clearLive(s.refCount); 1562 for (int k = 0; k < appList.size(); k++) { 1563 appearance.removeAMirrorUser((Shape3DRetained)appList.get(k)); 1564 } 1565 } 1566 } 1567 1568 s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY | 1569 J3dThread.UPDATE_TRANSFORM | 1570 // This is used to clear the scope info 1571 // of all the mirror shapes 1572 J3dThread.UPDATE_RENDERING_ENVIRONMENT | 1573 J3dThread.UPDATE_RENDER); 1574 1575 } 1576 1577 updatePickable(HashKey keys[], boolean pick[])1578 void updatePickable(HashKey keys[], boolean pick[]) { 1579 super.updatePickable(keys, pick); 1580 1581 Shape3DRetained shape; 1582 1583 if (!inSharedGroup) { 1584 shape = (Shape3DRetained) mirrorShape3D.get(0); 1585 shape.isPickable = pick[0]; 1586 } else { 1587 int size = mirrorShape3D.size(); 1588 for (int j=0; j< keys.length; j++) { 1589 for (int i=0; i < size; i++) { 1590 shape = (Shape3DRetained) mirrorShape3D.get(i); 1591 if (keys[j].equals(shape.key)) { 1592 shape.isPickable = pick[j]; 1593 break; 1594 } 1595 1596 } 1597 } 1598 } 1599 } 1600 1601 updateCollidable(HashKey keys[], boolean collide[])1602 void updateCollidable(HashKey keys[], boolean collide[]) { 1603 super.updateCollidable(keys, collide); 1604 Shape3DRetained shape; 1605 1606 if (!inSharedGroup) { 1607 shape = (Shape3DRetained) mirrorShape3D.get(0); 1608 shape.isCollidable = collide[0]; 1609 } else { 1610 int size = mirrorShape3D.size(); 1611 for (int j=0; j< keys.length; j++) { 1612 for (int i=0; i < size; i++) { 1613 shape = (Shape3DRetained) mirrorShape3D.get(i); 1614 if (keys[j].equals(shape.key)) { 1615 shape.isCollidable = collide[j]; 1616 break; 1617 } 1618 1619 } 1620 } 1621 } 1622 } 1623 getMirrorShape(SceneGraphPath path)1624 Shape3DRetained getMirrorShape(SceneGraphPath path) { 1625 if (!inSharedGroup) { 1626 return (Shape3DRetained) mirrorShape3D.get(0); 1627 } 1628 HashKey key = new HashKey(""); 1629 path.getHashKey(key); 1630 return getMirrorShape(key); 1631 } 1632 getMirrorShape(HashKey key)1633 Shape3DRetained getMirrorShape(HashKey key) { 1634 int i = key.equals(localToVworldKeys, 0, localToVworldKeys.length); 1635 if (i>=0) { 1636 return (Shape3DRetained) mirrorShape3D.get(i); 1637 } 1638 1639 // Not possible 1640 throw new RuntimeException("Shape3DRetained: MirrorShape Not found!"); 1641 } 1642 getMirrorObjects(ArrayList leafList, HashKey key)1643 void getMirrorObjects(ArrayList leafList, HashKey key) { 1644 Shape3DRetained ms; 1645 if (inSharedGroup) { 1646 ms = getMirrorShape(key); 1647 } 1648 else { 1649 ms = (Shape3DRetained)mirrorShape3D.get(0); 1650 } 1651 GeometryAtom ga = Shape3DRetained.getGeomAtom(ms); 1652 leafList.add(ga); 1653 1654 } 1655 setBoundsAutoCompute(boolean autoCompute)1656 void setBoundsAutoCompute(boolean autoCompute) { 1657 if (autoCompute != boundsAutoCompute) { 1658 if (autoCompute) { 1659 // localBounds may not have been set to bbox 1660 localBounds = new BoundingBox(); 1661 if (source.isLive() && morphedGeometryArray != null) { 1662 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 1663 mga.incrComputeGeoBounds(); // This compute the bbox if dirty 1664 mga.decrComputeGeoBounds(); 1665 } 1666 } 1667 1668 1669 localBounds = getBounds(); 1670 super.setBoundsAutoCompute(autoCompute); 1671 if (source.isLive()) { 1672 J3dMessage message = new J3dMessage(); 1673 message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; 1674 message.threads = J3dThread.UPDATE_TRANSFORM | 1675 J3dThread.UPDATE_GEOMETRY | 1676 J3dThread.UPDATE_RENDER; 1677 message.universe = universe; 1678 message.args[0] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 1679 message.args[1] = localBounds; 1680 VirtualUniverse.mc.processMessage(message); 1681 } 1682 } 1683 } 1684 updateBounds()1685 void updateBounds() { 1686 localBounds = getEffectiveBounds(); 1687 if (source.isLive()) { 1688 J3dMessage message = new J3dMessage(); 1689 message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED; 1690 message.threads = J3dThread.UPDATE_TRANSFORM | 1691 J3dThread.UPDATE_GEOMETRY | 1692 J3dThread.UPDATE_RENDER; 1693 message.universe = universe; 1694 message.args[0] = Shape3DRetained.getGeomAtomsArray(mirrorShape3D); 1695 message.args[1] = localBounds; 1696 VirtualUniverse.mc.processMessage(message); 1697 } 1698 } 1699 1700 /** 1701 * Initialization of morphed geometry 1702 */ initMorphedGeometry()1703 void initMorphedGeometry() { 1704 int vFormat, geoType, stripVCount[]; 1705 int iCount = 0; 1706 int numStrips = 0; 1707 int texCoordSetCount = 0; 1708 int texCoordSetMapLen = 0; 1709 int [] texCoordSetMap = null; 1710 int k; 1711 GeometryArrayRetained geo = geometryArrays[0]; 1712 vFormat = ((geo.getVertexFormat() | (GeometryArray.BY_REFERENCE)) & ~(GeometryArray.INTERLEAVED)) ; 1713 texCoordSetCount = geo.getTexCoordSetCount(); 1714 texCoordSetMapLen = geo.getTexCoordSetMapLength(); 1715 if (texCoordSetMapLen > 0) { 1716 texCoordSetMap = new int[texCoordSetMapLen]; 1717 geo.getTexCoordSetMap(texCoordSetMap); 1718 } 1719 geoType = geo.geoType; 1720 1721 switch (geoType){ 1722 case GeometryRetained.GEO_TYPE_QUAD_SET: 1723 this.morphedGeometryArray = 1724 new QuadArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1725 texCoordSetMap); 1726 break; 1727 case GeometryRetained.GEO_TYPE_TRI_SET: 1728 this.morphedGeometryArray = 1729 new TriangleArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1730 texCoordSetMap); 1731 break; 1732 case GeometryRetained.GEO_TYPE_POINT_SET: 1733 this.morphedGeometryArray = 1734 new PointArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1735 texCoordSetMap); 1736 break; 1737 case GeometryRetained.GEO_TYPE_LINE_SET: 1738 this.morphedGeometryArray = 1739 new LineArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1740 texCoordSetMap); 1741 break; 1742 case GeometryRetained.GEO_TYPE_TRI_STRIP_SET: 1743 numStrips = ((TriangleStripArrayRetained)geo).getNumStrips(); 1744 stripVCount = new int[numStrips]; 1745 ((TriangleStripArrayRetained)geo).getStripVertexCounts(stripVCount); 1746 this.morphedGeometryArray = 1747 new TriangleStripArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1748 texCoordSetMap, stripVCount); 1749 break; 1750 case GeometryRetained.GEO_TYPE_TRI_FAN_SET: 1751 numStrips = ((TriangleFanArrayRetained)geo).getNumStrips(); 1752 stripVCount = new int[numStrips]; 1753 ((TriangleFanArrayRetained)geo).getStripVertexCounts(stripVCount); 1754 this.morphedGeometryArray = 1755 new TriangleFanArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1756 texCoordSetMap, stripVCount); 1757 break; 1758 case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: 1759 numStrips = ((LineStripArrayRetained)geo).getNumStrips(); 1760 stripVCount = new int[numStrips]; 1761 ((LineStripArrayRetained)geo).getStripVertexCounts(stripVCount); 1762 this.morphedGeometryArray = 1763 new LineStripArray(geometryArrays[0].validVertexCount, vFormat, texCoordSetCount, 1764 texCoordSetMap, stripVCount); 1765 break; 1766 1767 case GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET: 1768 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1769 this.morphedGeometryArray = 1770 new IndexedQuadArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1771 texCoordSetMap, iCount); 1772 break; 1773 case GeometryRetained.GEO_TYPE_INDEXED_TRI_SET: 1774 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1775 this.morphedGeometryArray = 1776 new IndexedTriangleArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1777 texCoordSetMap, iCount); 1778 break; 1779 case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: 1780 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1781 this.morphedGeometryArray = 1782 new IndexedPointArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1783 texCoordSetMap, iCount); 1784 break; 1785 case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET: 1786 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1787 this.morphedGeometryArray = 1788 new IndexedLineArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1789 texCoordSetMap, iCount); 1790 break; 1791 case GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET: 1792 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1793 numStrips = ((IndexedTriangleStripArrayRetained)geo).getNumStrips(); 1794 stripVCount = new int[numStrips]; 1795 ((IndexedTriangleStripArrayRetained)geo).getStripIndexCounts(stripVCount); 1796 this.morphedGeometryArray = 1797 new IndexedTriangleStripArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1798 texCoordSetMap, iCount, stripVCount);break; 1799 case GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET: 1800 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1801 numStrips = ((IndexedTriangleFanArrayRetained)geo).getNumStrips(); 1802 stripVCount = new int[numStrips]; 1803 ((IndexedTriangleFanArrayRetained)geo).getStripIndexCounts(stripVCount); 1804 this.morphedGeometryArray = 1805 new IndexedTriangleFanArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1806 texCoordSetMap, iCount, stripVCount);break; 1807 case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: 1808 iCount = ((IndexedGeometryArrayRetained)geo).getIndexCount(); 1809 numStrips = ((IndexedLineStripArrayRetained)geo).getNumStrips(); 1810 stripVCount = new int[numStrips]; 1811 ((IndexedLineStripArrayRetained)geo).getStripIndexCounts(stripVCount); 1812 this.morphedGeometryArray = 1813 new IndexedLineStripArray(geometryArrays[0].getNumCoordCount(), vFormat, texCoordSetCount, 1814 texCoordSetMap, iCount, stripVCount);break; 1815 } 1816 if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) { 1817 IndexedGeometryArrayRetained igeo = (IndexedGeometryArrayRetained) 1818 geometryArrays[0]; 1819 IndexedGeometryArray morphedGeo = (IndexedGeometryArray) 1820 morphedGeometryArray; 1821 if ((vFormat & GeometryArray.COORDINATES) != 0) { 1822 morphedGeo.setCoordinateIndices(0, igeo.indexCoord); 1823 } 1824 if ((vFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { 1825 if ((vFormat & GeometryArray.NORMALS) != 0) { 1826 morphedGeo.setNormalIndices(0, igeo.indexNormal); 1827 } 1828 if ((vFormat & GeometryArray.COLOR) != 0) { 1829 morphedGeo.setColorIndices(0, igeo.indexColor); 1830 } 1831 if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { 1832 for (k = 0; k < texCoordSetCount; k++) { 1833 morphedGeo.setTextureCoordinateIndices(k, 0, 1834 igeo.indexTexCoord[k]); 1835 } 1836 } 1837 } 1838 } 1839 this.morphedGeometryArray.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE); 1840 1841 GeometryArrayRetained mga = (GeometryArrayRetained)morphedGeometryArray.retained; 1842 mga.updateData(this); 1843 1844 1845 } 1846 getMirrorShape3D(ArrayList list, HashKey k)1847 void getMirrorShape3D(ArrayList list, HashKey k) { 1848 Shape3DRetained ms; 1849 if (inSharedGroup) { 1850 ms = getMirrorShape(k); 1851 } 1852 else { 1853 ms = (Shape3DRetained)mirrorShape3D.get(0); 1854 } 1855 list.add(ms); 1856 1857 } 1858 compile(CompileState compState)1859 void compile(CompileState compState) { 1860 1861 super.compile(compState); 1862 1863 // XXXX: for now keep the static transform in the parent tg 1864 compState.keepTG = true; 1865 1866 if (J3dDebug.devPhase && J3dDebug.debug) { 1867 compState.numMorphs++; 1868 } 1869 } 1870 doErrorCheck(GeometryArrayRetained prevGeo, GeometryArrayRetained geo)1871 void doErrorCheck(GeometryArrayRetained prevGeo, GeometryArrayRetained geo) { 1872 1873 // If indexed Geometry array check the entire list instead of just the vcount 1874 if ((prevGeo.vertexFormat != geo.vertexFormat) || 1875 (prevGeo.validVertexCount != geo.validVertexCount) || 1876 (prevGeo.geoType != geo.geoType) || 1877 (prevGeo.texCoordSetCount != geo.texCoordSetCount)) { 1878 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1879 } 1880 if (geo.getTexCoordSetMapLength() != prevGeo.getTexCoordSetMapLength()){ 1881 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1882 } 1883 int texCoordSetMapLen = geo.getTexCoordSetMapLength(); 1884 int[] prevSvc= prevGeo.texCoordSetMap; 1885 int[] svc= geo.texCoordSetMap; 1886 for (int k = 0; k < texCoordSetMapLen; k++) { 1887 if (prevSvc[k] != svc[k]) 1888 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1889 } 1890 1891 if (geo instanceof GeometryStripArrayRetained) { 1892 prevSvc= ((GeometryStripArrayRetained)prevGeo).stripVertexCounts; 1893 svc= ((GeometryStripArrayRetained)geo).stripVertexCounts; 1894 if (prevSvc.length != svc.length) 1895 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1896 for (int k = 0; k < prevSvc.length; k++) { 1897 if (prevSvc[k] != svc[k]) 1898 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1899 } 1900 } else if (geo instanceof IndexedGeometryArrayRetained) { 1901 if (((IndexedGeometryArrayRetained)prevGeo).validIndexCount != ((IndexedGeometryArrayRetained)geo).validIndexCount) 1902 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1903 1904 // If by reference, then all array lengths should be same 1905 if (geo.getNumCoordCount() != prevGeo.getNumCoordCount() || 1906 geo.getNumColorCount() != prevGeo.getNumColorCount() || 1907 geo.getNumNormalCount() != prevGeo.getNumNormalCount()) { 1908 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1909 } 1910 int texCoordSetCount = geo.getTexCoordSetCount(); 1911 for (int k = 0; k < texCoordSetCount; k++) { 1912 if (geo.getNumTexCoordCount(k) != prevGeo.getNumTexCoordCount(k)) { 1913 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1914 } 1915 } 1916 1917 if (geo instanceof IndexedGeometryStripArrayRetained) { 1918 prevSvc= ((IndexedGeometryStripArrayRetained)prevGeo).stripIndexCounts; 1919 svc= ((IndexedGeometryStripArrayRetained)geo).stripIndexCounts; 1920 if (prevSvc.length != svc.length) 1921 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1922 for (int k = 0; k < prevSvc.length; k++) { 1923 if (prevSvc[k] != svc[k]) 1924 throw new IllegalArgumentException(J3dI18N.getString("MorphRetained1")); 1925 } 1926 } 1927 } 1928 } 1929 handleFrequencyChange(int bit)1930 void handleFrequencyChange(int bit) { 1931 int mask = 0; 1932 if (bit == Morph.ALLOW_GEOMETRY_ARRAY_WRITE) { 1933 mask = GEOMETRY_CHANGED; 1934 } 1935 else if (bit == Morph.ALLOW_APPEARANCE_WRITE) { 1936 mask = APPEARANCE_CHANGED; 1937 } 1938 else if (bit == Morph.ALLOW_APPEARANCE_OVERRIDE_WRITE) { 1939 mask = APPEARANCEOVERRIDE_CHANGED; 1940 } 1941 if (mask != 0) { 1942 if (source.getCapabilityIsFrequent(bit)) 1943 changedFrequent |= mask; 1944 else if (!source.isLive()) { 1945 changedFrequent &= ~mask; 1946 } 1947 } 1948 } 1949 searchGeometryAtoms(UnorderList list)1950 void searchGeometryAtoms(UnorderList list) { 1951 list.add(Shape3DRetained.getGeomAtom( 1952 (Shape3DRetained) mirrorShape3D.get(0))); 1953 } 1954 } 1955 1956 1957 1958 1959 1960