diff options
Diffstat (limited to 'src/javax/media/j3d/LightRetained.java')
-rw-r--r-- | src/javax/media/j3d/LightRetained.java | 1074 |
1 files changed, 1074 insertions, 0 deletions
diff --git a/src/javax/media/j3d/LightRetained.java b/src/javax/media/j3d/LightRetained.java new file mode 100644 index 0000000..7780713 --- /dev/null +++ b/src/javax/media/j3d/LightRetained.java @@ -0,0 +1,1074 @@ +/* + * Copyright 1996-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.Color3f; + +/** + * LightRetained is an abstract class that contains instance variable common to + * all lights. + */ + +abstract class LightRetained extends LeafRetained { + + // Statics used when something in the light changes + static final int ENABLE_CHANGED = 0x0001; + static final int SCOPE_CHANGED = 0x0002; + static final int BOUNDS_CHANGED = 0x0004; + static final int COLOR_CHANGED = 0x0008; + static final int BOUNDINGLEAF_CHANGED = 0x0010; + static final int INIT_MIRROR = 0x0020; + static final int CLEAR_MIRROR = 0x0040; + static final int LAST_DEFINED_BIT = 0x0040; + + // Indicates whether the light is turned on. + boolean lightOn = true; + + // The color of the light (white by default). + Color3f color = new Color3f(1.0f, 1.0f, 1.0f); + +// This node which specifies the hierarchical scope of the +// light. A null reference means that this light has universal +// scope. +Vector<GroupRetained> scopes = new Vector<GroupRetained>(); + + /** + * The Boundary object defining the lights's region of influence. + */ + Bounds regionOfInfluence = null; + + /** + * The bounding leaf reference + */ + BoundingLeafRetained boundingLeaf = null; + + /** + * The transformed value of the applicationRegion. + */ + Bounds region = null; + + /** + * This bitmask is set when something changes in the light + */ + int lightDirty = 0xffff; + + // This is a copy of the sgLight's dirty bits + int sgLightDirty = 0xffff; + + // The type of light + int lightType = -1; + + // This is true when this light is needed in the current light set + boolean isNeeded = false; + + // This is true when this light is referenced in an immediate mode context + boolean inImmCtx = false; + + // A back reference to the scene graph light, when this is a mirror light + LightRetained sgLight = null; + + // A HashKey for lights in a shared group + HashKey key = null; + + // An array of mirror lights, one for each instance of this light in a + // shared group. Entry 0 is the only one valid if we are not in a shared + // group. + LightRetained[] mirrorLights = new LightRetained[1]; + + // The number of valid lights in mirrorLights + int numMirrorLights = 0; + + // Indicated whether the light is a scoped light + boolean isScoped = false; + + // The object that contains the dynamic HashKey - a string type object + // Used in scoping + HashKey tempKey = new HashKey(250); + + /** + * A list of all the EnvironmentSets that reference this light. + * Note that multiple RenderBin update thread may access + * this shared environmentSets simultaneously. + * So we use UnorderList when sync. all the operations. + */ + UnorderList environmentSets = new UnorderList(1, EnvironmentSet.class); + + // Is true, if the mirror light is viewScoped + boolean isViewScoped = false; + + +/** + * Temporary list of newly added mirror lights, during any setlive + */ +ArrayList<LightRetained> newlyAddedMirrorLights = new ArrayList<LightRetained>(); + + // Target threads to be notified when light changes + static final int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT | + J3dThread.UPDATE_RENDER; + + /** + * Initialize the light on or off. + * @param state true or false to enable or disable the light + */ + void initEnable(boolean state) { + this.lightOn = state; + } + + /** + * Turns the light on or off and send a message + * @param state true or false to enable or disable the light + */ + void setEnable(boolean state) { + initEnable(state); + sendMessage(ENABLE_CHANGED, + (state ? Boolean.TRUE: Boolean.FALSE)); + } + + + /** + * Returns the state of the light (on/off). + * @return true if the light is on, false if the light is off. + */ + boolean getEnable() { + return this.lightOn; + } + + /** + * Initialize the color of this light node. + * @param color the value of this new light color + */ + void initColor(Color3f color) { + this.color.set(color); + } + + /** + * Sets the color of this light node and send a message + * @param color the value of this new light color + */ + void setColor(Color3f color) { + initColor(color); + sendMessage(COLOR_CHANGED, new Color3f(color)); + } + + /** + * Retrieves the color of this light. + * @param color the vector that will receive the color of this light + */ + void getColor(Color3f color) { + color.set(this.color); + } + + /** + * Initializes the specified scope with the scope provided. + * @param scope the new scope + * @param index which scope to replace + */ + void initScope(Group scope, int index) { + GroupRetained group = (GroupRetained)scope.retained; + scopes.setElementAt(group, index); + + } + + + /** + * Replaces the specified scope with the scope provided and + * send a message + * @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(); + Object[] scopeInfo = new Object[3]; + + GroupRetained group = scopes.get(index); + tempKey.reset(); + group.removeAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights, removeScopeList, tempKey); + + + group = (GroupRetained)scope.retained; + 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.addAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights,addScopeList, tempKey); + + + initScope(scope, index); + scopeInfo[0] = addScopeList; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo); + } + + /** + * Inserts the specified scope at specified index. + * @param scope the new scope + * @param index position to insert new scope at + */ + void initInsertScope(Group scope, int index) { + GroupRetained group = (GroupRetained)scope.retained; + scopes.insertElementAt(group, index); + group.setLightScope(); + } + + /** + * Inserts the specified scope at specified index. + * @param scope the new scope + * @param index position to insert new scope at + */ + void insertScope(Group scope, int index) { + + Object[] scopeInfo = new Object[3]; + ArrayList addScopeList = new ArrayList(); + GroupRetained group = (GroupRetained)scope.retained; + + tempKey.reset(); + group.addAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights,addScopeList, tempKey); + + initInsertScope(scope, index); + scopeInfo[0] = addScopeList; + scopeInfo[1] = null; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo); + } + + + /** + * Removes the scope at specified index. + * @param index which scope to remove + */ + void initRemoveScope(int index) { + GroupRetained group = scopes.remove(index); + group.removeLightScope(); + } + + + /** + * Removes the scope at specified index. + * @param index which scope to remove + */ + void removeScope(int index) { + + Object[] scopeInfo = new Object[3]; + ArrayList removeScopeList = new ArrayList(); + + GroupRetained group = scopes.elementAt(index); + tempKey.reset(); + group.removeAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights, removeScopeList, tempKey); + initRemoveScope(index); scopeInfo[0] = null; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo); + } + + + /** + * Removes the specified scope + * @param scope to be removed + */ + void removeScope(Group scope) { + int ind = indexOfScope(scope); + if(ind >= 0) + removeScope(ind); + } + + void initRemoveScope(Group scope) { + int ind = indexOfScope(scope); + if(ind >= 0) + initRemoveScope(ind); + } + + /** + * Removes all the scopes from this Light's list of scopes + */ + void removeAllScopes() { + int n = scopes.size(); + Object[] scopeInfo = new Object[3]; + ArrayList removeScopeList = new ArrayList(); + + for(int index = n-1; index >= 0; index--) { + GroupRetained group = scopes.elementAt(index); + tempKey.reset(); + group.removeAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights, removeScopeList, tempKey); + initRemoveScope(index); + } + scopeInfo[0] = null; + scopeInfo[1] = removeScopeList; + scopeInfo[2] = (Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo); + } + + 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 of the scope to be returned + * @return the scope at location index + */ + Group getScope(int index) { + return (Group)scopes.elementAt(index).source; + } + +/** + * Returns an enumeration object of the scope + * @return an enumeration object of the scope + */ +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. + * @param scope the scope to add to this node's list of scopes + */ + void initAddScope(Group scope) { + GroupRetained group = (GroupRetained)scope.retained; + scopes.addElement(group); + group.setLightScope(); + } + + /** + * 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.addAllNodesForScopedLight((inSharedGroup?numMirrorLights:1), mirrorLights,addScopeList, tempKey); + scopeInfo[0] = addScopeList; + scopeInfo[1] = null; + scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE: Boolean.FALSE); + sendMessage(SCOPE_CHANGED, scopeInfo); + } + + /** + * 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 scope + * @return index of the scope in this Light's list of scopes + */ + int indexOfScope(Group scope) { + if(scope != null) + return scopes.indexOf(scope.retained); + else + return scopes.indexOf(null); + } + + /** + * Initializes the Light's region of influence. + * @param region a region that contains the Light's new region of influence + */ + void initInfluencingBounds(Bounds region) { + if (region != null) { + regionOfInfluence = (Bounds) region.clone(); + if (staticTransform != null) { + regionOfInfluence.transform(staticTransform.transform); + } + } else { + regionOfInfluence = null; + } + } + + + /** + * Set the Light's region of influence and send a message + * @param region a region that contains the Light's new region of influence + */ + void setInfluencingBounds(Bounds region) { + initInfluencingBounds(region); + sendMessage(BOUNDS_CHANGED, + (region != null ? region.clone() : null)); + } + + /** + * Get the Light's region of influence + * @return this Light's region of influence information + */ + Bounds getInfluencingBounds() { + Bounds b = null; + + if (regionOfInfluence != null) { + b = (Bounds) regionOfInfluence.clone(); + if (staticTransform != null) { + Transform3D invTransform = staticTransform.getInvTransform(); + b.transform(invTransform); + } + } + return b; + } + + /** + * Initializes the Light's region of influence to the specified Leaf node. + */ + void initInfluencingBoundingLeaf(BoundingLeaf region) { + if (region != null) { + boundingLeaf = (BoundingLeafRetained)region.retained; + } else { + boundingLeaf = null; + } + } + + /** + * Set the Light's region of influence to the specified Leaf node. + */ + void setInfluencingBoundingLeaf(BoundingLeaf region) { + int i, numLgts; + + numLgts = numMirrorLights; + if (numMirrorLights == 0) + numLgts = 1; + + if (boundingLeaf != null) { + // Remove the mirror lights as users of the original bounding leaf + for (i = 0; i < numLgts; i++) { + boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorLights[i]); + } + } + + if (region != null) { + boundingLeaf = (BoundingLeafRetained)region.retained; + // Add all mirror lights as user of this bounding leaf + for (i = 0; i < numLgts; i++) { + boundingLeaf.mirrorBoundingLeaf.addUser(mirrorLights[i]); + } + } else { + boundingLeaf = null; + } + + sendMessage(BOUNDINGLEAF_CHANGED, + (boundingLeaf != null ? + boundingLeaf.mirrorBoundingLeaf : null)); + } + + /** + * Get the Light's region of influence. + */ + BoundingLeaf getInfluencingBoundingLeaf() { + return (boundingLeaf != null ? + (BoundingLeaf)boundingLeaf.source : 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); + } + + + // Called on the parent Light object and loops over the mirror object + void initMirrorObject(Object[] args) { + Shape3DRetained shape; + Object[] scopeInfo = (Object[])((Object[])args[4])[5]; + ArrayList gAtomList = (ArrayList)scopeInfo[1]; + Boolean scoped = (Boolean)scopeInfo[0]; + BoundingLeafRetained bl=(BoundingLeafRetained)((Object[])args[4])[0]; + Bounds bnds = (Bounds)((Object[])args[4])[1]; + int numLgts = ((Integer)args[2]).intValue(); + LightRetained[] mLgts = (LightRetained[]) args[3]; + int k; + + for ( k = 0; k < numLgts; k++) { + for (int i = 0; i < gAtomList.size(); i++) { + shape = ((GeometryAtom)gAtomList.get(i)).source; + shape.addLight(mLgts[k]); + } + mLgts[k].isScoped = scoped.booleanValue(); + } + + for (k = 0; k < numLgts; k++) { + mLgts[k].inBackgroundGroup = ((Boolean)((Object[])args[4])[2]).booleanValue(); + mLgts[k].geometryBackground = (BackgroundRetained)((Object[])args[4])[3]; + + + if (bl != null) { + mLgts[k].boundingLeaf = bl.mirrorBoundingLeaf; + mLgts[k].region = mLgts[k].boundingLeaf.transformedRegion; + } else { + mLgts[k].boundingLeaf = null; + mLgts[k].region = null; + } + + if (bnds != null) { + mLgts[k].regionOfInfluence = bnds; + if (mLgts[k].region == null) { + mLgts[k].region = (Bounds)regionOfInfluence.clone(); + mLgts[k].region.transform(regionOfInfluence, getLastLocalToVworld()); + } + } + else { + mLgts[k].regionOfInfluence = null; + } + mLgts[k].lightOn = ((Boolean)((Object[])args[4])[4]).booleanValue(); + + } + // if its a ambient light,then do a immediate update of color + if (this instanceof AmbientLightRetained) { + Color3f clr = (Color3f) ((Object[])args[4])[6]; + for (int i = 0; i < numLgts; i++) { + mLgts[i].color.set(clr); + } + } + + } + + /** + * This method is implemented by each light for rendering + * context updates. This default one does nothing. + */ + abstract void update(Context ctx, int lightSlot, double scale); + + + // This routine is called when rendering Env structure + // get a message, this routine updates values in the mirror object + // that are not used by the renderer + void updateImmediateMirrorObject(Object[] objs) { + int component = ((Integer)objs[1]).intValue(); + int numLgts = ((Integer)objs[2]).intValue(); + LightRetained[] mLgts = (LightRetained[]) objs[3]; + + // Color changed called immediately only for ambient lights + if ((component & COLOR_CHANGED) != 0) { + for (int i = 0; i < numLgts; i++) { + mLgts[i].color.set(((Color3f)objs[4])); + } + } + else if ((component & ENABLE_CHANGED) != 0) { + for (int i = 0; i < numLgts; i++) + mLgts[i].lightOn = ((Boolean)objs[4]).booleanValue(); + } + else if ((component & BOUNDS_CHANGED) != 0) { + for (int i = 0; i < numLgts; i++) { + mLgts[i].regionOfInfluence = (Bounds) objs[4]; + if (mLgts[i].boundingLeaf == null) { + if (objs[4] != null) { + mLgts[i].region = mLgts[i].regionOfInfluence.copy(mLgts[i].region); + mLgts[i].region.transform(mLgts[i].regionOfInfluence, + mLgts[i].getCurrentLocalToVworld()); + } + else { + mLgts[i].region = null; + } + } + } + } + else if ((component & BOUNDINGLEAF_CHANGED) != 0) { + for (int i = 0; i < numLgts; i++) { + mLgts[i].boundingLeaf=((BoundingLeafRetained)objs[4]); + if (objs[4] != null) { + mLgts[i].region = mLgts[i].boundingLeaf.transformedRegion; + } + else { // evaluate regionOfInfluence if not null + if (mLgts[i].regionOfInfluence != null) { + mLgts[i].region = mLgts[i].regionOfInfluence.copy(mLgts[i].region); + mLgts[i].region.transform(mLgts[i].regionOfInfluence, + mLgts[i].getCurrentLocalToVworld()); + } + else { + mLgts[i].region = null; + } + } + } + } + else if ((component & SCOPE_CHANGED) != 0) { + int j, i; + Object[] scopeList = (Object[])objs[4]; + ArrayList addList = (ArrayList)scopeList[0]; + ArrayList removeList = (ArrayList)scopeList[1]; + boolean isScoped = ((Boolean)scopeList[2]).booleanValue(); + + if (addList != null) { + for (i = 0; i < numLgts; i++) { + mLgts[i].isScoped = isScoped; + for (j = 0; j < addList.size(); j++) { + Shape3DRetained obj = ((GeometryAtom)addList.get(j)).source; + obj.addLight(mLgts[i]); + } + } + } + + if (removeList != null) { + for (i = 0; i < numLgts; i++) { + mLgts[i].isScoped = isScoped; + for (j = 0; j < removeList.size(); j++) { + Shape3DRetained obj = ((GeometryAtom)removeList.get(j)).source; + obj.removeLight(mLgts[i]); + } + } + } + } + + + } + + + + // The update Object function called during RenderingEnv objUpdate + // Note : if you add any more fields here , you need to update + // updateLight() in RenderingEnvironmentStructure + @Override + void updateMirrorObject(Object[] objs) { + + int component = ((Integer)objs[1]).intValue(); + int numLgts = ((Integer)objs[2]).intValue(); + LightRetained[] mLgts = (LightRetained[]) objs[3]; + + if ((component & COLOR_CHANGED) != 0) { + for (int i = 0; i < numLgts; i++) { + mLgts[i].color.set(((Color3f)objs[4])); + } + } + + if ((component & INIT_MIRROR) != 0) { + for (int i = 0; i < numLgts; i++) { + Color3f clr = (Color3f) ((Object[])objs[4])[6]; + mLgts[i].color.set(clr); + } + } + } + + /** Note: This routine will only be called on + * the mirror object - will update the object's + * cached region and transformed region + */ + + @Override + void updateBoundingLeaf() { + // This is necessary, if for example, the region + // changes from sphere to box. + if (boundingLeaf != null && boundingLeaf.switchState.currentSwitchOn) { + region = boundingLeaf.transformedRegion; + } else { // evaluate regionOfInfluence if not null + if (regionOfInfluence != null) { + region = regionOfInfluence.copy(region); + region.transform(regionOfInfluence, getCurrentLocalToVworld()); + } else { + region = null; + } + } + } + @Override + void getMirrorObjects(ArrayList leafList, HashKey key) { + if (!inSharedGroup) { + leafList.add(mirrorLights[0]); + } + else { + for (int i=0; i<numMirrorLights; i++) { + if (mirrorLights[i].key.equals(key)) { + leafList.add(mirrorLights[i]); + break; + } + } + + } + } + /** + * This gets the mirror light for this light given the key. + */ + LightRetained getMirrorLight(HashKey key) { + int i; + LightRetained[] newLights; + + if (inSharedGroup) { + for (i=0; i<numMirrorLights; i++) { + if (mirrorLights[i].key.equals(key)) { + return(mirrorLights[i]); + } + } + if (numMirrorLights == mirrorLights.length) { + newLights = new LightRetained[numMirrorLights*2]; + for (i=0; i<numMirrorLights; i++) { + newLights[i] = mirrorLights[i]; + } + mirrorLights = newLights; + } + // mirrorLights[numMirrorLights] = (LightRetained) + // this.clone(true); + mirrorLights[numMirrorLights] = (LightRetained) this.clone(); + // If the bounding leaf is not null , add this + // mirror object as a user + if (boundingLeaf != null) { + mirrorLights[numMirrorLights].boundingLeaf = this.boundingLeaf.mirrorBoundingLeaf; + if (mirrorLights[numMirrorLights].boundingLeaf != null) + mirrorLights[numMirrorLights].boundingLeaf.addUser(mirrorLights[numMirrorLights]); + } + // mirrorLights[numMirrorLights].key = new HashKey(key); + mirrorLights[numMirrorLights].key = key; + mirrorLights[numMirrorLights].sgLight = this; + return(mirrorLights[numMirrorLights++]); + } else { + if (mirrorLights[0] == null) { + //mirrorLights[0] = (LightRetained) this.clone(true); + mirrorLights[0] = (LightRetained) this.clone(); + // If the bounding leaf is not null , add this + // mirror object as a user + if (boundingLeaf != null) { + mirrorLights[0].boundingLeaf = this.boundingLeaf.mirrorBoundingLeaf; + if (mirrorLights[0].boundingLeaf != null) + mirrorLights[0].boundingLeaf.addUser(mirrorLights[0]); + } + mirrorLights[0].sgLight = this; + } + return(mirrorLights[0]); + } + } + + @Override + void setLive(SetLiveState s) { + LightRetained ml; + int i, j; + + newlyAddedMirrorLights.clear(); + if (inImmCtx) { + throw new IllegalSharingException(J3dI18N.getString("LightRetained0")); + } + super.doSetLive(s); + + if (s.inSharedGroup) { + for (i=0; i<s.keys.length; i++) { + ml = this.getMirrorLight(s.keys[i]); + ml.localToVworld = new Transform3D[1][]; + ml.localToVworldIndex = new int[1][]; + + j = s.keys[i].equals(localToVworldKeys, 0, + localToVworldKeys.length); + if(j < 0) { + System.err.println("LightRetained : Can't find hashKey"); + } + + ml.localToVworld[0] = localToVworld[j]; + ml.localToVworldIndex[0] = localToVworldIndex[j]; + // If its view Scoped, then add this list + // to be sent to Rendering Env + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(ml); + s.scopedNodesViewList.add(s.viewLists.get(i)); + } else { + s.nodeList.add(ml); + } + + newlyAddedMirrorLights.add(ml); + if (boundingLeaf != null) { + boundingLeaf.mirrorBoundingLeaf.addUser(ml); + } + if (s.transformTargets != null && + s.transformTargets[i] != null) { + s.transformTargets[i].addNode(ml, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + if (s.switchTargets != null && + s.switchTargets[i] != null) { + s.switchTargets[i].addNode(ml, Targets.ENV_TARGETS); + } + ml.switchState = s.switchStates.get(j); + + } + } else { + ml = this.getMirrorLight(null); + ml.localToVworld = new Transform3D[1][]; + ml.localToVworldIndex = new int[1][]; + ml.localToVworld[0] = this.localToVworld[0]; + ml.localToVworldIndex[0] = this.localToVworldIndex[0]; + // Initialization of the mirror object + // If its view Scoped, then add this list + // to be sent to Rendering Env + // System.err.println("lightSetLive, s.viewList = "+s.viewLists); + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(ml); + s.scopedNodesViewList.add(s.viewLists.get(0)); + } else { + s.nodeList.add(ml); + } + newlyAddedMirrorLights.add(ml); + if (boundingLeaf != null) { + boundingLeaf.mirrorBoundingLeaf.addUser(ml); + } + if (s.transformTargets != null && + s.transformTargets[0] != null) { + s.transformTargets[0].addNode(ml, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + if (s.switchTargets != null && + s.switchTargets[0] != null) { + s.switchTargets[0].addNode(ml, Targets.ENV_TARGETS); + } + ml.switchState = s.switchStates.get(0); + } + s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| + J3dThread.UPDATE_RENDER; + super.markAsLive(); + + } + + J3dMessage initMessage(int num) { + J3dMessage createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.universe = universe; + createMessage.type = J3dMessage.LIGHT_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); + + LightRetained[] mlts = new LightRetained[newlyAddedMirrorLights.size()]; + for (int i = 0; i < mlts.length; i++) { + mlts[i] = newlyAddedMirrorLights.get(i); + } + createMessage.args[2] = new Integer(mlts.length); + createMessage.args[3] = mlts; + + Object[] obj = new Object[num]; + obj[0] = boundingLeaf; + obj[1] = (regionOfInfluence != null?regionOfInfluence.clone():null); + obj[2] = (inBackgroundGroup? Boolean.TRUE:Boolean.FALSE); + obj[3] = geometryBackground; + obj[4] = (lightOn? Boolean.TRUE:Boolean.FALSE); + + ArrayList addScopeList = new ArrayList(); + for (int i = 0; i < scopes.size(); i++) { + GroupRetained group = scopes.get(i); + tempKey.reset(); + group.addAllNodesForScopedLight(mlts.length, mlts, addScopeList, tempKey); + } + Object[] scopeInfo = new Object[2]; + scopeInfo[0] = ((scopes.size() > 0) ? Boolean.TRUE:Boolean.FALSE); + scopeInfo[1] = addScopeList; + obj[5] = scopeInfo; + Color3f clr = new Color3f(color); + obj[6] = clr; + createMessage.args[4] = obj; + return createMessage; + + } + + // The default set of clearLive actions + @Override + void clearLive(SetLiveState s) { + LightRetained ml; + newlyAddedMirrorLights.clear(); + super.clearLive(s); + + if (inSharedGroup) { + for (int i=0; i<s.keys.length; i++) { + ml = this.getMirrorLight(s.keys[i]); + if (s.transformTargets != null && + s.transformTargets[i] != null) { + s.transformTargets[i].addNode(ml, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + newlyAddedMirrorLights.add(ml); + // Remove this mirror light as users of the bounding leaf + if (ml.boundingLeaf != null) { + ml.boundingLeaf.removeUser(ml); + ml.boundingLeaf = null; + } + if (s.switchTargets != null && + s.switchTargets[i] != null) { + s.switchTargets[i].addNode(ml, Targets.ENV_TARGETS); + } + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(ml); + s.scopedNodesViewList.add(s.viewLists.get(i)); + } else { + s.nodeList.add(ml); + } + } + } else { + ml = this.getMirrorLight(null); + + // Remove this mirror light as users of the bounding leaf + if (ml.boundingLeaf != null) { + ml.boundingLeaf.removeUser(ml); + ml.boundingLeaf = null; + } + if (s.switchTargets != null && + s.switchTargets[0] != null) { + s.switchTargets[0].addNode(ml, Targets.ENV_TARGETS); + } + if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { + s.viewScopedNodeList.add(ml); + //System.err.println("s.viewList is " + s.viewLists); + s.scopedNodesViewList.add(s.viewLists.get(0)); + } else { + s.nodeList.add(ml); + } + if (s.transformTargets != null && + s.transformTargets[0] != null) { + s.transformTargets[0].addNode(ml, Targets.ENV_TARGETS); + s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; + } + + + newlyAddedMirrorLights.add(ml); + } + s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT| + J3dThread.UPDATE_RENDER; + + + + if (scopes.size() > 0) { + J3dMessage createMessage = new J3dMessage(); + LightRetained[] mlts = new LightRetained[newlyAddedMirrorLights.size()]; + for (int i = 0; i < mlts.length; i++) { + mlts[i] = newlyAddedMirrorLights.get(i); + } + createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.universe = universe; + createMessage.type = J3dMessage.LIGHT_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.removeAllNodesForScopedLight(mlts.length, mlts, removeScopeList, tempKey); + } + createMessage.args[2] = removeScopeList; + createMessage.args[3] = new Integer(mlts.length); + createMessage.args[4] = mlts; + VirtualUniverse.mc.processMessage(createMessage); + } + } + + void clearMirrorObject(Object[] args) { + Shape3DRetained shape; + ArrayList shapeList = (ArrayList)args[2]; + LightRetained[] mLgts = (LightRetained[]) args[4]; + int numLgts = ((Integer)args[3]).intValue(); + + for (int k = 0; k < numLgts; k++) { + for (int i = 0; i < shapeList.size(); i++) { + shape = ((GeometryAtom)shapeList.get(i)).source; + shape.removeLight(mLgts[k]); + } + mLgts[k].isScoped = false; + + } + + } + + + + /** + * Clones only the retained side, internal use only + */ + @Override + protected Object clone() { + LightRetained lr = (LightRetained)super.clone(); + lr.color = new Color3f(color); + lr.scopes = new Vector<GroupRetained>(scopes); + lr.initInfluencingBoundingLeaf(getInfluencingBoundingLeaf()); + lr.region = null; + lr.lightDirty = 0xffff; + lr.sgLightDirty = 0xffff; + lr.universe = null; + lr.isNeeded = false; + lr.inImmCtx = false; + lr.sgLight = null; + lr.key = null; + lr.mirrorLights = new LightRetained[1]; + lr.numMirrorLights = 0; + lr.environmentSets = new UnorderList(1, EnvironmentSet.class); + return lr; + } + + + // Called during RenderingEnv object update + @Override + void updateTransformChange() { + } + + // Called on mirror object and updated when message is received + void updateImmediateTransformChange() { + // If bounding leaf is null, tranform the bounds object + if (boundingLeaf == null) { + if (regionOfInfluence != null) { + region = regionOfInfluence.copy(region); + region.transform(regionOfInfluence, + getCurrentLocalToVworld()); + } + + } + } + + void sendMessage(int attrMask, Object attr) { + J3dMessage createMessage = new J3dMessage(); + createMessage.threads = targetThreads; + createMessage.type = J3dMessage.LIGHT_CHANGED; + createMessage.universe = universe; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + if (inSharedGroup) + createMessage.args[2] = new Integer(numMirrorLights); + else + createMessage.args[2] = new Integer(1); + + createMessage.args[3] = mirrorLights.clone(); + createMessage.args[4] = attr; + VirtualUniverse.mc.processMessage(createMessage); + } + + @Override + void mergeTransform(TransformGroupRetained xform) { + super.mergeTransform(xform); + if (regionOfInfluence != null) { + regionOfInfluence.transform(xform.transform); + } + } +} + |