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