diff options
Diffstat (limited to 'src/javax/media/j3d/ModelClipRetained.java')
-rw-r--r-- | src/javax/media/j3d/ModelClipRetained.java | 1043 |
1 files changed, 1043 insertions, 0 deletions
diff --git a/src/javax/media/j3d/ModelClipRetained.java b/src/javax/media/j3d/ModelClipRetained.java new file mode 100644 index 0000000..04b248d --- /dev/null +++ b/src/javax/media/j3d/ModelClipRetained.java @@ -0,0 +1,1043 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package javax.media.j3d; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Vector; + +import javax.vecmath.Vector4d; + +/** + * The ModelClip retained object. + */ +class ModelClipRetained extends LeafRetained { + + // Statics used when something in the fog changes + static final int PLANE_CHANGED = 0x0001; + static final int PLANES_CHANGED = 0x0002; + static final int ENABLE_CHANGED = 0x0004; + static final int ENABLES_CHANGED = 0x0008; + static final int BOUNDS_CHANGED = 0x0010; + static final int BOUNDINGLEAF_CHANGED = 0x0020; + static final int SCOPE_CHANGED = 0x0040; + static final int INIT_MIRROR = 0x0080; + static final int CLEAR_MIRROR = 0x0100; + static final int LAST_DEFINED_BIT = 0x0100; + + /** + * The clip planes and the enable bits + */ + Vector4d[] planes = new Vector4d[6]; + boolean[] enables = new boolean[6]; + + Vector4d[] xformPlanes = new Vector4d[6]; + + // enableFlag is true if one of the enables is true + // only used by mirror object + boolean enableFlag = false; + + /** + * The Boundary object defining the model clip's region of influencing + */ + Bounds regionOfInfluence = null; + + /** + * The bounding leaf reference + */ + BoundingLeafRetained boundingLeaf = null; + + /** + * The transformed value of the influencingRegion. + */ + Bounds region = null; + +/** + * Vector of GroupRetained nodes that scopes this model clip. + */ +Vector<GroupRetained> scopes = new Vector<GroupRetained>(); + + //Boolean to indicate if this object is scoped (only used for mirror objects + boolean isScoped = false; + + // The object that contains the dynamic HashKey - a string type object + // Used in scoping + HashKey tempKey = new HashKey(250); + + // This is true when this model clip is referenced in an immediate mode context + boolean inImmCtx = false; + + // The mirror copy of this modelClip + ModelClipRetained mirrorModelClip = null; + + // A reference to the scene graph model clip + ModelClipRetained sgModelClip = null; + + // Target threads to be notified when model clip changes + final static int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | + J3dThread.UPDATE_RENDER; + + /** + * The EnvironmentSets which reference this model clip. + * Note that multiple RenderBin update thread may access + * this shared environmentSets simultaneously. + * So we use UnorderList which sync. all the operations. + */ + UnorderList environmentSets = new UnorderList(1, EnvironmentSet.class); + + // Is true, if the mirror clip is viewScoped + boolean isViewScoped = false; + + /** + * Constructs and initializes model clip planes + */ + ModelClipRetained() { + + // planes contains the negate default values + planes[0] = new Vector4d( 1.0, 0.0, 0.0,-1.0); + planes[1] = new Vector4d(-1.0, 0.0, 0.0,-1.0); + planes[2] = new Vector4d( 0.0, 1.0, 0.0,-1.0); + planes[3] = new Vector4d( 0.0,-1.0, 0.0,-1.0); + planes[4] = new Vector4d( 0.0, 0.0, 1.0,-1.0); + planes[5] = new Vector4d( 0.0, 0.0, -1.0,-1.0); + + for (int i = 0; i < 6; i++) + xformPlanes[i] = new Vector4d(planes[i]); + + enables[0] = enables[1] = enables[2] = enables[3] = + enables[4] = enables[5] = true; + } + + /** + * Initializes planes before the object is live + */ + void initPlanes(Vector4d[] planes) { + + if (staticTransform != null) { + Transform3D xform = staticTransform.getNormalTransform(); + for (int i = 0; i < 6; i++) { + this.planes[i].set(planes[i]); + xform.transform(this.planes[i], this.xformPlanes[i]); + } + } else { + for (int i = 0; i < 6; i++) { + this.planes[i].set(planes[i]); + this.xformPlanes[i].set(this.planes[i]); + } + } + } + + /** + * Sets the clip planes and send a message + */ + void setPlanes(Vector4d[] planes) { + Vector4d[] pl = new Vector4d[6]; + initPlanes(planes); + + for (int i = 0; i < 6; i++) { + pl[i] = new Vector4d(this.xformPlanes[i]); + } + + sendMessage(PLANES_CHANGED, pl, null); + } + + /** + * Initializes planes before the object is live + */ + void initPlane(int planeNum, Vector4d plane) { + if (planeNum < 0 || planeNum > 5) + throw new IllegalArgumentException(J3dI18N.getString("ModelClip6")); + + if (staticTransform != null) { + Transform3D xform = staticTransform.getNormalTransform(); + this.planes[planeNum].set(plane); + xform.transform(this.planes[planeNum], this.xformPlanes[planeNum]); + } else { + this.planes[planeNum].set(plane); + this.xformPlanes[planeNum].set(plane); + } + } + + /** + * Sets the clip planes and send a message + */ + void setPlane(int planeNum, Vector4d plane) { + initPlane(planeNum, plane); + sendMessage(PLANE_CHANGED, + new Integer(planeNum), + new Vector4d(this.xformPlanes[planeNum])); + } + + /** + * Gets planes + */ + void getPlanes(Vector4d[] planes){ + + for (int i = 0; i < 6; i++) { + planes[i].set(this.planes[i]); + } + } + + /** + * Gets the specified clipping plane + */ + void getPlane(int planeNum, Vector4d plane) { + if (planeNum < 0 || planeNum > 5) + throw new IllegalArgumentException(J3dI18N.getString("ModelClip6")); + plane.set(this.planes[planeNum]); + } + + /** + * Initializes planes before the object is live + */ + void initEnables(boolean[] enables) { + this.enables[0] = enables[0]; + this.enables[1] = enables[1]; + this.enables[2] = enables[2]; + this.enables[3] = enables[3]; + this.enables[4] = enables[4]; + this.enables[5] = enables[5]; + } + + /** + * Sets the clip planes and send a message + */ + void setEnables(boolean[] enables) { + Boolean[] en = new Boolean[6]; + + initEnables(enables); + en[0] = (enables[0] ? Boolean.TRUE: Boolean.FALSE); + en[1] = (enables[1] ? Boolean.TRUE: Boolean.FALSE); + en[2] = (enables[2] ? Boolean.TRUE: Boolean.FALSE); + en[3] = (enables[3] ? Boolean.TRUE: Boolean.FALSE); + en[4] = (enables[4] ? Boolean.TRUE: Boolean.FALSE); + en[5] = (enables[5] ? Boolean.TRUE: Boolean.FALSE); + + sendMessage(ENABLES_CHANGED, en, null); + } + + /** + * Initializes planes before the object is live + */ + void initEnable(int planeNum, boolean enable) { + if (planeNum < 0 || planeNum > 5) + throw new IllegalArgumentException(J3dI18N.getString("ModelClip6")); + this.enables[planeNum] = enable; + } + + /** + * Sets the clip planes and send a message + */ + void setEnable(int planeNum, boolean enable) { + initEnable(planeNum, enable); + sendMessage(ENABLE_CHANGED, + new Integer(planeNum), + (enable ? Boolean.TRUE: Boolean.FALSE)); + } + + /** + * Gets enables + */ + void getEnables(boolean[] enables) { + enables[0] = this.enables[0]; + enables[1] = this.enables[1]; + enables[2] = this.enables[2]; + enables[3] = this.enables[3]; + enables[4] = this.enables[4]; + enables[5] = this.enables[5]; + } + + /** + * Gets the specified enable + */ + boolean getEnable(int planeNum) { + if (planeNum < 0 || planeNum > 5) + throw new IllegalArgumentException(J3dI18N.getString("ModelClip6")); + return (this.enables[planeNum]); + } + + /** + * Set the Model Clip's region of influencing + */ + void initInfluencingBounds(Bounds region) { + if (region != null) { + this.regionOfInfluence = (Bounds) region.clone(); + if (staticTransform != null) { + regionOfInfluence.transform(staticTransform.transform); + } + } else { + this.regionOfInfluence = null; + } + } + + /** + * Set the Model Clip's region of influencing and send message + */ + void setInfluencingBounds(Bounds region) { + initInfluencingBounds(region); + sendMessage(BOUNDS_CHANGED, + (region != null ? (Bounds) region.clone(): null), + null); + } + + /** + * Get the Model Clip's region of influencing. + */ + Bounds getInfluencingBounds() { + Bounds b = null; + + if (regionOfInfluence != null) { + b = (Bounds) regionOfInfluence.clone(); + if (staticTransform != null) { + Transform3D invTransform = staticTransform.getInvTransform(); + b.transform(invTransform); + } + } + return b; + } + + /** + * Set the Model Clip's region of influencing to the specified Leaf node. + */ + void initInfluencingBoundingLeaf(BoundingLeaf region) { + if (region != null) { + boundingLeaf = (BoundingLeafRetained)region.retained; + } else { + boundingLeaf = null; + } + } + + /** + * Set the Model Clip's region of influencing to the specified Leaf node. + */ + void setInfluencingBoundingLeaf(BoundingLeaf region) { + if (boundingLeaf != null) + boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorModelClip); + if (region != null) { + boundingLeaf = (BoundingLeafRetained)region.retained; + boundingLeaf.mirrorBoundingLeaf.addUser(mirrorModelClip); + } else { + boundingLeaf = null; + } + + sendMessage(BOUNDINGLEAF_CHANGED, + (boundingLeaf != null ? + boundingLeaf.mirrorBoundingLeaf : null), + null); + } + + + /** + * Get the Model Clip's region of influencing. + */ + BoundingLeaf getInfluencingBoundingLeaf() { + return (boundingLeaf != null ? + (BoundingLeaf)boundingLeaf.source : null); + } + + /** + * Replaces the specified scope with the scope provided. + * @param scope the new scope + * @param index which scope to replace + */ + void initScope(Group scope, int index) { + scopes.setElementAt((GroupRetained)(scope.retained), index); + } + + /** + * Replaces the specified scope with the scope provided. + * @param scope the new scope + * @param index which scope to replace + */ + void setScope(Group scope, int index) { + + ArrayList addScopeList = new ArrayList(); + ArrayList removeScopeList = new ArrayList(); + GroupRetained group; + Object[] scopeInfo = new Object[3]; + + group = scopes.get(index); + tempKey.reset(); + group.removeAllNodesForScopedModelClip(mirrorModelClip, removeScopeList, tempKey); + + group = (GroupRetained)scope.retained; + initScope(scope, index); + tempKey.reset(); + // If its a group, then add the scope to the group, if + // its a shape, then keep a list to be added during + // updateMirrorObject + group.addAllNodesForScopedModelClip(mirrorModelClip,addScopeList, tempKey); + scopeInfo[0] = addScopeList; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE:Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo, null); + } + + /** + * Inserts the specified scope at specified index + * @param scope the new scope + * @param index position to insert new scope at + */ + void initInsertScope(Node scope, int index) { + GroupRetained group = (GroupRetained)scope.retained; + group.setMclipScope(); + scopes.insertElementAt((GroupRetained)(scope.retained), index); + } + + /** + * Inserts the specified scope at specified index and sends + * a message + * @param scope the new scope + * @param index position to insert new scope at + */ + void insertScope(Node scope, int index) { + Object[] scopeInfo = new Object[3]; + ArrayList addScopeList = new ArrayList(); + + initInsertScope(scope, index); + GroupRetained group = (GroupRetained)scope.retained; + tempKey.reset(); + group.addAllNodesForScopedModelClip(mirrorModelClip,addScopeList, tempKey); + scopeInfo[0] = addScopeList; + scopeInfo[1] = null; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo, null); + } + + + void initRemoveScope(int index) { + GroupRetained group = scopes.elementAt(index); + group.removeMclipScope(); + scopes.removeElementAt(index); + + } + + void removeScope(int index) { + + Object[] scopeInfo = new Object[3]; + ArrayList removeScopeList = new ArrayList(); + GroupRetained group = scopes.elementAt(index); + + initRemoveScope(index); + tempKey.reset(); + group.removeAllNodesForScopedModelClip(mirrorModelClip, removeScopeList, tempKey); + + scopeInfo[0] = null; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo, null); + } + + /** + * Removes the specified Group node from this ModelClip's list of + * scopes if the specified node is not found in the list of scoped + * nodes, method returns quietly. + * + * @param Group node to be removed + */ + void removeScope(Group node) { + int ind = indexOfScope(node); + if(ind >= 0) + removeScope(ind); + } + + void initRemoveScope(Group node) { + int ind = indexOfScope(node); + if(ind >= 0) + initRemoveScope(ind); + } + + /** + * Removes all the Group nodes from the ModelClip's scope + * list. The ModelClip reverts to universal scope. + */ + void removeAllScopes() { + Object[] scopeInfo = new Object[3]; + ArrayList removeScopeList = new ArrayList(); + int n = scopes.size(); + for(int index = n-1; index >= 0; index--) { + GroupRetained group = scopes.elementAt(index); + initRemoveScope(index); + tempKey.reset(); + group.removeAllNodesForScopedModelClip(mirrorModelClip, removeScopeList, tempKey); + } + + scopeInfo[0] = null; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo, null); + } + + + void initRemoveAllScopes() { + int n = scopes.size(); + for(int i = n-1; i >= 0; i--) { + initRemoveScope(i); + } + } + + /** + * Returns the scope specified by the index. + * @param index which scope to return + * @return the scoperen at location index + */ + Group getScope(int index) { + return (Group)scopes.elementAt(index).source; + } + +/** + * Returns an enumeration object of the scoperen. + * @return an enumeration object of the scoperen + */ +Enumeration<Group> getAllScopes() { + Enumeration<GroupRetained> elm = scopes.elements(); + Vector<Group> v = new Vector<Group>(scopes.size()); + while (elm.hasMoreElements()) { + v.add((Group)elm.nextElement().source); + } + return v.elements(); +} + + /** + * Appends the specified scope to this node's list of scopes before + * the fog is alive + * @param scope the scope to add to this node's list of scopes + */ + void initAddScope(Group scope) { + GroupRetained group = (GroupRetained)scope.retained; + scopes.addElement((GroupRetained)(scope.retained)); + group.setMclipScope(); + } + + /** + * Appends the specified scope to this node's list of scopes. + * @param scope the scope to add to this node's list of scopes + */ + void addScope(Group scope) { + + Object[] scopeInfo = new Object[3]; + ArrayList addScopeList = new ArrayList(); + GroupRetained group = (GroupRetained)scope.retained; + + initAddScope(scope); + tempKey.reset(); + group.addAllNodesForScopedModelClip(mirrorModelClip,addScopeList, tempKey); + scopeInfo[0] = addScopeList; + scopeInfo[1] = null; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo, null); + } + + /** + * Returns a count of this nodes' scopes. + * @return the number of scopes descendant from this node + */ + int numScopes() { + return scopes.size(); + } + + /** + * Returns the index of the specified Group node within the ModelClip's list of scoped + * Group nodes + * @param Group node whose index is desired + * @return index of this node + */ + int indexOfScope(Group node) { + if(node != null) + return scopes.indexOf(node.retained); + else + return scopes.indexOf(null); + } + + /** + * This sets the immedate mode context flag + */ + void setInImmCtx(boolean inCtx) { + inImmCtx = inCtx; + } + + /** + * This gets the immedate mode context flag + */ + boolean getInImmCtx() { + return (inImmCtx); + } + + + /** + * This method and its native counterpart update the native context + * model clip planes. + */ + void update(Canvas3D cv, int enableMask) { + cv.setModelViewMatrix(cv.ctx, + cv.vworldToEc.mat, + getLastLocalToVworld()); + update(cv.ctx, enableMask, getLastLocalToVworld()); + } + +void update(Context ctx, int enableMask, Transform3D trans) { + for (int i = 0; i < 6; i++) { + Vector4d v = xformPlanes[i]; + boolean enable = ((enableMask & (1 << i)) != 0); + Pipeline.getPipeline().updateModelClip(ctx, i, enable, + v.x, v.y, v.z, v.w); + } +} + + void initMirrorObject(Object[] args) { + Shape3DRetained shape; + Object[] scopeInfo = (Object[]) args[2]; + Boolean scoped = (Boolean)scopeInfo[0]; + ArrayList shapeList = (ArrayList)scopeInfo[1]; + BoundingLeafRetained bl=(BoundingLeafRetained)((Object[])args[4])[0]; + Bounds bnds = (Bounds)((Object[])args[4])[1]; + + for (int i = 0; i < shapeList.size(); i++) { + shape = ((GeometryAtom)shapeList.get(i)).source; + shape.addModelClip(mirrorModelClip); + } + mirrorModelClip.isScoped = scoped.booleanValue(); + + if (bl != null) { + mirrorModelClip.boundingLeaf = bl.mirrorBoundingLeaf; + mirrorModelClip.region = boundingLeaf.transformedRegion; + } else { + mirrorModelClip.boundingLeaf = null; + mirrorModelClip.region = null; + } + + if (bnds != null) { + mirrorModelClip.regionOfInfluence = bnds; + if (mirrorModelClip.region == null) { + mirrorModelClip.region = (Bounds)regionOfInfluence.clone(); + mirrorModelClip.region.transform(regionOfInfluence, getLastLocalToVworld()); + } + } + else { + mirrorModelClip.regionOfInfluence = null; + } + boolean[] ens = (boolean[])((Object[])args[4])[2]; + + for (int i = 0; i < ens.length; i++) { + mirrorModelClip.enables[i] = ens[i]; + } + mirrorModelClip.enableFlag = mirrorModelClip.enables[0] | + mirrorModelClip.enables[1] | + mirrorModelClip.enables[2] | + mirrorModelClip.enables[3] | + mirrorModelClip.enables[4] | + mirrorModelClip.enables[5] ; + + } + + + + @Override + void updateMirrorObject(Object[] objs) { + int component = ((Integer)objs[1]).intValue(); + if ((component & PLANES_CHANGED) != 0) { + Vector4d[] pl = ((Vector4d[]) objs[2]); + + for (int i = 0; i < 6; i++) { + mirrorModelClip.xformPlanes[i].set(pl[i]); + } + } + else if ((component & PLANE_CHANGED) != 0) { + int planeNum = ((Integer)objs[2]).intValue(); + + mirrorModelClip.xformPlanes[planeNum].set((Vector4d)objs[3]); + } + else if ((component & INIT_MIRROR) != 0) { + Vector4d[] pl = (Vector4d[]) objs[3]; + for (int i = 0; i < 6; i++) { + mirrorModelClip.xformPlanes[i].set(pl[i]); + } + } + } + + // The update Object function. + void updateImmediateMirrorObject(Object[] objs) { + int component = ((Integer)objs[1]).intValue(); + + if ((component & BOUNDINGLEAF_CHANGED) != 0) { + mirrorModelClip.boundingLeaf = (BoundingLeafRetained)objs[2]; + if (objs[2] != null) { + mirrorModelClip.region = mirrorModelClip.boundingLeaf.transformedRegion; + } + else { + if (mirrorModelClip.regionOfInfluence != null) { + mirrorModelClip.region = mirrorModelClip.regionOfInfluence.copy(mirrorModelClip.region); + mirrorModelClip.region.transform(mirrorModelClip.regionOfInfluence, + getCurrentLocalToVworld()); + } + else { + mirrorModelClip.region = null; + } + + } + } + + if ((component & BOUNDS_CHANGED) != 0) { + mirrorModelClip.regionOfInfluence = (Bounds) objs[2]; + if (mirrorModelClip.boundingLeaf == null) { + if (objs[2] != null) { + mirrorModelClip.region = mirrorModelClip.regionOfInfluence.copy(mirrorModelClip.region); + + mirrorModelClip.region.transform(mirrorModelClip.regionOfInfluence, + getCurrentLocalToVworld()); + } + else { + mirrorModelClip.region = null; + } + } + } + + if ((component & SCOPE_CHANGED) != 0) { + Object[] scopeList = (Object[])objs[2]; + ArrayList addList = (ArrayList)scopeList[0]; + ArrayList removeList = (ArrayList)scopeList[1]; + boolean isScoped = ((Boolean)scopeList[2]).booleanValue(); + + if (addList != null) { + mirrorModelClip.isScoped = isScoped; + for (int i = 0; i < addList.size(); i++) { + Shape3DRetained obj = ((GeometryAtom)addList.get(i)).source; + obj.addModelClip(mirrorModelClip); + } + } + + if (removeList != null) { + mirrorModelClip.isScoped = isScoped; + for (int i = 0; i < removeList.size(); i++) { + Shape3DRetained obj = ((GeometryAtom)removeList.get(i)).source; + obj.removeModelClip(mirrorModelClip); + } + } + } + + if ((component & ENABLES_CHANGED) != 0) { + Boolean[] en = ((Boolean[]) objs[2]); + + mirrorModelClip.enables[0] = en[0].booleanValue(); + mirrorModelClip.enables[1] = en[1].booleanValue(); + mirrorModelClip.enables[2] = en[2].booleanValue(); + mirrorModelClip.enables[3] = en[3].booleanValue(); + mirrorModelClip.enables[4] = en[4].booleanValue(); + mirrorModelClip.enables[5] = en[5].booleanValue(); + mirrorModelClip.enableFlag = mirrorModelClip.enables[0] | + mirrorModelClip.enables[1] | + mirrorModelClip.enables[2] | + mirrorModelClip.enables[3] | + mirrorModelClip.enables[4] | + mirrorModelClip.enables[5] ; + } else if ((component & ENABLE_CHANGED) != 0) { + int planeNum = ((Integer)objs[2]).intValue(); + + mirrorModelClip.enables[planeNum] = ((Boolean)objs[3]).booleanValue(); + mirrorModelClip.enableFlag = mirrorModelClip.enables[0] | + mirrorModelClip.enables[1] | + mirrorModelClip.enables[2] | + mirrorModelClip.enables[3] | + mirrorModelClip.enables[4] | + mirrorModelClip.enables[5] ; + } + } + + + /** Note: This routine will only be called on + * the mirror object - will update the object's + * cached region and transformed region + */ + @Override + void updateBoundingLeaf() { + if (boundingLeaf != null && boundingLeaf.switchState.currentSwitchOn) { + region = boundingLeaf.transformedRegion; + } else { + if (regionOfInfluence != null) { + region = regionOfInfluence.copy(region); + region.transform(regionOfInfluence, getCurrentLocalToVworld()); + } else { + region = null; + } + } + } + + + @Override + void setLive(SetLiveState s) { + GroupRetained group; + + super.doSetLive(s); + + if (inSharedGroup) { + throw new + IllegalSharingException(J3dI18N.getString("ModelClipRetained1")); + } + + // Create the mirror object + + + if (mirrorModelClip == null) { + mirrorModelClip = (ModelClipRetained)this.clone(); + mirrorModelClip.boundingLeaf = null; + mirrorModelClip.sgModelClip = this; + } + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(mirrorModelClip); + s.scopedNodesViewList.add(s.viewLists.get(0)); + } else { + s.nodeList.add(mirrorModelClip); + } + + // If bounding leaf is not null, add the mirror object as a user + // so that any changes to the bounding leaf will be received + if (boundingLeaf != null) { + boundingLeaf.mirrorBoundingLeaf.addUser(mirrorModelClip); + } + // process switch leaf + if (s.switchTargets != null && + s.switchTargets[0] != null) { + s.switchTargets[0].addNode(mirrorModelClip, Targets.ENV_TARGETS); + } + mirrorModelClip.switchState = s.switchStates.get(0); + + // add this model clip to the transform target + if (s.transformTargets != null && s.transformTargets[0] != null) { + s.transformTargets[0].addNode(mirrorModelClip, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + + s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| + J3dThread.UPDATE_RENDER; + super.markAsLive(); + + + // Initialize the mirror object, this needs to be done, when + // renderBin is not accessing any of the fields + J3dMessage createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.universe = universe; + createMessage.type = J3dMessage.MODELCLIP_CHANGED; + createMessage.args[0] = this; + // a snapshot of all attributes that needs to be initialized + // in the mirror object + createMessage.args[1]= new Integer(INIT_MIRROR); + ArrayList addScopeList = new ArrayList(); + for (int i = 0; i < scopes.size(); i++) { + group = scopes.get(i); + tempKey.reset(); + group.addAllNodesForScopedModelClip(mirrorModelClip, addScopeList, tempKey); + } + Object[] scopeInfo = new Object[2]; + scopeInfo[0] = ((scopes.size() > 0) ? Boolean.TRUE:Boolean.FALSE); + scopeInfo[1] = addScopeList; + createMessage.args[2] = scopeInfo; + createMessage.args[3] = xformPlanes.clone(); + + Object[] obj = new Object[3]; + obj[0] = boundingLeaf; + obj[1] = (regionOfInfluence != null?regionOfInfluence.clone():null); + obj[2] = enables.clone(); + createMessage.args[4] = obj; + VirtualUniverse.mc.processMessage(createMessage); + + + } + + + /** + * This clearLive routine first calls the superclass's method, then + * it removes itself to the list of model clip + */ + @Override + void clearLive(SetLiveState s) { + + super.clearLive(s); + s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| + J3dThread.UPDATE_RENDER; + if (s.switchTargets != null && + s.switchTargets[0] != null) { + s.switchTargets[0].addNode(mirrorModelClip, Targets.ENV_TARGETS); + } + // Remove this mirror light as users of the bounding leaf + if (mirrorModelClip.boundingLeaf != null) + mirrorModelClip.boundingLeaf.removeUser(mirrorModelClip); + + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(mirrorModelClip); + s.scopedNodesViewList.add(s.viewLists.get(0)); + } else { + s.nodeList.add(mirrorModelClip); + } + if (s.transformTargets != null && s.transformTargets[0] != null) { + s.transformTargets[0].addNode(mirrorModelClip, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + + + if (scopes.size() > 0) { + J3dMessage createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.universe = universe; + createMessage.type = J3dMessage.MODELCLIP_CHANGED; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(CLEAR_MIRROR); + ArrayList removeScopeList = new ArrayList(); + for (int i = 0; i < scopes.size(); i++) { + GroupRetained group = scopes.get(i); + tempKey.reset(); + group.removeAllNodesForScopedModelClip(mirrorModelClip, removeScopeList, tempKey); + } + createMessage.args[2] = removeScopeList; + VirtualUniverse.mc.processMessage(createMessage); + } + } + + // This is called on the parent object + void clearMirrorObject(Object[] args) { + Shape3DRetained shape; + ArrayList shapeList = (ArrayList)args[2]; + + for (int i = 0; i < shapeList.size(); i++) { + shape = ((GeometryAtom)shapeList.get(i)).source; + shape.removeModelClip(mirrorModelClip); + } + + mirrorModelClip.isScoped = false; + + } + + + // Clone the retained side only, internal use only + @Override + protected Object clone() { + ModelClipRetained mc = (ModelClipRetained)super.clone(); + + mc.planes = new Vector4d[6]; + for (int i = 0; i < 6; i++) { + mc.planes[i] = new Vector4d(this.planes[i]); + mc.xformPlanes[i] = new Vector4d(this.xformPlanes[i]); + } + + mc.enables = new boolean[6]; + getEnables(mc.enables); + + // Derive the enables flag + mc.enableFlag = (mc.enables[0] | + mc.enables[1] | + mc.enables[2] | + mc.enables[3] | + mc.enables[4] | + mc.enables[5] ); + + mc.inImmCtx = false; + mc.region = null; + mc.sgModelClip = null; + mc.mirrorModelClip = null; + mc.environmentSets = new UnorderList(1, EnvironmentSet.class); + + if (regionOfInfluence != null) { + mc.regionOfInfluence = (Bounds) regionOfInfluence.clone(); + } + + return mc; + } + + + // Called on mirror object + void updateImmediateTransformChange() { + // If bounding leaf is null, tranform the bounds object + if (boundingLeaf == null) { + if (regionOfInfluence != null) { + region = regionOfInfluence.copy(region); + region.transform(regionOfInfluence, + sgModelClip.getCurrentLocalToVworld()); + } + + } + } + + + void printPlane(int index, String string) + { + System.err.println(string + " : < " + planes[index].toString() + + " > " + enables[index]); + } + + void printPlanes(String string, Vector4d[] planes) + { + System.err.println(string); + printPlane(0, "[0]"); + printPlane(1, "[1]"); + printPlane(2, "[2]"); + printPlane(3, "[3]"); + printPlane(4, "[4]"); + printPlane(5, "[5]"); + } + + + void printEnables(String string, boolean[] enables) + { + System.err.println(string); + System.err.println("[0] : < " + enables[0] + " >"); + System.err.println("[1] : < " + enables[1] + " >"); + System.err.println("[2] : < " + enables[2] + " >"); + System.err.println("[3] : < " + enables[3] + " >"); + System.err.println("[4] : < " + enables[4] + " >"); + System.err.println("[5] : < " + enables[5] + " >"); + } + + final void sendMessage(int attrMask, Object attr1, Object attr2) { + J3dMessage createMessage = new J3dMessage(); + createMessage.threads = targetThreads; + createMessage.type = J3dMessage.MODELCLIP_CHANGED; + createMessage.universe = universe; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr1; + createMessage.args[3] = attr2; + VirtualUniverse.mc.processMessage(createMessage); + } + + @Override + void mergeTransform(TransformGroupRetained staticTransform) { + super.mergeTransform(staticTransform); + + if (regionOfInfluence != null) { + regionOfInfluence.transform(staticTransform.transform); + } + + Transform3D xform = staticTransform.getNormalTransform(); + for (int i = 0; i < 6; i++) { + xform.transform(planes[i], xformPlanes[i]); + } + } + @Override + void getMirrorObjects(ArrayList leafList, HashKey key) { + leafList.add(mirrorModelClip); + } +} |