0001: /*
0002: * $RCSfile: ModelClipRetained.java,v $
0003: *
0004: * Copyright 1999-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.6 $
0028: * $Date: 2008/02/28 20:17:26 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import java.util.Enumeration;
0035: import java.util.Vector;
0036: import java.util.ArrayList;
0037: import javax.vecmath.*;
0038:
0039: /**
0040: * The ModelClip retained object.
0041: */
0042: class ModelClipRetained extends LeafRetained {
0043:
0044: // Statics used when something in the fog changes
0045: static final int PLANE_CHANGED = 0x0001;
0046: static final int PLANES_CHANGED = 0x0002;
0047: static final int ENABLE_CHANGED = 0x0004;
0048: static final int ENABLES_CHANGED = 0x0008;
0049: static final int BOUNDS_CHANGED = 0x0010;
0050: static final int BOUNDINGLEAF_CHANGED = 0x0020;
0051: static final int SCOPE_CHANGED = 0x0040;
0052: static final int INIT_MIRROR = 0x0080;
0053: static final int CLEAR_MIRROR = 0x0100;
0054: static final int LAST_DEFINED_BIT = 0x0100;
0055:
0056: /**
0057: * The clip planes and the enable bits
0058: */
0059: Vector4d[] planes = new Vector4d[6];
0060: boolean[] enables = new boolean[6];
0061:
0062: Vector4d[] xformPlanes = new Vector4d[6];
0063:
0064: // enableFlag is true if one of the enables is true
0065: // only used by mirror object
0066: boolean enableFlag = false;
0067:
0068: /**
0069: * The Boundary object defining the model clip's region of influencing
0070: */
0071: Bounds regionOfInfluence = null;
0072:
0073: /**
0074: * The bounding leaf reference
0075: */
0076: BoundingLeafRetained boundingLeaf = null;
0077:
0078: /**
0079: * The transformed value of the influencingRegion.
0080: */
0081: Bounds region = null;
0082:
0083: /**
0084: * Vector of GroupRetained nodes that scopes this model clip.
0085: */
0086: Vector scopes = new Vector();
0087:
0088: //Boolean to indicate if this object is scoped (only used for mirror objects
0089: boolean isScoped = false;
0090:
0091: // The object that contains the dynamic HashKey - a string type object
0092: // Used in scoping
0093: HashKey tempKey = new HashKey(250);
0094:
0095: // This is true when this model clip is referenced in an immediate mode context
0096: boolean inImmCtx = false;
0097:
0098: // The mirror copy of this modelClip
0099: ModelClipRetained mirrorModelClip = null;
0100:
0101: // A reference to the scene graph model clip
0102: ModelClipRetained sgModelClip = null;
0103:
0104: // Target threads to be notified when model clip changes
0105: final static int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
0106: | J3dThread.UPDATE_RENDER;
0107:
0108: /**
0109: * The EnvironmentSets which reference this model clip.
0110: * Note that multiple RenderBin update thread may access
0111: * this shared environmentSets simultaneously.
0112: * So we use UnorderList which sync. all the operations.
0113: */
0114: UnorderList environmentSets = new UnorderList(1,
0115: EnvironmentSet.class);
0116:
0117: // Is true, if the mirror clip is viewScoped
0118: boolean isViewScoped = false;
0119:
0120: /**
0121: * Constructs and initializes model clip planes
0122: */
0123: ModelClipRetained() {
0124:
0125: // planes contains the negate default values
0126: planes[0] = new Vector4d(1.0, 0.0, 0.0, -1.0);
0127: planes[1] = new Vector4d(-1.0, 0.0, 0.0, -1.0);
0128: planes[2] = new Vector4d(0.0, 1.0, 0.0, -1.0);
0129: planes[3] = new Vector4d(0.0, -1.0, 0.0, -1.0);
0130: planes[4] = new Vector4d(0.0, 0.0, 1.0, -1.0);
0131: planes[5] = new Vector4d(0.0, 0.0, -1.0, -1.0);
0132:
0133: for (int i = 0; i < 6; i++)
0134: xformPlanes[i] = new Vector4d(planes[i]);
0135:
0136: enables[0] = enables[1] = enables[2] = enables[3] = enables[4] = enables[5] = true;
0137: }
0138:
0139: /**
0140: * Initializes planes before the object is live
0141: */
0142: void initPlanes(Vector4d[] planes) {
0143:
0144: if (staticTransform != null) {
0145: Transform3D xform = staticTransform.getNormalTransform();
0146: for (int i = 0; i < 6; i++) {
0147: this .planes[i].set(planes[i]);
0148: xform.transform(this .planes[i], this .xformPlanes[i]);
0149: }
0150: } else {
0151: for (int i = 0; i < 6; i++) {
0152: this .planes[i].set(planes[i]);
0153: this .xformPlanes[i].set(this .planes[i]);
0154: }
0155: }
0156: }
0157:
0158: /**
0159: * Sets the clip planes and send a message
0160: */
0161: void setPlanes(Vector4d[] planes) {
0162: Vector4d[] pl = new Vector4d[6];
0163: initPlanes(planes);
0164:
0165: for (int i = 0; i < 6; i++) {
0166: pl[i] = new Vector4d(this .xformPlanes[i]);
0167: }
0168:
0169: sendMessage(PLANES_CHANGED, pl, null);
0170: }
0171:
0172: /**
0173: * Initializes planes before the object is live
0174: */
0175: void initPlane(int planeNum, Vector4d plane) {
0176: if (planeNum < 0 || planeNum > 5)
0177: throw new IllegalArgumentException(J3dI18N
0178: .getString("ModelClip6"));
0179:
0180: if (staticTransform != null) {
0181: Transform3D xform = staticTransform.getNormalTransform();
0182: this .planes[planeNum].set(plane);
0183: xform.transform(this .planes[planeNum],
0184: this .xformPlanes[planeNum]);
0185: } else {
0186: this .planes[planeNum].set(plane);
0187: this .xformPlanes[planeNum].set(plane);
0188: }
0189: }
0190:
0191: /**
0192: * Sets the clip planes and send a message
0193: */
0194: void setPlane(int planeNum, Vector4d plane) {
0195: initPlane(planeNum, plane);
0196: sendMessage(PLANE_CHANGED, new Integer(planeNum), new Vector4d(
0197: this .xformPlanes[planeNum]));
0198: }
0199:
0200: /**
0201: * Gets planes
0202: */
0203: void getPlanes(Vector4d[] planes) {
0204:
0205: for (int i = 0; i < 6; i++) {
0206: planes[i].set(this .planes[i]);
0207: }
0208: }
0209:
0210: /**
0211: * Gets the specified clipping plane
0212: */
0213: void getPlane(int planeNum, Vector4d plane) {
0214: if (planeNum < 0 || planeNum > 5)
0215: throw new IllegalArgumentException(J3dI18N
0216: .getString("ModelClip6"));
0217: plane.set(this .planes[planeNum]);
0218: }
0219:
0220: /**
0221: * Initializes planes before the object is live
0222: */
0223: void initEnables(boolean[] enables) {
0224: this .enables[0] = enables[0];
0225: this .enables[1] = enables[1];
0226: this .enables[2] = enables[2];
0227: this .enables[3] = enables[3];
0228: this .enables[4] = enables[4];
0229: this .enables[5] = enables[5];
0230: }
0231:
0232: /**
0233: * Sets the clip planes and send a message
0234: */
0235: void setEnables(boolean[] enables) {
0236: Boolean[] en = new Boolean[6];
0237:
0238: initEnables(enables);
0239: en[0] = (enables[0] ? Boolean.TRUE : Boolean.FALSE);
0240: en[1] = (enables[1] ? Boolean.TRUE : Boolean.FALSE);
0241: en[2] = (enables[2] ? Boolean.TRUE : Boolean.FALSE);
0242: en[3] = (enables[3] ? Boolean.TRUE : Boolean.FALSE);
0243: en[4] = (enables[4] ? Boolean.TRUE : Boolean.FALSE);
0244: en[5] = (enables[5] ? Boolean.TRUE : Boolean.FALSE);
0245:
0246: sendMessage(ENABLES_CHANGED, en, null);
0247: }
0248:
0249: /**
0250: * Initializes planes before the object is live
0251: */
0252: void initEnable(int planeNum, boolean enable) {
0253: if (planeNum < 0 || planeNum > 5)
0254: throw new IllegalArgumentException(J3dI18N
0255: .getString("ModelClip6"));
0256: this .enables[planeNum] = enable;
0257: }
0258:
0259: /**
0260: * Sets the clip planes and send a message
0261: */
0262: void setEnable(int planeNum, boolean enable) {
0263: initEnable(planeNum, enable);
0264: sendMessage(ENABLE_CHANGED, new Integer(planeNum),
0265: (enable ? Boolean.TRUE : Boolean.FALSE));
0266: }
0267:
0268: /**
0269: * Gets enables
0270: */
0271: void getEnables(boolean[] enables) {
0272: enables[0] = this .enables[0];
0273: enables[1] = this .enables[1];
0274: enables[2] = this .enables[2];
0275: enables[3] = this .enables[3];
0276: enables[4] = this .enables[4];
0277: enables[5] = this .enables[5];
0278: }
0279:
0280: /**
0281: * Gets the specified enable
0282: */
0283: boolean getEnable(int planeNum) {
0284: if (planeNum < 0 || planeNum > 5)
0285: throw new IllegalArgumentException(J3dI18N
0286: .getString("ModelClip6"));
0287: return (this .enables[planeNum]);
0288: }
0289:
0290: /**
0291: * Set the Model Clip's region of influencing
0292: */
0293: void initInfluencingBounds(Bounds region) {
0294: if (region != null) {
0295: this .regionOfInfluence = (Bounds) region.clone();
0296: if (staticTransform != null) {
0297: regionOfInfluence.transform(staticTransform.transform);
0298: }
0299: } else {
0300: this .regionOfInfluence = null;
0301: }
0302: }
0303:
0304: /**
0305: * Set the Model Clip's region of influencing and send message
0306: */
0307: void setInfluencingBounds(Bounds region) {
0308: initInfluencingBounds(region);
0309: sendMessage(BOUNDS_CHANGED, (region != null ? (Bounds) region
0310: .clone() : null), null);
0311: }
0312:
0313: /**
0314: * Get the Model Clip's region of influencing.
0315: */
0316: Bounds getInfluencingBounds() {
0317: Bounds b = null;
0318:
0319: if (regionOfInfluence != null) {
0320: b = (Bounds) regionOfInfluence.clone();
0321: if (staticTransform != null) {
0322: Transform3D invTransform = staticTransform
0323: .getInvTransform();
0324: b.transform(invTransform);
0325: }
0326: }
0327: return b;
0328: }
0329:
0330: /**
0331: * Set the Model Clip's region of influencing to the specified Leaf node.
0332: */
0333: void initInfluencingBoundingLeaf(BoundingLeaf region) {
0334: if (region != null) {
0335: boundingLeaf = (BoundingLeafRetained) region.retained;
0336: } else {
0337: boundingLeaf = null;
0338: }
0339: }
0340:
0341: /**
0342: * Set the Model Clip's region of influencing to the specified Leaf node.
0343: */
0344: void setInfluencingBoundingLeaf(BoundingLeaf region) {
0345: if (boundingLeaf != null)
0346: boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorModelClip);
0347: if (region != null) {
0348: boundingLeaf = (BoundingLeafRetained) region.retained;
0349: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorModelClip);
0350: } else {
0351: boundingLeaf = null;
0352: }
0353:
0354: sendMessage(BOUNDINGLEAF_CHANGED,
0355: (boundingLeaf != null ? boundingLeaf.mirrorBoundingLeaf
0356: : null), null);
0357: }
0358:
0359: /**
0360: * Get the Model Clip's region of influencing.
0361: */
0362: BoundingLeaf getInfluencingBoundingLeaf() {
0363: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
0364: : null);
0365: }
0366:
0367: /**
0368: * Replaces the specified scope with the scope provided.
0369: * @param scope the new scope
0370: * @param index which scope to replace
0371: */
0372: void initScope(Group scope, int index) {
0373: scopes.setElementAt((GroupRetained) (scope.retained), index);
0374: }
0375:
0376: /**
0377: * Replaces the specified scope with the scope provided.
0378: * @param scope the new scope
0379: * @param index which scope to replace
0380: */
0381: void setScope(Group scope, int index) {
0382:
0383: ArrayList addScopeList = new ArrayList();
0384: ArrayList removeScopeList = new ArrayList();
0385: GroupRetained group;
0386: Object[] scopeInfo = new Object[3];
0387:
0388: group = (GroupRetained) scopes.get(index);
0389: tempKey.reset();
0390: group.removeAllNodesForScopedModelClip(mirrorModelClip,
0391: removeScopeList, tempKey);
0392:
0393: group = (GroupRetained) scope.retained;
0394: initScope(scope, index);
0395: tempKey.reset();
0396: // If its a group, then add the scope to the group, if
0397: // its a shape, then keep a list to be added during
0398: // updateMirrorObject
0399: group.addAllNodesForScopedModelClip(mirrorModelClip,
0400: addScopeList, tempKey);
0401: scopeInfo[0] = addScopeList;
0402: scopeInfo[1] = removeScopeList;
0403: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0404: : Boolean.FALSE);
0405: sendMessage(SCOPE_CHANGED, scopeInfo, null);
0406: }
0407:
0408: /**
0409: * Inserts the specified scope at specified index
0410: * @param scope the new scope
0411: * @param index position to insert new scope at
0412: */
0413: void initInsertScope(Node scope, int index) {
0414: GroupRetained group = (GroupRetained) scope.retained;
0415: group.setMclipScope();
0416: scopes.insertElementAt((GroupRetained) (scope.retained), index);
0417: }
0418:
0419: /**
0420: * Inserts the specified scope at specified index and sends
0421: * a message
0422: * @param scope the new scope
0423: * @param index position to insert new scope at
0424: */
0425: void insertScope(Node scope, int index) {
0426: Object[] scopeInfo = new Object[3];
0427: ArrayList addScopeList = new ArrayList();
0428:
0429: initInsertScope(scope, index);
0430: GroupRetained group = (GroupRetained) scope.retained;
0431: tempKey.reset();
0432: group.addAllNodesForScopedModelClip(mirrorModelClip,
0433: addScopeList, tempKey);
0434: scopeInfo[0] = addScopeList;
0435: scopeInfo[1] = null;
0436: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0437: : Boolean.FALSE);
0438: sendMessage(SCOPE_CHANGED, scopeInfo, null);
0439: }
0440:
0441: void initRemoveScope(int index) {
0442: GroupRetained group = (GroupRetained) scopes.elementAt(index);
0443: group.removeMclipScope();
0444: scopes.removeElementAt(index);
0445:
0446: }
0447:
0448: void removeScope(int index) {
0449:
0450: Object[] scopeInfo = new Object[3];
0451: ArrayList removeScopeList = new ArrayList();
0452: GroupRetained group = (GroupRetained) scopes.elementAt(index);
0453:
0454: initRemoveScope(index);
0455: tempKey.reset();
0456: group.removeAllNodesForScopedModelClip(mirrorModelClip,
0457: removeScopeList, tempKey);
0458:
0459: scopeInfo[0] = null;
0460: scopeInfo[1] = removeScopeList;
0461: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0462: : Boolean.FALSE);
0463: sendMessage(SCOPE_CHANGED, scopeInfo, null);
0464: }
0465:
0466: /**
0467: * Removes the specified Group node from this ModelClip's list of
0468: * scopes if the specified node is not found in the list of scoped
0469: * nodes, method returns quietly.
0470: *
0471: * @param Group node to be removed
0472: */
0473: void removeScope(Group node) {
0474: int ind = indexOfScope(node);
0475: if (ind >= 0)
0476: removeScope(ind);
0477: }
0478:
0479: void initRemoveScope(Group node) {
0480: int ind = indexOfScope(node);
0481: if (ind >= 0)
0482: initRemoveScope(ind);
0483: }
0484:
0485: /**
0486: * Removes all the Group nodes from the ModelClip's scope
0487: * list. The ModelClip reverts to universal scope.
0488: */
0489: void removeAllScopes() {
0490: Object[] scopeInfo = new Object[3];
0491: ArrayList removeScopeList = new ArrayList();
0492: int n = scopes.size();
0493: for (int index = n - 1; index >= 0; index--) {
0494: GroupRetained group = (GroupRetained) scopes
0495: .elementAt(index);
0496: initRemoveScope(index);
0497: tempKey.reset();
0498: group.removeAllNodesForScopedModelClip(mirrorModelClip,
0499: removeScopeList, tempKey);
0500: }
0501:
0502: scopeInfo[0] = null;
0503: scopeInfo[1] = removeScopeList;
0504: scopeInfo[2] = (Boolean.FALSE);
0505: sendMessage(SCOPE_CHANGED, scopeInfo, null);
0506: }
0507:
0508: void initRemoveAllScopes() {
0509: int n = scopes.size();
0510: for (int i = n - 1; i >= 0; i--) {
0511: initRemoveScope(i);
0512: }
0513: }
0514:
0515: /**
0516: * Returns the scope specified by the index.
0517: * @param index which scope to return
0518: * @return the scoperen at location index
0519: */
0520: Group getScope(int index) {
0521: return (Group) (((GroupRetained) (scopes.elementAt(index))).source);
0522: }
0523:
0524: /**
0525: * Returns an enumeration object of the scoperen.
0526: * @return an enumeration object of the scoperen
0527: */
0528: Enumeration getAllScopes() {
0529: Enumeration elm = scopes.elements();
0530: Vector v = new Vector(scopes.size());
0531: while (elm.hasMoreElements()) {
0532: v.add(((GroupRetained) elm.nextElement()).source);
0533: }
0534: return v.elements();
0535: }
0536:
0537: /**
0538: * Appends the specified scope to this node's list of scopes before
0539: * the fog is alive
0540: * @param scope the scope to add to this node's list of scopes
0541: */
0542: void initAddScope(Group scope) {
0543: GroupRetained group = (GroupRetained) scope.retained;
0544: scopes.addElement((GroupRetained) (scope.retained));
0545: group.setMclipScope();
0546: }
0547:
0548: /**
0549: * Appends the specified scope to this node's list of scopes.
0550: * @param scope the scope to add to this node's list of scopes
0551: */
0552: void addScope(Group scope) {
0553:
0554: Object[] scopeInfo = new Object[3];
0555: ArrayList addScopeList = new ArrayList();
0556: GroupRetained group = (GroupRetained) scope.retained;
0557:
0558: initAddScope(scope);
0559: tempKey.reset();
0560: group.addAllNodesForScopedModelClip(mirrorModelClip,
0561: addScopeList, tempKey);
0562: scopeInfo[0] = addScopeList;
0563: scopeInfo[1] = null;
0564: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0565: : Boolean.FALSE);
0566: sendMessage(SCOPE_CHANGED, scopeInfo, null);
0567: }
0568:
0569: /**
0570: * Returns a count of this nodes' scopes.
0571: * @return the number of scopes descendant from this node
0572: */
0573: int numScopes() {
0574: return scopes.size();
0575: }
0576:
0577: /**
0578: * Returns the index of the specified Group node within the ModelClip's list of scoped
0579: * Group nodes
0580: * @param Group node whose index is desired
0581: * @return index of this node
0582: */
0583: int indexOfScope(Group node) {
0584: if (node != null)
0585: return scopes.indexOf((GroupRetained) node.retained);
0586: else
0587: return scopes.indexOf(null);
0588: }
0589:
0590: /**
0591: * This sets the immedate mode context flag
0592: */
0593: void setInImmCtx(boolean inCtx) {
0594: inImmCtx = inCtx;
0595: }
0596:
0597: /**
0598: * This gets the immedate mode context flag
0599: */
0600: boolean getInImmCtx() {
0601: return (inImmCtx);
0602: }
0603:
0604: /**
0605: * This method and its native counterpart update the native context
0606: * model clip planes.
0607: */
0608: void update(Canvas3D cv, int enableMask) {
0609: cv.setModelViewMatrix(cv.ctx, cv.vworldToEc.mat,
0610: getLastLocalToVworld());
0611: update(cv.ctx, enableMask, getLastLocalToVworld());
0612: }
0613:
0614: void update(Context ctx, int enableMask, Transform3D trans) {
0615: if (!VirtualUniverse.mc.isD3D()) {
0616: for (int i = 0; i < 6; i++) {
0617: Pipeline.getPipeline().updateModelClip(ctx, i,
0618: ((enableMask & (1 << i)) != 0),
0619: xformPlanes[i].x, xformPlanes[i].y,
0620: xformPlanes[i].z, xformPlanes[i].w);
0621: }
0622: return;
0623: }
0624:
0625: // For D3D we need to transform the plane equations from local to
0626: // world coordinate.
0627: Transform3D invtrans = new Transform3D(trans);
0628:
0629: // can't call getNormalTransform() since it will cache
0630: // normalTransform and may return previous result next time.
0631: invtrans.invert();
0632: invtrans.transpose();
0633:
0634: for (int i = 0; i < 6; i++) {
0635: if ((enableMask & (1 << i)) != 0) {
0636:
0637: Vector4d vec = new Vector4d(xformPlanes[i].x,
0638: xformPlanes[i].y, xformPlanes[i].z,
0639: xformPlanes[i].w);
0640: vec.normalize();
0641: invtrans.transform(vec);
0642: Pipeline.getPipeline().updateModelClip(ctx, i, true,
0643: vec.x, vec.y, vec.z, vec.w);
0644:
0645: } else {
0646: Pipeline.getPipeline().updateModelClip(ctx, i, false,
0647: 0, 0, 0, 0);
0648: }
0649: }
0650: }
0651:
0652: void initMirrorObject(Object[] args) {
0653: Shape3DRetained shape;
0654: Object[] scopeInfo = (Object[]) args[2];
0655: Boolean scoped = (Boolean) scopeInfo[0];
0656: ArrayList shapeList = (ArrayList) scopeInfo[1];
0657: BoundingLeafRetained bl = (BoundingLeafRetained) ((Object[]) args[4])[0];
0658: Bounds bnds = (Bounds) ((Object[]) args[4])[1];
0659:
0660: for (int i = 0; i < shapeList.size(); i++) {
0661: shape = ((GeometryAtom) shapeList.get(i)).source;
0662: shape.addModelClip(mirrorModelClip);
0663: }
0664: mirrorModelClip.isScoped = scoped.booleanValue();
0665:
0666: if (bl != null) {
0667: mirrorModelClip.boundingLeaf = bl.mirrorBoundingLeaf;
0668: mirrorModelClip.region = boundingLeaf.transformedRegion;
0669: } else {
0670: mirrorModelClip.boundingLeaf = null;
0671: mirrorModelClip.region = null;
0672: }
0673:
0674: if (bnds != null) {
0675: mirrorModelClip.regionOfInfluence = bnds;
0676: if (mirrorModelClip.region == null) {
0677: mirrorModelClip.region = (Bounds) regionOfInfluence
0678: .clone();
0679: mirrorModelClip.region.transform(regionOfInfluence,
0680: getLastLocalToVworld());
0681: }
0682: } else {
0683: mirrorModelClip.regionOfInfluence = null;
0684: }
0685: boolean[] ens = (boolean[]) ((Object[]) args[4])[2];
0686:
0687: for (int i = 0; i < ens.length; i++) {
0688: mirrorModelClip.enables[i] = ens[i];
0689: }
0690: mirrorModelClip.enableFlag = mirrorModelClip.enables[0]
0691: | mirrorModelClip.enables[1]
0692: | mirrorModelClip.enables[2]
0693: | mirrorModelClip.enables[3]
0694: | mirrorModelClip.enables[4]
0695: | mirrorModelClip.enables[5];
0696:
0697: }
0698:
0699: void updateMirrorObject(Object[] objs) {
0700: int component = ((Integer) objs[1]).intValue();
0701: if ((component & PLANES_CHANGED) != 0) {
0702: Vector4d[] pl = ((Vector4d[]) objs[2]);
0703:
0704: for (int i = 0; i < 6; i++) {
0705: mirrorModelClip.xformPlanes[i].set(pl[i]);
0706: }
0707: } else if ((component & PLANE_CHANGED) != 0) {
0708: int planeNum = ((Integer) objs[2]).intValue();
0709:
0710: mirrorModelClip.xformPlanes[planeNum]
0711: .set((Vector4d) objs[3]);
0712: } else if ((component & INIT_MIRROR) != 0) {
0713: Vector4d[] pl = (Vector4d[]) objs[3];
0714: for (int i = 0; i < 6; i++) {
0715: mirrorModelClip.xformPlanes[i].set(pl[i]);
0716: }
0717: }
0718: }
0719:
0720: // The update Object function.
0721: void updateImmediateMirrorObject(Object[] objs) {
0722: int component = ((Integer) objs[1]).intValue();
0723: Transform3D trans;
0724:
0725: if ((component & BOUNDINGLEAF_CHANGED) != 0) {
0726: mirrorModelClip.boundingLeaf = (BoundingLeafRetained) objs[2];
0727: if (objs[2] != null) {
0728: mirrorModelClip.region = (Bounds) mirrorModelClip.boundingLeaf.transformedRegion;
0729: } else {
0730: if (mirrorModelClip.regionOfInfluence != null) {
0731: mirrorModelClip.region = ((Bounds) mirrorModelClip.regionOfInfluence)
0732: .copy(mirrorModelClip.region);
0733: mirrorModelClip.region.transform(
0734: mirrorModelClip.regionOfInfluence,
0735: getCurrentLocalToVworld());
0736: } else {
0737: mirrorModelClip.region = null;
0738: }
0739:
0740: }
0741: }
0742:
0743: if ((component & BOUNDS_CHANGED) != 0) {
0744: mirrorModelClip.regionOfInfluence = (Bounds) objs[2];
0745: if (mirrorModelClip.boundingLeaf == null) {
0746: if (objs[2] != null) {
0747: mirrorModelClip.region = ((Bounds) mirrorModelClip.regionOfInfluence)
0748: .copy(mirrorModelClip.region);
0749:
0750: mirrorModelClip.region.transform(
0751: mirrorModelClip.regionOfInfluence,
0752: getCurrentLocalToVworld());
0753: } else {
0754: mirrorModelClip.region = null;
0755: }
0756: }
0757: }
0758:
0759: if ((component & SCOPE_CHANGED) != 0) {
0760: Object[] scopeList = (Object[]) objs[2];
0761: ArrayList addList = (ArrayList) scopeList[0];
0762: ArrayList removeList = (ArrayList) scopeList[1];
0763: boolean isScoped = ((Boolean) scopeList[2]).booleanValue();
0764:
0765: if (addList != null) {
0766: mirrorModelClip.isScoped = isScoped;
0767: for (int i = 0; i < addList.size(); i++) {
0768: Shape3DRetained obj = ((GeometryAtom) addList
0769: .get(i)).source;
0770: obj.addModelClip(mirrorModelClip);
0771: }
0772: }
0773:
0774: if (removeList != null) {
0775: mirrorModelClip.isScoped = isScoped;
0776: for (int i = 0; i < removeList.size(); i++) {
0777: Shape3DRetained obj = ((GeometryAtom) removeList
0778: .get(i)).source;
0779: obj.removeModelClip(mirrorModelClip);
0780: }
0781: }
0782: }
0783:
0784: if ((component & ENABLES_CHANGED) != 0) {
0785: Boolean[] en = ((Boolean[]) objs[2]);
0786:
0787: mirrorModelClip.enables[0] = en[0].booleanValue();
0788: mirrorModelClip.enables[1] = en[1].booleanValue();
0789: mirrorModelClip.enables[2] = en[2].booleanValue();
0790: mirrorModelClip.enables[3] = en[3].booleanValue();
0791: mirrorModelClip.enables[4] = en[4].booleanValue();
0792: mirrorModelClip.enables[5] = en[5].booleanValue();
0793: mirrorModelClip.enableFlag = mirrorModelClip.enables[0]
0794: | mirrorModelClip.enables[1]
0795: | mirrorModelClip.enables[2]
0796: | mirrorModelClip.enables[3]
0797: | mirrorModelClip.enables[4]
0798: | mirrorModelClip.enables[5];
0799: } else if ((component & ENABLE_CHANGED) != 0) {
0800: int planeNum = ((Integer) objs[2]).intValue();
0801:
0802: mirrorModelClip.enables[planeNum] = ((Boolean) objs[3])
0803: .booleanValue();
0804: mirrorModelClip.enableFlag = mirrorModelClip.enables[0]
0805: | mirrorModelClip.enables[1]
0806: | mirrorModelClip.enables[2]
0807: | mirrorModelClip.enables[3]
0808: | mirrorModelClip.enables[4]
0809: | mirrorModelClip.enables[5];
0810: }
0811: }
0812:
0813: /** Note: This routine will only be called on
0814: * the mirror object - will update the object's
0815: * cached region and transformed region
0816: */
0817: void updateBoundingLeaf() {
0818: if (boundingLeaf != null
0819: && boundingLeaf.switchState.currentSwitchOn) {
0820: region = boundingLeaf.transformedRegion;
0821: } else {
0822: if (regionOfInfluence != null) {
0823: region = regionOfInfluence.copy(region);
0824: region.transform(regionOfInfluence,
0825: getCurrentLocalToVworld());
0826: } else {
0827: region = null;
0828: }
0829: }
0830: }
0831:
0832: void setLive(SetLiveState s) {
0833: GroupRetained group;
0834:
0835: super .doSetLive(s);
0836:
0837: if (inSharedGroup) {
0838: throw new IllegalSharingException(J3dI18N
0839: .getString("ModelClipRetained1"));
0840: }
0841:
0842: // Create the mirror object
0843:
0844: if (mirrorModelClip == null) {
0845: mirrorModelClip = (ModelClipRetained) this .clone();
0846: mirrorModelClip.boundingLeaf = null;
0847: mirrorModelClip.sgModelClip = this ;
0848: }
0849: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
0850: s.viewScopedNodeList.add(mirrorModelClip);
0851: s.scopedNodesViewList.add(s.viewLists.get(0));
0852: } else {
0853: s.nodeList.add(mirrorModelClip);
0854: }
0855:
0856: // If bounding leaf is not null, add the mirror object as a user
0857: // so that any changes to the bounding leaf will be received
0858: if (boundingLeaf != null) {
0859: boundingLeaf.mirrorBoundingLeaf.addUser(mirrorModelClip);
0860: }
0861: // process switch leaf
0862: if (s.switchTargets != null && s.switchTargets[0] != null) {
0863: s.switchTargets[0].addNode(mirrorModelClip,
0864: Targets.ENV_TARGETS);
0865: }
0866: mirrorModelClip.switchState = (SwitchState) s.switchStates
0867: .get(0);
0868:
0869: // add this model clip to the transform target
0870: if (s.transformTargets != null && s.transformTargets[0] != null) {
0871: s.transformTargets[0].addNode(mirrorModelClip,
0872: Targets.ENV_TARGETS);
0873: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0874: }
0875:
0876: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
0877: | J3dThread.UPDATE_RENDER;
0878: super .markAsLive();
0879:
0880: // Initialize the mirror object, this needs to be done, when
0881: // renderBin is not accessing any of the fields
0882: J3dMessage createMessage = new J3dMessage();
0883: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
0884: createMessage.universe = universe;
0885: createMessage.type = J3dMessage.MODELCLIP_CHANGED;
0886: createMessage.args[0] = this ;
0887: // a snapshot of all attributes that needs to be initialized
0888: // in the mirror object
0889: createMessage.args[1] = new Integer(INIT_MIRROR);
0890: ArrayList addScopeList = new ArrayList();
0891: for (int i = 0; i < scopes.size(); i++) {
0892: group = (GroupRetained) scopes.get(i);
0893: tempKey.reset();
0894: group.addAllNodesForScopedModelClip(mirrorModelClip,
0895: addScopeList, tempKey);
0896: }
0897: Object[] scopeInfo = new Object[2];
0898: scopeInfo[0] = ((scopes.size() > 0) ? Boolean.TRUE
0899: : Boolean.FALSE);
0900: scopeInfo[1] = addScopeList;
0901: createMessage.args[2] = scopeInfo;
0902: createMessage.args[3] = xformPlanes.clone();
0903:
0904: Object[] obj = new Object[3];
0905: obj[0] = boundingLeaf;
0906: obj[1] = (regionOfInfluence != null ? regionOfInfluence.clone()
0907: : null);
0908: obj[2] = enables.clone();
0909: createMessage.args[4] = obj;
0910: VirtualUniverse.mc.processMessage(createMessage);
0911:
0912: }
0913:
0914: /**
0915: * This clearLive routine first calls the superclass's method, then
0916: * it removes itself to the list of model clip
0917: */
0918: void clearLive(SetLiveState s) {
0919:
0920: super .clearLive(s);
0921: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
0922: | J3dThread.UPDATE_RENDER;
0923: if (s.switchTargets != null && s.switchTargets[0] != null) {
0924: s.switchTargets[0].addNode(mirrorModelClip,
0925: Targets.ENV_TARGETS);
0926: }
0927: // Remove this mirror light as users of the bounding leaf
0928: if (mirrorModelClip.boundingLeaf != null)
0929: mirrorModelClip.boundingLeaf.removeUser(mirrorModelClip);
0930:
0931: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
0932: s.viewScopedNodeList.add(mirrorModelClip);
0933: s.scopedNodesViewList.add(s.viewLists.get(0));
0934: } else {
0935: s.nodeList.add(mirrorModelClip);
0936: }
0937: if (s.transformTargets != null && s.transformTargets[0] != null) {
0938: s.transformTargets[0].addNode(mirrorModelClip,
0939: Targets.ENV_TARGETS);
0940: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0941: }
0942:
0943: if (scopes.size() > 0) {
0944: J3dMessage createMessage = new J3dMessage();
0945: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
0946: createMessage.universe = universe;
0947: createMessage.type = J3dMessage.MODELCLIP_CHANGED;
0948: createMessage.args[0] = this ;
0949: createMessage.args[1] = new Integer(CLEAR_MIRROR);
0950: ArrayList removeScopeList = new ArrayList();
0951: for (int i = 0; i < scopes.size(); i++) {
0952: GroupRetained group = (GroupRetained) scopes.get(i);
0953: tempKey.reset();
0954: group.removeAllNodesForScopedModelClip(mirrorModelClip,
0955: removeScopeList, tempKey);
0956: }
0957: createMessage.args[2] = removeScopeList;
0958: VirtualUniverse.mc.processMessage(createMessage);
0959: }
0960: }
0961:
0962: // This is called on the parent object
0963: void clearMirrorObject(Object[] args) {
0964: Shape3DRetained shape;
0965: ArrayList shapeList = (ArrayList) args[2];
0966: ArrayList removeScopeList = new ArrayList();
0967:
0968: for (int i = 0; i < shapeList.size(); i++) {
0969: shape = ((GeometryAtom) shapeList.get(i)).source;
0970: shape.removeModelClip(mirrorModelClip);
0971: }
0972:
0973: mirrorModelClip.isScoped = false;
0974:
0975: }
0976:
0977: // Clone the retained side only, internal use only
0978: protected Object clone() {
0979: ModelClipRetained mc = (ModelClipRetained) super .clone();
0980:
0981: mc.planes = new Vector4d[6];
0982: for (int i = 0; i < 6; i++) {
0983: mc.planes[i] = new Vector4d(this .planes[i]);
0984: mc.xformPlanes[i] = new Vector4d(this .xformPlanes[i]);
0985: }
0986:
0987: mc.enables = new boolean[6];
0988: getEnables(mc.enables);
0989:
0990: // Derive the enables flag
0991: mc.enableFlag = (mc.enables[0] | mc.enables[1] | mc.enables[2]
0992: | mc.enables[3] | mc.enables[4] | mc.enables[5]);
0993:
0994: mc.inImmCtx = false;
0995: mc.region = null;
0996: mc.sgModelClip = null;
0997: mc.mirrorModelClip = null;
0998: mc.environmentSets = new UnorderList(1, EnvironmentSet.class);
0999:
1000: if (regionOfInfluence != null) {
1001: mc.regionOfInfluence = (Bounds) regionOfInfluence.clone();
1002: }
1003:
1004: return mc;
1005: }
1006:
1007: // Called on mirror object
1008: void updateImmediateTransformChange() {
1009: // If bounding leaf is null, tranform the bounds object
1010: if (boundingLeaf == null) {
1011: if (regionOfInfluence != null) {
1012: region = regionOfInfluence.copy(region);
1013: region.transform(regionOfInfluence, sgModelClip
1014: .getCurrentLocalToVworld());
1015: }
1016:
1017: }
1018: }
1019:
1020: void printPlane(int index, String string) {
1021: System.err.println(string + " : < " + planes[index].toString()
1022: + " > " + enables[index]);
1023: }
1024:
1025: void printPlanes(String string, Vector4d[] planes) {
1026: System.err.println(string);
1027: printPlane(0, "[0]");
1028: printPlane(1, "[1]");
1029: printPlane(2, "[2]");
1030: printPlane(3, "[3]");
1031: printPlane(4, "[4]");
1032: printPlane(5, "[5]");
1033: }
1034:
1035: void printEnables(String string, boolean[] enables) {
1036: System.err.println(string);
1037: System.err.println("[0] : < " + enables[0] + " >");
1038: System.err.println("[1] : < " + enables[1] + " >");
1039: System.err.println("[2] : < " + enables[2] + " >");
1040: System.err.println("[3] : < " + enables[3] + " >");
1041: System.err.println("[4] : < " + enables[4] + " >");
1042: System.err.println("[5] : < " + enables[5] + " >");
1043: }
1044:
1045: final void sendMessage(int attrMask, Object attr1, Object attr2) {
1046: J3dMessage createMessage = new J3dMessage();
1047: createMessage.threads = targetThreads;
1048: createMessage.type = J3dMessage.MODELCLIP_CHANGED;
1049: createMessage.universe = universe;
1050: createMessage.args[0] = this ;
1051: createMessage.args[1] = new Integer(attrMask);
1052: createMessage.args[2] = attr1;
1053: createMessage.args[3] = attr2;
1054: VirtualUniverse.mc.processMessage(createMessage);
1055: }
1056:
1057: void mergeTransform(TransformGroupRetained staticTransform) {
1058: super .mergeTransform(staticTransform);
1059:
1060: if (regionOfInfluence != null) {
1061: regionOfInfluence.transform(staticTransform.transform);
1062: }
1063:
1064: Transform3D xform = staticTransform.getNormalTransform();
1065: for (int i = 0; i < 6; i++) {
1066: xform.transform(planes[i], xformPlanes[i]);
1067: }
1068: }
1069:
1070: void getMirrorObjects(ArrayList leafList, HashKey key) {
1071: leafList.add(mirrorModelClip);
1072: }
1073: }
|