0001: /*
0002: * $RCSfile: LightRetained.java,v $
0003: *
0004: * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.7 $
0028: * $Date: 2008/02/28 20:17:25 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import javax.vecmath.*;
0035: import java.util.Enumeration;
0036: import java.util.Vector;
0037: import java.util.ArrayList;
0038:
0039: /**
0040: * LightRetained is an abstract class that contains instance variable common to
0041: * all lights.
0042: */
0043:
0044: abstract class LightRetained extends LeafRetained {
0045:
0046: // Statics used when something in the light changes
0047: static final int ENABLE_CHANGED = 0x0001;
0048: static final int SCOPE_CHANGED = 0x0002;
0049: static final int BOUNDS_CHANGED = 0x0004;
0050: static final int COLOR_CHANGED = 0x0008;
0051: static final int BOUNDINGLEAF_CHANGED = 0x0010;
0052: static final int INIT_MIRROR = 0x0020;
0053: static final int CLEAR_MIRROR = 0x0040;
0054: static final int LAST_DEFINED_BIT = 0x0040;
0055:
0056: // Indicates whether the light is turned on.
0057: boolean lightOn = true;
0058:
0059: // The color of the light (white by default).
0060: Color3f color = new Color3f(1.0f, 1.0f, 1.0f);
0061:
0062: // This node which specifies the hierarchical scope of the
0063: // light. A null reference means that this light has universal
0064: // scope.
0065: Vector scopes = new Vector();
0066:
0067: /**
0068: * The Boundary object defining the lights's region of influence.
0069: */
0070: Bounds regionOfInfluence = null;
0071:
0072: /**
0073: * The bounding leaf reference
0074: */
0075: BoundingLeafRetained boundingLeaf = null;
0076:
0077: /**
0078: * The transformed value of the applicationRegion.
0079: */
0080: Bounds region = null;
0081:
0082: /**
0083: * This bitmask is set when something changes in the light
0084: */
0085: int lightDirty = 0xffff;
0086:
0087: // This is a copy of the sgLight's dirty bits
0088: int sgLightDirty = 0xffff;
0089:
0090: // The type of light
0091: int lightType = -1;
0092:
0093: // This is true when this light is needed in the current light set
0094: boolean isNeeded = false;
0095:
0096: // This is true when this light is referenced in an immediate mode context
0097: boolean inImmCtx = false;
0098:
0099: // A back reference to the scene graph light, when this is a mirror light
0100: LightRetained sgLight = null;
0101:
0102: // A HashKey for lights in a shared group
0103: HashKey key = null;
0104:
0105: // An array of mirror lights, one for each instance of this light in a
0106: // shared group. Entry 0 is the only one valid if we are not in a shared
0107: // group.
0108: LightRetained[] mirrorLights = new LightRetained[1];
0109:
0110: // The number of valid lights in mirrorLights
0111: int numMirrorLights = 0;
0112:
0113: // Indicated whether the light is a scoped light
0114: boolean isScoped = false;
0115:
0116: // The object that contains the dynamic HashKey - a string type object
0117: // Used in scoping
0118: HashKey tempKey = new HashKey(250);
0119:
0120: /**
0121: * A list of all the EnvironmentSets that reference this light.
0122: * Note that multiple RenderBin update thread may access
0123: * this shared environmentSets simultaneously.
0124: * So we use UnorderList when sync. all the operations.
0125: */
0126: UnorderList environmentSets = new UnorderList(1,
0127: EnvironmentSet.class);
0128:
0129: // Is true, if the mirror light is viewScoped
0130: boolean isViewScoped = false;
0131:
0132: /**
0133: * Temporary list of newly added mirror lights, during any setlive
0134: */
0135: ArrayList newlyAddedMirrorLights = new ArrayList();
0136:
0137: // Target threads to be notified when light changes
0138: static final int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
0139: | J3dThread.UPDATE_RENDER;
0140:
0141: /**
0142: * Initialize the light on or off.
0143: * @param state true or false to enable or disable the light
0144: */
0145: void initEnable(boolean state) {
0146: this .lightOn = state;
0147: }
0148:
0149: /**
0150: * Turns the light on or off and send a message
0151: * @param state true or false to enable or disable the light
0152: */
0153: void setEnable(boolean state) {
0154: initEnable(state);
0155: sendMessage(ENABLE_CHANGED, (state ? Boolean.TRUE
0156: : Boolean.FALSE));
0157: }
0158:
0159: /**
0160: * Returns the state of the light (on/off).
0161: * @return true if the light is on, false if the light is off.
0162: */
0163: boolean getEnable() {
0164: return this .lightOn;
0165: }
0166:
0167: /**
0168: * Initialize the color of this light node.
0169: * @param color the value of this new light color
0170: */
0171: void initColor(Color3f color) {
0172: this .color.set(color);
0173: }
0174:
0175: /**
0176: * Sets the color of this light node and send a message
0177: * @param color the value of this new light color
0178: */
0179: void setColor(Color3f color) {
0180: initColor(color);
0181: sendMessage(COLOR_CHANGED, new Color3f(color));
0182: }
0183:
0184: /**
0185: * Retrieves the color of this light.
0186: * @param color the vector that will receive the color of this light
0187: */
0188: void getColor(Color3f color) {
0189: color.set(this .color);
0190: }
0191:
0192: /**
0193: * Initializes the specified scope with the scope provided.
0194: * @param scope the new scope
0195: * @param index which scope to replace
0196: */
0197: void initScope(Group scope, int index) {
0198: GroupRetained group = (GroupRetained) scope.retained;
0199: scopes.setElementAt(group, index);
0200:
0201: }
0202:
0203: /**
0204: * Replaces the specified scope with the scope provided and
0205: * send a message
0206: * @param scope the new scope
0207: * @param index which scope to replace
0208: */
0209: void setScope(Group scope, int index) {
0210: ArrayList addScopeList = new ArrayList();
0211: ArrayList removeScopeList = new ArrayList();
0212: GroupRetained group;
0213: Object[] scopeInfo = new Object[3];
0214:
0215: group = (GroupRetained) scopes.get(index);
0216: tempKey.reset();
0217: group.removeAllNodesForScopedLight(
0218: (inSharedGroup ? numMirrorLights : 1), mirrorLights,
0219: removeScopeList, tempKey);
0220:
0221: group = (GroupRetained) scope.retained;
0222: tempKey.reset();
0223: // If its a group, then add the scope to the group, if
0224: // its a shape, then keep a list to be added during
0225: // updateMirrorObject
0226: group.addAllNodesForScopedLight(
0227: (inSharedGroup ? numMirrorLights : 1), mirrorLights,
0228: addScopeList, tempKey);
0229:
0230: initScope(scope, index);
0231: J3dMessage createMessage = new J3dMessage();
0232: scopeInfo[0] = addScopeList;
0233: scopeInfo[1] = removeScopeList;
0234: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0235: : Boolean.FALSE);
0236: sendMessage(SCOPE_CHANGED, scopeInfo);
0237: }
0238:
0239: /**
0240: * Inserts the specified scope at specified index.
0241: * @param scope the new scope
0242: * @param index position to insert new scope at
0243: */
0244: void initInsertScope(Group scope, int index) {
0245: GroupRetained group = (GroupRetained) scope.retained;
0246: scopes.insertElementAt(group, index);
0247: group.setLightScope();
0248: }
0249:
0250: /**
0251: * Inserts the specified scope at specified index.
0252: * @param scope the new scope
0253: * @param index position to insert new scope at
0254: */
0255: void insertScope(Group scope, int index) {
0256:
0257: Object[] scopeInfo = new Object[3];
0258: ArrayList addScopeList = new ArrayList();
0259: GroupRetained group = (GroupRetained) scope.retained;
0260:
0261: tempKey.reset();
0262: group.addAllNodesForScopedLight(
0263: (inSharedGroup ? numMirrorLights : 1), mirrorLights,
0264: addScopeList, tempKey);
0265:
0266: initInsertScope(scope, index);
0267: scopeInfo[0] = addScopeList;
0268: scopeInfo[1] = null;
0269: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0270: : Boolean.FALSE);
0271: sendMessage(SCOPE_CHANGED, scopeInfo);
0272: }
0273:
0274: /**
0275: * Removes the scope at specified index.
0276: * @param index which scope to remove
0277: */
0278: void initRemoveScope(int index) {
0279: GroupRetained group = (GroupRetained) scopes.elementAt(index);
0280: scopes.removeElementAt(index);
0281: group.removeLightScope();
0282: }
0283:
0284: /**
0285: * Removes the scope at specified index.
0286: * @param index which scope to remove
0287: */
0288: void removeScope(int index) {
0289:
0290: Object[] scopeInfo = new Object[3];
0291: ArrayList removeScopeList = new ArrayList();
0292:
0293: GroupRetained group = (GroupRetained) scopes.elementAt(index);
0294: tempKey.reset();
0295: group.removeAllNodesForScopedLight(
0296: (inSharedGroup ? numMirrorLights : 1), mirrorLights,
0297: removeScopeList, tempKey);
0298: initRemoveScope(index);
0299: scopeInfo[0] = null;
0300: scopeInfo[1] = removeScopeList;
0301: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0302: : Boolean.FALSE);
0303: sendMessage(SCOPE_CHANGED, scopeInfo);
0304: }
0305:
0306: /**
0307: * Removes the specified scope
0308: * @param scope to be removed
0309: */
0310: void removeScope(Group scope) {
0311: int ind = indexOfScope(scope);
0312: if (ind >= 0)
0313: removeScope(ind);
0314: }
0315:
0316: void initRemoveScope(Group scope) {
0317: int ind = indexOfScope(scope);
0318: if (ind >= 0)
0319: initRemoveScope(ind);
0320: }
0321:
0322: /**
0323: * Removes all the scopes from this Light's list of scopes
0324: */
0325: void removeAllScopes() {
0326: int n = scopes.size();
0327: Object[] scopeInfo = new Object[3];
0328: ArrayList removeScopeList = new ArrayList();
0329: GroupRetained group;
0330:
0331: for (int index = n - 1; index >= 0; index--) {
0332: group = (GroupRetained) scopes.elementAt(index);
0333: tempKey.reset();
0334: group.removeAllNodesForScopedLight(
0335: (inSharedGroup ? numMirrorLights : 1),
0336: mirrorLights, removeScopeList, tempKey);
0337: initRemoveScope(index);
0338: }
0339: scopeInfo[0] = null;
0340: scopeInfo[1] = removeScopeList;
0341: scopeInfo[2] = (Boolean.FALSE);
0342: sendMessage(SCOPE_CHANGED, scopeInfo);
0343: }
0344:
0345: void initRemoveAllScopes() {
0346: int n = scopes.size();
0347: for (int i = n - 1; i >= 0; i--)
0348: initRemoveScope(i);
0349: }
0350:
0351: /**
0352: * Returns the scope specified by the index.
0353: * @param index of the scope to be returned
0354: * @return the scope at location index
0355: */
0356: Group getScope(int index) {
0357: return (Group) (((GroupRetained) (scopes.elementAt(index))).source);
0358: }
0359:
0360: /**
0361: * Returns an enumeration object of the scope
0362: * @return an enumeration object of the scope
0363: */
0364: Enumeration getAllScopes() {
0365: Enumeration elm = scopes.elements();
0366: Vector v = new Vector(scopes.size());
0367: while (elm.hasMoreElements()) {
0368: v.add(((GroupRetained) elm.nextElement()).source);
0369: }
0370: return v.elements();
0371: }
0372:
0373: /**
0374: * Appends the specified scope to this node's list of scopes.
0375: * @param scope the scope to add to this node's list of scopes
0376: */
0377: void initAddScope(Group scope) {
0378: GroupRetained group = (GroupRetained) scope.retained;
0379: scopes.addElement(group);
0380: group.setLightScope();
0381: }
0382:
0383: /**
0384: * Appends the specified scope to this node's list of scopes.
0385: * @param scope the scope to add to this node's list of scopes
0386: */
0387: void addScope(Group scope) {
0388: Object[] scopeInfo = new Object[3];
0389: ArrayList addScopeList = new ArrayList();
0390: GroupRetained group = (GroupRetained) scope.retained;
0391:
0392: initAddScope(scope);
0393: tempKey.reset();
0394: group.addAllNodesForScopedLight(
0395: (inSharedGroup ? numMirrorLights : 1), mirrorLights,
0396: addScopeList, tempKey);
0397: scopeInfo[0] = addScopeList;
0398: scopeInfo[1] = null;
0399: scopeInfo[2] = (scopes.size() > 0 ? Boolean.TRUE
0400: : Boolean.FALSE);
0401: sendMessage(SCOPE_CHANGED, scopeInfo);
0402: }
0403:
0404: /**
0405: * Returns a count of this nodes' scopes.
0406: * @return the number of scopes descendant from this node
0407: */
0408: int numScopes() {
0409: return scopes.size();
0410: }
0411:
0412: /**
0413: * Returns the index of the specified scope
0414: * @return index of the scope in this Light's list of scopes
0415: */
0416: int indexOfScope(Group scope) {
0417: if (scope != null)
0418: return scopes.indexOf((GroupRetained) scope.retained);
0419: else
0420: return scopes.indexOf(null);
0421: }
0422:
0423: /**
0424: * Initializes the Light's region of influence.
0425: * @param region a region that contains the Light's new region of influence
0426: */
0427: void initInfluencingBounds(Bounds region) {
0428: if (region != null) {
0429: regionOfInfluence = (Bounds) region.clone();
0430: if (staticTransform != null) {
0431: regionOfInfluence.transform(staticTransform.transform);
0432: }
0433: } else {
0434: regionOfInfluence = null;
0435: }
0436: }
0437:
0438: /**
0439: * Set the Light's region of influence and send a message
0440: * @param region a region that contains the Light's new region of influence
0441: */
0442: void setInfluencingBounds(Bounds region) {
0443: initInfluencingBounds(region);
0444: sendMessage(BOUNDS_CHANGED, (region != null ? region.clone()
0445: : null));
0446: }
0447:
0448: /**
0449: * Get the Light's region of influence
0450: * @return this Light's region of influence information
0451: */
0452: Bounds getInfluencingBounds() {
0453: Bounds b = null;
0454:
0455: if (regionOfInfluence != null) {
0456: b = (Bounds) regionOfInfluence.clone();
0457: if (staticTransform != null) {
0458: Transform3D invTransform = staticTransform
0459: .getInvTransform();
0460: b.transform(invTransform);
0461: }
0462: }
0463: return b;
0464: }
0465:
0466: /**
0467: * Initializes the Light's region of influence to the specified Leaf node.
0468: */
0469: void initInfluencingBoundingLeaf(BoundingLeaf region) {
0470: if (region != null) {
0471: boundingLeaf = (BoundingLeafRetained) region.retained;
0472: } else {
0473: boundingLeaf = null;
0474: }
0475: }
0476:
0477: /**
0478: * Set the Light's region of influence to the specified Leaf node.
0479: */
0480: void setInfluencingBoundingLeaf(BoundingLeaf region) {
0481: int i, numLgts;
0482:
0483: numLgts = numMirrorLights;
0484: if (numMirrorLights == 0)
0485: numLgts = 1;
0486:
0487: if (boundingLeaf != null) {
0488: // Remove the mirror lights as users of the original bounding leaf
0489: for (i = 0; i < numLgts; i++) {
0490: boundingLeaf.mirrorBoundingLeaf
0491: .removeUser(mirrorLights[i]);
0492: }
0493: }
0494:
0495: if (region != null) {
0496: boundingLeaf = (BoundingLeafRetained) region.retained;
0497: // Add all mirror lights as user of this bounding leaf
0498: for (i = 0; i < numLgts; i++) {
0499: boundingLeaf.mirrorBoundingLeaf
0500: .addUser(mirrorLights[i]);
0501: }
0502: } else {
0503: boundingLeaf = null;
0504: }
0505:
0506: sendMessage(BOUNDINGLEAF_CHANGED,
0507: (boundingLeaf != null ? boundingLeaf.mirrorBoundingLeaf
0508: : null));
0509: }
0510:
0511: /**
0512: * Get the Light's region of influence.
0513: */
0514: BoundingLeaf getInfluencingBoundingLeaf() {
0515: return (boundingLeaf != null ? (BoundingLeaf) boundingLeaf.source
0516: : null);
0517: }
0518:
0519: /**
0520: * This sets the immedate mode context flag
0521: */
0522: void setInImmCtx(boolean inCtx) {
0523: inImmCtx = inCtx;
0524: }
0525:
0526: /**
0527: * This gets the immedate mode context flag
0528: */
0529: boolean getInImmCtx() {
0530: return (inImmCtx);
0531: }
0532:
0533: // Called on the parent Light object and loops over the mirror object
0534: void initMirrorObject(Object[] args) {
0535: Shape3DRetained shape;
0536: Object[] scopeInfo = (Object[]) ((Object[]) args[4])[5];
0537: ArrayList gAtomList = (ArrayList) scopeInfo[1];
0538: Boolean scoped = (Boolean) scopeInfo[0];
0539: BoundingLeafRetained bl = (BoundingLeafRetained) ((Object[]) args[4])[0];
0540: Bounds bnds = (Bounds) ((Object[]) args[4])[1];
0541: int numLgts = ((Integer) args[2]).intValue();
0542: LightRetained[] mLgts = (LightRetained[]) args[3];
0543: int k;
0544:
0545: for (k = 0; k < numLgts; k++) {
0546: for (int i = 0; i < gAtomList.size(); i++) {
0547: shape = ((GeometryAtom) gAtomList.get(i)).source;
0548: shape.addLight(mLgts[k]);
0549: }
0550: mLgts[k].isScoped = scoped.booleanValue();
0551: }
0552:
0553: for (k = 0; k < numLgts; k++) {
0554: mLgts[k].inBackgroundGroup = ((Boolean) ((Object[]) args[4])[2])
0555: .booleanValue();
0556: mLgts[k].geometryBackground = (BackgroundRetained) ((Object[]) args[4])[3];
0557:
0558: if (bl != null) {
0559: mLgts[k].boundingLeaf = bl.mirrorBoundingLeaf;
0560: mLgts[k].region = mLgts[k].boundingLeaf.transformedRegion;
0561: } else {
0562: mLgts[k].boundingLeaf = null;
0563: mLgts[k].region = null;
0564: }
0565:
0566: if (bnds != null) {
0567: mLgts[k].regionOfInfluence = bnds;
0568: if (mLgts[k].region == null) {
0569: mLgts[k].region = (Bounds) regionOfInfluence
0570: .clone();
0571: mLgts[k].region.transform(regionOfInfluence,
0572: getLastLocalToVworld());
0573: }
0574: } else {
0575: mLgts[k].regionOfInfluence = null;
0576: }
0577: mLgts[k].lightOn = ((Boolean) ((Object[]) args[4])[4])
0578: .booleanValue();
0579:
0580: }
0581: // if its a ambient light,then do a immediate update of color
0582: if (this instanceof AmbientLightRetained) {
0583: Color3f clr = (Color3f) ((Object[]) args[4])[6];
0584: for (int i = 0; i < numLgts; i++) {
0585: mLgts[i].color.set(clr);
0586: }
0587: }
0588:
0589: }
0590:
0591: /**
0592: * This method is implemented by each light for rendering
0593: * context updates. This default one does nothing.
0594: */
0595: abstract void update(Context ctx, int lightSlot, double scale);
0596:
0597: // This routine is called when rendering Env structure
0598: // get a message, this routine updates values in the mirror object
0599: // that are not used by the renderer
0600: void updateImmediateMirrorObject(Object[] objs) {
0601: Transform3D trans = null;
0602: int component = ((Integer) objs[1]).intValue();
0603: int numLgts = ((Integer) objs[2]).intValue();
0604: LightRetained[] mLgts = (LightRetained[]) objs[3];
0605:
0606: // Color changed called immediately only for ambient lights
0607: if ((component & COLOR_CHANGED) != 0) {
0608: for (int i = 0; i < numLgts; i++) {
0609: mLgts[i].color.set(((Color3f) objs[4]));
0610: }
0611: } else if ((component & ENABLE_CHANGED) != 0) {
0612: for (int i = 0; i < numLgts; i++)
0613: mLgts[i].lightOn = ((Boolean) objs[4]).booleanValue();
0614: } else if ((component & BOUNDS_CHANGED) != 0) {
0615: for (int i = 0; i < numLgts; i++) {
0616: mLgts[i].regionOfInfluence = (Bounds) objs[4];
0617: if (mLgts[i].boundingLeaf == null) {
0618: if (objs[4] != null) {
0619: mLgts[i].region = ((Bounds) mLgts[i].regionOfInfluence)
0620: .copy(mLgts[i].region);
0621: mLgts[i].region.transform(
0622: mLgts[i].regionOfInfluence, mLgts[i]
0623: .getCurrentLocalToVworld());
0624: } else {
0625: mLgts[i].region = null;
0626: }
0627: }
0628: }
0629: } else if ((component & BOUNDINGLEAF_CHANGED) != 0) {
0630: for (int i = 0; i < numLgts; i++) {
0631: mLgts[i].boundingLeaf = ((BoundingLeafRetained) objs[4]);
0632: if (objs[4] != null) {
0633: mLgts[i].region = (Bounds) mLgts[i].boundingLeaf.transformedRegion;
0634: } else { // evaluate regionOfInfluence if not null
0635: if (mLgts[i].regionOfInfluence != null) {
0636: mLgts[i].region = ((Bounds) mLgts[i].regionOfInfluence)
0637: .copy(mLgts[i].region);
0638: mLgts[i].region.transform(
0639: mLgts[i].regionOfInfluence, mLgts[i]
0640: .getCurrentLocalToVworld());
0641: } else {
0642: mLgts[i].region = null;
0643: }
0644: }
0645: }
0646: } else if ((component & SCOPE_CHANGED) != 0) {
0647: int nscopes, j, i;
0648: GroupRetained group;
0649: Vector currentScopes;
0650: Object[] scopeList = (Object[]) objs[4];
0651: ArrayList addList = (ArrayList) scopeList[0];
0652: ArrayList removeList = (ArrayList) scopeList[1];
0653: boolean isScoped = ((Boolean) scopeList[2]).booleanValue();
0654:
0655: if (addList != null) {
0656: for (i = 0; i < numLgts; i++) {
0657: mLgts[i].isScoped = isScoped;
0658: for (j = 0; j < addList.size(); j++) {
0659: Shape3DRetained obj = ((GeometryAtom) addList
0660: .get(j)).source;
0661: obj.addLight(mLgts[i]);
0662: }
0663: }
0664: }
0665:
0666: if (removeList != null) {
0667: for (i = 0; i < numLgts; i++) {
0668: mLgts[i].isScoped = isScoped;
0669: for (j = 0; j < removeList.size(); j++) {
0670: Shape3DRetained obj = ((GeometryAtom) removeList
0671: .get(j)).source;
0672: ((Shape3DRetained) obj).removeLight(mLgts[i]);
0673: }
0674: }
0675: }
0676: }
0677:
0678: }
0679:
0680: // The update Object function called during RenderingEnv objUpdate
0681: // Note : if you add any more fields here , you need to update
0682: // updateLight() in RenderingEnvironmentStructure
0683: void updateMirrorObject(Object[] objs) {
0684:
0685: Transform3D trans = null;
0686: int component = ((Integer) objs[1]).intValue();
0687: int numLgts = ((Integer) objs[2]).intValue();
0688: LightRetained[] mLgts = (LightRetained[]) objs[3];
0689:
0690: if ((component & COLOR_CHANGED) != 0) {
0691: for (int i = 0; i < numLgts; i++) {
0692: mLgts[i].color.set(((Color3f) objs[4]));
0693: }
0694: }
0695:
0696: if ((component & INIT_MIRROR) != 0) {
0697: for (int i = 0; i < numLgts; i++) {
0698: Color3f clr = (Color3f) ((Object[]) objs[4])[6];
0699: mLgts[i].color.set(clr);
0700: }
0701: }
0702: }
0703:
0704: /** Note: This routine will only be called on
0705: * the mirror object - will update the object's
0706: * cached region and transformed region
0707: */
0708:
0709: void updateBoundingLeaf() {
0710: // This is necessary, if for example, the region
0711: // changes from sphere to box.
0712: if (boundingLeaf != null
0713: && boundingLeaf.switchState.currentSwitchOn) {
0714: region = boundingLeaf.transformedRegion;
0715: } else { // evaluate regionOfInfluence if not null
0716: if (regionOfInfluence != null) {
0717: region = regionOfInfluence.copy(region);
0718: region.transform(regionOfInfluence,
0719: getCurrentLocalToVworld());
0720: } else {
0721: region = null;
0722: }
0723: }
0724: }
0725:
0726: void getMirrorObjects(ArrayList leafList, HashKey key) {
0727: if (!inSharedGroup) {
0728: leafList.add(mirrorLights[0]);
0729: } else {
0730: for (int i = 0; i < numMirrorLights; i++) {
0731: if (mirrorLights[i].key.equals(key)) {
0732: leafList.add(mirrorLights[i]);
0733: break;
0734: }
0735: }
0736:
0737: }
0738: }
0739:
0740: /**
0741: * This gets the mirror light for this light given the key.
0742: */
0743: LightRetained getMirrorLight(HashKey key) {
0744: int i;
0745: LightRetained[] newLights;
0746:
0747: if (inSharedGroup) {
0748: for (i = 0; i < numMirrorLights; i++) {
0749: if (mirrorLights[i].key.equals(key)) {
0750: return (mirrorLights[i]);
0751: }
0752: }
0753: if (numMirrorLights == mirrorLights.length) {
0754: newLights = new LightRetained[numMirrorLights * 2];
0755: for (i = 0; i < numMirrorLights; i++) {
0756: newLights[i] = mirrorLights[i];
0757: }
0758: mirrorLights = newLights;
0759: }
0760: // mirrorLights[numMirrorLights] = (LightRetained)
0761: // this.clone(true);
0762: mirrorLights[numMirrorLights] = (LightRetained) this
0763: .clone();
0764: // If the bounding leaf is not null , add this
0765: // mirror object as a user
0766: if (boundingLeaf != null) {
0767: mirrorLights[numMirrorLights].boundingLeaf = this .boundingLeaf.mirrorBoundingLeaf;
0768: if (mirrorLights[numMirrorLights].boundingLeaf != null)
0769: mirrorLights[numMirrorLights].boundingLeaf
0770: .addUser(mirrorLights[numMirrorLights]);
0771: }
0772: // mirrorLights[numMirrorLights].key = new HashKey(key);
0773: mirrorLights[numMirrorLights].key = key;
0774: mirrorLights[numMirrorLights].sgLight = this ;
0775: return (mirrorLights[numMirrorLights++]);
0776: } else {
0777: if (mirrorLights[0] == null) {
0778: //mirrorLights[0] = (LightRetained) this.clone(true);
0779: mirrorLights[0] = (LightRetained) this .clone();
0780: // If the bounding leaf is not null , add this
0781: // mirror object as a user
0782: if (boundingLeaf != null) {
0783: mirrorLights[0].boundingLeaf = this .boundingLeaf.mirrorBoundingLeaf;
0784: if (mirrorLights[0].boundingLeaf != null)
0785: mirrorLights[0].boundingLeaf
0786: .addUser(mirrorLights[0]);
0787: }
0788: mirrorLights[0].sgLight = this ;
0789: }
0790: return (mirrorLights[0]);
0791: }
0792: }
0793:
0794: void setLive(SetLiveState s) {
0795: LightRetained ml;
0796: int i, j;
0797:
0798: newlyAddedMirrorLights.clear();
0799: if (inImmCtx) {
0800: throw new IllegalSharingException(J3dI18N
0801: .getString("LightRetained0"));
0802: }
0803: super .doSetLive(s);
0804:
0805: if (s.inSharedGroup) {
0806: for (i = 0; i < s.keys.length; i++) {
0807: ml = this .getMirrorLight(s.keys[i]);
0808: ml.localToVworld = new Transform3D[1][];
0809: ml.localToVworldIndex = new int[1][];
0810:
0811: j = s.keys[i].equals(localToVworldKeys, 0,
0812: localToVworldKeys.length);
0813: if (j < 0) {
0814: System.err
0815: .println("LightRetained : Can't find hashKey");
0816: }
0817:
0818: ml.localToVworld[0] = localToVworld[j];
0819: ml.localToVworldIndex[0] = localToVworldIndex[j];
0820: // If its view Scoped, then add this list
0821: // to be sent to Rendering Env
0822: if ((s.viewScopedNodeList != null)
0823: && (s.viewLists != null)) {
0824: s.viewScopedNodeList.add(ml);
0825: s.scopedNodesViewList.add(s.viewLists.get(i));
0826: } else {
0827: s.nodeList.add(ml);
0828: }
0829:
0830: newlyAddedMirrorLights.add(ml);
0831: if (boundingLeaf != null) {
0832: boundingLeaf.mirrorBoundingLeaf.addUser(ml);
0833: }
0834: if (s.transformTargets != null
0835: && s.transformTargets[i] != null) {
0836: s.transformTargets[i].addNode(ml,
0837: Targets.ENV_TARGETS);
0838: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0839: }
0840: if (s.switchTargets != null
0841: && s.switchTargets[i] != null) {
0842: s.switchTargets[i].addNode(ml, Targets.ENV_TARGETS);
0843: }
0844: ml.switchState = (SwitchState) s.switchStates.get(j);
0845:
0846: }
0847: } else {
0848: ml = this .getMirrorLight(null);
0849: ml.localToVworld = new Transform3D[1][];
0850: ml.localToVworldIndex = new int[1][];
0851: ml.localToVworld[0] = this .localToVworld[0];
0852: ml.localToVworldIndex[0] = this .localToVworldIndex[0];
0853: // Initialization of the mirror object
0854: // If its view Scoped, then add this list
0855: // to be sent to Rendering Env
0856: // System.err.println("lightSetLive, s.viewList = "+s.viewLists);
0857: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
0858: s.viewScopedNodeList.add(ml);
0859: s.scopedNodesViewList.add(s.viewLists.get(0));
0860: } else {
0861: s.nodeList.add(ml);
0862: }
0863: newlyAddedMirrorLights.add(ml);
0864: if (boundingLeaf != null) {
0865: boundingLeaf.mirrorBoundingLeaf.addUser(ml);
0866: }
0867: if (s.transformTargets != null
0868: && s.transformTargets[0] != null) {
0869: s.transformTargets[0].addNode(ml, Targets.ENV_TARGETS);
0870: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0871: }
0872: if (s.switchTargets != null && s.switchTargets[0] != null) {
0873: s.switchTargets[0].addNode(ml, Targets.ENV_TARGETS);
0874: }
0875: ml.switchState = (SwitchState) s.switchStates.get(0);
0876: }
0877: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
0878: | J3dThread.UPDATE_RENDER;
0879: super .markAsLive();
0880:
0881: }
0882:
0883: J3dMessage initMessage(int num) {
0884: J3dMessage createMessage = new J3dMessage();
0885: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
0886: createMessage.universe = universe;
0887: createMessage.type = J3dMessage.LIGHT_CHANGED;
0888: createMessage.args[0] = this ;
0889: // a snapshot of all attributes that needs to be initialized
0890: // in the mirror object
0891: createMessage.args[1] = new Integer(INIT_MIRROR);
0892:
0893: LightRetained[] mlts = new LightRetained[newlyAddedMirrorLights
0894: .size()];
0895: for (int i = 0; i < mlts.length; i++) {
0896: mlts[i] = (LightRetained) newlyAddedMirrorLights.get(i);
0897: }
0898: createMessage.args[2] = new Integer(mlts.length);
0899: createMessage.args[3] = mlts;
0900:
0901: Object[] obj = new Object[num];
0902: obj[0] = boundingLeaf;
0903: obj[1] = (regionOfInfluence != null ? regionOfInfluence.clone()
0904: : null);
0905: obj[2] = (inBackgroundGroup ? Boolean.TRUE : Boolean.FALSE);
0906: obj[3] = geometryBackground;
0907: obj[4] = (lightOn ? Boolean.TRUE : Boolean.FALSE);
0908:
0909: ArrayList addScopeList = new ArrayList();
0910: for (int i = 0; i < scopes.size(); i++) {
0911: GroupRetained group = (GroupRetained) scopes.get(i);
0912: tempKey.reset();
0913: group.addAllNodesForScopedLight(mlts.length, mlts,
0914: addScopeList, tempKey);
0915: }
0916: Object[] scopeInfo = new Object[2];
0917: scopeInfo[0] = ((scopes.size() > 0) ? Boolean.TRUE
0918: : Boolean.FALSE);
0919: scopeInfo[1] = addScopeList;
0920: obj[5] = scopeInfo;
0921: Color3f clr = new Color3f(color);
0922: obj[6] = clr;
0923: createMessage.args[4] = obj;
0924: return createMessage;
0925:
0926: }
0927:
0928: // The default set of clearLive actions
0929: void clearLive(SetLiveState s) {
0930: LightRetained ml;
0931: newlyAddedMirrorLights.clear();
0932: super .clearLive(s);
0933:
0934: if (inSharedGroup) {
0935: for (int i = 0; i < s.keys.length; i++) {
0936: ml = this .getMirrorLight(s.keys[i]);
0937: if (s.transformTargets != null
0938: && s.transformTargets[i] != null) {
0939: s.transformTargets[i].addNode(ml,
0940: Targets.ENV_TARGETS);
0941: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0942: }
0943: newlyAddedMirrorLights.add(ml);
0944: // Remove this mirror light as users of the bounding leaf
0945: if (ml.boundingLeaf != null) {
0946: ml.boundingLeaf.removeUser(ml);
0947: ml.boundingLeaf = null;
0948: }
0949: if (s.switchTargets != null
0950: && s.switchTargets[i] != null) {
0951: s.switchTargets[i].addNode(ml, Targets.ENV_TARGETS);
0952: }
0953: if ((s.viewScopedNodeList != null)
0954: && (s.viewLists != null)) {
0955: s.viewScopedNodeList.add(ml);
0956: s.scopedNodesViewList.add(s.viewLists.get(i));
0957: } else {
0958: s.nodeList.add(ml);
0959: }
0960: }
0961: } else {
0962: ml = this .getMirrorLight(null);
0963:
0964: // Remove this mirror light as users of the bounding leaf
0965: if (ml.boundingLeaf != null) {
0966: ml.boundingLeaf.removeUser(ml);
0967: ml.boundingLeaf = null;
0968: }
0969: if (s.switchTargets != null && s.switchTargets[0] != null) {
0970: s.switchTargets[0].addNode(ml, Targets.ENV_TARGETS);
0971: }
0972: if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
0973: s.viewScopedNodeList.add(ml);
0974: //System.err.println("s.viewList is " + s.viewLists);
0975: s.scopedNodesViewList.add(s.viewLists.get(0));
0976: } else {
0977: s.nodeList.add(ml);
0978: }
0979: if (s.transformTargets != null
0980: && s.transformTargets[0] != null) {
0981: s.transformTargets[0].addNode(ml, Targets.ENV_TARGETS);
0982: s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
0983: }
0984:
0985: newlyAddedMirrorLights.add(ml);
0986: }
0987: s.notifyThreads |= J3dThread.UPDATE_RENDERING_ENVIRONMENT
0988: | J3dThread.UPDATE_RENDER;
0989:
0990: if (scopes.size() > 0) {
0991: J3dMessage createMessage = new J3dMessage();
0992: LightRetained[] mlts = new LightRetained[newlyAddedMirrorLights
0993: .size()];
0994: for (int i = 0; i < mlts.length; i++) {
0995: mlts[i] = (LightRetained) newlyAddedMirrorLights.get(i);
0996: }
0997: createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT;
0998: createMessage.universe = universe;
0999: createMessage.type = J3dMessage.LIGHT_CHANGED;
1000: createMessage.args[0] = this ;
1001: createMessage.args[1] = new Integer(CLEAR_MIRROR);
1002: ArrayList removeScopeList = new ArrayList();
1003: for (int i = 0; i < scopes.size(); i++) {
1004: GroupRetained group = (GroupRetained) scopes.get(i);
1005: tempKey.reset();
1006: group.removeAllNodesForScopedLight(mlts.length, mlts,
1007: removeScopeList, tempKey);
1008: }
1009: createMessage.args[2] = removeScopeList;
1010: createMessage.args[3] = new Integer(mlts.length);
1011: createMessage.args[4] = mlts;
1012: VirtualUniverse.mc.processMessage(createMessage);
1013: }
1014: }
1015:
1016: void clearMirrorObject(Object[] args) {
1017: Shape3DRetained shape;
1018: ArrayList shapeList = (ArrayList) args[2];
1019: ArrayList removeScopeList = new ArrayList();
1020: LightRetained[] mLgts = (LightRetained[]) args[4];
1021: int numLgts = ((Integer) args[3]).intValue();
1022:
1023: for (int k = 0; k < numLgts; k++) {
1024: for (int i = 0; i < shapeList.size(); i++) {
1025: shape = ((GeometryAtom) shapeList.get(i)).source;
1026: shape.removeLight(mLgts[k]);
1027: }
1028: mLgts[k].isScoped = false;
1029:
1030: }
1031:
1032: }
1033:
1034: /**
1035: * Clones only the retained side, internal use only
1036: */
1037: protected Object clone() {
1038: LightRetained lr = (LightRetained) super .clone();
1039: lr.color = new Color3f(color);
1040: lr.scopes = (Vector) scopes.clone();
1041: lr.initInfluencingBoundingLeaf(getInfluencingBoundingLeaf());
1042: lr.region = null;
1043: lr.lightDirty = 0xffff;
1044: lr.sgLightDirty = 0xffff;
1045: lr.universe = null;
1046: lr.isNeeded = false;
1047: lr.inImmCtx = false;
1048: lr.sgLight = null;
1049: lr.key = null;
1050: lr.mirrorLights = new LightRetained[1];
1051: lr.numMirrorLights = 0;
1052: lr.environmentSets = new UnorderList(1, EnvironmentSet.class);
1053: return lr;
1054: }
1055:
1056: // Called during RenderingEnv object update
1057: void updateTransformChange() {
1058: }
1059:
1060: // Called on mirror object and updated when message is received
1061: void updateImmediateTransformChange() {
1062: // If bounding leaf is null, tranform the bounds object
1063: if (boundingLeaf == null) {
1064: if (regionOfInfluence != null) {
1065: region = regionOfInfluence.copy(region);
1066: region.transform(regionOfInfluence,
1067: getCurrentLocalToVworld());
1068: }
1069:
1070: }
1071: }
1072:
1073: void sendMessage(int attrMask, Object attr) {
1074: J3dMessage createMessage = new J3dMessage();
1075: createMessage.threads = targetThreads;
1076: createMessage.type = J3dMessage.LIGHT_CHANGED;
1077: createMessage.universe = universe;
1078: createMessage.args[0] = this ;
1079: createMessage.args[1] = new Integer(attrMask);
1080: if (inSharedGroup)
1081: createMessage.args[2] = new Integer(numMirrorLights);
1082: else
1083: createMessage.args[2] = new Integer(1);
1084:
1085: createMessage.args[3] = mirrorLights.clone();
1086: createMessage.args[4] = attr;
1087: VirtualUniverse.mc.processMessage(createMessage);
1088: }
1089:
1090: void mergeTransform(TransformGroupRetained xform) {
1091: super.mergeTransform(xform);
1092: if (regionOfInfluence != null) {
1093: regionOfInfluence.transform(xform.transform);
1094: }
1095: }
1096: }
|