aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/TextureBin.java
diff options
context:
space:
mode:
authorHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
committerHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
commit7a2e20caac9db6f789a7b3fab344b9758af45335 (patch)
treeb5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/TextureBin.java
parentf76ce302c4bb2a9f03bbee571ec5d05c29633023 (diff)
j3dcore: flatten the directory structure a bit
Signed-off-by: Harvey Harrison <[email protected]>
Diffstat (limited to 'src/javax/media/j3d/TextureBin.java')
-rw-r--r--src/javax/media/j3d/TextureBin.java1543
1 files changed, 1543 insertions, 0 deletions
diff --git a/src/javax/media/j3d/TextureBin.java b/src/javax/media/j3d/TextureBin.java
new file mode 100644
index 0000000..9af0cc1
--- /dev/null
+++ b/src/javax/media/j3d/TextureBin.java
@@ -0,0 +1,1543 @@
+/*
+ * 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 java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The TextureBin manages a collection of TextureSetting objects.
+ * All objects in the TextureBin share the same Texture reference.
+ */
+
+
+//class TextureBin extends Object implements ObjectUpdate, NodeComponentUpdate {
+class TextureBin extends Object implements ObjectUpdate {
+
+ TextureUnitStateRetained [] texUnitState = null;
+
+ // number of active texture unit
+ private int numActiveTexUnit;
+
+ /**
+ * The RenderBin for this object
+ */
+ RenderBin renderBin = null;
+
+ /**
+ * The EnvironmentSet that this TextureBin resides
+ */
+ EnvironmentSet environmentSet = null;
+
+ /**
+ * The AttributeBin that this TextureBin resides
+ */
+ AttributeBin attributeBin = null;
+
+ /**
+ * The ShaderBin that this TextureBin resides
+ */
+ ShaderBin shaderBin = null;
+
+ /**
+ * The references to the next and previous TextureBins in the
+ * list.
+ */
+ TextureBin next = null;
+ TextureBin prev = null;
+
+ /**
+ * Oring of the equivalence bits for all appearance attrs under
+ * this renderBin
+ */
+ int equivalent = 0;
+
+ /**
+ * If any of the texture reference in an appearance is frequently
+ * changable, then a separate TextureBin will be created for this
+ * appearance, and this TextureBin is marked as the sole user of
+ * this appearance, and app will be pointing to the appearance
+ * being referenced by this TextureBin. Otherwise, app is null
+ */
+ AppearanceRetained app = null;
+
+
+ /**
+ * Sole user node component dirty mask. The first bit is reserved
+ * for node component reference dirty bit. It is set if any of the
+ * texture related node component reference in the appearance is
+ * being modified. The second bit onwords are for the individual
+ * TextureUnitState dirty bit. The ith bit set means the (i-1)
+ * texture unit state is modified. Note, this mask only supports
+ * 30 texture unit states. If the appearance uses more than 31
+ * texture unit states, then the modification of the 32nd texture
+ * unit state and up will have the first bit set, that means
+ * the TextureBin will be reset, rather than only the particular
+ * texture unit state will be reset.
+ */
+ int soleUserCompDirty;
+
+ static final int SOLE_USER_DIRTY_REF = 0x1;
+ static final int SOLE_USER_DIRTY_TA = 0x2;
+ static final int SOLE_USER_DIRTY_TC = 0x4;
+ static final int SOLE_USER_DIRTY_TEXTURE = 0x8;
+ static final int SOLE_USER_DIRTY_TUS = 0x10;
+
+
+/**
+ * The hashMap of RenderMolecules in this TextureBin this is used in rendering,
+ * the key used is localToVworld
+ */
+HashMap<Transform3D[], ArrayList<RenderMolecule>> addOpaqueRMs = new HashMap<Transform3D[], ArrayList<RenderMolecule>>();
+HashMap<Transform3D[], ArrayList<RenderMolecule>> addTransparentRMs = new HashMap<Transform3D[], ArrayList<RenderMolecule>>();
+
+// A hashmap based on localToVworld for fast
+// insertion of new renderMolecules
+HashMap<Transform3D[], RenderMolecule> opaqueRenderMoleculeMap = new HashMap<Transform3D[], RenderMolecule>();
+HashMap<Transform3D[], RenderMolecule> transparentRenderMoleculeMap = new HashMap<Transform3D[], RenderMolecule>();
+
+ // List of renderMolecules - used in rendering ..
+ RenderMolecule opaqueRMList = null;
+
+ RenderMolecule transparentRMList = null;
+ TransparentRenderingInfo parentTInfo;
+
+ int numRenderMolecules = 0;
+ int numEditingRenderMolecules = 0;
+
+ int tbFlag = 0; // a general bitmask for TextureBin
+
+ // Following are the bits used in flag
+
+ final static int ON_RENDER_BIN_LIST = 0x0001;
+ final static int ON_UPDATE_LIST = 0x0002;
+ final static int SOLE_USER = 0x0004;
+ final static int CONTIGUOUS_ACTIVE_UNITS = 0x0008;
+ final static int RESORT = 0x0010;
+ final static int ON_UPDATE_CHECK_LIST = 0x0020;
+
+ final static int USE_DISPLAYLIST = -2;
+ final static int USE_VERTEXARRAY = -1;
+
+ TextureBin(TextureUnitStateRetained[] state, AppearanceRetained app,
+ RenderBin rb) {
+ renderBin = rb;
+ tbFlag = 0;
+ reset(state, app);
+ }
+
+
+ /**
+ * For now, clone everything just like the other NodeComponent
+ */
+ void reset(TextureUnitStateRetained[] state, AppearanceRetained app) {
+
+ prev = null;
+ next = null;
+ opaqueRMList = null;
+ transparentRMList = null;
+ numEditingRenderMolecules = 0;
+
+ // Issue 249 - check for sole user only if property is set
+ // determine if this appearance is a sole user of this
+ // TextureBin
+ tbFlag &= ~TextureBin.SOLE_USER;
+ if (VirtualUniverse.mc.allowSoleUser) {
+ if ((app != null) &&
+ (app.changedFrequent &
+ (AppearanceRetained.TEXTURE |
+ AppearanceRetained.TEXCOORD_GEN |
+ AppearanceRetained.TEXTURE_ATTR |
+ AppearanceRetained.TEXTURE_UNIT_STATE)) != 0) {
+ tbFlag |= TextureBin.SOLE_USER;
+
+ }
+ }
+
+ if ((tbFlag & TextureBin.SOLE_USER) != 0) {
+ this.app = app;
+ } else {
+ this.app = null;
+ }
+
+ resetTextureState(state);
+
+ if ((tbFlag & TextureBin.ON_RENDER_BIN_LIST) == 0) {
+ renderBin.addTextureBin(this);
+ tbFlag |= TextureBin.ON_RENDER_BIN_LIST;
+ }
+
+ }
+
+ void resetTextureState(TextureUnitStateRetained[] state) {
+
+ int i;
+ boolean foundDisableUnit = false;
+ numActiveTexUnit = 0;
+ boolean soleUser = ((tbFlag & TextureBin.SOLE_USER) != 0);
+ TextureRetained prevFirstTexture = null;
+ TextureRetained tex;
+
+ tbFlag |= TextureBin.CONTIGUOUS_ACTIVE_UNITS;
+
+ if (state != null) {
+
+ foundDisableUnit = false;
+
+ if (texUnitState == null || (texUnitState.length != state.length)) {
+ texUnitState = new TextureUnitStateRetained[state.length];
+ } else if (texUnitState.length > 0 && texUnitState[0] != null) {
+ prevFirstTexture = texUnitState[0].texture;
+ }
+
+ for (i = 0; i < state.length; i++) {
+ if (state[i] == null) {
+ texUnitState[i] = null;
+ foundDisableUnit = true;
+ } else {
+
+ // create a clone texture unit state
+ if (texUnitState[i] == null) {
+ texUnitState[i] = new TextureUnitStateRetained();
+ }
+
+ // for sole user TextureUnitState, save
+ // the node component reference in the mirror reference
+ // of the cloned copy for equal test, and
+ // for native download optimization
+ if (soleUser || state[i].changedFrequent != 0) {
+ texUnitState[i].mirror = state[i];
+ }
+
+ // for the lowest level of node component in
+ // TextureBin, clone it only if it is not
+ // changedFrequent; in other words, if the
+ // lowest level of texture related node components
+ // such as TextureAttributes & TexCoordGen is
+ // changedFrequent, have the cloned texUnitState
+ // reference the mirror of those node components
+ // directly. For Texture, we'll always reference
+ // the mirror.
+
+ // decrement the TextureBin ref count of the previous
+ // texture
+ tex = texUnitState[i].texture;
+ if (tex != null) {
+ tex.decTextureBinRefCount(this);
+ if (soleUser &&
+ (tex.getTextureBinRefCount(this) == 0) &&
+ (tex != state[i].texture)) {
+ // In this case texture change but
+ // TextureBin will not invoke clear() to reset.
+ // So we need to free the texture resource here.
+ renderBin.addTextureResourceFreeList(tex);
+ }
+ }
+
+ texUnitState[i].texture = state[i].texture;
+
+ // increment the TextureBin ref count of the new
+ // texture
+
+ if (texUnitState[i].texture != null) {
+ texUnitState[i].texture.incTextureBinRefCount(this);
+ }
+
+ if (state[i].texAttrs != null) {
+
+ if (state[i].texAttrs.changedFrequent != 0) {
+ texUnitState[i].texAttrs = state[i].texAttrs;
+
+ } else {
+
+ // need to check for texAttrs.source because
+ // texAttrs could be pointing to the mirror
+ // in the last frame, so don't want to
+ // overwrite the mirror
+
+ if (texUnitState[i].texAttrs == null ||
+ texUnitState[i].texAttrs.source != null) {
+ texUnitState[i].texAttrs =
+ new TextureAttributesRetained();
+ }
+ texUnitState[i].texAttrs.set(
+ state[i].texAttrs);
+ texUnitState[i].texAttrs.mirrorCompDirty = true;
+
+ // for sole user TextureBin, we are saving
+ // the mirror node component in the mirror
+ // reference in the clone object. This
+ // will be used in state download to
+ // avoid redundant download
+
+ if (soleUser) {
+ texUnitState[i].texAttrs.mirror =
+ state[i].texAttrs;
+ } else {
+ texUnitState[i].texAttrs.mirror = null;
+ }
+
+ }
+ } else {
+ texUnitState[i].texAttrs = null;
+ }
+
+
+ if (state[i].texGen != null) {
+ if (state[i].texGen.changedFrequent != 0) {
+ texUnitState[i].texGen = state[i].texGen;
+ } else {
+
+ // need to check for texGen.source because
+ // texGen could be pointing to the mirror
+ // in the last frame, so don't want to
+ // overwrite the mirror
+
+ if (texUnitState[i].texGen == null ||
+ texUnitState[i].texGen.source != null) {
+ texUnitState[i].texGen =
+ new TexCoordGenerationRetained();
+ }
+
+ texUnitState[i].texGen.set(state[i].texGen);
+ texUnitState[i].texGen.mirrorCompDirty = true;
+
+
+ // for sole user TextureBin, we are saving
+ // the mirror node component in the mirror
+ // reference in the clone object. This
+ // will be used in state download to
+ // avoid redundant download
+
+ if (soleUser) {
+ texUnitState[i].texGen.mirror = state[i].texGen;
+ } else {
+ texUnitState[i].texGen.mirror = null;
+ }
+ }
+ } else {
+ texUnitState[i].texGen = null;
+ }
+
+
+ // Track the last active texture unit and the total number
+ // of active texture units. Note that this total number
+ // now includes disabled units so that there is always
+ // a one-to-one mapping. We no longer remap texture units.
+ if (texUnitState[i].isTextureEnabled()) {
+ numActiveTexUnit = i + 1;
+
+ if (foundDisableUnit) {
+
+ // mark that active texture units are not
+ // contiguous
+ tbFlag &= ~TextureBin.CONTIGUOUS_ACTIVE_UNITS;
+ }
+ } else {
+ foundDisableUnit = true;
+ }
+ }
+ }
+
+ // check to see if the TextureBin sorting criteria is
+ // modified for this textureBin; if yes, mark that
+ // resorting is needed
+
+ if ((texUnitState[0] == null && prevFirstTexture != null) ||
+ (texUnitState[0] != null &&
+ texUnitState[0].texture != prevFirstTexture)) {
+ tbFlag |= TextureBin.RESORT;
+ }
+
+ } else {
+
+ // check to see if the TextureBin sorting criteria is
+ // modified for this textureBin; if yes, mark that
+ // resorting is needed
+
+ if (texUnitState != null && texUnitState[0].texture != null) {
+ tbFlag |= TextureBin.RESORT;
+ }
+ texUnitState = null;
+ }
+
+ soleUserCompDirty = 0;
+ }
+
+
+ /**
+ * The TextureBin is to be removed from RenderBin,
+ * do the proper unsetting of any references
+ */
+ void clear() {
+
+ // make sure there is no reference to the scenegraph
+ app = null;
+
+ // for each texture referenced in the texture units, decrement
+ // the reference count. If the reference count == 0, tell
+ // the renderer to free up the resource
+ if (texUnitState != null) {
+
+ TextureRetained tex;
+
+ for (int i = 0; i < texUnitState.length; i++) {
+ if (texUnitState[i] != null) {
+ if (texUnitState[i].texture != null) {
+ tex = texUnitState[i].texture;
+ tex.decTextureBinRefCount(this);
+
+ if (tex.getTextureBinRefCount(this) == 0) {
+ renderBin.addTextureResourceFreeList(tex);
+ }
+
+ texUnitState[i].texture = null;
+ }
+
+ // make sure there is no more reference to the scenegraph
+
+ texUnitState[i].mirror = null;
+ texUnitState[i].texture = null;
+ if (texUnitState[i].texAttrs != null &&
+ texUnitState[i].texAttrs.source != null) {
+ texUnitState[i].texAttrs = null;
+ }
+ if (texUnitState[i].texGen != null &&
+ texUnitState[i].texGen.source != null) {
+ texUnitState[i].texGen = null;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * This tests if the qiven textureUnitState matches this TextureBin
+ */
+ boolean equals(TextureUnitStateRetained state[], RenderAtom ra) {
+ // if this TextureBin is a soleUser case or the incoming
+ // app has changedFrequent bit set for any of the texture
+ // related component, then either the current TextureBin
+ // or the incoming app requires the same app match
+ if (((tbFlag & TextureBin.SOLE_USER) != 0) ||
+ ((ra.app != null) &&
+ (ra.app.changedFrequent &
+ (AppearanceRetained.TEXTURE |
+ AppearanceRetained.TEXCOORD_GEN |
+ AppearanceRetained.TEXTURE_ATTR |
+ AppearanceRetained.TEXTURE_UNIT_STATE)) != 0)) {
+
+ if (app == ra.app) {
+
+ // if this textureBin is currently on a zombie state,
+ // we'll need to put it on the update list to reevaluate
+ // the state, because while it is on a zombie state,
+ // texture state could have been changed. Example,
+ // application could have detached an appearance,
+ // made changes to the texture references, and then
+ // reattached the appearance. In this case, the texture
+ // changes would not have reflected to the textureBin
+
+ if (numEditingRenderMolecules == 0) {
+
+ //System.err.println("===> TB in zombie state " + this);
+
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_REF;
+ }
+ return true;
+
+ } else {
+ return false;
+ }
+ }
+
+ if (texUnitState == null && state == null)
+ return (true);
+
+ if (texUnitState == null || state == null)
+ return (false);
+
+ if (state.length != texUnitState.length)
+ return (false);
+
+ for (int i = 0; i < texUnitState.length; i++) {
+ // If texture Unit State is null
+ if (texUnitState[i] == null) {
+ if (state[i] != null)
+ return (false);
+ }
+ else {
+ if (!texUnitState[i].equivalent(state[i])) {
+ return (false);
+ }
+ }
+ }
+
+ // Check if the image component has changed(may be a clearLive texture
+ // change img component. setLive case)
+ //
+ if ((tbFlag & TextureBin.ON_RENDER_BIN_LIST) == 0) {
+ renderBin.addTextureBin(this);
+ tbFlag |= TextureBin.ON_RENDER_BIN_LIST;
+ }
+
+ return (true);
+
+ }
+
+
+ /*
+ // updateNodeComponentCheck is called for each soleUser TextureBin
+ // into which new renderAtom has been added. This method is called before
+ // updateNodeComponent() to allow TextureBin to catch any node
+ // component changes that have been missed because the changes
+ // come when there is no active renderAtom associated with the
+ // TextureBin. See bug# 4503926 for details.
+ public void updateNodeComponentCheck() {
+
+ //System.err.println("TextureBin.updateNodeComponentCheck()");
+
+ tbFlag &= ~TextureBin.ON_UPDATE_CHECK_LIST;
+
+ if ((soleUserCompDirty & SOLE_USER_DIRTY_REF) != 0) {
+ return ;
+ }
+
+ if ((app.compChanged & (AppearanceRetained.TEXTURE |
+ AppearanceRetained.TEXCOORD_GEN |
+ AppearanceRetained.TEXTURE_ATTR |
+ AppearanceRetained.TEXTURE_UNIT_STATE)) != 0) {
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_REF;
+
+ } else if (app.texUnitState != null) {
+
+ // if one texture unit state has to be reevaluated, then
+ // it's enough update checking because reevaluating texture unit
+ // state will automatically take care of its node component
+ // updates.
+
+ boolean done = false;
+
+ for (int i = 0; i < app.texUnitState.length && !done; i++) {
+ if (app.texUnitState[i] != null) {
+ if (app.texUnitState[i].compChanged != 0) {
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TUS;
+ done = true;
+ } else {
+ if (app.texUnitState[i].texAttrs != null &&
+ app.texUnitState[i].texAttrs.compChanged != 0) {
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TA;
+ }
+ if (app.texUnitState[i].texGen != null &&
+ app.texUnitState[i].texGen.compChanged != 0) {
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TC;
+ }
+ if (app.texUnitState[i].texture != null &&
+ ((app.texUnitState[i].texture.compChanged &
+ TextureRetained.ENABLE_CHANGED) != 0)) {
+ if (soleUserCompDirty == 0) {
+ this.renderBin.tbUpdateList.add(this);
+ }
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TEXTURE;
+ }
+ }
+ }
+ }
+ }
+ }
+ */
+
+
+
+
+ /**
+ * updateNodeComponent is called from RenderBin to update the
+ * clone copy of the sole user node component in TextureBin when the
+ * corresponding node component is being modified
+ */
+ public void updateNodeComponent() {
+
+ // don't bother to update if the TextureBin is already
+ // removed from RenderBin
+
+ if ((tbFlag & TextureBin.ON_RENDER_BIN_LIST) == 0)
+ return;
+
+ // if any of the texture reference in the appearance referenced
+ // by a sole user TextureBin is being modified, just do a reset
+
+ if (((tbFlag & TextureBin.SOLE_USER) != 0) &&
+ ((soleUserCompDirty & TextureBin.SOLE_USER_DIRTY_REF) != 0)) {
+
+ resetTextureState(app.texUnitState);
+ return;
+ }
+
+ if (texUnitState == null) {
+ soleUserCompDirty = 0;
+ return;
+ }
+
+ if ((soleUserCompDirty & TextureBin.SOLE_USER_DIRTY_TUS) != 0) {
+
+ // Now take care of the Texture Unit State changes
+ TextureUnitStateRetained tus, mirrorTUS = null;
+ boolean soleUser = ((tbFlag & TextureBin.SOLE_USER) != 0);
+
+ for (int i = 0; i < texUnitState.length; i++) {
+ tus = texUnitState[i];
+ if (tus != null) {
+ if (tus.mirror != null) {
+
+ mirrorTUS = (TextureUnitStateRetained)tus.mirror;
+
+ if (tus.texture != mirrorTUS.texture) {
+ if (tus.texture != null) {
+ tus.texture.decTextureBinRefCount(this);
+ }
+ tus.texture = mirrorTUS.texture;
+ if (tus.texture != null) {
+ tus.texture.incTextureBinRefCount(this);
+ }
+
+ // the first texture (TextureBin sorting
+ // criteria) is modified, so needs to resort
+
+ if (i == 0) {
+ tbFlag |= TextureBin.RESORT;
+ }
+ }
+
+
+ if (mirrorTUS.texAttrs != null) {
+ if (mirrorTUS.texAttrs.changedFrequent != 0) {
+ tus.texAttrs = mirrorTUS.texAttrs;
+ } else {
+ if (tus.texAttrs == null ||
+ tus.texAttrs.source != null) {
+ tus.texAttrs =
+ new TextureAttributesRetained();
+ }
+ tus.texAttrs.set(mirrorTUS.texAttrs);
+ tus.texAttrs.mirrorCompDirty = true;
+
+ if (soleUser) {
+ tus.texAttrs.mirror = mirrorTUS.texAttrs;
+ } else {
+ tus.texAttrs.mirror = null;
+ }
+ }
+ } else {
+ tus.texAttrs = null;
+ }
+
+ if (mirrorTUS.texGen != null) {
+ if (mirrorTUS.texGen.changedFrequent != 0) {
+ tus.texGen = mirrorTUS.texGen;
+ } else {
+ if (tus.texGen == null ||
+ tus.texGen.source != null) {
+ tus.texGen =
+ new TexCoordGenerationRetained();
+ }
+ tus.texGen.set(mirrorTUS.texGen);
+ tus.texGen.mirrorCompDirty = true;
+
+ if (soleUser) {
+ tus.texGen.mirror = mirrorTUS.texGen;
+ } else {
+ tus.texGen.mirror = null;
+ }
+ }
+ } else {
+ tus.texGen = null;
+ }
+ }
+ }
+ }
+
+ // need to reEvaluate # of active textures after the update
+ soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TEXTURE;
+
+ // TextureUnitState update automatically taken care of
+ // TextureAttributes & TexCoordGeneration update
+
+ soleUserCompDirty &= ~(TextureBin.SOLE_USER_DIRTY_TA |
+ TextureBin.SOLE_USER_DIRTY_TC);
+ }
+
+ if ((soleUserCompDirty & TextureBin.SOLE_USER_DIRTY_TEXTURE) != 0) {
+
+
+
+ boolean foundDisableUnit = false;
+
+ numActiveTexUnit = 0;
+ tbFlag |= TextureBin.CONTIGUOUS_ACTIVE_UNITS;
+ for (int i = 0; i < texUnitState.length; i++) {
+
+ // Track the last active texture unit and the total number
+ // of active texture units. Note that this total number
+ // now includes disabled units so that there is always
+ // a one-to-one mapping. We no longer remap texture units.
+ if (texUnitState[i] != null &&
+ texUnitState[i].isTextureEnabled()) {
+ numActiveTexUnit = i + 1;
+
+ if (foundDisableUnit) {
+
+ // mark that active texture units are not
+ // contiguous
+ tbFlag &= ~TextureBin.CONTIGUOUS_ACTIVE_UNITS;
+ }
+ } else {
+ foundDisableUnit = true;
+ }
+ }
+ }
+
+ if ((soleUserCompDirty & TextureBin.SOLE_USER_DIRTY_TA) != 0) {
+ for (int i = 0; i < texUnitState.length; i++) {
+ if (texUnitState[i] != null &&
+ texUnitState[i].texAttrs != null &&
+ texUnitState[i].texAttrs.mirror != null &&
+ texUnitState[i].texAttrs.mirror.changedFrequent != 0) {
+ texUnitState[i].texAttrs = (TextureAttributesRetained)
+ texUnitState[i].texAttrs.mirror;
+ }
+ }
+ }
+
+ if ((soleUserCompDirty & TextureBin.SOLE_USER_DIRTY_TC) != 0) {
+ for (int i = 0; i < texUnitState.length; i++) {
+ if (texUnitState[i] != null &&
+ texUnitState[i].texGen != null &&
+ texUnitState[i].texGen.mirror != null &&
+ texUnitState[i].texGen.mirror.changedFrequent != 0) {
+ texUnitState[i].texGen = (TexCoordGenerationRetained)
+ texUnitState[i].texGen.mirror;
+ }
+ }
+ }
+
+ soleUserCompDirty = 0;
+ }
+
+ @Override
+ public void updateObject() {
+ if (!addOpaqueRMs.isEmpty()) {
+ opaqueRMList = addAll(opaqueRenderMoleculeMap, addOpaqueRMs,
+ opaqueRMList, true);
+ }
+ if (!addTransparentRMs.isEmpty()) {
+ // If transparent and not in bg geometry and inodepth
+ // sorted transparency
+ if (transparentRMList == null &&
+ (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE ||
+ environmentSet.lightBin.geometryBackground != null)) {
+ // System.err.println("========> addTransparentTextureBin "+this);
+ transparentRMList = addAll(transparentRenderMoleculeMap,
+ addTransparentRMs, transparentRMList, false);
+ // Eventhough we are adding to transparentList , if all the RMS
+ // have been switched already due to changeLists, then there is
+ // nothing to add, and TBIN does not have any transparentRMList
+ if (transparentRMList != null) {
+ renderBin.addTransparentObject(this);
+ }
+
+ }
+ else {
+ transparentRMList = addAll(transparentRenderMoleculeMap,
+ addTransparentRMs, transparentRMList, false);
+ }
+ }
+ tbFlag &= ~TextureBin.ON_UPDATE_LIST;
+
+ }
+
+
+ /**
+ * Each list of renderMoledule with the same localToVworld
+ * is connect by rm.next and rm.prev.
+ * At the end of the list (i.e. rm.next = null) the field
+ * rm.nextMap is link to another list (with the same
+ * localToVworld). So during rendering it will traverse
+ * rm.next until this is null, then follow the .nextMap
+ * to access another list and use rm.next to continue
+ * until both rm.next and rm.nextMap are null.
+ *
+ * renderMoleculeMap is use to assist faster location of
+ * renderMolecule List with the same localToVWorld. The
+ * start of renderMolecule in the list with same
+ * localToVworld is insert in renderMoleculeMap. This
+ * map is clean up at removeRenderMolecule(). TextureBin
+ * also use the map for quick location of renderMolecule
+ * with the same localToVworld and attributes in
+ * findRenderMolecule().
+ */
+RenderMolecule addAll(HashMap<Transform3D[], RenderMolecule> renderMoleculeMap,
+ HashMap<Transform3D[], ArrayList<RenderMolecule>> addRMs,
+ RenderMolecule startList, boolean opaqueList) {
+ int i;
+ Collection<ArrayList<RenderMolecule>> c = addRMs.values();
+ Iterator<ArrayList<RenderMolecule>> listIterator = c.iterator();
+ RenderMolecule renderMoleculeList, head;
+
+ while (listIterator.hasNext()) {
+ boolean changed = false;
+ ArrayList<RenderMolecule> curList = listIterator.next();
+ RenderMolecule r = curList.get(0);
+ // If this is a opaque one , but has been switched to a transparentList or
+ // vice-versa (dur to changeLists function called before this), then
+ // do nothing!
+ // For changedFrequent case: Consider the case when a RM is added
+ // (so is in the addRM list) and then
+ // a change in transparent value occurs that make it from opaque to
+ // transparent (the switch is handled before this function is called)
+ if (r.isOpaqueOrInOG != opaqueList) {
+ continue;
+ }
+ // Get the list of renderMolecules for this transform
+ renderMoleculeList = renderMoleculeMap.get(r.localToVworld);
+ if (renderMoleculeList == null) {
+ renderMoleculeList = r;
+ renderMoleculeMap.put(r.localToVworld, renderMoleculeList);
+ // Add this renderMolecule at the beginning of RM list
+ if (startList == null) {
+ startList = r;
+ r.nextMap = null;
+ r.prevMap = null;
+ startList.dirtyAttrsAcrossRms = RenderMolecule.ALL_DIRTY_BITS;
+ }
+ else {
+ r.nextMap = startList;
+ startList.prevMap = r;
+ startList = r;
+ startList.nextMap.checkEquivalenceWithLeftNeighbor(r,
+ RenderMolecule.ALL_DIRTY_BITS);
+ }
+
+ }
+ else {
+ // Insert the renderMolecule next to a RM that has equivalent
+ // texture unit state
+ if ((head = insertRenderMolecule(r, renderMoleculeList)) != null) {
+ if (renderMoleculeList.prevMap != null) {
+ renderMoleculeList.prevMap.nextMap = head;
+ }
+ head.prevMap = renderMoleculeList.prevMap;
+ renderMoleculeList.prevMap = null;
+ renderMoleculeList = head;
+ changed = true;
+ }
+ }
+ for (i = 1; i < curList.size(); i++) {
+ r = curList.get(i);
+ // If this is a opaque one , but has been switched to a transparentList or
+ // vice-versa (dur to changeLists function called before this), then
+ // do nothing!
+ // For changedFrequent case: Consider the case when a RM is added
+ // (so is in the addRM list) and then
+ // a change in transparent value occurs that make it from opaque to
+ // transparent (the switch is handled before this function is called)
+ if (r.isOpaqueOrInOG != opaqueList)
+ continue;
+ if ((head = insertRenderMolecule(r, renderMoleculeList)) != null) {
+ if (renderMoleculeList.prevMap != null) {
+ renderMoleculeList.prevMap.nextMap = head;
+ }
+ head.prevMap = renderMoleculeList.prevMap;
+ renderMoleculeList.prevMap = null;
+ renderMoleculeList = head;
+ changed = true;
+ }
+
+ }
+ if (changed) {
+ renderMoleculeMap.put(r.localToVworld, renderMoleculeList);
+ if (renderMoleculeList.prevMap != null) {
+ renderMoleculeList.checkEquivalenceWithLeftNeighbor(
+ renderMoleculeList.prevMap,
+ RenderMolecule.ALL_DIRTY_BITS);
+ }
+ else {
+ startList = renderMoleculeList;
+ startList.dirtyAttrsAcrossRms =
+ RenderMolecule.ALL_DIRTY_BITS;
+ }
+ }
+ }
+
+ addRMs.clear();
+ return startList;
+ }
+
+
+ // XXXX: Could the analysis be done during insertRenderMolecule?
+ // Return the head of the list,
+ // if the insertion occurred at beginning of the list
+ RenderMolecule insertRenderMolecule(RenderMolecule r,
+ RenderMolecule renderMoleculeList) {
+ RenderMolecule rm, retval;
+
+ // Look for a RM that has an equivalent material
+ rm = renderMoleculeList;
+ while (rm != null) {
+ if (rm.material == r.material ||
+ (rm.definingMaterial != null &&
+ rm.definingMaterial.equivalent(r.definingMaterial))) {
+ // Put it here
+ r.next = rm;
+ r.prev = rm.prev;
+ if (rm.prev == null) {
+ renderMoleculeList = r;
+ retval = renderMoleculeList;
+ } else {
+ rm.prev.next = r;
+ retval = null;
+ }
+ rm.prev = r;
+ r.checkEquivalenceWithBothNeighbors(RenderMolecule.ALL_DIRTY_BITS);
+ return retval;
+ }
+ // If they are not equivalent, then skip to the first one
+ // that has a different material using the dirty bits
+ else {
+ rm = rm.next;
+ while (rm != null &&
+ ((rm.dirtyAttrsAcrossRms & RenderMolecule.MATERIAL_DIRTY) == 0)) {
+ rm = rm.next;
+ }
+ }
+ }
+ // Just put it up front
+ r.next = renderMoleculeList;
+ renderMoleculeList.prev = r;
+ renderMoleculeList = r;
+ r.checkEquivalenceWithBothNeighbors(RenderMolecule.ALL_DIRTY_BITS);
+ return renderMoleculeList;
+ }
+
+
+ /**
+ * Adds the given RenderMolecule to this TextureBin
+ */
+ void addRenderMolecule(RenderMolecule r, RenderBin rb) {
+ r.textureBin = this;
+
+ HashMap<Transform3D[], ArrayList<RenderMolecule>> map;
+ if (r.isOpaqueOrInOG)
+ map = addOpaqueRMs;
+ else
+ map = addTransparentRMs;
+
+ ArrayList<RenderMolecule> list = map.get(r.localToVworld);
+ if (list == null) {
+ list = new ArrayList<RenderMolecule>();
+ map.put(r.localToVworld, list);
+ }
+ list.add(r);
+
+ if ((tbFlag & TextureBin.ON_UPDATE_LIST) == 0) {
+ tbFlag |= TextureBin.ON_UPDATE_LIST;
+ rb.objUpdateList.add(this);
+ }
+ }
+
+ /**
+ * Removes the given RenderMolecule from this TextureBin
+ */
+ void removeRenderMolecule(RenderMolecule r) {
+ int index;
+ boolean found = false;
+ RenderMolecule rmlist;
+ HashMap<Transform3D[], ArrayList<RenderMolecule>> addMap;
+ HashMap<Transform3D[], RenderMolecule> allMap;
+ r.textureBin = null;
+
+ if (r.isOpaqueOrInOG) {
+ rmlist = opaqueRMList;
+ allMap = opaqueRenderMoleculeMap;
+ addMap = addOpaqueRMs;
+ }
+ else {
+ rmlist = transparentRMList;
+ allMap = transparentRenderMoleculeMap;
+ addMap = addTransparentRMs;
+ }
+ // If the renderMolecule being remove is contained in addRMs, then
+ // remove the renderMolecule from the addList
+ ArrayList<RenderMolecule> list = addMap.get(r.localToVworld);
+ if (list != null) {
+ if ((index = list.indexOf(r)) != -1) {
+ list.remove(index);
+ // If this was the last element for this localToVworld, then remove
+ // the entry from the addRMs list
+ if (list.isEmpty()) {
+ addMap.remove(r.localToVworld);
+ }
+
+ r.prev = null;
+ r.next = null;
+ found = true;
+ }
+ }
+ if (!found) {
+ RenderMolecule head = removeOneRM(r, allMap, rmlist);
+
+ r.soleUserCompDirty = 0;
+ r.onUpdateList = 0;
+ if (r.definingPolygonAttributes != null &&
+ (r.definingPolygonAttributes.changedFrequent != 0))
+ r.definingPolygonAttributes = null;
+
+ if (r.definingLineAttributes != null &&
+ (r.definingLineAttributes.changedFrequent != 0))
+ r.definingLineAttributes = null;
+
+ if (r.definingPointAttributes != null &&
+ (r.definingPointAttributes.changedFrequent != 0))
+ r.definingPointAttributes = null;
+
+ if (r.definingMaterial != null &&
+ (r.definingMaterial.changedFrequent != 0))
+ r.definingMaterial = null;
+
+ if (r.definingColoringAttributes != null &&
+ (r.definingColoringAttributes.changedFrequent != 0))
+ r.definingColoringAttributes = null;
+
+ if (r.definingTransparency != null &&
+ (r.definingTransparency.changedFrequent != 0))
+ r.definingTransparency = null;
+
+ renderBin.removeRenderMolecule(r);
+ if (r.isOpaqueOrInOG) {
+ opaqueRMList = head;
+ }
+ else {
+ transparentRMList = head;
+ }
+
+ }
+ // If the renderMolecule removed is not opaque then ..
+ if (!r.isOpaqueOrInOG && transparentRMList == null && (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE ||
+ environmentSet.lightBin.geometryBackground != null)) {
+ renderBin.removeTransparentObject(this);
+ }
+ // If the rm removed is the one that is referenced in the tinfo
+ // then change this reference
+ else if (parentTInfo != null && parentTInfo.rm == r) {
+ parentTInfo.rm = transparentRMList;
+ }
+ // Removal of this texture setting from the texCoordGenartion
+ // is done during the removeRenderAtom routine in RenderMolecule.java
+ // Only remove this texture bin if there are no more renderMolcules
+ // waiting to be added
+ if (opaqueRenderMoleculeMap.isEmpty() && addOpaqueRMs.isEmpty() &&
+ transparentRenderMoleculeMap.isEmpty() && addTransparentRMs.isEmpty()) {
+ if ((tbFlag & TextureBin.ON_RENDER_BIN_LIST) != 0) {
+ tbFlag &= ~TextureBin.ON_RENDER_BIN_LIST;
+ renderBin.removeTextureBin(this);
+ }
+
+ shaderBin.removeTextureBin(this);
+ texUnitState = null;
+ }
+ }
+
+ /**
+ * This method is called to update the state for this
+ * TextureBin. This is only applicable in the single-pass case.
+ * Multi-pass render will have to take care of its own
+ * state update.
+ */
+ void updateAttributes(Canvas3D cv) {
+
+ boolean dirty = ((cv.canvasDirty & (Canvas3D.TEXTUREBIN_DIRTY|
+ Canvas3D.TEXTUREATTRIBUTES_DIRTY)) != 0);
+
+ if (cv.textureBin == this && !dirty) {
+ return;
+ }
+
+ cv.textureBin = this;
+
+ // save the current number of active texture unit so as
+ // to be able to reset the one that is not enabled in this bin
+
+ int lastActiveTexUnitIdx = -1;
+
+ // Get the number of available texture units; this depends on
+ // whether or not shaders are being used.
+ boolean useShaders = (shaderBin.shaderProgram != null);
+ int availableTextureUnits =
+ useShaders ? cv.maxTextureImageUnits : cv.maxTextureUnits;
+
+ // If the number of active texture units is greater than the number of
+ // supported units, then we
+ // need to set a flag indicating that the texture units are invalid.
+ boolean disableTexture = false;
+
+ if (numActiveTexUnit > availableTextureUnits) {
+ disableTexture = true;
+// System.err.println("*** TextureBin : number of texture units exceeded");
+ }
+
+ // set the number active texture unit in Canvas3D
+ if (disableTexture) {
+ cv.setNumActiveTexUnit(0);
+ }
+ else {
+ cv.setNumActiveTexUnit(numActiveTexUnit);
+ }
+
+ // state update
+ if (numActiveTexUnit <= 0 || disableTexture) {
+ if (cv.getLastActiveTexUnit() >= 0) {
+ // no texture units enabled
+
+ // when the canvas supports multi texture units,
+ // we'll need to reset texture for all texture units
+ if (cv.multiTexAccelerated) {
+ for (int i = 0; i <= cv.getLastActiveTexUnit(); i++) {
+ cv.resetTexture(cv.ctx, i);
+ }
+ // set the active texture unit back to 0
+ cv.setNumActiveTexUnit(0);
+ cv.activeTextureUnit(cv.ctx, 0);
+ } else {
+ cv.resetTexture(cv.ctx, -1);
+ }
+ cv.setLastActiveTexUnit(-1);
+ }
+ } else {
+
+ int j = 0;
+
+ for (int i = 0; i < texUnitState.length; i++) {
+
+ if (j >= cv.texUnitState.length) {
+ // We finish enabling the texture state.
+ // Note that it is possible
+ // texUnitState.length > cv.texUnitState.length
+
+ break;
+ }
+
+ if ((texUnitState[i] != null) &&
+ texUnitState[i].isTextureEnabled()) {
+ if (dirty ||
+ cv.texUnitState[j].mirror == null ||
+ cv.texUnitState[j].mirror != texUnitState[i].mirror) {
+ // update the texture unit state
+ texUnitState[i].updateNative(j, cv, false, false);
+ cv.texUnitState[j].mirror = texUnitState[i].mirror;
+ }
+
+ // create a mapping that maps an active texture
+ // unit to a texture unit state
+
+ lastActiveTexUnitIdx = j;
+ } else {
+ if (j <= cv.getLastActiveTexUnit()) {
+ cv.resetTexture(cv.ctx, j);
+ }
+ }
+
+ j++;
+ }
+
+ // make sure to disable the remaining texture units
+ // since they could have been enabled from the previous
+ // texture bin
+
+ for (int i = j; i <= cv.getLastActiveTexUnit(); i++) {
+ cv.resetTexture(cv.ctx, i);
+ }
+
+ cv.setLastActiveTexUnit(lastActiveTexUnitIdx);
+
+ // set the active texture unit back to 0
+ cv.activeTextureUnit(cv.ctx, 0);
+
+ }
+ cv.canvasDirty &= ~Canvas3D.TEXTUREBIN_DIRTY;
+ }
+
+
+/**
+ * Renders this TextureBin
+ */
+void render(Canvas3D cv) {
+ render(cv, opaqueRMList);
+}
+
+void render(Canvas3D cv, RenderMolecule rlist) {
+ // include this TextureBin to the to-be-updated state set in canvas
+ cv.setStateToUpdate(Canvas3D.TEXTUREBIN_BIT, this);
+ renderList(cv, USE_DISPLAYLIST, rlist);
+}
+
+void render(Canvas3D cv, TransparentRenderingInfo rlist) {
+ // include this TextureBin to the to-be-updated state set in canvas
+ cv.setStateToUpdate(Canvas3D.TEXTUREBIN_BIT, this);
+ renderList(cv, USE_DISPLAYLIST, rlist);
+}
+
+ /**
+ * render list of RenderMolecule
+ */
+ void renderList(Canvas3D cv, int pass, RenderMolecule rlist) {
+ assert pass < 0;
+
+ // bit mask of all attr fields that are equivalent across
+ // renderMolecules thro. ORing of invisible RMs.
+ int combinedDirtyBits = 0;
+ boolean rmVisible = true;
+ RenderMolecule rm = rlist;
+
+ while (rm != null) {
+ if(rmVisible) {
+ combinedDirtyBits = rm.dirtyAttrsAcrossRms;
+ }
+ else {
+ combinedDirtyBits |= rm.dirtyAttrsAcrossRms;
+ }
+
+ rmVisible = rm.render(cv, pass, combinedDirtyBits);
+
+
+ // next render molecule or the nextmap
+ if (rm.next == null) {
+ rm = rm.nextMap;
+ }
+ else {
+ rm = rm.next;
+ }
+ }
+ }
+
+
+ /**
+ * render sorted transparent list
+ */
+ void renderList(Canvas3D cv, int pass, TransparentRenderingInfo tinfo) {
+ assert pass < 0;
+
+ RenderMolecule rm = tinfo.rm;
+ if (rm.isSwitchOn()) {
+ rm.transparentSortRender(cv, pass, tinfo);
+ }
+ }
+
+
+ void changeLists(RenderMolecule r) {
+ RenderMolecule renderMoleculeList, rmlist = null, head;
+ HashMap<Transform3D[], RenderMolecule> allMap = null;
+ boolean newRM = false;
+ // System.err.println("changeLists r = "+r+" tBin = "+this);
+ // If its a new RM then do nothing, otherwise move lists
+ if (r.isOpaqueOrInOG) {
+ if (opaqueRMList == null &&
+ (r.prev == null && r.prevMap == null && r.next == null &&
+ r.nextMap == null)) {
+ newRM = true;
+ }
+ else {
+ rmlist = opaqueRMList;
+ allMap = opaqueRenderMoleculeMap;
+ }
+
+ }
+ else {
+ if (transparentRMList == null &&
+ (r.prev == null && r.prevMap == null && r.next == null &&
+ r.nextMap == null) ){
+ newRM = true;
+ }
+ else {
+ rmlist = transparentRMList;
+ allMap = transparentRenderMoleculeMap;
+ }
+ }
+ if (!newRM) {
+ head = removeOneRM(r, allMap, rmlist);
+
+ if (r.isOpaqueOrInOG) {
+ opaqueRMList = head;
+ }
+ else {
+ transparentRMList = head;
+ if (transparentRMList == null &&
+ (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE ||
+ environmentSet.lightBin.geometryBackground != null)) {
+ renderBin.removeTransparentObject(this);
+ }
+ // Issue 129: remove the RM's render atoms from the
+ // list of transparent render atoms
+ if ((renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) &&
+ (environmentSet.lightBin.geometryBackground == null)) {
+ r.addRemoveTransparentObject(renderBin, false);
+ }
+ }
+ }
+ HashMap<Transform3D[], RenderMolecule> renderMoleculeMap;
+ RenderMolecule startList;
+
+ // Now insert in the other bin
+ r.evalAlphaUsage(shaderBin.attributeBin.definingRenderingAttributes, texUnitState);
+ r.isOpaqueOrInOG = r.isOpaque() ||r.inOrderedGroup;
+ if (r.isOpaqueOrInOG) {
+ startList = opaqueRMList;
+ renderMoleculeMap = opaqueRenderMoleculeMap;
+ markDlistAsDirty(r);
+ }
+ else {
+ startList = transparentRMList;
+ renderMoleculeMap = transparentRenderMoleculeMap;
+ if ((r.primaryMoleculeType &RenderMolecule.DLIST_MOLECULE) != 0 &&
+ renderBin.transpSortMode != View.TRANSPARENCY_SORT_NONE) {
+ renderBin.addDisplayListResourceFreeList(r);
+ renderBin.removeDirtyRenderMolecule(r);
+
+ r.vwcBounds.set(null);
+ r.displayListId = 0;
+ r.displayListIdObj = null;
+ // Change the group type for all the rlistInfo in the primaryList
+ RenderAtomListInfo rinfo = r.primaryRenderAtomList;
+ while (rinfo != null) {
+ rinfo.groupType = RenderAtom.SEPARATE_DLIST_PER_RINFO;
+ if (rinfo.renderAtom.dlistIds == null) {
+ rinfo.renderAtom.dlistIds = new int[rinfo.renderAtom.rListInfo.length];
+
+ for (int k = 0; k < rinfo.renderAtom.dlistIds.length; k++) {
+ rinfo.renderAtom.dlistIds[k] = -1;
+ }
+ }
+ if (rinfo.renderAtom.dlistIds[rinfo.index] == -1) {
+ rinfo.renderAtom.dlistIds[rinfo.index] = VirtualUniverse.mc.getDisplayListId().intValue();
+ renderBin.addDlistPerRinfo.add(rinfo);
+ }
+ rinfo = rinfo.next;
+ }
+ r.primaryMoleculeType = RenderMolecule.SEPARATE_DLIST_PER_RINFO_MOLECULE;
+ }
+ else {
+ markDlistAsDirty(r);
+ }
+
+ }
+ renderMoleculeList = renderMoleculeMap.get(r.localToVworld);
+
+ if (renderMoleculeList == null) {
+ renderMoleculeList = r;
+ renderMoleculeMap.put(r.localToVworld, renderMoleculeList);
+ // Add this renderMolecule at the beginning of RM list
+ if (startList == null) {
+ startList = r;
+ r.nextMap = null;
+ r.prevMap = null;
+ }
+ else {
+ r.nextMap = startList;
+ startList.prevMap = r;
+ startList = r;
+ startList.nextMap.checkEquivalenceWithLeftNeighbor(r,RenderMolecule.ALL_DIRTY_BITS);
+ }
+ // Issue 67 : since we are adding the new RM at the head, we must
+ // set all dirty bits unconditionally
+ startList.dirtyAttrsAcrossRms = RenderMolecule.ALL_DIRTY_BITS;
+ }
+ else {
+ // Insert the renderMolecule next to a RM that has equivalent
+ // texture unit state
+ if ((head = insertRenderMolecule(r, renderMoleculeList)) != null) {
+ if (renderMoleculeList.prevMap != null) {
+ renderMoleculeList.prevMap.nextMap = head;
+ }
+ head.prevMap = renderMoleculeList.prevMap;
+ renderMoleculeList.prevMap = null;
+ renderMoleculeList = head;
+ renderMoleculeMap.put(r.localToVworld, renderMoleculeList);
+ if (renderMoleculeList.prevMap != null) {
+ renderMoleculeList.checkEquivalenceWithLeftNeighbor(renderMoleculeList.prevMap,
+ RenderMolecule.ALL_DIRTY_BITS);
+ }
+ else {
+ startList.dirtyAttrsAcrossRms = RenderMolecule.ALL_DIRTY_BITS;
+ startList = renderMoleculeList;
+ }
+ }
+
+ }
+ if (r.isOpaqueOrInOG) {
+ opaqueRMList = startList;
+ }
+ else {
+ // If transparent and not in bg geometry and inodepth sorted transparency
+ if (transparentRMList == null&&
+ (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE ||
+ environmentSet.lightBin.geometryBackground != null)) {
+ transparentRMList = startList;
+ renderBin.addTransparentObject(this);
+ }
+ else {
+ transparentRMList = startList;
+ }
+ // Issue 129: add the RM's render atoms to the list of
+ // transparent render atoms
+ // XXXX: do we need to resort the list after the add???
+ if ((renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) &&
+ (environmentSet.lightBin.geometryBackground == null)) {
+ r.addRemoveTransparentObject(renderBin, true);
+ }
+ }
+ }
+
+ RenderMolecule removeOneRM(RenderMolecule r, HashMap<Transform3D[], RenderMolecule> allMap, RenderMolecule list) {
+ RenderMolecule rmlist = list;
+ // In the middle, just remove and update
+ if (r.prev != null && r.next != null) {
+ r.prev.next = r.next;
+ r.next.prev = r.prev;
+ r.next.checkEquivalenceWithLeftNeighbor(r.prev,RenderMolecule.ALL_DIRTY_BITS);
+ }
+ // If whats is removed is at the end of an entry
+ else if (r.prev != null && r.next == null) {
+ r.prev.next = r.next;
+ r.prev.nextMap = r.nextMap;
+ if (r.nextMap != null) {
+ r.nextMap.prevMap = r.prev;
+ r.nextMap.checkEquivalenceWithLeftNeighbor(r.prev,RenderMolecule.ALL_DIRTY_BITS);
+ }
+ }
+ else if (r.prev == null && r.next != null) {
+ r.next.prev = null;
+ r.next.prevMap = r.prevMap;
+ if (r.prevMap != null) {
+ r.prevMap.nextMap = r.next;
+ r.next.checkEquivalenceWithLeftNeighbor(r.prevMap,RenderMolecule.ALL_DIRTY_BITS);
+ }
+ // Head of the rmList
+ else {
+ rmlist = r.next;
+ rmlist.dirtyAttrsAcrossRms = RenderMolecule.ALL_DIRTY_BITS;
+ }
+ allMap.put(r.localToVworld, r.next);
+ }
+ // Update the maps and remove this entry from the map list
+ else if (r.prev == null && r.next == null) {
+ if (r.prevMap != null) {
+ r.prevMap.nextMap = r.nextMap;
+
+ }
+ else {
+ rmlist = r.nextMap;
+ if (r.nextMap != null) {
+ rmlist.dirtyAttrsAcrossRms = RenderMolecule.ALL_DIRTY_BITS;
+ }
+ }
+ if (r.nextMap != null) {
+ r.nextMap.prevMap = r.prevMap;
+ if (r.prevMap != null) {
+ r.nextMap.checkEquivalenceWithLeftNeighbor(r.prevMap,RenderMolecule.ALL_DIRTY_BITS);
+ }
+
+ }
+
+ allMap.remove(r.localToVworld);
+
+
+ }
+ r.prev = null;
+ r.next = null;
+ r.prevMap = null;
+ r.nextMap = null;
+ return rmlist;
+ }
+
+ void markDlistAsDirty(RenderMolecule r) {
+
+ if (r.primaryMoleculeType == RenderMolecule.DLIST_MOLECULE) {
+ renderBin.addDirtyRenderMolecule(r);
+ }
+ else if (r.primaryMoleculeType == RenderMolecule.SEPARATE_DLIST_PER_RINFO_MOLECULE) {
+ RenderAtomListInfo ra = r.primaryRenderAtomList;
+ while (ra != null) {
+ renderBin.addDlistPerRinfo.add(ra);
+ ra = ra.next;
+ }
+ }
+ }
+
+
+ void decrActiveRenderMolecule() {
+ numEditingRenderMolecules--;
+
+ if (numEditingRenderMolecules == 0) {
+
+ // if number of editing renderMolecules goes to 0,
+ // inform the shaderBin that this textureBin goes to
+ // zombie state
+
+ shaderBin.decrActiveTextureBin();
+ }
+ }
+
+ void incrActiveRenderMolecule() {
+
+ if (numEditingRenderMolecules == 0) {
+
+ // if this textureBin is in zombie state, inform
+ // the shaderBin that this textureBin is activated again.
+
+ shaderBin.incrActiveTextureBin();
+ }
+
+ numEditingRenderMolecules++;
+ }
+}