diff options
Diffstat (limited to 'src/javax/media/j3d/EnvironmentSet.java')
-rw-r--r-- | src/javax/media/j3d/EnvironmentSet.java | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/src/javax/media/j3d/EnvironmentSet.java b/src/javax/media/j3d/EnvironmentSet.java new file mode 100644 index 0000000..ab22747 --- /dev/null +++ b/src/javax/media/j3d/EnvironmentSet.java @@ -0,0 +1,549 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package javax.media.j3d; + +import java.util.ArrayList; + +import javax.vecmath.Color3f; + +/** + * The LightBin manages a collection of EnvironmentSet objects. + * The number of objects managed depends upon the number of Lights + * in each EnvironmentSet and the number of lights supported by + * the underlying rendering layer. + */ + +class EnvironmentSet extends Object implements ObjectUpdate{ + // A list of pre-defined bits to indicate which component + // of the rendermolecule changed + static final int LIGHTENABLE_CHANGED = 0x01; + static final int AMBIENT_CHANGED = 0x02; + static final int FOG_CHANGED = 0x04; + static final int MODELCLIP_CHANGED = 0x08; + +/** + * The ArrayList of Lights in this EnvironmentSet + */ +ArrayList<LightRetained> lights = new ArrayList<LightRetained>(); + + /** + * The position of the light in the lightbin that the + * lights in this environment set corresponds to + */ + int[] ltPos = null; + + +/** + * The arraylist of ambient lights in this env list + */ +ArrayList<LightRetained> ambLights = new ArrayList<LightRetained>(); + + /** + * The LightBin that this EnvironmentSet resides + */ + LightBin lightBin = null; + + /** + * The bitmask of light slots that need to be enabled for this + */ + long enableMask = 0; + + /** + * The cached scene ambient component for this EnvirionmentSet + */ + Color3f sceneAmbient = new Color3f(); + + /** + * The RenderBin for this EnvirionmentSet + */ + RenderBin renderBin = null; + + /** + * The fog for this EnvironmentSet + */ + FogRetained fog = null; + + + /** + * The model clip for this EnvironmentSet + */ + ModelClipRetained modelClip = null; + + /** + * enable mask for the model clip planes in this environment set + */ + int enableMCMask = 0; // enable mask used in modelClip.update() + int enableMCMaskCache = 0; // enable mask computed in renderBin that + // is copied into enableMCMask in updateObject + + /** + * The references to the next and previous LightBins in the + * list. + */ + EnvironmentSet next = null; + EnvironmentSet prev = null; + +/** + * List of attrributeBins to be added next Frame + */ +ArrayList<AttributeBin> addAttributeBins = new ArrayList<AttributeBin>(); + + /** + * Canvas Dirty Mask for + */ + int canvasDirty = 0; + + /** + * cached value of enable mask + */ + long enableMaskCache = 0; + + /** + * + */ + boolean onUpdateList = false; + + /** + * The list of AttributeBins in this EnvironmentSet + */ + AttributeBin attributeBinList = null; + + EnvironmentSet(RenderAtom ra, LightRetained[] lightList, FogRetained fog, + ModelClipRetained modelClip, RenderBin rb) { + renderBin = rb; + reset(ra, lightList, fog, modelClip); + } + + private void reset(RenderAtom ra, LightRetained[] lightList, FogRetained fog, + ModelClipRetained modelClip) { + int i; + LightRetained light; + + prev = null; + next = null; + onUpdateList = false; + attributeBinList = null; + lights.clear(); + ambLights.clear(); + sceneAmbient.x = 0.0f; + sceneAmbient.y = 0.0f; + sceneAmbient.z = 0.0f; + if (lightList != null) { + for (i=0; i<lightList.length; i++) { + light = lightList[i]; + if (light.nodeType == NodeRetained.AMBIENTLIGHT) { + ambLights.add(light); + sceneAmbient.x += light.color.x; + sceneAmbient.y += light.color.y; + sceneAmbient.z += light.color.z; + } + else { + lights.add(light); + } + } + if (sceneAmbient.x > 1.0f) { + sceneAmbient.x = 1.0f; + } + if (sceneAmbient.y > 1.0f) { + sceneAmbient.y = 1.0f; + } + if (sceneAmbient.z > 1.0f) { + sceneAmbient.z = 1.0f; + } + } + + this.fog = fog; + + this.modelClip = modelClip; + enableMCMaskCache = 0; + if (modelClip != null) { + for (i = 0; i < 6; i++) { + if (modelClip.enables[i]) + enableMCMaskCache |= 1 << i; + } + enableMCMask = enableMCMaskCache; + } + + // Allocate the ltPos array + ltPos = new int[lights.size()]; + enableMask = 0; + + // Issue 466 : add the env set to the light, fog, and model clip + // lists only after the newly constructed env set is initialized + if (lightList != null) { + for (i=0; i<lightList.length; i++) { + lightList[i].environmentSets.add(this); + } + } + + if (fog != null) { + fog.environmentSets.add(this); + } + + if (modelClip != null) { + modelClip.environmentSets.add(this); + } + } + + /** + * This tests if the qiven lights and fog match this EnviornmentSet + */ + boolean equals(RenderAtom ra, LightRetained[] lights, FogRetained fog, + ModelClipRetained modelClip) { + int i; + + + // First see if the lights match. + if (lights == null && ambLights == null) { + if (this.lights.size() == 0) { + if (this.fog == fog) { + return (true); + } else { + return (false); + } + } else { + return (false); + } + } + + if ((this.lights.size() + this.ambLights.size())!= lights.length) { + return (false); + } + + for (i=0; i<lights.length; i++) { + if (lights[i].nodeType == LightRetained.AMBIENTLIGHT) { + if (!this.ambLights.contains(lights[i])) { + return (false); + } + } + else { + if (!this.lights.contains(lights[i])) { + return (false); + } + } + } + + // Now check fog + if (this.fog != fog) { + return (false); + } + + // Now check model clip + if (this.modelClip != modelClip) { + return (false); + } + + return (true); + } + + + /** + * This tests if the qiven lights match this EnviornmentSet + */ + boolean equalLights(LightRetained[] lights) { + int i; + + // First see if the lights match. + if (lights == null && ambLights == null) { + if (this.lights.size() == 0) { + return (true); + } + } + + if ((this.lights.size() + this.ambLights.size())!= lights.length) { + return (false); + } + + for (i=0; i<lights.length; i++) { + if (lights[i].nodeType == LightRetained.AMBIENTLIGHT) { + if (!this.ambLights.contains(lights[i])) { + return (false); + } + } + else { + if (!this.lights.contains(lights[i])) { + return (false); + } + } + } + + return (true); + } + + + @Override + public void updateObject() { + int i; + AttributeBin a; + + if (addAttributeBins.size() > 0) { + a = addAttributeBins.get(0); + if (attributeBinList == null) { + attributeBinList = a; + + } + else { + a.next = attributeBinList; + attributeBinList.prev = a; + attributeBinList = a; + } + for (i = 1; i < addAttributeBins.size() ; i++) { + a = addAttributeBins.get(i); + a.next = attributeBinList; + attributeBinList.prev = a; + attributeBinList = a; + } + } + + addAttributeBins.clear(); + + if (canvasDirty != 0) { + Canvas3D canvases[] = renderBin.view.getCanvases(); + + for (i = 0; i < canvases.length; i++) { + canvases[i].canvasDirty |= canvasDirty; + } + + if ((canvasDirty & Canvas3D.AMBIENTLIGHT_DIRTY) != 0) { + updateSceneAmbient(); + } + + if ((canvasDirty & Canvas3D.LIGHTENABLES_DIRTY) != 0) { + enableMask = enableMaskCache; + } + + if ((canvasDirty & Canvas3D.MODELCLIP_DIRTY) != 0) { + enableMCMask = enableMCMaskCache; + } + + canvasDirty = 0; + } + onUpdateList = false; + } + + /** + * Adds the given AttributeBin to this EnvironmentSet. + */ + void addAttributeBin(AttributeBin a, RenderBin rb) { + a.environmentSet = this; + addAttributeBins.add(a); + if (!onUpdateList) { + rb.objUpdateList.add(this); + onUpdateList = true; + } + } + + /** + * Removes the given AttributeBin from this EnvironmentSet. + */ + void removeAttributeBin(AttributeBin a) { + int i; + + a.environmentSet = null; + // If the attributeBin being remove is contained in addAttributeBins, then + // remove the attributeBin from the addList + if (addAttributeBins.contains(a)) { + addAttributeBins.remove(addAttributeBins.indexOf(a)); + } + else { + if (a.prev == null) { // At the head of the list + attributeBinList = a.next; + if (a.next != null) { + a.next.prev = null; + } + } else { // In the middle or at the end. + a.prev.next = a.next; + if (a.next != null) { + a.next.prev = a.prev; + } + } + } + a.prev = null; + a.next = null; + + if (a.definingRenderingAttributes != null && + (a.definingRenderingAttributes.changedFrequent != 0)) + a.definingRenderingAttributes = null; + a.onUpdateList &= ~AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST; + + if (attributeBinList == null && addAttributeBins.size() == 0) { + // Now remove this environment set from all the lights and fogs + // that use this + int sz = lights.size(); + for (i=0; i < sz; i++) { + lights.get(i).environmentSets.remove(this); + } + sz = ambLights.size(); + for (i = 0; i < sz; i++) { + ambLights.get(i).environmentSets.remove(this); + } + if (fog != null) { + fog.environmentSets.remove(this); + } + lightBin.removeEnvironmentSet(this); + } + } + + void updateSceneAmbient() + { + int i; + sceneAmbient.x = 0.0f; + sceneAmbient.y = 0.0f; + sceneAmbient.z = 0.0f; + for (i=0; i<ambLights.size(); i++) { + LightRetained aL = ambLights.get(i); + if (aL.lightOn) { + sceneAmbient.x += aL.color.x; + sceneAmbient.y += aL.color.y; + sceneAmbient.z += aL.color.z; + } + } + if (sceneAmbient.x > 1.0f) { + sceneAmbient.x = 1.0f; + } + if (sceneAmbient.y > 1.0f) { + sceneAmbient.y = 1.0f; + } + if (sceneAmbient.z > 1.0f) { + sceneAmbient.z = 1.0f; + } + } + + /** + * Renders this EnvironmentSet + */ + void render(Canvas3D cv) { + AttributeBin a; + + // include this EnvironmentSet to the to-be-updated list in Canvas + cv.setStateToUpdate(Canvas3D.ENVIRONMENTSET_BIT, this); + + a = attributeBinList; + while (a != null) { + a.render(cv); + a = a.next; + } + } + + + void updateAttributes(Canvas3D cv) { + double scale; + boolean updateSceneAmbient = false, updateLightEnables = false; + boolean updateModelClip = false, updateFog = false; + // within frame + if (cv.environmentSet != this ) { + if (cv.enableMask != enableMask) { + updateLightEnables = true; + } + + if (cv.sceneAmbient.x != sceneAmbient.x || + cv.sceneAmbient.y != sceneAmbient.y || + cv.sceneAmbient.z != sceneAmbient.z ) { + updateSceneAmbient = true; + } + + if (cv.fog != fog) { + updateFog = true; + } + + if (cv.modelClip != modelClip) { + updateModelClip = true; + } + } + + // Check for dirtybit. + if ((cv.canvasDirty & (Canvas3D.LIGHTENABLES_DIRTY| + Canvas3D.AMBIENTLIGHT_DIRTY| + Canvas3D.FOG_DIRTY| + Canvas3D.MODELCLIP_DIRTY| + Canvas3D.VIEW_MATRIX_DIRTY)) != 0) { + + if ((cv.canvasDirty & Canvas3D.LIGHTENABLES_DIRTY) != 0) { + updateLightEnables = true; + } + + if ((cv.canvasDirty & Canvas3D.AMBIENTLIGHT_DIRTY) != 0) { + updateSceneAmbient = true; + } + + if ((cv.canvasDirty & Canvas3D.FOG_DIRTY) != 0) { + updateFog = true; + } + + if ((cv.canvasDirty & Canvas3D.MODELCLIP_DIRTY) != 0) { + updateModelClip = true; + } + + if ((cv.canvasDirty & Canvas3D.VIEW_MATRIX_DIRTY) != 0) { + updateFog = true; + updateModelClip = true; + } + } + + // do states update here. + if (updateLightEnables) { + cv.setLightEnables(cv.ctx, enableMask, renderBin.maxLights); + cv.enableMask = enableMask; + } + + if (updateSceneAmbient) { + cv.setSceneAmbient(cv.ctx, sceneAmbient.x, + sceneAmbient.y, sceneAmbient.z); + cv.sceneAmbient.set(sceneAmbient); + } + + if (updateFog) { + if (fog != null) { + scale = lightBin.geometryBackground == null? + cv.canvasViewCache.getVworldToCoexistenceScale(): + cv.canvasViewCache.getInfVworldToCoexistenceScale(); + fog.update(cv.ctx, scale); + } else { + cv.disableFog(cv.ctx); + } + cv.fog = fog; + } + + if (updateModelClip) { + if (modelClip != null) { + modelClip.update(cv, enableMCMask); + } else { + cv.disableModelClip(cv.ctx); + } + cv.modelClip = modelClip; + } + + cv.canvasDirty &= ~(Canvas3D.LIGHTENABLES_DIRTY| + Canvas3D.AMBIENTLIGHT_DIRTY | + Canvas3D.FOG_DIRTY | + Canvas3D.MODELCLIP_DIRTY | + Canvas3D.VIEW_MATRIX_DIRTY); + + cv.environmentSet = this; + + } +} |