/* * 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 lights = new ArrayList(); /** * 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 ambLights = new ArrayList(); /** * 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 addAttributeBins = new ArrayList(); /** * 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 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 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 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; } }