0001: /*
0002: * $RCSfile: MorphRetained.java,v $
0003: *
0004: * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.10 $
0028: * $Date: 2008/02/28 20:17:26 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import javax.vecmath.*;
0035: import java.util.ArrayList;
0036: import java.util.Vector;
0037:
0038: /**
0039: * A morph leaf node consisting of geometery and appearance properties.
0040: */
0041:
0042: class MorphRetained extends LeafRetained implements GeometryUpdater {
0043:
0044: // These bits should match the Shape3D bits ...(Since the mirrors for
0045: // both are Shape3DRetained
0046: static final int GEOMETRY_CHANGED = 0x00001;
0047: static final int APPEARANCE_CHANGED = 0x00002;
0048: static final int COLLISION_CHANGED = 0x00004;
0049: static final int BOUNDS_CHANGED = 0x00008;
0050: static final int APPEARANCEOVERRIDE_CHANGED = 0x00010;
0051: static final int UPDATE_MORPH = 0x00020;
0052:
0053: private static final double TOLERANCE = 1.0e-4;
0054:
0055: /**
0056: * The mirror Shape3DRetained nodes for this object. There is one
0057: * mirror for each instance of this Shape3D node. If it is not in
0058: * a SharedGroup, only index 0 is valid.
0059: */
0060: ArrayList mirrorShape3D = new ArrayList();
0061:
0062: // Target threads to be notified when morph changes
0063: final static int targetThreads = (J3dThread.UPDATE_RENDER | J3dThread.UPDATE_GEOMETRY);
0064:
0065: /**
0066: * The appearance component of the morph node.
0067: */
0068: AppearanceRetained appearance = null;
0069:
0070: /**
0071: * The Geosets associated with the morph node.
0072: */
0073: GeometryArrayRetained geometryArrays[];
0074:
0075: private int numGeometryArrays = 0;
0076:
0077: /**
0078: * The weight vector the morph node.
0079: */
0080: double weights[];
0081:
0082: /**
0083: * Reference to the BranchGroup path of this mirror shape
0084: * This is used for picking only.
0085: */
0086: BranchGroupRetained branchGroupPath[];
0087:
0088: // cache value for picking in mirror shape.
0089: // True if all the node of the path from this to root are all pickable
0090: boolean isPickable = true;
0091:
0092: // cache value for collidable in mirror shape.
0093: // True if all the node of the path from this to root are all collidable
0094: boolean isCollidable = true;
0095:
0096: // closest switch parent
0097: SwitchRetained closestSwitchParent = null;
0098:
0099: // the child index from the closest switch parent
0100: int closestSwitchIndex = -1;
0101:
0102: // Is this Morph visible ? The default is true.
0103: boolean visible = true;
0104:
0105: // geometry Bounds in local coordinate
0106: Bounds bounds = null;
0107:
0108: // geometry Bounds in virtual world coordinate
0109: BoundingBox vwcBounds = new BoundingBox();
0110:
0111: // collision Bound in local coordinate
0112: Bounds collisionBound = null;
0113:
0114: // collision Bounds in virtual world coordinate
0115: Bounds collisionVwcBound = null;
0116:
0117: GeometryArray morphedGeometryArray = null;
0118:
0119: // Morph data
0120: float[] Mcoord = null;
0121: float[] Mcolor = null;
0122: float[] Mnormal = null;
0123: // First dimension is the coordSet, second dimenension is the vertex index
0124: // each vertex has 2 or 3floats
0125: float[][] MtexCoord = null;
0126:
0127: // Whether the normal appearance is overrided by the alternate app
0128: boolean appearanceOverrideEnable = false;
0129:
0130: int changedFrequent = 0;
0131:
0132: MorphRetained() {
0133: this .nodeType = NodeRetained.MORPH;
0134: localBounds = new BoundingBox();
0135: ((BoundingBox) localBounds).setLower(1.0, 1.0, 1.0);
0136: ((BoundingBox) localBounds).setUpper(-1.0, -1.0, -1.0);
0137: }
0138:
0139: /**
0140: * Sets the collision bounds of a node.
0141: * @param bounds the bounding object for the node
0142: */
0143: void setCollisionBounds(Bounds bounds) {
0144: if (bounds != null) {
0145: collisionBound = (Bounds) bounds.clone();
0146: } else {
0147: collisionBound = null;
0148: }
0149: if (source.isLive()) {
0150: // Notify Geometry Structure to set mirror shape collision
0151: // bound and check for collision
0152: J3dMessage message = new J3dMessage();
0153: message.type = J3dMessage.COLLISION_BOUND_CHANGED;
0154: message.threads = J3dThread.UPDATE_TRANSFORM;
0155: message.universe = universe;
0156: message.args[1] = collisionBound;
0157: VirtualUniverse.mc.processMessage(message);
0158: }
0159: }
0160:
0161: /**
0162: * Sets the geometric bounds of a node.
0163: * @param bounds the bounding object for the node
0164: */
0165: void setBounds(Bounds bounds) {
0166: super .setBounds(bounds);
0167: if (source.isLive() && !boundsAutoCompute) {
0168: J3dMessage message = new J3dMessage();
0169: message.type = J3dMessage.REGION_BOUND_CHANGED;
0170: message.threads = J3dThread.UPDATE_TRANSFORM
0171: | targetThreads;
0172: message.universe = universe;
0173: message.args[0] = Shape3DRetained
0174: .getGeomAtomsArray(mirrorShape3D);
0175: message.args[1] = localBounds;
0176: VirtualUniverse.mc.processMessage(message);
0177: }
0178: }
0179:
0180: /**
0181: * Gets the collision bounds of a node.
0182: * @return the node's bounding object
0183: */
0184: Bounds getCollisionBounds() {
0185: return (collisionBound == null ? null : (Bounds) collisionBound
0186: .clone());
0187: }
0188:
0189: /**
0190: * Sets the geometryArrays component of the Morph node.
0191: * @param geometryArrays the new vector of geometryArrays for the morph node
0192: */
0193: void setGeometryArrays(GeometryArray geometryArrays[]) {
0194: int i;
0195:
0196: if ((geometryArrays == null || geometryArrays.length == 0)
0197: && numGeometryArrays == 0)
0198: return;
0199:
0200: GeometryArrayRetained geo, prevGeo;
0201:
0202: if (numGeometryArrays != 0
0203: && (geometryArrays == null || numGeometryArrays != geometryArrays.length))
0204: throw new IllegalArgumentException(J3dI18N
0205: .getString("MorphRetained0"));
0206:
0207: for (i = 1; i < geometryArrays.length; i++) {
0208: if (geometryArrays[i] == null
0209: || geometryArrays[i - 1] == null)
0210: throw new IllegalArgumentException(J3dI18N
0211: .getString("MorphRetained1"));
0212: geo = (GeometryArrayRetained) geometryArrays[i].retained;
0213: prevGeo = (GeometryArrayRetained) geometryArrays[i - 1].retained;
0214: if (prevGeo == null || geo == null) {
0215: throw new IllegalArgumentException(J3dI18N
0216: .getString("MorphRetained1"));
0217:
0218: }
0219: doErrorCheck(prevGeo, geo);
0220: }
0221:
0222: // Check the first one for vertex attributes
0223: geo = (GeometryArrayRetained) geometryArrays[0].retained;
0224: if ((geo.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
0225: throw new UnsupportedOperationException(J3dI18N
0226: .getString("MorphRetained9"));
0227: }
0228:
0229: // Check if the first one is in Immediate context
0230: if (geometryArrays[0] != null) {
0231: geo = (GeometryArrayRetained) geometryArrays[0].retained;
0232: }
0233:
0234: if (numGeometryArrays == 0) {
0235: this .geometryArrays = new GeometryArrayRetained[geometryArrays.length];
0236: numGeometryArrays = geometryArrays.length;
0237: }
0238:
0239: for (i = 0; i < numGeometryArrays; i++) {
0240: geo = (GeometryArrayRetained) geometryArrays[i].retained;
0241: if (((Morph) this .source).isLive()) {
0242: if (this .geometryArrays[i] != null) {
0243: this .geometryArrays[i].clearLive(refCount);
0244: this .geometryArrays[i].removeMorphUser(this );
0245: }
0246: if (geo != null) {
0247: geo.setLive(inBackgroundGroup, refCount);
0248: geo.addMorphUser(this );
0249: }
0250: }
0251:
0252: this .geometryArrays[i] = geo;
0253: }
0254: if (this .geometryArrays[0] == null)
0255: return;
0256:
0257: if (weights == null) {
0258: weights = new double[numGeometryArrays];
0259: weights[0] = 1.0;
0260: int vFormat = this .geometryArrays[0].vertexFormat;
0261: // default is zero when new array
0262: //for (i=1; i < numGeometryArrays;i++) weights[i] = 0.0;
0263:
0264: int texCoordSetCount = this .geometryArrays[0]
0265: .getTexCoordSetCount();
0266: if (this .geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
0267: Mcoord = new float[this .geometryArrays[0]
0268: .getNumCoordCount() * 3];
0269:
0270: if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3)
0271: Mcolor = new float[this .geometryArrays[0]
0272: .getNumColorCount() * 3];
0273: else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4)
0274: Mcolor = new float[this .geometryArrays[0]
0275: .getNumColorCount() * 4];
0276:
0277: MtexCoord = new float[texCoordSetCount][];
0278: if ((vFormat & GeometryArray.NORMALS) != 0)
0279: Mnormal = new float[this .geometryArrays[0]
0280: .getNumNormalCount() * 3];
0281: for (int k = 0; k < texCoordSetCount; k++) {
0282: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
0283: MtexCoord[k] = new float[this .geometryArrays[0]
0284: .getNumTexCoordCount(k) * 2];
0285: else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0))
0286: MtexCoord[k] = new float[this .geometryArrays[0]
0287: .getNumTexCoordCount(k) * 3];
0288: else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0))
0289: MtexCoord[k] = new float[this .geometryArrays[0]
0290: .getNumTexCoordCount(k) * 4];
0291: }
0292: } else {
0293: Mcoord = new float[this .geometryArrays[0].validVertexCount * 3];
0294:
0295: if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
0296: Mcolor = new float[this .geometryArrays[0].validVertexCount * 3];
0297: } else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
0298: Mcolor = new float[this .geometryArrays[0].validVertexCount * 4];
0299: }
0300: MtexCoord = new float[texCoordSetCount][];
0301: if ((vFormat & GeometryArray.NORMALS) != 0) {
0302: Mnormal = new float[this .geometryArrays[0].validVertexCount * 3];
0303: }
0304: for (int k = 0; k < texCoordSetCount; k++) {
0305: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
0306: MtexCoord[k] = new float[this .geometryArrays[0].validVertexCount * 2];
0307: else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0))
0308: MtexCoord[k] = new float[this .geometryArrays[0].validVertexCount * 3];
0309: else if (((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0))
0310: MtexCoord[k] = new float[this .geometryArrays[0].validVertexCount * 4];
0311: }
0312: }
0313: }
0314:
0315: // create a new morphedGeometryArray
0316: initMorphedGeometry();
0317:
0318: if (source.isLive()) {
0319:
0320: Shape3DRetained shape = (Shape3DRetained) mirrorShape3D
0321: .get(0);
0322:
0323: shape.setMorphGeometry(morphedGeometryArray, mirrorShape3D);
0324:
0325: J3dMessage mChangeMessage = null;
0326: mChangeMessage = new J3dMessage();
0327: mChangeMessage.type = J3dMessage.MORPH_CHANGED;
0328: mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_TRANSFORM);
0329: // If its a indexed geometry array, unindexify in renderBin
0330: if (this .geometryArrays[0] instanceof IndexedGeometryArrayRetained)
0331: mChangeMessage.threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
0332: mChangeMessage.args[0] = this ;
0333: mChangeMessage.args[1] = new Integer(GEOMETRY_CHANGED);
0334: // a shadow copy of this ArrayList instance. (The elements themselves are not copied.)
0335: mChangeMessage.args[3] = Shape3DRetained
0336: .getGeomAtomsArray(mirrorShape3D);
0337: mChangeMessage.universe = universe;
0338: VirtualUniverse.mc.processMessage(mChangeMessage);
0339:
0340: if (boundsAutoCompute) {
0341: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
0342: // Compute the bounds once
0343: mga.incrComputeGeoBounds();// This compute the bbox if dirty
0344: mga.decrComputeGeoBounds();
0345: }
0346: }
0347:
0348: }
0349:
0350: /**
0351: * Retrieves the geometryArrays component of this Morph node.
0352: * @param index the index of GeometryArray to be returned
0353: * @return the geometryArray component of this morph node
0354: */
0355: GeometryArray getGeometryArray(int index) {
0356: return (GeometryArray) this .geometryArrays[index].source;
0357: }
0358:
0359: /**
0360: * Sets the appearance component of this Morph node.
0361: * @param appearance the new apearance component for this morph node
0362: */
0363: void setAppearance(Appearance newAppearance) {
0364: boolean visibleIsDirty = false;
0365:
0366: if (((Morph) this .source).isLive()) {
0367:
0368: if (appearance != null) {
0369: this .appearance.clearLive(refCount);
0370: for (int i = mirrorShape3D.size() - 1; i >= 0; i--) {
0371: this .appearance
0372: .removeAMirrorUser((Shape3DRetained) mirrorShape3D
0373: .get(i));
0374: }
0375: }
0376:
0377: if (newAppearance != null) {
0378: ((AppearanceRetained) newAppearance.retained).setLive(
0379: inBackgroundGroup, refCount);
0380: appearance = ((AppearanceRetained) newAppearance.retained);
0381: int size = mirrorShape3D.size();
0382: for (int i = 0; i < size; i++) {
0383: appearance
0384: .addAMirrorUser((Shape3DRetained) mirrorShape3D
0385: .get(i));
0386: }
0387: if ((appearance.renderingAttributes != null)
0388: && (visible != appearance.renderingAttributes.visible)) {
0389: visible = appearance.renderingAttributes.visible;
0390: visibleIsDirty = true;
0391: }
0392: } else {
0393: if (visible == false) {
0394: visible = true;
0395: visibleIsDirty = true;
0396: }
0397: }
0398:
0399: // Send a message
0400: int size = 0;
0401:
0402: if (visibleIsDirty)
0403: size = 2;
0404: else
0405: size = 1;
0406: J3dMessage[] createMessage = new J3dMessage[size];
0407: createMessage[0] = new J3dMessage();
0408: createMessage[0].threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
0409: | J3dThread.UPDATE_RENDER;
0410: createMessage[0].type = J3dMessage.MORPH_CHANGED;
0411: createMessage[0].universe = universe;
0412: createMessage[0].args[0] = this ;
0413: createMessage[0].args[1] = new Integer(APPEARANCE_CHANGED);
0414: Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D
0415: .size()];
0416: mirrorShape3D.toArray(s3dArr);
0417: createMessage[0].args[2] = s3dArr;
0418: Object[] obj = new Object[2];
0419: if (newAppearance == null) {
0420: obj[0] = null;
0421: } else {
0422: obj[0] = appearance.mirror;
0423: }
0424: obj[1] = new Integer(changedFrequent);
0425: createMessage[0].args[3] = obj;
0426: createMessage[0].args[4] = Shape3DRetained
0427: .getGeomAtomsArray(mirrorShape3D);
0428: if (visibleIsDirty) {
0429: createMessage[1] = new J3dMessage();
0430: createMessage[1].threads = J3dThread.UPDATE_GEOMETRY;
0431: createMessage[1].type = J3dMessage.SHAPE3D_CHANGED;
0432: createMessage[1].universe = universe;
0433: createMessage[1].args[0] = this ;
0434: createMessage[1].args[1] = new Integer(
0435: APPEARANCE_CHANGED);
0436: createMessage[1].args[2] = visible ? Boolean.TRUE
0437: : Boolean.FALSE;
0438: createMessage[1].args[3] = createMessage[0].args[4];
0439: }
0440: VirtualUniverse.mc.processMessage(createMessage);
0441: } else {
0442: if (newAppearance == null) {
0443: appearance = null;
0444: } else {
0445: appearance = (AppearanceRetained) newAppearance.retained;
0446: }
0447: }
0448: }
0449:
0450: /**
0451: * Retrieves the morph node's appearance component.
0452: * @return the morph node's appearance
0453: */
0454: Appearance getAppearance() {
0455: return (appearance == null ? null
0456: : (Appearance) this .appearance.source);
0457: }
0458:
0459: void setAppearanceOverrideEnable(boolean flag) {
0460: if (((Morph) this .source).isLive()) {
0461:
0462: // Send a message
0463: J3dMessage createMessage = new J3dMessage();
0464: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
0465: | J3dThread.UPDATE_RENDER;
0466: ;
0467: createMessage.type = J3dMessage.MORPH_CHANGED;
0468: createMessage.universe = universe;
0469: createMessage.args[0] = this ;
0470: createMessage.args[1] = new Integer(
0471: APPEARANCEOVERRIDE_CHANGED);
0472: Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D
0473: .size()];
0474: mirrorShape3D.toArray(s3dArr);
0475: createMessage.args[2] = s3dArr;
0476: Object[] obj = new Object[2];
0477: if (flag) {
0478: obj[0] = Boolean.TRUE;
0479: } else {
0480: obj[0] = Boolean.FALSE;
0481: }
0482: obj[1] = new Integer(changedFrequent);
0483: createMessage.args[3] = obj;
0484: createMessage.args[4] = Shape3DRetained
0485: .getGeomAtomsArray(mirrorShape3D);
0486: VirtualUniverse.mc.processMessage(createMessage);
0487: }
0488: appearanceOverrideEnable = flag;
0489: }
0490:
0491: boolean getAppearanceOverrideEnable() {
0492: return appearanceOverrideEnable;
0493: }
0494:
0495: boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags) {
0496:
0497: Transform3D localToVworld = pickInfo.getLocalToVWorldRef();
0498:
0499: Transform3D vworldToLocal = new Transform3D();
0500: vworldToLocal.invert(localToVworld);
0501: PickShape newPS = pickShape.transform(vworldToLocal);
0502:
0503: GeometryRetained geo = (GeometryRetained) (morphedGeometryArray.retained);
0504:
0505: if (geo.mirrorGeometry != null) {
0506: geo = geo.mirrorGeometry;
0507: }
0508:
0509: if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0)
0510: && ((flags & PickInfo.CLOSEST_DISTANCE) == 0)
0511: && ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0)
0512: && ((flags & PickInfo.ALL_GEOM_INFO) == 0)) {
0513: return geo.intersect(newPS, null, 0, null, null, 0);
0514: } else {
0515: Point3d closestIPnt = new Point3d();
0516: Point3d iPnt = new Point3d();
0517: Point3d iPntVW = new Point3d();
0518:
0519: if (geo.intersect(newPS, pickInfo, flags, iPnt, geo, 0)) {
0520:
0521: iPntVW.set(iPnt);
0522: localToVworld.transform(iPntVW);
0523: double distance = pickShape.distance(iPntVW);
0524:
0525: if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) {
0526: pickInfo.setClosestDistance(distance);
0527: }
0528: if ((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) {
0529: pickInfo.setClosestIntersectionPoint(iPnt);
0530: }
0531: return true;
0532: }
0533: }
0534: return false;
0535: }
0536:
0537: /**
0538: * Check if the geometry component of this shape node under path
0539: * intersects with the pickShape.
0540: * @return true if intersected else false. If return is true, dist
0541: * contains the closest distance of intersection if it is not
0542: * equal to null.
0543: */
0544: boolean intersect(SceneGraphPath path, PickShape pickShape,
0545: double[] dist) {
0546:
0547: // This method will not do bound intersect check, as it assume caller
0548: // has already done that. ( For performance and code simplification
0549: // reasons. )
0550:
0551: int flags;
0552: PickInfo pickInfo = new PickInfo();
0553:
0554: Transform3D localToVworld = path.getTransform();
0555: if (localToVworld == null) {
0556: throw new RuntimeException(J3dI18N
0557: .getString("MorphRetained5"));
0558: }
0559:
0560: pickInfo.setLocalToVWorldRef(localToVworld);
0561: //System.err.println("MorphRetained.intersect() : ");
0562: if (dist == null) {
0563: //System.err.println(" no dist request ....");
0564: return intersect(pickInfo, pickShape, 0);
0565: }
0566:
0567: flags = PickInfo.CLOSEST_DISTANCE;
0568: if (intersect(pickInfo, pickShape, flags)) {
0569: dist[0] = pickInfo.getClosestDistance();
0570: return true;
0571: }
0572:
0573: return false;
0574:
0575: }
0576:
0577: /**
0578: * Sets the Morph node's weight vector
0579: * @param wieghts the new vector of weights for the morph node
0580: */
0581: void setWeights(double weights[]) {
0582: int i;
0583: double sum = 0.0;
0584:
0585: if (weights.length != numGeometryArrays)
0586: throw new IllegalArgumentException(J3dI18N
0587: .getString("MorphRetained7"));
0588:
0589: for (i = weights.length - 1; i >= 0; i--) {
0590: sum += weights[i];
0591: }
0592:
0593: if (Math.abs(sum - 1.0) > TOLERANCE)
0594: throw new IllegalArgumentException(J3dI18N
0595: .getString("MorphRetained8"));
0596:
0597: // Weights array is ALWAYS malloced in setGeometryArrays method
0598: for (i = numGeometryArrays - 1; i >= 0; i--)
0599: this .weights[i] = weights[i];
0600:
0601: if (source.isLive()) {
0602: ((GeometryArrayRetained) morphedGeometryArray.retained)
0603: .updateData(this );
0604: J3dMessage mChangeMessage = null;
0605: mChangeMessage = new J3dMessage();
0606: mChangeMessage.type = J3dMessage.MORPH_CHANGED;
0607: mChangeMessage.threads = (J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_TRANSFORM);
0608: // If its a indexed geometry array, unindexify in renderBin
0609: if (this .geometryArrays[0] instanceof IndexedGeometryArrayRetained)
0610: mChangeMessage.threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
0611: mChangeMessage.args[0] = this ;
0612: mChangeMessage.args[1] = new Integer(GEOMETRY_CHANGED);
0613: mChangeMessage.args[3] = Shape3DRetained
0614: .getGeomAtomsArray(mirrorShape3D);
0615: mChangeMessage.universe = universe;
0616: VirtualUniverse.mc.processMessage(mChangeMessage);
0617: }
0618:
0619: }
0620:
0621: /**
0622: * Retrieves the Morph node's weight vector
0623: * @return the morph node's weight vector.
0624: */
0625: double[] getWeights() {
0626: return (double[]) weights.clone();
0627: }
0628:
0629: /**
0630: * Gets the bounding object of a node.
0631: * @return the node's bounding object
0632: */
0633: Bounds getBounds() {
0634: if (boundsAutoCompute) {
0635: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
0636: if (mga != null) {
0637: synchronized (mga.geoBounds) {
0638: return (Bounds) mga.geoBounds.clone();
0639: }
0640: } else {
0641: return null;
0642: }
0643: } else {
0644: return super .getBounds();
0645: }
0646: }
0647:
0648: Bounds getEffectiveBounds() {
0649: if (boundsAutoCompute) {
0650: return getBounds();
0651: } else {
0652: return super .getEffectiveBounds();
0653: }
0654: }
0655:
0656: /**
0657: * ONLY needed for SHAPE, MORPH, and LINK node type.
0658: * Compute the combine bounds of bounds and its localBounds.
0659: */
0660: void computeCombineBounds(Bounds bounds) {
0661:
0662: if (boundsAutoCompute) {
0663: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
0664: if (mga != null) {
0665: synchronized (mga.geoBounds) {
0666: bounds.combine((Bounds) mga.geoBounds);
0667: }
0668: }
0669: } else {
0670: // Should this be lock too ? ( MT safe ? )
0671: synchronized (localBounds) {
0672: bounds.combine((Bounds) localBounds);
0673: }
0674: }
0675: }
0676:
0677: // Return the number of geometry arrays in this MorphRetained object.
0678: int getNumGeometryArrays() {
0679: return numGeometryArrays;
0680: }
0681:
0682: // If the geometry of a morph changes, make sure that the
0683: // validVertexCount has not changed
0684: void updateMorphedGeometryArray(GeometryArrayRetained geo,
0685: boolean coordinatesChanged) {
0686: if (numGeometryArrays > 0) {
0687: // check if not the first geo, then compare with the first geometry
0688: if (geometryArrays[0] != geo) {
0689: doErrorCheck(geo, geometryArrays[0]);
0690: } else {
0691: // if first geo, compare with the second geo
0692: if (numGeometryArrays > 1) {
0693: doErrorCheck(geo, geometryArrays[1]);
0694: }
0695:
0696: }
0697: }
0698:
0699: ((GeometryArrayRetained) morphedGeometryArray.retained)
0700: .updateData(this );
0701: // Compute the bounds once
0702: if (boundsAutoCompute && coordinatesChanged) {
0703: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
0704: mga.incrComputeGeoBounds(); // This compute the bbox if dirty
0705: mga.decrComputeGeoBounds();
0706: }
0707: }
0708:
0709: /**
0710: * Update GeometryArray computed by morphing input GeometryArrays
0711: * with weights
0712: */
0713: public void updateData(Geometry mga) {
0714:
0715: int i, j, k, vFormat, geoType, stripVCount[];
0716: int iCount = 0;
0717: int numStrips = 0;
0718: int texCoordSetCount = 0;
0719: float coord[] = new float[3], color[] = new float[4], normal[] = new float[3], texCoord[] = new float[3];
0720:
0721: vFormat = geometryArrays[0].vertexFormat;
0722: geoType = ((GeometryArrayRetained) geometryArrays[0]).geoType;
0723: texCoordSetCount = geometryArrays[0].getTexCoordSetCount();
0724:
0725: int vc = 0, nc = 0, cc = 0, n = 0;
0726: int count = 0;
0727: if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
0728: count = geometryArrays[0].getNumCoordCount();
0729: } else {
0730: count = geometryArrays[0].validVertexCount;
0731: }
0732:
0733: for (i = 0; i < count; i++) {
0734: Mcoord[vc++] = Mcoord[vc++] = Mcoord[vc++] = 0.0f;
0735: }
0736:
0737: if ((vFormat & GeometryArray.COLOR) != 0) {
0738: if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
0739: count = geometryArrays[0].getNumColorCount();
0740: } else {
0741: count = geometryArrays[0].validVertexCount;
0742: }
0743: for (i = 0; i < count; i++) {
0744: if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3)
0745: Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = 0.0f;
0746:
0747: else if ((vFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4)
0748: Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = Mcolor[cc++] = 0.0f;
0749: }
0750: }
0751:
0752: if ((vFormat & GeometryArray.NORMALS) != 0) {
0753: if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
0754: count = geometryArrays[0].getNumNormalCount();
0755: } else {
0756: count = geometryArrays[0].validVertexCount;
0757: }
0758: for (i = 0; i < count; i++) {
0759: Mnormal[nc++] = Mnormal[nc++] = Mnormal[nc++] = 0.0f;
0760: }
0761: }
0762:
0763: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
0764: for (k = 0; k < texCoordSetCount; k++) {
0765: if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
0766: count = geometryArrays[0].getNumTexCoordCount(k);
0767: } else {
0768: count = geometryArrays[0].validVertexCount;
0769: }
0770: int tcount = 0;
0771: for (i = 0; i < count; i++) {
0772: MtexCoord[k][tcount++] = MtexCoord[k][tcount++] = 0.0f;
0773: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
0774: MtexCoord[k][tcount++] = 0.0f;
0775: } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
0776: MtexCoord[k][tcount++] = 0.0f;
0777: MtexCoord[k][tcount++] = 0.0f;
0778: }
0779: }
0780: }
0781: }
0782: // If by copy, then ...
0783: if ((vFormat & GeometryArray.BY_REFERENCE) == 0) {
0784: count = 0;
0785: for (j = 0; j < numGeometryArrays; j++) {
0786: double w = weights[j];
0787: if (w != 0) {
0788: vc = 0;
0789: nc = 0;
0790: cc = 0;
0791: int initialVertex = 0;
0792: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0793: initialVertex = 0;
0794: count = geometryArrays[j].getNumCoordCount();
0795: } else {
0796: initialVertex = geometryArrays[j]
0797: .getInitialVertexIndex();
0798: count = geometryArrays[j].validVertexCount;
0799: }
0800: int endVertex = initialVertex + count;
0801: for (i = initialVertex; i < endVertex; i++) {
0802: geometryArrays[j].getCoordinate(i, coord);
0803: Mcoord[vc++] += coord[0] * w;
0804: Mcoord[vc++] += coord[1] * w;
0805: Mcoord[vc++] += coord[2] * w;
0806: }
0807:
0808: if ((vFormat & GeometryArray.COLOR) != 0) {
0809: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0810: count = geometryArrays[j]
0811: .getNumColorCount();
0812: }
0813: endVertex = initialVertex + count;
0814: for (i = initialVertex; i < endVertex; i++) {
0815: geometryArrays[j].getColor(i, color);
0816: Mcolor[cc++] += color[0] * w;
0817: Mcolor[cc++] += color[1] * w;
0818: Mcolor[cc++] += color[2] * w;
0819: if ((vFormat & GeometryArray.WITH_ALPHA) != 0)
0820: Mcolor[cc++] += color[3] * w;
0821: }
0822: }
0823: if ((vFormat & GeometryArray.NORMALS) != 0) {
0824: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0825: count = geometryArrays[j]
0826: .getNumNormalCount();
0827: }
0828: endVertex = initialVertex + count;
0829: for (i = initialVertex; i < endVertex; i++) {
0830: geometryArrays[j].getNormal(i, normal);
0831: Mnormal[nc++] += normal[0] * w;
0832: Mnormal[nc++] += normal[1] * w;
0833: Mnormal[nc++] += normal[2] * w;
0834: }
0835: }
0836:
0837: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
0838: for (k = 0; k < texCoordSetCount; k++) {
0839: int tcount = 0;
0840: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0841: count = geometryArrays[j]
0842: .getNumTexCoordCount(i);
0843: }
0844: endVertex = initialVertex + count;
0845: for (i = initialVertex; i < endVertex; i++) {
0846: geometryArrays[j].getTextureCoordinate(
0847: k, i, texCoord);
0848: MtexCoord[k][tcount++] += texCoord[0]
0849: * w;
0850: MtexCoord[k][tcount++] += texCoord[1]
0851: * w;
0852: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
0853: MtexCoord[k][tcount++] += texCoord[2]
0854: * w;
0855: } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
0856: MtexCoord[k][tcount++] += texCoord[2]
0857: * w;
0858: MtexCoord[k][tcount++] += texCoord[3]
0859: * w;
0860: }
0861: }
0862: }
0863: }
0864: }
0865: }
0866: } else {
0867: int vIndex, tIndex, cIndex, nIndex, tstride = 0, cstride = 0;
0868: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
0869: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
0870: tstride = 2;
0871: } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
0872: tstride = 3;
0873: } else {
0874: tstride = 4;
0875: }
0876: }
0877:
0878: if ((vFormat & GeometryArray.COLOR) != 0) {
0879: cstride = 3;
0880: if ((vFormat & GeometryArray.WITH_ALPHA) != 0)
0881: cstride = 4;
0882: }
0883:
0884: if ((vFormat & GeometryArray.INTERLEAVED) != 0) {
0885: float[] vdata;
0886: int stride;
0887:
0888: stride = geometryArrays[0].stride();
0889: int coffset = geometryArrays[0].colorOffset();
0890: int noffset = geometryArrays[0].normalOffset();
0891: int voffset = geometryArrays[0].coordinateOffset();
0892: int offset = 0;
0893:
0894: int initialVertex = 0;
0895: for (j = 0; j < numGeometryArrays; j++) {
0896: double w = weights[j];
0897: if (w != 0) {
0898: vc = 0;
0899: nc = 0;
0900: cc = 0;
0901: n = 0;
0902: vdata = geometryArrays[j]
0903: .getInterleavedVertices();
0904: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
0905: for (k = 0; k < texCoordSetCount; k++) {
0906: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0907: tIndex = 0;
0908: count = geometryArrays[j]
0909: .getNumCoordCount();
0910: } else {
0911: tIndex = geometryArrays[j]
0912: .getInitialVertexIndex();
0913: count = geometryArrays[j].validVertexCount;
0914: }
0915: offset = (tIndex * stride) + k
0916: * tstride;
0917: int tcount = 0;
0918: for (i = 0; i < count; i++, offset += stride) {
0919: MtexCoord[k][tcount++] += vdata[offset]
0920: * w;
0921: MtexCoord[k][tcount++] += vdata[offset + 1]
0922: * w;
0923: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
0924: MtexCoord[k][tcount++] += vdata[offset + 2]
0925: * w;
0926: } else if ((vFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
0927: MtexCoord[k][tcount++] += vdata[offset + 2]
0928: * w;
0929: MtexCoord[k][tcount++] += vdata[offset + 3]
0930: * w;
0931: }
0932: }
0933: }
0934:
0935: }
0936: if ((vFormat & GeometryArray.COLOR) != 0) {
0937: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0938: cIndex = 0;
0939: count = geometryArrays[j]
0940: .getNumCoordCount();
0941: } else {
0942: cIndex = geometryArrays[j]
0943: .getInitialVertexIndex();
0944: count = geometryArrays[j].validVertexCount;
0945: }
0946: offset = (cIndex * stride) + coffset;
0947: for (i = 0; i < count; i++, offset += stride) {
0948: Mcolor[cc++] += vdata[offset] * w;
0949: Mcolor[cc++] += vdata[offset + 1] * w;
0950: Mcolor[cc++] += vdata[offset + 2] * w;
0951: if ((vFormat & GeometryArray.WITH_ALPHA) != 0)
0952: Mcolor[cc++] += vdata[offset + 3]
0953: * w;
0954:
0955: }
0956: }
0957:
0958: if ((vFormat & GeometryArray.NORMALS) != 0) {
0959: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0960: nIndex = 0;
0961: count = geometryArrays[j]
0962: .getNumCoordCount();
0963: } else {
0964: nIndex = geometryArrays[j]
0965: .getInitialVertexIndex();
0966: count = geometryArrays[j].validVertexCount;
0967: }
0968: offset = (nIndex * stride) + noffset;
0969: for (i = 0; i < count; i++, offset += stride) {
0970: Mnormal[nc++] += vdata[offset] * w;
0971: Mnormal[nc++] += vdata[offset + 1] * w;
0972: Mnormal[nc++] += vdata[offset + 2] * w;
0973: }
0974: }
0975: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
0976: vIndex = 0;
0977: count = geometryArrays[j]
0978: .getNumCoordCount();
0979: } else {
0980: vIndex = geometryArrays[j]
0981: .getInitialVertexIndex();
0982: count = geometryArrays[j].validVertexCount;
0983: }
0984: offset = (vIndex * stride) + voffset;
0985: for (i = 0; i < count; i++, offset += stride) {
0986: Mcoord[vc++] += vdata[offset] * w;
0987: Mcoord[vc++] += vdata[offset + 1] * w;
0988: Mcoord[vc++] += vdata[offset + 2] * w;
0989:
0990: }
0991: }
0992: }
0993: } else {
0994: float byteToFloatScale = 1.0f / 255.0f;
0995: for (j = 0; j < numGeometryArrays; j++) {
0996: double w = weights[j];
0997: if (w != 0) {
0998: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
0999: switch ((geometryArrays[j].vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
1000: case GeometryArrayRetained.TF:
1001: for (k = 0; k < texCoordSetCount; k++) {
1002: float[] tf = geometryArrays[j]
1003: .getTexCoordRefFloat(k);
1004: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1005: tIndex = 0;
1006: count = geometryArrays[j]
1007: .getNumTexCoordCount(k);
1008: } else {
1009: tIndex = geometryArrays[j]
1010: .getInitialTexCoordIndex(k);
1011: count = geometryArrays[j].validVertexCount;
1012: }
1013: tIndex *= tstride;
1014: int tcount = 0;
1015: for (i = 0; i < count; i++) {
1016: MtexCoord[k][tcount++] += tf[tIndex++]
1017: * w;
1018: MtexCoord[k][tcount++] += tf[tIndex++]
1019: * w;
1020: if ((vFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)
1021: MtexCoord[k][tcount++] += tf[tIndex++]
1022: * w;
1023: }
1024: }
1025: break;
1026: case GeometryArrayRetained.T2F:
1027: for (k = 0; k < texCoordSetCount; k++) {
1028: int tcount = 0;
1029: float[] tf = geometryArrays[j]
1030: .getTexCoordRefFloat(k);
1031: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1032: tIndex = 0;
1033: count = geometryArrays[j]
1034: .getNumTexCoordCount(k);
1035: } else {
1036: tIndex = geometryArrays[j]
1037: .getInitialTexCoordIndex(k);
1038: count = geometryArrays[j].validVertexCount;
1039: }
1040: TexCoord2f[] t2f = geometryArrays[j]
1041: .getTexCoordRef2f(k);
1042: for (i = 0; i < count; i++, tIndex++) {
1043: MtexCoord[k][tcount++] += t2f[tIndex].x
1044: * w;
1045: MtexCoord[k][tcount++] += t2f[tIndex].y
1046: * w;
1047: }
1048: }
1049: break;
1050: case GeometryArrayRetained.T3F:
1051: for (k = 0; k < texCoordSetCount; k++) {
1052: int tcount = 0;
1053: TexCoord3f[] t3f = geometryArrays[j]
1054: .getTexCoordRef3f(k);
1055: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1056: tIndex = 0;
1057: count = geometryArrays[j]
1058: .getNumTexCoordCount(k);
1059: } else {
1060: tIndex = geometryArrays[j]
1061: .getInitialTexCoordIndex(k);
1062: count = geometryArrays[j].validVertexCount;
1063: }
1064: for (i = 0; i < count; i++, tIndex++) {
1065: MtexCoord[k][tcount++] += t3f[tIndex].x
1066: * w;
1067: MtexCoord[k][tcount++] += t3f[tIndex].y
1068: * w;
1069: MtexCoord[k][tcount++] += t3f[tIndex].z
1070: * w;
1071: }
1072: }
1073: break;
1074:
1075: }
1076: }
1077: if ((vFormat & GeometryArray.COLOR) != 0) {
1078: double val = byteToFloatScale * w;
1079: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1080: cIndex = 0;
1081: count = geometryArrays[j]
1082: .getNumColorCount();
1083: } else {
1084: cIndex = geometryArrays[j]
1085: .getInitialColorIndex();
1086: count = geometryArrays[j].validVertexCount;
1087: }
1088:
1089: switch ((geometryArrays[j].vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
1090: case GeometryArrayRetained.CF:
1091: float[] cf = geometryArrays[j]
1092: .getColorRefFloat();
1093: cc = 0;
1094: cIndex *= cstride;
1095: for (i = 0; i < count; i++) {
1096: Mcolor[cc++] += cf[cIndex++] * w;
1097: Mcolor[cc++] += cf[cIndex++] * w;
1098: Mcolor[cc++] += cf[cIndex++] * w;
1099: if ((vFormat & GeometryArray.WITH_ALPHA) != 0)
1100: Mcolor[cc++] += cf[cIndex++]
1101: * w;
1102: }
1103: break;
1104: case GeometryArrayRetained.CUB:
1105: byte[] cub = geometryArrays[j]
1106: .getColorRefByte();
1107: cc = 0;
1108: cIndex *= cstride;
1109: for (i = 0; i < count; i++) {
1110: Mcolor[cc++] += (cub[cIndex++] & 0xff)
1111: * val;
1112: Mcolor[cc++] += (cub[cIndex++] & 0xff)
1113: * val;
1114: Mcolor[cc++] += (cub[cIndex++] & 0xff)
1115: * val;
1116: if ((vFormat & GeometryArray.WITH_ALPHA) != 0)
1117: Mcolor[cc++] += (cub[cIndex++] & 0xff)
1118: * val;
1119: }
1120:
1121: break;
1122: case GeometryArrayRetained.C3F:
1123: Color3f[] c3f = geometryArrays[j]
1124: .getColorRef3f();
1125: cc = 0;
1126: for (i = 0; i < count; i++, cIndex++) {
1127: Mcolor[cc++] += c3f[cIndex].x * w;
1128: Mcolor[cc++] += c3f[cIndex].y * w;
1129: Mcolor[cc++] += c3f[cIndex].z * w;
1130: }
1131: break;
1132: case GeometryArrayRetained.C4F:
1133: Color4f[] c4f = geometryArrays[j]
1134: .getColorRef4f();
1135: cc = 0;
1136: for (i = 0; i < count; i++, cIndex++) {
1137: Mcolor[cc++] += c4f[cIndex].x * w;
1138: Mcolor[cc++] += c4f[cIndex].y * w;
1139: Mcolor[cc++] += c4f[cIndex].z * w;
1140: Mcolor[cc++] += c4f[cIndex].w * w;
1141: }
1142: break;
1143: case GeometryArrayRetained.C3UB:
1144: Color3b[] c3b = geometryArrays[j]
1145: .getColorRef3b();
1146: cc = 0;
1147: for (i = 0; i < count; i++, cIndex++) {
1148: Mcolor[cc++] += (c3b[cIndex].x & 0xff)
1149: * val;
1150: Mcolor[cc++] += (c3b[cIndex].y & 0xff)
1151: * val;
1152: Mcolor[cc++] += (c3b[cIndex].z & 0xff)
1153: * val;
1154: }
1155: break;
1156: case GeometryArrayRetained.C4UB:
1157: Color4b[] c4b = geometryArrays[j]
1158: .getColorRef4b();
1159: cc = 0;
1160: for (i = 0; i < count; i++, cIndex++) {
1161: Mcolor[cc++] += (c4b[cIndex].x & 0xff)
1162: * val;
1163: Mcolor[cc++] += (c4b[cIndex].y & 0xff)
1164: * val;
1165: Mcolor[cc++] += (c4b[cIndex].z & 0xff)
1166: * val;
1167: Mcolor[cc++] += (c4b[cIndex].w & 0xff)
1168: * val;
1169: }
1170: break;
1171:
1172: }
1173: }
1174: if ((vFormat & GeometryArray.NORMALS) != 0) {
1175: nc = 0;
1176: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1177: nIndex = 0;
1178: count = geometryArrays[j]
1179: .getNumNormalCount();
1180: } else {
1181: nIndex = geometryArrays[j]
1182: .getInitialNormalIndex();
1183: count = geometryArrays[j].validVertexCount;
1184: }
1185: switch ((geometryArrays[j].vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
1186: case GeometryArrayRetained.NF:
1187: float[] nf = geometryArrays[j]
1188: .getNormalRefFloat();
1189: nIndex *= 3;
1190: for (i = 0; i < count; i++) {
1191: Mnormal[nc++] += nf[nIndex++] * w;
1192: Mnormal[nc++] += nf[nIndex++] * w;
1193: Mnormal[nc++] += nf[nIndex++] * w;
1194: }
1195: break;
1196: case GeometryArrayRetained.N3F:
1197: Vector3f[] n3f = geometryArrays[j]
1198: .getNormalRef3f();
1199: for (i = 0; i < count; i++, nIndex++) {
1200: Mnormal[nc++] += n3f[nIndex].x * w;
1201: Mnormal[nc++] += n3f[nIndex].y * w;
1202: Mnormal[nc++] += n3f[nIndex].z * w;
1203: }
1204: break;
1205: }
1206: }
1207: // Handle vertices ..
1208: vc = 0;
1209: if (geometryArrays[j] instanceof IndexedGeometryArrayRetained) {
1210: vIndex = 0;
1211: count = geometryArrays[j]
1212: .getNumCoordCount();
1213: } else {
1214: vIndex = geometryArrays[j]
1215: .getInitialCoordIndex();
1216: count = geometryArrays[j].validVertexCount;
1217: }
1218: switch ((geometryArrays[j].vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
1219: case GeometryArrayRetained.PF:
1220: float[] pf = geometryArrays[j]
1221: .getCoordRefFloat();
1222: vIndex *= 3;
1223: for (i = 0; i < count; i++) {
1224: Mcoord[vc++] += pf[vIndex++] * w;
1225: Mcoord[vc++] += pf[vIndex++] * w;
1226: Mcoord[vc++] += pf[vIndex++] * w;
1227: }
1228: break;
1229: case GeometryArrayRetained.PD:
1230: double[] pd = geometryArrays[j]
1231: .getCoordRefDouble();
1232: vIndex *= 3;
1233: for (i = 0; i < count; i++) {
1234: Mcoord[vc++] += (float) pd[vIndex++]
1235: * w;
1236: Mcoord[vc++] += (float) pd[vIndex++]
1237: * w;
1238: Mcoord[vc++] += (float) pd[vIndex++]
1239: * w;
1240: }
1241: break;
1242: case GeometryArrayRetained.P3F:
1243: Point3f[] p3f = geometryArrays[j]
1244: .getCoordRef3f();
1245: for (i = 0; i < count; i++, vIndex++) {
1246: Mcoord[vc++] += p3f[vIndex].x * w;
1247: Mcoord[vc++] += p3f[vIndex].y * w;
1248: Mcoord[vc++] += p3f[vIndex].z * w;
1249: }
1250: break;
1251: case GeometryArrayRetained.P3D:
1252: Point3d[] p3d = geometryArrays[j]
1253: .getCoordRef3d();
1254: for (i = 0; i < count; i++, vIndex++) {
1255: Mcoord[vc++] += (float) p3d[vIndex].x
1256: * w;
1257: Mcoord[vc++] += (float) p3d[vIndex].y
1258: * w;
1259: Mcoord[vc++] += (float) p3d[vIndex].z
1260: * w;
1261: }
1262: break;
1263:
1264: }
1265:
1266: }
1267: }
1268: }
1269: }
1270:
1271: GeometryArrayRetained mgaR = (GeometryArrayRetained) mga.retained;
1272:
1273: mgaR.setCoordRefFloat(Mcoord);
1274:
1275: if ((vFormat & GeometryArray.COLOR) != 0)
1276: mgaR.setColorRefFloat(Mcolor);
1277:
1278: // *******Need to normalize normals
1279: if ((vFormat & GeometryArray.NORMALS) != 0)
1280: mgaR.setNormalRefFloat(Mnormal);
1281:
1282: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
1283: for (k = 0; k < texCoordSetCount; k++) {
1284: mgaR.setTexCoordRefFloat(k, MtexCoord[k]);
1285: }
1286: }
1287: }
1288:
1289: void updateImmediateMirrorObject(Object[] objs) {
1290: int i;
1291:
1292: int component = ((Integer) objs[1]).intValue();
1293: Shape3DRetained[] msArr = (Shape3DRetained[]) objs[2];
1294: if ((component & APPEARANCE_CHANGED) != 0) {
1295: Object[] arg = (Object[]) objs[3];
1296: int val = ((Integer) arg[1]).intValue();
1297: for (i = msArr.length - 1; i >= 0; i--) {
1298: msArr[i].appearance = (AppearanceRetained) arg[0];
1299: msArr[i].changedFrequent = val;
1300: }
1301: }
1302: if ((component & APPEARANCEOVERRIDE_CHANGED) != 0) {
1303: Object[] arg = (Object[]) objs[3];
1304: int val = ((Integer) arg[1]).intValue();
1305: System.err.println("ChangedFrequent = " + changedFrequent);
1306: for (i = msArr.length - 1; i >= 0; i--) {
1307: msArr[i].appearanceOverrideEnable = ((Boolean) arg[0])
1308: .booleanValue();
1309: msArr[i].changedFrequent = val;
1310: }
1311: }
1312: }
1313:
1314: /**
1315: * assign a name to this node when it is made live.
1316: */
1317: void setLive(SetLiveState s) {
1318: int i, j;
1319: Shape3DRetained shape;
1320: ArrayList msList = new ArrayList();
1321: GeometryAtom ga;
1322: int oldrefCount = refCount;
1323:
1324: super .doSetLive(s);
1325: nodeId = universe.getNodeId();
1326:
1327: for (i = 0; i < numGeometryArrays; i++) {
1328: synchronized (geometryArrays[i].liveStateLock) {
1329: geometryArrays[i]
1330: .setLive(inBackgroundGroup, s.refCount);
1331: // Add this morph object as user the first time
1332: if (oldrefCount <= 0) {
1333: geometryArrays[i].addMorphUser(this );
1334: }
1335: }
1336: }
1337:
1338: if (this .morphedGeometryArray == null) {
1339: initMorphedGeometry();
1340:
1341: }
1342: ((GeometryArrayRetained) (morphedGeometryArray.retained))
1343: .setLive(inBackgroundGroup, s.refCount);
1344:
1345: if (boundsAutoCompute) {
1346: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
1347: // Compute the bounds once
1348: mga.incrComputeGeoBounds(); // This compute the bbox if dirty
1349: mga.decrComputeGeoBounds();
1350: localBounds.setWithLock(mga.geoBounds);
1351: }
1352:
1353: if (inSharedGroup) {
1354: for (i = 0; i < s.keys.length; i++) {
1355: shape = new Shape3DRetained();
1356: shape.key = s.keys[i];
1357: shape.localToVworld = new Transform3D[1][];
1358: shape.localToVworldIndex = new int[1][];
1359:
1360: j = s.keys[i].equals(localToVworldKeys, 0,
1361: localToVworldKeys.length);
1362: if (j < 0) {
1363: System.err
1364: .println("MorphRetained : Can't find hashKey");
1365: }
1366:
1367: shape.localToVworld[0] = localToVworld[j];
1368: shape.localToVworldIndex[0] = localToVworldIndex[j];
1369: shape.branchGroupPath = (BranchGroupRetained[]) branchGroupPaths
1370: .get(j);
1371: shape.isPickable = s.pickable[i];
1372: shape.isCollidable = s.collidable[i];
1373:
1374: shape.initMirrorShape3D(s, this , j);
1375: mirrorShape3D.add(j, shape);
1376:
1377: msList.add(shape);
1378: // Add any scoped lights to the mirror shape
1379: if (s.lights != null) {
1380: ArrayList l = (ArrayList) s.lights.get(j);
1381: if (l != null) {
1382: for (int m = 0; m < l.size(); m++) {
1383: shape.addLight((LightRetained) l.get(m));
1384: }
1385: }
1386: }
1387:
1388: // Add any scoped fog
1389: if (s.fogs != null) {
1390: ArrayList l = (ArrayList) s.fogs.get(j);
1391: if (l != null) {
1392: for (int m = 0; m < l.size(); m++) {
1393: shape.addFog((FogRetained) l.get(m));
1394: }
1395: }
1396: }
1397:
1398: // Add any scoped modelClip
1399: if (s.modelClips != null) {
1400: ArrayList l = (ArrayList) s.modelClips.get(j);
1401: if (l != null) {
1402: for (int m = 0; m < l.size(); m++) {
1403: shape.addModelClip((ModelClipRetained) l
1404: .get(m));
1405: }
1406: }
1407: }
1408:
1409: // Add any scoped alt app
1410: if (s.altAppearances != null) {
1411: ArrayList l = (ArrayList) s.altAppearances.get(j);
1412: if (l != null) {
1413: for (int m = 0; m < l.size(); m++) {
1414: shape
1415: .addAltApp((AlternateAppearanceRetained) l
1416: .get(m));
1417: }
1418: }
1419: }
1420:
1421: if (s.viewLists != null)
1422: shape.viewList = (ArrayList) s.viewLists.get(i);
1423: else
1424: shape.viewList = null;
1425:
1426: // ((GeometryArrayRetained)(morphedGeometryArray.retained)).addUser(shape);
1427:
1428: ga = Shape3DRetained.getGeomAtom(shape);
1429:
1430: // Add the geometry atom for this shape to the Targets
1431: s.nodeList.add(ga);
1432:
1433: if (s.transformTargets != null
1434: && s.transformTargets[i] != null) {
1435: s.transformTargets[i].addNode(ga,
1436: Targets.GEO_TARGETS);
1437: }
1438: if (s.switchTargets != null
1439: && s.switchTargets[i] != null) {
1440: s.switchTargets[i].addNode(shape,
1441: Targets.GEO_TARGETS);
1442: shape.closestSwitchParent = s.closestSwitchParents[i];
1443: shape.closestSwitchIndex = s.closestSwitchIndices[i];
1444: }
1445: shape.switchState = (SwitchState) s.switchStates.get(j);
1446:
1447: }
1448: } else {
1449: shape = new Shape3DRetained();
1450: shape.localToVworld = new Transform3D[1][];
1451: shape.localToVworldIndex = new int[1][];
1452: shape.localToVworld[0] = this .localToVworld[0];
1453: shape.localToVworldIndex[0] = this .localToVworldIndex[0];
1454: shape.branchGroupPath = (BranchGroupRetained[]) branchGroupPaths
1455: .get(0);
1456: shape.isPickable = s.pickable[0];
1457: shape.isCollidable = s.collidable[0];
1458: shape.initMirrorShape3D(s, this , 0);
1459: mirrorShape3D.add(shape);
1460:
1461: msList.add(shape);
1462: // Add any scoped lights to the mirror shape
1463: if (s.lights != null) {
1464: ArrayList l = (ArrayList) s.lights.get(0);
1465: if (l != null) {
1466: for (int m = 0; m < l.size(); m++) {
1467: shape.addLight((LightRetained) l.get(m));
1468: }
1469: }
1470: }
1471:
1472: // Add any scoped fog
1473: if (s.fogs != null) {
1474: ArrayList l = (ArrayList) s.fogs.get(0);
1475: if (l != null) {
1476: for (int m = 0; m < l.size(); m++) {
1477: shape.addFog((FogRetained) l.get(m));
1478: }
1479: }
1480: }
1481:
1482: // Add any scoped modelClip
1483: if (s.modelClips != null) {
1484: ArrayList l = (ArrayList) s.modelClips.get(0);
1485: if (l != null) {
1486: for (int m = 0; m < l.size(); m++) {
1487: shape
1488: .addModelClip((ModelClipRetained) l
1489: .get(m));
1490: }
1491: }
1492: }
1493:
1494: // Add any scoped alt app
1495: if (s.altAppearances != null) {
1496: ArrayList l = (ArrayList) s.altAppearances.get(0);
1497: if (l != null) {
1498: for (int m = 0; m < l.size(); m++) {
1499: shape.addAltApp((AlternateAppearanceRetained) l
1500: .get(m));
1501: }
1502: }
1503: }
1504:
1505: if (s.viewLists != null)
1506: shape.viewList = (ArrayList) s.viewLists.get(0);
1507: else
1508: shape.viewList = null;
1509:
1510: // ((GeometryArrayRetained)(morphedGeometryArray.retained)).addUser(shape);
1511:
1512: ga = Shape3DRetained.getGeomAtom(shape);
1513:
1514: // Add the geometry atom for this shape to the Targets
1515: s.nodeList.add(ga);
1516:
1517: if (s.transformTargets != null
1518: && s.transformTargets[0] != null) {
1519: s.transformTargets[0].addNode(ga, Targets.GEO_TARGETS);
1520: }
1521: if (s.switchTargets != null && s.switchTargets[0] != null) {
1522: s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS);
1523: shape.closestSwitchParent = s.closestSwitchParents[0];
1524: shape.closestSwitchIndex = s.closestSwitchIndices[0];
1525: }
1526: shape.switchState = (SwitchState) s.switchStates.get(0);
1527: }
1528: if (appearance != null) {
1529: synchronized (appearance.liveStateLock) {
1530: appearance.setLive(inBackgroundGroup, s.refCount);
1531: appearance.initMirrorObject();
1532: if (appearance.renderingAttributes != null)
1533: visible = appearance.renderingAttributes.visible;
1534: for (int k = 0; k < msList.size(); k++) {
1535: Shape3DRetained sh = (Shape3DRetained) msList
1536: .get(k);
1537: sh.appearance = (AppearanceRetained) appearance.mirror;
1538: appearance.addAMirrorUser(sh);
1539: }
1540: }
1541:
1542: } else {
1543: for (int k = 0; k < msList.size(); k++) {
1544: Shape3DRetained sh = (Shape3DRetained) msList.get(k);
1545: sh.appearance = null;
1546: }
1547: }
1548:
1549: s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY
1550: | J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_RENDER | J3dThread.UPDATE_RENDERING_ATTRIBUTES);
1551:
1552: // Need to clone the geometry , if its indexed ...
1553: if (refCount == 1
1554: && this .geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
1555: J3dMessage mChangeMessage = new J3dMessage();
1556: mChangeMessage.type = J3dMessage.MORPH_CHANGED;
1557: mChangeMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
1558: mChangeMessage.args[0] = this ;
1559: mChangeMessage.args[1] = new Integer(GEOMETRY_CHANGED);
1560: mChangeMessage.universe = universe;
1561: VirtualUniverse.mc.processMessage(mChangeMessage);
1562: }
1563: super .markAsLive();
1564:
1565: }
1566:
1567: /**
1568: * assign a name to this node when it is made live.
1569: */
1570: void clearLive(SetLiveState s) {
1571: int i, j;
1572: Shape3DRetained shape;
1573: Object[] shapes;
1574: ArrayList appList = new ArrayList();
1575: GeometryAtom ga;
1576:
1577: super .clearLive(s);
1578:
1579: for (i = 0; i < numGeometryArrays; i++) {
1580: synchronized (geometryArrays[i].liveStateLock) {
1581: geometryArrays[i].clearLive(s.refCount);
1582: // Remove this morph object as user, when the last branch
1583: // is clearlived
1584: if (refCount <= 0) {
1585: geometryArrays[i].removeMorphUser(this );
1586: }
1587: }
1588: }
1589: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
1590:
1591: mga.clearLive(s.refCount);
1592:
1593: if (inSharedGroup) {
1594: shapes = mirrorShape3D.toArray();
1595: for (i = 0; i < s.keys.length; i++) {
1596: for (j = 0; j < shapes.length; j++) {
1597: shape = (Shape3DRetained) shapes[j];
1598: if (shape.key.equals(s.keys[i])) {
1599: // clearMirrorShape(shape);
1600: mirrorShape3D.remove(j);
1601: if (s.switchTargets != null
1602: && s.switchTargets[i] != null) {
1603: s.switchTargets[i].addNode(shape,
1604: Targets.GEO_TARGETS);
1605: }
1606: if (appearance != null)
1607: appList.add(shape);
1608:
1609: // ((GeometryArrayRetained)(morphedGeometryArray.retained)).removeUser(shape);
1610: ga = Shape3DRetained.getGeomAtom(shape);
1611:
1612: // Add the geometry atoms for this shape to the Targets
1613: s.nodeList.add(ga);
1614: if (s.transformTargets != null
1615: && s.transformTargets[i] != null) {
1616: s.transformTargets[i].addNode(ga,
1617: Targets.GEO_TARGETS);
1618: }
1619: }
1620: }
1621: }
1622: } else {
1623: // Only entry 0 is valid
1624: shape = (Shape3DRetained) mirrorShape3D.get(0);
1625: // clearMirrorShape(shape);
1626: mirrorShape3D.remove(0);
1627: if (s.switchTargets != null && s.switchTargets[0] != null) {
1628: s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS);
1629: }
1630: if (appearance != null)
1631: appList.add(shape);
1632:
1633: // ((GeometryArrayRetained)(morphedGeometryArray.retained)).removeUser(shape);
1634: ga = Shape3DRetained.getGeomAtom(shape);
1635:
1636: // Add the geometry atom for this shape to the Targets
1637: s.nodeList.add(ga);
1638: if (s.transformTargets != null
1639: && s.transformTargets[0] != null) {
1640: s.transformTargets[0].addNode(ga, Targets.GEO_TARGETS);
1641: }
1642: }
1643: if (appearance != null) {
1644: synchronized (appearance.liveStateLock) {
1645: appearance.clearLive(s.refCount);
1646: for (int k = 0; k < appList.size(); k++) {
1647: appearance
1648: .removeAMirrorUser((Shape3DRetained) appList
1649: .get(k));
1650: }
1651: }
1652: }
1653:
1654: s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY
1655: | J3dThread.UPDATE_TRANSFORM |
1656: // This is used to clear the scope info
1657: // of all the mirror shapes
1658: J3dThread.UPDATE_RENDERING_ENVIRONMENT | J3dThread.UPDATE_RENDER);
1659:
1660: }
1661:
1662: void updatePickable(HashKey keys[], boolean pick[]) {
1663: super .updatePickable(keys, pick);
1664:
1665: Shape3DRetained shape;
1666:
1667: if (!inSharedGroup) {
1668: shape = (Shape3DRetained) mirrorShape3D.get(0);
1669: shape.isPickable = pick[0];
1670: } else {
1671: int size = mirrorShape3D.size();
1672: for (int j = 0; j < keys.length; j++) {
1673: for (int i = 0; i < size; i++) {
1674: shape = (Shape3DRetained) mirrorShape3D.get(i);
1675: if (keys[j].equals(shape.key)) {
1676: shape.isPickable = pick[j];
1677: break;
1678: }
1679:
1680: }
1681: }
1682: }
1683: }
1684:
1685: void updateCollidable(HashKey keys[], boolean collide[]) {
1686: super .updateCollidable(keys, collide);
1687: Shape3DRetained shape;
1688:
1689: if (!inSharedGroup) {
1690: shape = (Shape3DRetained) mirrorShape3D.get(0);
1691: shape.isCollidable = collide[0];
1692: } else {
1693: int size = mirrorShape3D.size();
1694: for (int j = 0; j < keys.length; j++) {
1695: for (int i = 0; i < size; i++) {
1696: shape = (Shape3DRetained) mirrorShape3D.get(i);
1697: if (keys[j].equals(shape.key)) {
1698: shape.isCollidable = collide[j];
1699: break;
1700: }
1701:
1702: }
1703: }
1704: }
1705: }
1706:
1707: Shape3DRetained getMirrorShape(SceneGraphPath path) {
1708: if (!inSharedGroup) {
1709: return (Shape3DRetained) mirrorShape3D.get(0);
1710: }
1711: HashKey key = new HashKey("");
1712: path.getHashKey(key);
1713: return getMirrorShape(key);
1714: }
1715:
1716: Shape3DRetained getMirrorShape(HashKey key) {
1717: int i = key.equals(localToVworldKeys, 0,
1718: localToVworldKeys.length);
1719: if (i >= 0) {
1720: return (Shape3DRetained) mirrorShape3D.get(i);
1721: }
1722:
1723: // Not possible
1724: throw new RuntimeException(
1725: "Shape3DRetained: MirrorShape Not found!");
1726: }
1727:
1728: void getMirrorObjects(ArrayList leafList, HashKey key) {
1729: Shape3DRetained ms;
1730: if (inSharedGroup) {
1731: ms = getMirrorShape(key);
1732: } else {
1733: ms = (Shape3DRetained) mirrorShape3D.get(0);
1734: }
1735: GeometryAtom ga = Shape3DRetained.getGeomAtom(ms);
1736: leafList.add(ga);
1737:
1738: }
1739:
1740: void setBoundsAutoCompute(boolean autoCompute) {
1741: if (autoCompute != boundsAutoCompute) {
1742: if (autoCompute) {
1743: // localBounds may not have been set to bbox
1744: localBounds = new BoundingBox();
1745: if (source.isLive() && morphedGeometryArray != null) {
1746: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
1747: mga.incrComputeGeoBounds(); // This compute the bbox if dirty
1748: mga.decrComputeGeoBounds();
1749: }
1750: }
1751:
1752: localBounds = getBounds();
1753: super .setBoundsAutoCompute(autoCompute);
1754: if (source.isLive()) {
1755: J3dMessage message = new J3dMessage();
1756: message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED;
1757: message.threads = J3dThread.UPDATE_TRANSFORM
1758: | J3dThread.UPDATE_GEOMETRY
1759: | J3dThread.UPDATE_RENDER;
1760: message.universe = universe;
1761: message.args[0] = Shape3DRetained
1762: .getGeomAtomsArray(mirrorShape3D);
1763: message.args[1] = localBounds;
1764: VirtualUniverse.mc.processMessage(message);
1765: }
1766: }
1767: }
1768:
1769: void updateBounds() {
1770: localBounds = getEffectiveBounds();
1771: if (source.isLive()) {
1772: J3dMessage message = new J3dMessage();
1773: message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED;
1774: message.threads = J3dThread.UPDATE_TRANSFORM
1775: | J3dThread.UPDATE_GEOMETRY
1776: | J3dThread.UPDATE_RENDER;
1777: message.universe = universe;
1778: message.args[0] = Shape3DRetained
1779: .getGeomAtomsArray(mirrorShape3D);
1780: message.args[1] = localBounds;
1781: VirtualUniverse.mc.processMessage(message);
1782: }
1783: }
1784:
1785: /**
1786: * Initialization of morphed geometry
1787: */
1788: void initMorphedGeometry() {
1789: int vFormat, geoType, stripVCount[];
1790: int iCount = 0;
1791: int numStrips = 0;
1792: int texCoordSetCount = 0;
1793: int texCoordSetMapLen = 0;
1794: int[] texCoordSetMap = null;
1795: int k;
1796: GeometryArrayRetained geo = geometryArrays[0];
1797: vFormat = ((geo.getVertexFormat() | (GeometryArray.BY_REFERENCE)) & ~(GeometryArray.INTERLEAVED));
1798: texCoordSetCount = geo.getTexCoordSetCount();
1799: texCoordSetMapLen = geo.getTexCoordSetMapLength();
1800: if (texCoordSetMapLen > 0) {
1801: texCoordSetMap = new int[texCoordSetMapLen];
1802: geo.getTexCoordSetMap(texCoordSetMap);
1803: }
1804: geoType = geo.geoType;
1805:
1806: switch (geoType) {
1807: case GeometryRetained.GEO_TYPE_QUAD_SET:
1808: this .morphedGeometryArray = new QuadArray(
1809: geometryArrays[0].validVertexCount, vFormat,
1810: texCoordSetCount, texCoordSetMap);
1811: break;
1812: case GeometryRetained.GEO_TYPE_TRI_SET:
1813: this .morphedGeometryArray = new TriangleArray(
1814: geometryArrays[0].validVertexCount, vFormat,
1815: texCoordSetCount, texCoordSetMap);
1816: break;
1817: case GeometryRetained.GEO_TYPE_POINT_SET:
1818: this .morphedGeometryArray = new PointArray(
1819: geometryArrays[0].validVertexCount, vFormat,
1820: texCoordSetCount, texCoordSetMap);
1821: break;
1822: case GeometryRetained.GEO_TYPE_LINE_SET:
1823: this .morphedGeometryArray = new LineArray(
1824: geometryArrays[0].validVertexCount, vFormat,
1825: texCoordSetCount, texCoordSetMap);
1826: break;
1827: case GeometryRetained.GEO_TYPE_TRI_STRIP_SET:
1828: numStrips = ((TriangleStripArrayRetained) geo)
1829: .getNumStrips();
1830: stripVCount = new int[numStrips];
1831: ((TriangleStripArrayRetained) geo)
1832: .getStripVertexCounts(stripVCount);
1833: this .morphedGeometryArray = new TriangleStripArray(
1834: geometryArrays[0].validVertexCount, vFormat,
1835: texCoordSetCount, texCoordSetMap, stripVCount);
1836: break;
1837: case GeometryRetained.GEO_TYPE_TRI_FAN_SET:
1838: numStrips = ((TriangleFanArrayRetained) geo).getNumStrips();
1839: stripVCount = new int[numStrips];
1840: ((TriangleFanArrayRetained) geo)
1841: .getStripVertexCounts(stripVCount);
1842: this .morphedGeometryArray = new TriangleFanArray(
1843: geometryArrays[0].validVertexCount, vFormat,
1844: texCoordSetCount, texCoordSetMap, stripVCount);
1845: break;
1846: case GeometryRetained.GEO_TYPE_LINE_STRIP_SET:
1847: numStrips = ((LineStripArrayRetained) geo).getNumStrips();
1848: stripVCount = new int[numStrips];
1849: ((LineStripArrayRetained) geo)
1850: .getStripVertexCounts(stripVCount);
1851: this .morphedGeometryArray = new LineStripArray(
1852: geometryArrays[0].validVertexCount, vFormat,
1853: texCoordSetCount, texCoordSetMap, stripVCount);
1854: break;
1855:
1856: case GeometryRetained.GEO_TYPE_INDEXED_QUAD_SET:
1857: iCount = ((IndexedGeometryArrayRetained) geo)
1858: .getIndexCount();
1859: this .morphedGeometryArray = new IndexedQuadArray(
1860: geometryArrays[0].getNumCoordCount(), vFormat,
1861: texCoordSetCount, texCoordSetMap, iCount);
1862: break;
1863: case GeometryRetained.GEO_TYPE_INDEXED_TRI_SET:
1864: iCount = ((IndexedGeometryArrayRetained) geo)
1865: .getIndexCount();
1866: this .morphedGeometryArray = new IndexedTriangleArray(
1867: geometryArrays[0].getNumCoordCount(), vFormat,
1868: texCoordSetCount, texCoordSetMap, iCount);
1869: break;
1870: case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET:
1871: iCount = ((IndexedGeometryArrayRetained) geo)
1872: .getIndexCount();
1873: this .morphedGeometryArray = new IndexedPointArray(
1874: geometryArrays[0].getNumCoordCount(), vFormat,
1875: texCoordSetCount, texCoordSetMap, iCount);
1876: break;
1877: case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET:
1878: iCount = ((IndexedGeometryArrayRetained) geo)
1879: .getIndexCount();
1880: this .morphedGeometryArray = new IndexedLineArray(
1881: geometryArrays[0].getNumCoordCount(), vFormat,
1882: texCoordSetCount, texCoordSetMap, iCount);
1883: break;
1884: case GeometryRetained.GEO_TYPE_INDEXED_TRI_STRIP_SET:
1885: iCount = ((IndexedGeometryArrayRetained) geo)
1886: .getIndexCount();
1887: numStrips = ((IndexedTriangleStripArrayRetained) geo)
1888: .getNumStrips();
1889: stripVCount = new int[numStrips];
1890: ((IndexedTriangleStripArrayRetained) geo)
1891: .getStripIndexCounts(stripVCount);
1892: this .morphedGeometryArray = new IndexedTriangleStripArray(
1893: geometryArrays[0].getNumCoordCount(), vFormat,
1894: texCoordSetCount, texCoordSetMap, iCount,
1895: stripVCount);
1896: break;
1897: case GeometryRetained.GEO_TYPE_INDEXED_TRI_FAN_SET:
1898: iCount = ((IndexedGeometryArrayRetained) geo)
1899: .getIndexCount();
1900: numStrips = ((IndexedTriangleFanArrayRetained) geo)
1901: .getNumStrips();
1902: stripVCount = new int[numStrips];
1903: ((IndexedTriangleFanArrayRetained) geo)
1904: .getStripIndexCounts(stripVCount);
1905: this .morphedGeometryArray = new IndexedTriangleFanArray(
1906: geometryArrays[0].getNumCoordCount(), vFormat,
1907: texCoordSetCount, texCoordSetMap, iCount,
1908: stripVCount);
1909: break;
1910: case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET:
1911: iCount = ((IndexedGeometryArrayRetained) geo)
1912: .getIndexCount();
1913: numStrips = ((IndexedLineStripArrayRetained) geo)
1914: .getNumStrips();
1915: stripVCount = new int[numStrips];
1916: ((IndexedLineStripArrayRetained) geo)
1917: .getStripIndexCounts(stripVCount);
1918: this .morphedGeometryArray = new IndexedLineStripArray(
1919: geometryArrays[0].getNumCoordCount(), vFormat,
1920: texCoordSetCount, texCoordSetMap, iCount,
1921: stripVCount);
1922: break;
1923: }
1924: if (geometryArrays[0] instanceof IndexedGeometryArrayRetained) {
1925: IndexedGeometryArrayRetained igeo = (IndexedGeometryArrayRetained) geometryArrays[0];
1926: IndexedGeometryArray morphedGeo = (IndexedGeometryArray) morphedGeometryArray;
1927: if ((vFormat & GeometryArray.COORDINATES) != 0) {
1928: morphedGeo.setCoordinateIndices(0, igeo.indexCoord);
1929: }
1930: if ((vFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) {
1931: if ((vFormat & GeometryArray.NORMALS) != 0) {
1932: morphedGeo.setNormalIndices(0, igeo.indexNormal);
1933: }
1934: if ((vFormat & GeometryArray.COLOR) != 0) {
1935: morphedGeo.setColorIndices(0, igeo.indexColor);
1936: }
1937: if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
1938: for (k = 0; k < texCoordSetCount; k++) {
1939: morphedGeo.setTextureCoordinateIndices(k, 0,
1940: igeo.indexTexCoord[k]);
1941: }
1942: }
1943: }
1944: }
1945: this .morphedGeometryArray
1946: .setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);
1947:
1948: GeometryArrayRetained mga = (GeometryArrayRetained) morphedGeometryArray.retained;
1949: mga.updateData(this );
1950:
1951: }
1952:
1953: void getMirrorShape3D(ArrayList list, HashKey k) {
1954: Shape3DRetained ms;
1955: if (inSharedGroup) {
1956: ms = getMirrorShape(k);
1957: } else {
1958: ms = (Shape3DRetained) mirrorShape3D.get(0);
1959: }
1960: list.add(ms);
1961:
1962: }
1963:
1964: void compile(CompileState compState) {
1965:
1966: super .compile(compState);
1967:
1968: // XXXX: for now keep the static transform in the parent tg
1969: compState.keepTG = true;
1970:
1971: if (J3dDebug.devPhase && J3dDebug.debug) {
1972: compState.numMorphs++;
1973: }
1974: }
1975:
1976: void doErrorCheck(GeometryArrayRetained prevGeo,
1977: GeometryArrayRetained geo) {
1978:
1979: // If indexed Geometry array check the entire list instead of just the vcount
1980: if ((prevGeo.vertexFormat != geo.vertexFormat)
1981: || (prevGeo.validVertexCount != geo.validVertexCount)
1982: || (prevGeo.geoType != geo.geoType)
1983: || (prevGeo.texCoordSetCount != geo.texCoordSetCount)) {
1984: throw new IllegalArgumentException(J3dI18N
1985: .getString("MorphRetained1"));
1986: }
1987: if (geo.getTexCoordSetMapLength() != prevGeo
1988: .getTexCoordSetMapLength()) {
1989: throw new IllegalArgumentException(J3dI18N
1990: .getString("MorphRetained1"));
1991: }
1992: int texCoordSetMapLen = geo.getTexCoordSetMapLength();
1993: int[] prevSvc = prevGeo.texCoordSetMap;
1994: int[] svc = geo.texCoordSetMap;
1995: for (int k = 0; k < texCoordSetMapLen; k++) {
1996: if (prevSvc[k] != svc[k])
1997: throw new IllegalArgumentException(J3dI18N
1998: .getString("MorphRetained1"));
1999: }
2000:
2001: if (geo instanceof GeometryStripArrayRetained) {
2002: prevSvc = ((GeometryStripArrayRetained) prevGeo).stripVertexCounts;
2003: svc = ((GeometryStripArrayRetained) geo).stripVertexCounts;
2004: if (prevSvc.length != svc.length)
2005: throw new IllegalArgumentException(J3dI18N
2006: .getString("MorphRetained1"));
2007: for (int k = 0; k < prevSvc.length; k++) {
2008: if (prevSvc[k] != svc[k])
2009: throw new IllegalArgumentException(J3dI18N
2010: .getString("MorphRetained1"));
2011: }
2012: } else if (geo instanceof IndexedGeometryArrayRetained) {
2013: if (((IndexedGeometryArrayRetained) prevGeo).validIndexCount != ((IndexedGeometryArrayRetained) geo).validIndexCount)
2014: throw new IllegalArgumentException(J3dI18N
2015: .getString("MorphRetained1"));
2016:
2017: // If by reference, then all array lengths should be same
2018: if (geo.getNumCoordCount() != prevGeo.getNumCoordCount()
2019: || geo.getNumColorCount() != prevGeo
2020: .getNumColorCount()
2021: || geo.getNumNormalCount() != prevGeo
2022: .getNumNormalCount()) {
2023: throw new IllegalArgumentException(J3dI18N
2024: .getString("MorphRetained1"));
2025: }
2026: int texCoordSetCount = geo.getTexCoordSetCount();
2027: for (int k = 0; k < texCoordSetCount; k++) {
2028: if (geo.getNumTexCoordCount(k) != prevGeo
2029: .getNumTexCoordCount(k)) {
2030: throw new IllegalArgumentException(J3dI18N
2031: .getString("MorphRetained1"));
2032: }
2033: }
2034:
2035: if (geo instanceof IndexedGeometryStripArrayRetained) {
2036: prevSvc = ((IndexedGeometryStripArrayRetained) prevGeo).stripIndexCounts;
2037: svc = ((IndexedGeometryStripArrayRetained) geo).stripIndexCounts;
2038: if (prevSvc.length != svc.length)
2039: throw new IllegalArgumentException(J3dI18N
2040: .getString("MorphRetained1"));
2041: for (int k = 0; k < prevSvc.length; k++) {
2042: if (prevSvc[k] != svc[k])
2043: throw new IllegalArgumentException(J3dI18N
2044: .getString("MorphRetained1"));
2045: }
2046: }
2047: }
2048: }
2049:
2050: void handleFrequencyChange(int bit) {
2051: int mask = 0;
2052: if (bit == Morph.ALLOW_GEOMETRY_ARRAY_WRITE) {
2053: mask = GEOMETRY_CHANGED;
2054: } else if (bit == Morph.ALLOW_APPEARANCE_WRITE) {
2055: mask = APPEARANCE_CHANGED;
2056: } else if (bit == Morph.ALLOW_APPEARANCE_OVERRIDE_WRITE) {
2057: mask = APPEARANCEOVERRIDE_CHANGED;
2058: }
2059: if (mask != 0) {
2060: if (source.getCapabilityIsFrequent(bit))
2061: changedFrequent |= mask;
2062: else if (!source.isLive()) {
2063: changedFrequent &= ~mask;
2064: }
2065: }
2066: }
2067:
2068: void searchGeometryAtoms(UnorderList list) {
2069: list.add(Shape3DRetained
2070: .getGeomAtom((Shape3DRetained) mirrorShape3D.get(0)));
2071: }
2072: }
|