📄 lightbin.java
字号:
/* * $RCSfile: LightBin.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.6 $ * $Date: 2007/02/09 17:18:08 $ * $State: Exp $ */package javax.media.j3d;import javax.vecmath.*;import java.util.ArrayList;/** * 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 LightBin extends Object implements ObjectUpdate { /** * The maximum number of lights in a LightBin */ int maxLights = -1; /** * The Array of Light references in this LightBin. * This array is always maxLights in length. */ LightRetained[] lights = null; /** * An Array of reference counts for shared lights in * among EnvirionmentSets */ int[] lightsRef = null; /** * The number of empty light slots in this LightBin */ int numEmptySlots = -1; /** * The RenderBin for this object */ RenderBin renderBin = null; /** * The references to the next and previous LightBins in the * list. */ LightBin next = null; LightBin prev = null; /** * The list of EnvironmentSets in this LightBin. */ EnvironmentSet environmentSetList = null; /** * List of envSet to be added for the next iteration */ ArrayList insertEnvSet = new ArrayList(); /** * cache of the canvasDirty */ int canvasDirty = 0; /** * lightDirty Mask cache , used to * mark the lightdirty bits for next frame */ int lightDirtyMaskCache = 0; /** * lightDirty Mask used during rendering */ int lightDirtyMask = 0; /** * List of pointLts in this lightbin * Need to reload these lights when vworld scale changes */ ArrayList pointLts = new ArrayList(); int[] pointLtsSlotIndex; // OrderedGroup info OrderedCollection orderedCollection = null; boolean onUpdateList = false; // background node that contains geometry BackgroundRetained geometryBackground = null; LightBin(int maxLights, RenderBin rb, boolean isOpaque) { this.maxLights = maxLights; this.numEmptySlots = maxLights; lights = new LightRetained[maxLights]; lightsRef = new int[maxLights]; renderBin = rb; } void reset(boolean inOpaque) { prev = null; next = null; orderedCollection = null; environmentSetList = null; onUpdateList = false; geometryBackground = null; // No need to reset the lights and lightRef if (J3dDebug.devPhase && J3dDebug.debug) { for (int i=0; i<maxLights; i++) { J3dDebug.doAssert(lights[i] == null, "lights[i] == null"); J3dDebug.doAssert(lightsRef[i] == 0, "lightsRef[i] == 0"); } } } void setOrderedInfo(OrderedCollection oc) { orderedCollection = oc; } /** * Checks to see if an EnvironmentSet will fit into * this LightBin. It takes into account shared lights. */ boolean willEnvironmentSetFit(EnvironmentSet e) { int i, j, numEsLights, slotsNeeded; LightRetained light; numEsLights = e.lights.size(); slotsNeeded = numEsLights; for (i=0; i<numEsLights; i++) { light = (LightRetained) e.lights.get(i); if (light instanceof AmbientLightRetained) { continue; } for (j=0; j<maxLights; j++) { if (lights[j] == light) { slotsNeeded--; break; } } } if (slotsNeeded > numEmptySlots) { return (false); } else { return (true); } } /** * Adds the new EnvironmentSet to this LightBin. */ void addEnvironmentSet(EnvironmentSet e, RenderBin rb) { int i, j, numEsLights; LightRetained light; numEsLights = e.lights.size(); for (i=0; i<numEsLights; i++) { light = (LightRetained) e.lights.get(i); if (light instanceof AmbientLightRetained) { continue; } for (j=0; j<maxLights; j++) { if (lights[j] == light) { if (light.lightOn) { e.enableMask |= 1<<j; } lightsRef[j]++; // Keep a reference to the position of the light // in the light bin that this light in the envSet // refers e.ltPos[i] = j; break; } } if (j==maxLights) { // Find an empty slot for (j=0; j<maxLights; j++) { if (lights[j] == null) { lights[j] = light; lightsRef[j] = 1; if (light instanceof PointLightRetained) { pointLts.add(light); // save the destinated light slot for point // so that point light can be updated without // referencing the lights list int pointLtsSlotIndexLen = 0; if (pointLtsSlotIndex != null) pointLtsSlotIndexLen = pointLtsSlotIndex.length; if (pointLtsSlotIndexLen < pointLts.size()) { int[] newIndexList = new int[pointLtsSlotIndexLen + 8]; for (int x = 0; x < pointLtsSlotIndexLen; x++) { newIndexList[x] = pointLtsSlotIndex[x]; } pointLtsSlotIndex = newIndexList; } pointLtsSlotIndex[pointLts.size() - 1] = j; } if (light.lightOn) { e.enableMask |= 1<<j; } // Keep a reference to the position of the light // in the light bin that this light in the envSet // refers e.ltPos[i] = j; numEmptySlots--; break; } } } } e.lightBin = this; e.enableMaskCache = e.enableMask; insertEnvSet.add(e); if (!onUpdateList) { rb.objUpdateList.add(this); onUpdateList = true; } } public void updateObject() { int i, j; EnvironmentSet e ; // Handle insertion if (insertEnvSet.size() > 0) { e = (EnvironmentSet)insertEnvSet.get(0); if (environmentSetList == null) { environmentSetList = e; } else { e.next = environmentSetList; environmentSetList.prev = e; environmentSetList = e; } for (i = 1; i < insertEnvSet.size(); i++) { e = (EnvironmentSet)insertEnvSet.get(i); e.next = environmentSetList; environmentSetList.prev = e; environmentSetList = e; } } insertEnvSet.clear(); if (canvasDirty != 0) { Canvas3D canvases[] = renderBin.view.getCanvases(); for (i = 0; i < canvases.length; i++) { canvases[i].canvasDirty |= canvasDirty; } lightDirtyMask = lightDirtyMaskCache; canvasDirty = 0; lightDirtyMaskCache = 0; } onUpdateList = false; } /** * Removes the given EnvironmentSet from this LightBin. */ void removeEnvironmentSet(EnvironmentSet e) { int i, j, numEsLights; LightRetained light; e.lightBin = null; // If envSet being remove is contained in envSet, then // remove the envSet from the addList if (insertEnvSet.contains(e)) { insertEnvSet.remove(insertEnvSet.indexOf(e)); } else { numEsLights = e.lights.size(); for (i=0; i<numEsLights; i++) { light = (LightRetained) e.lights.get(i); for (j=0; j<maxLights; j++) { if (lights[j] == light) { lightsRef[j]--; if (lightsRef[j] == 0) { if (light instanceof PointLightRetained) pointLts.remove(pointLts.indexOf(light)); lights[j] = null; // If the lightBin is dirty unset the mask lightDirtyMaskCache &= ~(1 << j); // since the canvas may already be updated, lightDirtyMask &= ~(1 << j); numEmptySlots++; } break; } } } if (e.prev == null) { // At the head of the list environmentSetList = e.next; if (e.next != null) { e.next.prev = null; } } else { // In the middle or at the end. e.prev.next = e.next; if (e.next != null) { e.next.prev = e.prev; } } // Mark all canvases that uses this environment set as Canvas3D canvases[] = renderBin.view.getCanvases(); for (i = 0; i < canvases.length; i++) { // Mark the environmentSet cached by all the canvases as null // to force to reEvaluate when it comes back from the freelist // During envset::render(), we only check for the pointers not // being the same, so we need to take care of the env set // gotten from the freelist from one frame to another canvases[i].environmentSet = null; } } e.prev = null; e.next = null; if (environmentSetList == null && insertEnvSet.size() == 0) { renderBin.removeLightBin(this); geometryBackground = null; } } /** * Renders this LightBin */ void render(Canvas3D cv) { EnvironmentSet e; // include this LightBin to the to-be-updated list in Canvas cv.setStateToUpdate(Canvas3D.LIGHTBIN_BIT, this); e = environmentSetList; while (e != null) { e.render(cv); e = e.next; } } void updateAttributes(Canvas3D cv) { int i; double scale; int frameCount = VirtualUniverse.mc.frameCount; // TODO: When working on issue 15 and 88, we realise that the // logic in this method flaw. As we are ready into 1.3.2beta1 // phase, and there isn't an existing issue related to the logic // error in method, we decided not to fix it for now. This method // should have the logic as in EnvironmentSet.updateAttributes(); // The fix to issue 15 and 88. // within frames if (cv.lightBin != this) { if (geometryBackground == null) { scale = cv.canvasViewCache.getVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.vworldToVpc); } else { scale = cv.canvasViewCache.getInfVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.infVworldToVpc); } for (i=0; i<maxLights; i++) { if (lights[i] != null) { if (cv.lights[i] != lights[i] || cv.frameCount[i] != frameCount) { cv.lights[i] = lights[i]; cv.frameCount[i] = frameCount; lights[i].update(cv.ctx, i,scale); } } } cv.lightBin = this; cv.canvasDirty &= ~Canvas3D.LIGHTBIN_DIRTY; // invalidate canvas cached enableMask cv.enableMask = -1; } // across frames else if ((cv.canvasDirty & Canvas3D.LIGHTBIN_DIRTY) != 0) { // Just update the dirty lights if (geometryBackground == null) { scale = cv.canvasViewCache.getVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.vworldToVpc); } else { scale = cv.canvasViewCache.getInfVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.infVworldToVpc); } i = 0; int mask = lightDirtyMask; while (mask != 0) { if ((mask & 1) != 0) { lights[i].update(cv.ctx, i, scale); cv.lights[i] = lights[i]; cv.frameCount[i] = frameCount; } mask >>= 1; i++; } cv.canvasDirty &= ~Canvas3D.LIGHTBIN_DIRTY; } else if ((pointLts.size() > 0) && ((cv.canvasDirty & Canvas3D.VIEW_MATRIX_DIRTY) != 0 )) { if (geometryBackground == null) { scale = cv.canvasViewCache.getVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.vworldToVpc); } else { scale = cv.canvasViewCache.getInfVworldToCoexistenceScale(); cv.setModelViewMatrix(cv.ctx, cv.vpcToEc.mat, renderBin.infVworldToVpc); } for (i = 0; i < pointLts.size(); i++) { LightRetained lt = (LightRetained) pointLts.get(i); lt.update(cv.ctx, pointLtsSlotIndex[i], scale); cv.lights[pointLtsSlotIndex[i]] = lt; cv.frameCount[pointLtsSlotIndex[i]] = frameCount; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -