aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/LightRetained.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/media/j3d/LightRetained.java')
-rw-r--r--src/javax/media/j3d/LightRetained.java1074
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);
+ }
+ }
+}
+