
javax.media.j3d.RenderBin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of j3dcore Show documentation
Show all versions of j3dcore Show documentation
3D Graphics API for the Java Platform
/*
* Copyright 1998-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.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
/**
* The RenderBin is a structure that optimizes rendering by doing efficient
* state sorting of objects to be rendered.
*/
class RenderBin extends J3dStructure implements ObjectUpdate {
/**
* The list of RenderAtoms
*/
ArrayList renderAtoms = new ArrayList(5);
/**
* A couple ArrayLists used during light Processing
*/
ArrayList lightMessageList = new ArrayList(5);
// Messges retrieved when a message is sent to RenderingEnv Structure
J3dMessage[] m;
/**
* List of renderMolecules that are soleUser have to do a 2 pass, first update
* values then sort based on equivalent material
*/
ArrayList rmUpdateList = new ArrayList();
ArrayList aBinUpdateList = new ArrayList();
/**
* List of ShaderBin that are soleUser that needs to have its components updated @updateObject
* time
*/
ArrayList sBinUpdateList = new ArrayList();
/**
* List of TextureBin that are soleUser that needs to have its components
* updated @updateObject time
*/
ArrayList tbUpdateList = new ArrayList();
/**
* List of Bins that are soleUser that have new renderAtom added into, which
* requires a pre-update screening to check if any of its node component changes
* could have been missed because the changes happen when all the render atoms
* are temporarily removed from the bin.
*/
ArrayList updateCheckList = new ArrayList();
/**
* The number of lights supported by the underlying context.
*/
int maxLights;
/**
* The opaque objects
*/
LightBin opaqueBin = null;
/**
* OpaqueBins to be added for the next frame
*/
LightBin addOpaqueBin = null;
// This is a list of textureBins to be rendered, if the transpSortPolicy
// is NONE, otherwise, if the transpSortPolicy is geometry, then
// this is the list of renderAtoms to be rendered
ArrayList allTransparentObjects = new ArrayList(5);
TransparentRenderingInfo transparentInfo;
/**
* List of RenderAtoms whose postion have changed - only used for depth sorted
* transparency
*/
ArrayList positionDirtyList = new ArrayList(5);
/**
* Used when ColoringAttributes is null
*/
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
/**
* Used when Background is null
*/
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
/**
* The backgound color data.
*/
BackgroundRetained background = new BackgroundRetained();
/**
* The view platform transforms.
*/
// used for rendering - lights and fog modelling
Transform3D vworldToVpc = new Transform3D();
// used for updating vpSchedSphere
Transform3D vpcToVworld = new Transform3D();
/**
* Two bounding spheres to track the scheduling region of
* the view platform.
*/
BoundingSphere vpSchedSphereInVworld = new BoundingSphere();
/**
* To cache the view frustum bounding box.
*/
BoundingBox viewFrustumBBox = new BoundingBox();
BoundingBox canvasFrustumBBox = new BoundingBox();
/**
* To ensure that vpcToVworld is valid (not null) for the first pass
*/
boolean afterFirst = false;
/**
* back clip distance in vworld
*/
double backClipDistanceInVworld;
boolean backClipActive = false;
/**
* These variables control when compaction occurs
*/
int frameCount = 0;
int frameCountCutoff = 150;
int notVisibleCount = 75;
long removeCutoffTime = -1;
/**
* variables to process transform messages
*/
boolean transformMsg = false;
UpdateTargets targets = null;
ArrayList blUsers = null;
/**
* The View for this render bin
*/
View view = null;
private Comparator transparencySortComparator = null;
private ArrayList toBeAddedTextureResourceFreeList = new ArrayList(5);
private ArrayList displayListResourceFreeList = new ArrayList(5);
// a list of top level OrderedGroups
ArrayList orderedBins = new ArrayList(5);
// List of changed elements in the environment that needs to
// be reloaded
ArrayList changedLts = new ArrayList(5);
ArrayList changedFogs = new ArrayList(5);
ArrayList changedModelClips = new ArrayList(5);
// Flag to indicate whether the canvas should be marked
static int REEVALUATE_LIGHTS = 0x1;
static int REEVALUATE_FOG = 0x2;
static int REEVALUATE_MCLIP = 0x4;
static int REEVALUATE_ALL_ENV = REEVALUATE_LIGHTS | REEVALUATE_FOG | REEVALUATE_MCLIP;
int envDirty = 0;
private boolean reEvaluateBg = true;
private boolean reloadBgTexture = true;
boolean reEvaluateClip = true;
boolean reEvaluateSortMode = false;
// list of renderMolecule
// RenderBin will not reused in two different universe, so it is
// safe to pass null in last parameters in new IndexedUnorderSet()
IndexedUnorderSet renderMoleculeList =
new IndexedUnorderSet(RenderMolecule.class,
RenderMolecule.RENDER_MOLECULE_LIST, null);
// List of renderAtoms that have a shared dlist (due to geo.refCount > 1)
// Fix for Issue 5: change this to a Set rather than a list to
// avoid duplicates entried
Collection sharedDList = new HashSet();
ArrayList dirtyRenderMoleculeList = new ArrayList(5);
/**
* ArrayList of objects to be updated
*/
ArrayList objUpdateList = new ArrayList(5);
ArrayList raLocaleVwcBoundsUpdateList = new ArrayList(5);
/**
* remove the bins first before adding them to new ones
*/
IndexedUnorderSet removeRenderAtomInRMList =
new IndexedUnorderSet(RenderMolecule.class,
RenderMolecule.REMOVE_RENDER_ATOM_IN_RM_LIST, null);
/**
* list of affect OrderedGroups with childIndexOrder changed.
*/
ArrayList ogCIOList = new ArrayList(5);
/**
* list of ordered bins from which orderedCollection are added/removed
*/
ArrayList obList = new ArrayList(5);
/**
* Ordered Bin processing
*/
ArrayList> orderedBinsList = new ArrayList>(5);
ArrayList> toBeAddedBinList = new ArrayList>(5);
/**
* arraylist of geometry that should be locked to ensure
* that the same snapshot of the geometry is rendered
* across all canvases
*/
ArrayList lockGeometryList = new ArrayList(5);
/**
* arraylist of dlist that will be rebuilt
*/
ArrayList dlistLockList = new ArrayList(5);
// Background node that contains geometry
BackgroundRetained geometryBackground = null;
// background geometry processing
LightBin bgOpaqueBin = null;
LightBin bgAddOpaqueBin = null;
ArrayList bgOrderedBins = new ArrayList(5);
TransparentRenderingInfo bgTransparentInfo;
// vworldToVpc for background geometry
Transform3D infVworldToVpc = new Transform3D();
// true if vpcToVworld has been modified
boolean vpcToVworldDirty = true;
// current active background
BackgroundRetained currentActiveBackground = new BackgroundRetained();
// Flag to indicate that alternate app is dirty
boolean altAppearanceDirty = true;
// List of node components that need special processing, due to
// extensions
ArrayList nodeComponentList = new ArrayList(5);
// List of node components ***for this frame*** that need special
// processing due to extension
ArrayList newNodeComponentList = new ArrayList(5);
ArrayList removeNodeComponentList = new ArrayList(5);
ArrayList dirtyNodeComponentList = new ArrayList(5);
ArrayList textureBinList = new ArrayList(5);
/**
* arraylist of refernce geometry that should be locked when transparency
* is on, so that we can make a mirror copy of the colors safely
*/
ArrayList dirtyReferenceGeomList = new ArrayList(5);
// list of all Oriented RenderAtoms
ArrayList orientedRAs = new ArrayList(5);
// list of Oriented RenderAtoms whose orientedTransforms require update
ArrayList dirtyOrientedRAs = new ArrayList(5);
// Cached copy of dirty oriented RAs to be updated in MasterControl
ArrayList cachedDirtyOrientedRAs = null;
// list of offScreen message that
ArrayList offScreenMessage = new ArrayList(5);
// Vector used for locale translation
Vector3d localeTranslation = new Vector3d();
// Separate dlists that were added/removed in this snapshot
private HashSet addDlist = new HashSet();
private HashSet removeDlist = new HashSet();
// Separate dlists per rinfo that were added/removed in this snapshot
ArrayList addDlistPerRinfo = new ArrayList(5);
ArrayList removeDlistPerRinfo = new ArrayList(5);
Locale locale = null;
// Set to true if locale changes as part of UPDATE_VIEW message
boolean localeChanged = false;
// Cached copy to be used by all RenderMolecules
DisplayListRenderMethod dlistRenderMethod = null;
// Need to query BHTree again with visibility policy change
boolean reactivateView = false;
/**
* A flag indicates that the cached visible GeometryAtoms for this RenderBin might
* be invalid.
*/
private boolean visGAIsDirty = false;
/**
* A flag indicates that a visibility query to the GeometryStructure is needed.
*/
private boolean visQuery = false;
// Temporary dirtylist
ArrayList dirtyList = new ArrayList(5);
// Transaprency sort mode
int transpSortMode = View.TRANSPARENCY_SORT_NONE;
int cachedTranspSortMode = View.TRANSPARENCY_SORT_NONE;
// Temporary dirtylist
private LinkedHashSet dirtyDepthSortRenderAtom = new LinkedHashSet();
private int numDirtyTinfo = 0;
// Eye position in vworld
Point3d eyeInVworld = new Point3d();
// Number of RenderAtomListInfo in the depthSortedList
int nElements = 0;
/**
* Constructs a new RenderBin
*/
RenderBin(VirtualUniverse u, View v) {
super(u, J3dThread.UPDATE_RENDER);
vworldToVpc.setIdentity();
universe = u;
view = v;
transpSortMode = v.transparencySortingPolicy;
cachedTranspSortMode = v.transparencySortingPolicy;
maxLights = VirtualUniverse.mc.maxLights;
ViewPlatform vp = view.getViewPlatform();
if (vp != null) {
locale = ((ViewPlatformRetained) (vp.retained)).locale;
}
dlistRenderMethod = (DisplayListRenderMethod)
VirtualUniverse.mc.getDisplayListRenderMethod();
}
/**
* updateObject
*/
@Override
public void updateObject() {
int i, j, k;
RenderAtomListInfo ra;
LightBin tmp;
ObjectUpdate ob;
OrderedBin orderBin;
int size;
// System.err.println("dirtyRenderMoleculeList.size = "+dirtyRenderMoleculeList.size());
// System.err.println("reEvaluateBg = "+reEvaluateBg);
// System.err.println("reEvaluateClip = "+reEvaluateClip);
// System.err.println("<========+End All Cached Values===========>");
// Add the new lightBins that have been created
// System.err.println("objUpdateList.size = "+objUpdateList.size());
// System.err.println("addOpaqueBin = "+addOpaqueBin);
// System.err.println("opaqueBin = "+opaqueBin);
// List of renderMolecule from which renderAtoms have been removed
size = removeRenderAtomInRMList.size();
if (size > 0) {
RenderMolecule[] rmArr = (RenderMolecule[])
removeRenderAtomInRMList.toArray(false);
for (i=0 ; i 0) {
for (i = 0 ; i < size; i++) {
orderBin = obList.get(i);
orderBin.addRemoveOrderedCollection();
}
}
size = ogCIOList.size();
if(size > 0) {
for(i=0; i 0 ) {
for (i = 0; i < size; i++) {
ArrayList obs = orderedBinsList.get(i);
ArrayList list = toBeAddedBinList.get(i);
int lSize = list.size();
for (j = 0; j < lSize; j++) {
obs.add(list.get(j));
}
}
}
size = raLocaleVwcBoundsUpdateList.size();
if ( size > 0) {
RenderAtom renderAtom;
for (i = 0; i < size; i++) {
renderAtom = raLocaleVwcBoundsUpdateList.get(i);
renderAtom.updateLocaleVwcBounds();
}
}
if ((size = aBinUpdateList.size()) > 0) {
for (i = 0; i < size; i++) {
AttributeBin abin = aBinUpdateList.get(i);
abin.updateNodeComponent();
}
}
if ((size = sBinUpdateList.size()) > 0) {
for (i = 0; i < size; i++) {
ShaderBin sbin = sBinUpdateList.get(i);
sbin.updateNodeComponent();
}
}
// Update the sole user TextureBins.
if (tbUpdateList.size() > 0) {
TextureBin tb;
size = tbUpdateList.size();
for (i = 0; i < size; i++) {
tb = tbUpdateList.get(i);
tb.updateNodeComponent();
}
// do another pass to re-sort TextureBin based on the
// texture in the first texture unit state
for (i = 0; i < size; i++) {
tb = tbUpdateList.get(i);
// Bug Id : 4701430 - Have to be sure tb.shaderBin is
// not equal to null. This is a temporary fix for j3d1.3.
if (((tb.tbFlag & TextureBin.RESORT) != 0) &&
(tb.shaderBin != null)) {
tb.shaderBin.reInsertTextureBin(tb);
tb.tbFlag &= ~TextureBin.RESORT;
}
}
}
// Update the soleUser node components first
// This way material equivalence during insertion
// of new RMs is based on the updated ones
if ((size = rmUpdateList.size()) > 0) {
for (i = 0; i < size; i++) {
RenderMolecule rm = rmUpdateList.get(i);
boolean changeLists = rm.updateNodeComponent();
// If an existing rm went from opaque to transparent or vice-versa
// and has not been removed, then switch the RM
if (changeLists && rm.textureBin != null) {
rm.textureBin.changeLists(rm);
}
}
for (i = 0; i < size; i++) {
rmUpdateList.get(i).reEvaluateEquivalence();
}
}
size = objUpdateList.size();
if ( size > 0) {
for (i = 0; i < size; i++) {
ob = objUpdateList.get(i);
ob.updateObject();
}
}
size = dirtyReferenceGeomList.size();
if ( size > 0) {
GeometryArrayRetained geo;
Canvas3D canvases[] = view.getCanvases();
for (i = 0; i < size; i++) {
geo = dirtyReferenceGeomList.get(i);
// Evaluate the nodeComponentList for all the canvases
geo.geomLock.getLock();
j = 0;
// Do the setup only once{if necessary} for each geometry
boolean found = false;
while(j < canvases.length && !found) {
if ((geo.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
geo.setupMirrorInterleavedColorPointer(true);
found = true;
}
else {
geo.setupMirrorColorPointer((geo.vertexType & GeometryArrayRetained.COLOR_DEFINED),true);
found = true;
}
j++;
}
geo.geomLock.unLock();
}
}
if (reEvaluateBg) {
setBackground(currentActiveBackground);
}
size = textureBinList.size();
//System.err.println("textureBinList.size= " + size);
if (size > 0) {
Canvas3D canvasList[][] = view.getCanvasList(false);
Canvas3D cv;
boolean useSharedCtx = false;
TextureRetained texture;
// do a quick check to see if there is any canvas using
// shared context
for (j = 0; j < canvasList.length && !useSharedCtx; j++) {
cv = canvasList[j][0];
if (cv.useSharedCtx) {
useSharedCtx = true;
}
}
for (int m = 0; m 0) {
//System.err.println("newNodeComponentlist.size= " + size);
Canvas3D canvases[] = view.getCanvases();
for (i = 0; i < size; i++) {
// Evaluate the nodeComponentList for all the canvases
ImageComponentRetained nc = (ImageComponentRetained)newNodeComponentList.get(i);
if (nc.isByReference()) {
nc.geomLock.getLock();
for (j = 0; j 0) {
for (i = 0; i < size; i++) {
nodeComponentList.remove(removeNodeComponentList.get(i));
}
}
// reevaluate dirty node component
size = dirtyNodeComponentList.size();
if (size > 0) {
Canvas3D canvases[] = view.getCanvases();
for (i = 0; i < size; i++) {
// Evaluate the nodeComponentList for all the canvases
ImageComponentRetained nc =
(ImageComponentRetained)dirtyNodeComponentList.get(i);
if (nc.isByReference()) {
nc.geomLock.getLock();
for (j = 0; j 1);
// renderBin is ready now, so send the offScreen message
size = offScreenMessage.size();
if ( size > 0) {
for (i=size-1; i>=0; i--) {
J3dMessage m = offScreenMessage.get(i);
m.threads = J3dThread.RENDER_THREAD;
((Canvas3D)m.args[0]).screen.renderer.rendererStructure.addMessage(m);
// the above call will increment the reference count again
m.decRefcount();
}
}
// called from renderBin when there are dirtyOrientedRAs
// This routin cache the dirtyOrintedRAs to be updated
// by mastercontrol
if (dirtyOrientedRAs.size() > 0) {
// Keep a copy to be handled by mastercontrol
cachedDirtyOrientedRAs = new ArrayList(dirtyOrientedRAs);
}
boolean sortAll = false;
if (reEvaluateSortMode && transpSortMode != cachedTranspSortMode) {
convertTransparentRenderingStruct(transpSortMode, cachedTranspSortMode);
transpSortMode = cachedTranspSortMode;
if (transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) {
if (transparentInfo != null){
sortAll = true;
}
}
}
if (vpcToVworldDirty) {
vworldToVpc.invert(vpcToVworld);
// Have the send down the lights, so set the canvas
// lightbin to null
Canvas3D canvases[] = view.getCanvases();
for (i = 0; i < canvases.length; i++) {
canvases[i].lightBin = null;
}
if (canvases.length > 0) {
Transform3D xform;
canvases[0].getCenterEyeInImagePlate(eyeInVworld);
// xform is imagePlateToLocal
xform = canvases[0].canvasViewCache.getImagePlateToVworld();
xform.transform(eyeInVworld);
}
if (transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY && transparentInfo != null) {
// System.err.println("sortAll 1");
sortAll = true;
}
}
size = dirtyDepthSortRenderAtom.size();
if (sortAll || size > 0) {
int tsize = allTransparentObjects.size();
double zVal;
for (i = 0; i < tsize; i++) {
RenderAtom renderAtom = (RenderAtom)allTransparentObjects.get(i);
for (k = 0; k < renderAtom.rListInfo.length; k++) {
if (renderAtom.rListInfo[k].geometry() == null)
continue;
zVal = renderAtom.geometryAtom.centroid[k].distanceSquared(eyeInVworld);
renderAtom.parentTInfo[k].zVal = zVal;
renderAtom.parentTInfo[k].geometryAtom = renderAtom.geometryAtom;
}
}
// Check to see if a majority of the transparent Objects have changed
// If less than 66% of all transparentStructs are dirty
// then, remove and insert, otherwise resort everything
if (size > 0 && 1.5f * numDirtyTinfo > nElements) {
// System.err.println("sortAll 3, size = "+size);
sortAll = true;
}
if (size > 0) {
TransparentRenderingInfo dirtyList = null;
Iterator dirtyDepthSortIterator = dirtyDepthSortRenderAtom.iterator();
while (dirtyDepthSortIterator.hasNext()) {
RenderAtom renderAtom = dirtyDepthSortIterator.next();
if (!renderAtom.inRenderBin())
continue;
renderAtom.dirtyMask &= ~RenderAtom.IN_SORTED_POS_DIRTY_TRANSP_LIST;
if (!sortAll) {
dirtyList = collectDirtyTRInfo(dirtyList, renderAtom);
}
}
if (dirtyList != null) {
// System.err.println("====> sort Some");
dirtyList = depthSortAll(dirtyList);
// Now merge the newly sorted list with the old one
transparentInfo = mergeDepthSort(transparentInfo, dirtyList);
}
}
// Sort all the transparent renderAtoms
if (sortAll) {
transparentInfo = depthSortAll(transparentInfo);
}
}
// Remove entries that are found on both the add and remove lists
if (addDlist.size() > 0 && removeDlist.size() > 0) {
RenderAtomListInfo arr[] = new RenderAtomListInfo[addDlist.size()];
arr = addDlist.toArray(arr);
for (i = 0; i < arr.length; i++) {
if (removeDlist.contains(arr[i])) {
addDlist.remove(arr[i]);
removeDlist.remove(arr[i]);
}
}
}
if (addDlist.size() > 0 || removeDlist.size() > 0) {
Canvas3D canvasList[][] = view.getCanvasList(false);
Canvas3D cv;
ArrayList rlist = new ArrayList(5);
for (i = 0; i < canvasList.length; i++) {
cv = canvasList[i][0];
if (cv.useSharedCtx) {
// Do this only once per renderer for this view
if (!rlist.contains(cv.screen.renderer)) {
rlist.add(cv.screen.renderer);
updateDlistRendererResource(cv.screen.renderer);
}
} else {
updateDlistCanvasResource(canvasList[i]);
}
}
}
if (dirtyRenderMoleculeList.size() > 0 ||
addDlistPerRinfo.size() > 0 ||
removeDlistPerRinfo.size() > 0 ||
displayListResourceFreeList.size() > 0 ||
toBeAddedTextureResourceFreeList.size() > 0 ) {
Canvas3D canvasList[][] = view.getCanvasList(false);
Canvas3D cv;
for (i = 0; i < canvasList.length; i++) {
cv = canvasList[i][0];
if (cv.useSharedCtx && (cv.screen.renderer != null)) {
updateRendererResource(cv.screen.renderer);
} else {
updateCanvasResource(canvasList[i]);
}
}
Integer id;
size = displayListResourceFreeList.size();
for (i = 0; i < size; i++) {
id = displayListResourceFreeList.get(i);
VirtualUniverse.mc.freeDisplayListId(id);
}
// lock list of dlist
// XXXX: Instead of copying could we keep 2 arrays
// and just toggle?
size = dirtyRenderMoleculeList.size();
for (i = 0; i < size; i++) {
RenderMolecule rm = dirtyRenderMoleculeList.get(i);
rm.onUpdateList = 0;
ra = rm.primaryRenderAtomList;
while (ra != null) {
dlistLockList.add(ra.geometry());
ra = ra.next;
}
}
size = addDlistPerRinfo.size();
for (i = 0; i < size; i++) {
ra = addDlistPerRinfo.get(i);
if (ra.geometry() != null) {
dlistLockList.add(ra.geometry());
}
}
}
clearAllUpdateObjectState();
/*
if (opaqueBin != null) {
System.err.println(this + "***** Begin Dumping OpaqueBin *****");
dumpBin(opaqueBin);
System.err.println("***** End Dumping OpaqueBin *****");
}
*/
}
// Shared context case
void updateDlistRendererResource(Renderer rdr) {
int i;
int size = 0;
RenderAtomListInfo arr[];
RenderAtomListInfo ra;
// XXXX: there is a possible problem in the case of multiple
// renderers (i.e., multiple screens). Unless the
// MasterControl sends us a separate message for each
// renderer, we won't create a new display list for renderers
// other than the one passed into this method.
if (rdr == null) {
return;
}
if ((size = addDlist.size()) > 0) {
arr = new RenderAtomListInfo[size];
arr = addDlist.toArray(arr);
for (i = 0; i < size; i++) {
ra = arr[i];
GeometryArrayRetained geo = (GeometryArrayRetained)ra.geometry();
// First time thru this renderer or the context that
// it is built for no longer matches the context
// used in the renderer, create a dlist
sharedDList.add(ra);
geo.addDlistUser(this, ra);
if (((geo.resourceCreationMask & rdr.rendererBit) == 0) ||
(geo.getDlistTimeStamp(rdr.rendererBit) !=
rdr.sharedCtxTimeStamp)) {
geo.resourceCreationMask |= rdr.rendererBit;
dirtyList.add(ra);
}
}
}
if ((size = removeDlist.size()) > 0) {
arr = new RenderAtomListInfo[size];
arr = removeDlist.toArray(arr);
for (i = 0; i < size; i++) {
ra = arr[i];
sharedDList.remove(ra);
GeometryArrayRetained geo = (GeometryArrayRetained)ra.geometry();
geo.removeDlistUser(this, ra);
// System.err.println("========> geo.refcount = "+geo.refCount);
// add this geometry's dlist to be freed
if (geo.isDlistUserSetEmpty(this)) {
rdr.displayListResourceFreeList.add(geo.dlistObj);
geo.resourceCreationMask &= ~rdr.rendererBit;
// All Dlist on all renderer have been freed, then return dlistID
if (geo.resourceCreationMask == 0) {
geo.freeDlistId();
}
}
}
}
if ((size = dirtyList.size()) > 0) {
for (i = 0; i < size; i++) {
ra = dirtyList.get(i);
GeometryArrayRetained geo = (GeometryArrayRetained)ra.geometry();
if ( (geo.resourceCreationMask & rdr.rendererBit) != 0) {
rdr.dirtyRenderAtomList.add(ra);
}
}
rdr.dirtyDisplayList = true;
dirtyList.clear();
}
}
// Non-shared context case
void updateDlistCanvasResource(Canvas3D[] canvases) {
int i, j;
Canvas3D cv;
int size = 0;
RenderAtomListInfo arr[];
RenderAtomListInfo ra;
// Add the newly added dlist to the sharedList
if ((size = addDlist.size()) > 0) {
arr = new RenderAtomListInfo[size];
arr = addDlist.toArray(arr);
for (i = 0; i 0) {
arr = new RenderAtomListInfo[size];
arr = removeDlist.toArray(arr);
for (i = 0; i < size; i++) {
sharedDList.remove(arr[i]);
// Fix for Issue 5: remove this render atom from the list of users
// of its geometry for this RenderBin
GeometryArrayRetained geo = (GeometryArrayRetained) arr[i].geometry();
geo.removeDlistUser(this, arr[i]);
}
}
// add to the dirty list per canvas
for (j = 0; j < canvases.length; j++) {
cv = canvases[j];
if ((size = addDlist.size()) > 0) {
arr = new RenderAtomListInfo[size];
arr = addDlist.toArray(arr);
for (i = 0; i 0) {
arr = new RenderAtomListInfo[size];
arr = removeDlist.toArray(arr);
for (i = 0; i < size; i++) {
GeometryArrayRetained geo =
(GeometryArrayRetained) arr[i].geometry();
// add this geometry's dlist to be freed
if (geo.isDlistUserSetEmpty(this)) {
if (cv.ctx != null) {
canvases[j].displayListResourceFreeList.add(geo.dlistObj);
}
geo.resourceCreationMask &= ~canvases[j].canvasBit;
// All Dlist on all canvases have been freed, then return dlistID
if (geo.resourceCreationMask == 0)
geo.freeDlistId();
}
}
}
if ((size = dirtyList.size()) > 0) {
for (i = 0; i 0) {
for (int j = 0; j < size; j++) {
RenderAtomListInfo rinfo = addDlistPerRinfo.get(j);
if (rinfo.renderAtom.inRenderBin()) {
Object[] obj = new Object[2];
obj[0] = rinfo;
obj[1] = rinfo.renderAtom.renderMolecule;
rdr.dirtyDlistPerRinfoList.add(obj);
}
}
rdr.dirtyDisplayList = true;
}
// Take care of display lists that should be rebuilt
size = dirtyRenderMoleculeList.size();
if (size > 0) {
for (int j = 0; j < size; j++) {
rm = dirtyRenderMoleculeList.get(j);
rdr.dirtyRenderMoleculeList.add(rm);
}
rdr.dirtyDisplayList = true;
}
// Take care of texture that should be freed
size = toBeAddedTextureResourceFreeList.size();
int id;
for (int j=0; j < size; j++) {
tex = toBeAddedTextureResourceFreeList.get(j);
id = tex.objectId;
if ((id >= rdr.textureIDResourceTable.size()) ||
(id <= 0) ||
(rdr.textureIDResourceTable.get(id) != tex)) {
// tex.objectId may change by another Renderer thread,
// need find original texID from searching
// rdr.textureIdResourceTable
id = rdr.textureIDResourceTable.indexOf(tex);
if (id <= 0) {
continue;
}
}
// Since multiple renderBins (in the same screen)
// can share a texture object, make sure that
// we are not duplicating what has been added
// by a different renderBin in the same screen
if ((tex.resourceCreationMask & rdr.rendererBit) != 0) {
texIdObj = new Integer(id);
if (!rdr.textureIdResourceFreeList.contains(texIdObj)) {
rdr.textureIdResourceFreeList.add(texIdObj);
tex.resourceCreationMask &= ~rdr.rendererBit;
}
}
}
// Take care of display list that should be freed
size = displayListResourceFreeList.size();
Integer displayListIDObj;
for (int j=0; j 0) {
for ( j = 0; j < size; j++) {
RenderAtomListInfo rinfo = addDlistPerRinfo.get(j);
if (rinfo.renderAtom.inRenderBin()) {
Object[] obj = new Object[2];
obj[0] = rinfo;
obj[1] = rinfo.renderAtom.renderMolecule;
cv.dirtyDlistPerRinfoList.add(obj);
}
}
cv.dirtyDisplayList = true;
}
// Take care of display lists that should be rebuilt
size = dirtyRenderMoleculeList.size();
if (size > 0) {
for (j = 0; j < size; j++) {
rm = dirtyRenderMoleculeList.get(j);
cv.dirtyRenderMoleculeList.add(rm);
}
cv.dirtyDisplayList = true;
}
// Take care of texture that should be freed
size = toBeAddedTextureResourceFreeList.size();
int id;
for (j=0; j < size; j++) {
tex = toBeAddedTextureResourceFreeList.get(j);
id = tex.objectId;
if ((id >= cv.textureIDResourceTable.size()) ||
(id <= 0) ||
(cv.textureIDResourceTable.get(id) != tex)) {
// tex.objectId may change by another Renderer thread,
// need find original texID from searching
// rdr.textureIdResourceTable
id = cv.textureIDResourceTable.indexOf(tex);
if (id <= 0) {
continue;
}
}
if ((tex.resourceCreationMask & cv.canvasBit) != 0) {
texIdObj = new Integer(id);
cv.textureIdResourceFreeList.add(texIdObj);
tex.resourceCreationMask &= ~cv.canvasBit;
}
}
// Take care of display list that should be freed
size = displayListResourceFreeList.size();
for (j=0; j < size; j++) {
cv.displayListResourceFreeList.add(displayListResourceFreeList.get(j));
}
// Take care of display list that should be freed
size = removeDlistPerRinfo.size();
for (j=0; j < size; j++) {
RenderAtomListInfo ra = removeDlistPerRinfo.get(j);
cv.displayListResourceFreeList.add(new Integer(ra.renderAtom.dlistIds[ra.index]));
ra.groupType = 0;
ra.renderAtom.dlistIds[ra.index] = -1;
}
}
}
@Override
void processMessages(long referenceTime) {
int i;
J3dMessage messages[], m;
int component;
messages = getMessages(referenceTime);
int nMsg = getNumMessage();
if (nMsg > 0) {
for (i=0; i < nMsg; i++) {
m = messages[i];
switch (m.type) {
case J3dMessage.INSERT_NODES:
insertNodes(m);
m.decRefcount();
break;
case J3dMessage.REMOVE_NODES:
removeNodes(m);
m.decRefcount();
break;
case J3dMessage.TRANSFORM_CHANGED:
transformMsg = true;
m.decRefcount();
break;
case J3dMessage.LIGHT_CHANGED:
// if none of the mirror lights are scoped to this view
// ignore this message
LightRetained[] mLts =(LightRetained[])m.args[3] ;
for (int k = 0; k < mLts.length; k++) {
if (universe.renderingEnvironmentStructure.isLightScopedToThisView(mLts[k], view)) {
lightMessageList.add(m);
break;
}
}
break;
case J3dMessage.SWITCH_CHANGED:
visGAIsDirty = true;
visQuery = true;
processSwitchChanged(m, referenceTime);
// may need to process dirty switched-on transform
if (universe.transformStructure.getLazyUpdate()) {
transformMsg = true;
}
m.decRefcount();
break;
case J3dMessage.BACKGROUND_CHANGED:
BackgroundRetained bg = (BackgroundRetained)m.args[0];
if (universe.renderingEnvironmentStructure.isBgScopedToThisView(bg, view)) {
reEvaluateBg = true;
reloadBgTexture = true;
}
m.decRefcount();
break;
case J3dMessage.CLIP_CHANGED:
ClipRetained c = (ClipRetained)m.args[0];
if (universe.renderingEnvironmentStructure.isClipScopedToThisView(c, view))
reEvaluateClip = true;
m.decRefcount();
break;
case J3dMessage.TRANSPARENCYATTRIBUTES_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingTransparency != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.TRANSPARENCY_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.POLYGONATTRIBUTES_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingPolygonAttributes != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.POLYGONATTRS_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.LINEATTRIBUTES_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingLineAttributes != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.LINEATTRS_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.POINTATTRIBUTES_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingPointAttributes != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.POINTATTRS_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.MATERIAL_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingMaterial != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.MATERIAL_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.COLORINGATTRIBUTES_CHANGED:
{
NodeComponentRetained nc = (NodeComponentRetained) m.args[0];
GeometryAtom[] gaArr = (GeometryAtom[])m.args[3];
RenderAtom ra = null;
int start = -1;
// Get the first ra that is visible
// Get the first ra that is visible
for (int k = 0; (k < gaArr.length && (start < 0)); k++) {
ra = gaArr[k].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = k;
}
}
if (start >= 0) {
boolean restructure = (nc.mirror.changedFrequent == 0 ||
ra.renderMolecule.definingColoringAttributes != nc.mirror);
processRenderMoleculeNodeComponentChanged(m.args,
RenderMolecule.COLORINGATTRS_DIRTY,
start, restructure);
}
m.decRefcount();
break;
}
case J3dMessage.TEXTUREATTRIBUTES_CHANGED:
processTextureAttributesChanged(
(NodeComponentRetained) m.args[0],
(GeometryAtom[])m.args[3]);
m.decRefcount();
break;
case J3dMessage.IMAGE_COMPONENT_CHANGED:
addDirtyNodeComponent((NodeComponentRetained)m.args[0]);
m.decRefcount();
break;
case J3dMessage.TEXTURE_UNIT_STATE_CHANGED:
processTextureUnitStateChanged(
(NodeComponentRetained) m.args[0],
(GeometryAtom[])m.args[3]);
m.decRefcount();
break;
case J3dMessage.TEXCOORDGENERATION_CHANGED:
processTexCoordGenerationChanged( (NodeComponentRetained) m.args[0],
(GeometryAtom[])m.args[3]);
m.decRefcount();
break;
case J3dMessage.TEXTURE_CHANGED:
// Texture is always in a sole user position
processTextureChanged((NodeComponentRetained) m.args[0],
(GeometryAtom[])m.args[3],
m.args);
m.decRefcount();
break;
case J3dMessage.SHADER_APPEARANCE_CHANGED:
case J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED:
case J3dMessage.SHADER_ATTRIBUTE_CHANGED:
processShaderComponentChanged(m.args);
m.decRefcount();
break;
case J3dMessage.RENDERINGATTRIBUTES_CHANGED:
processAttributeBinNodeComponentChanged(m.args);
component = ((Integer)m.args[1]).intValue();
if (component == RenderingAttributesRetained.VISIBLE) {
visGAIsDirty = true;
visQuery = true;
}
m.decRefcount();
break;
case J3dMessage.APPEARANCE_CHANGED:
processAppearanceChanged(m.args);
m.decRefcount();
break;
case J3dMessage.FOG_CHANGED:
FogRetained mfog = ((FogRetained)m.args[0]).mirrorFog;
if (universe.renderingEnvironmentStructure.isFogScopedToThisView(mfog, view)) {
processFogChanged(m.args);
}
m.decRefcount();
break;
case J3dMessage.ALTERNATEAPPEARANCE_CHANGED:
AlternateAppearanceRetained maltapp = ((AlternateAppearanceRetained)m.args[0]).mirrorAltApp;
if (universe.renderingEnvironmentStructure.isAltAppScopedToThisView(maltapp, view)) {
altAppearanceDirty = true;
}
m.decRefcount();
break;
case J3dMessage.MODELCLIP_CHANGED:
ModelClipRetained mc= ((ModelClipRetained)m.args[0]).mirrorModelClip;
if (universe.renderingEnvironmentStructure.isMclipScopedToThisView(mc, view)) {
processModelClipChanged(m.args);
}
m.decRefcount();
break;
case J3dMessage.BOUNDINGLEAF_CHANGED:
processBoundingLeafChanged(m.args,
referenceTime);
m.decRefcount();
break;
case J3dMessage.SHAPE3D_CHANGED:
processShapeChanged(m.args, referenceTime);
m.decRefcount();
break;
case J3dMessage.ORIENTEDSHAPE3D_CHANGED:
processOrientedShape3DChanged((Object[])m.args[0]);
m.decRefcount();
break;
case J3dMessage.MORPH_CHANGED:
processMorphChanged(m.args, referenceTime);
component = ((Integer)m.args[1]).intValue();
if ((component & MorphRetained.GEOMETRY_CHANGED) == 0) {
visGAIsDirty = true;
visQuery = true;
}
m.decRefcount();
break;
case J3dMessage.UPDATE_VIEW:
{
View v = (View)m.args[0];
ViewPlatform vp = v.getViewPlatform();
int comp = ((Integer)(m.args[2])).intValue();
int value = ((Integer)(m.args[3])).intValue();
if (comp == View.TRANSP_SORT_POLICY_CHANGED) {
if (value != transpSortMode) {
reEvaluateSortMode = true;
cachedTranspSortMode = value;
}
} else if (vp != null) {
if (value != transpSortMode) {
reEvaluateSortMode = true;
cachedTranspSortMode = value;
}
updateViewPlatform((ViewPlatformRetained)vp.retained,
((Float)m.args[1]).floatValue());
visQuery = true;
// XXXX : Handle view.visibilityPolicy changed.
if(((View.VISIBILITY_POLICY_DIRTY != 0) &&
(View.VISIBILITY_DRAW_ALL != view.viewCache.visibilityPolicy)) ||
locale != ((ViewPlatformRetained) (vp.retained)).locale) {
for (int n = (renderAtoms.size() - 1); n>=0 ; n--) {
removeARenderAtom(renderAtoms.get(n));
}
renderAtoms.clear();
visGAIsDirty = true;
if (locale != ((ViewPlatformRetained) (vp.retained)).locale) {
locale = ((ViewPlatformRetained) (vp.retained)).locale;
localeChanged = true;
}
}
}
m.decRefcount();
}
break;
case J3dMessage.UPDATE_VIEWPLATFORM:
updateViewPlatform((ViewPlatformRetained) m.args[0],
((Float)m.args[1]).floatValue());
m.decRefcount();
break;
case J3dMessage.TEXT3D_DATA_CHANGED:
processDataChanged((Object[])m.args[0],
(Object[])m.args[1],
referenceTime);
m.decRefcount();
break;
case J3dMessage.GEOMETRY_CHANGED:
processGeometryChanged(m.args);
visGAIsDirty = true;
visQuery = true;
m.decRefcount();
break;
case J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED:
case J3dMessage.REGION_BOUND_CHANGED:
processGeometryAtomsChanged((Object[])m.args[0]);
visGAIsDirty = true;
visQuery = true;
m.decRefcount();
break;
case J3dMessage.TEXT3D_TRANSFORM_CHANGED:
processText3DTransformChanged((Object[])m.args[0],
(Object[])m.args[1],
referenceTime);
visQuery = true;
m.decRefcount();
break;
case J3dMessage.ORDERED_GROUP_INSERTED:
processOrderedGroupInserted(m);
// Do not do decRefcount() here. We'll do it in updateObject().
ogCIOList.add(m);
break;
case J3dMessage.ORDERED_GROUP_REMOVED:
processOrderedGroupRemoved(m);
// Do not do decRefcount() here. We'll do it in updateObject().
ogCIOList.add(m);
break;
case J3dMessage.ORDERED_GROUP_TABLE_CHANGED:
// Do not do decRefcount() here. We'll do it in updateObject().
ogCIOList.add(m);
break;
case J3dMessage.RENDER_OFFSCREEN:
offScreenMessage.add(m);
break;
case J3dMessage.VIEWSPECIFICGROUP_CHANGED:
processViewSpecificGroupChanged(m);
visQuery = true;
m.decRefcount();
break;
default:
m.decRefcount();
}
}
if (transformMsg) {
processTransformChanged(referenceTime);
transformMsg = false;
}
if (lightMessageList.size() > 0) {
processLightChanged();
lightMessageList.clear();
}
VirtualUniverse.mc.addMirrorObject(this);
// clear the array to prevent memory leaks
Arrays.fill(messages, 0, nMsg, null);
}
if (reEvaluateBg) {
currentActiveBackground = universe.renderingEnvironmentStructure.
getApplicationBackground(vpSchedSphereInVworld, locale, view);
}
if (visQuery) {
GeometryAtom[] bgGeometryAtoms;
boolean allEnComp;
// computeViewFrustumBox in VisibilityStructure.
computeViewFrustumBBox(viewFrustumBBox);
// System.err.println("viewFrustumBBox = " + this);
ViewPlatform vp = view.getViewPlatform();
if (vp != null) {
allEnComp = universe.geometryStructure.
getVisibleBHTrees(this, viewFrustumBBox,
locale, referenceTime,
visGAIsDirty || reactivateView || localeChanged ||
((view.viewCache.vcDirtyMask &
View.VISIBILITY_POLICY_DIRTY) != 0),
view.viewCache.visibilityPolicy);
reactivateView = false;
// process background geometry atoms
if (currentActiveBackground != null &&
currentActiveBackground.geometryBranch != null) {
bgGeometryAtoms =
currentActiveBackground.getBackgroundGeometryAtoms();
if (bgGeometryAtoms != null) {
processBgGeometryAtoms(bgGeometryAtoms, referenceTime);
}
}
if(!allEnComp) {
// Increment the framecount for compaction ...
frameCount++;
if (frameCount > frameCountCutoff) {
frameCount = 0;
checkForCompaction();
}
else if (frameCount == notVisibleCount) {
removeCutoffTime = referenceTime;
}
}
}
// Reset dirty bits.
visGAIsDirty = false;
visQuery = false;
}
// Two environments are dirty
// If lights, fog or model clip have been added/removed, then
// reEvaluate RenderAtoms and mark the lightbin and
// env set dirty if applicable
if (envDirty == REEVALUATE_ALL_ENV || envDirty == 3 ||
envDirty > 4) {
reEvaluateEnv(changedLts, changedFogs, changedModelClips, true,
altAppearanceDirty);
}
else if (envDirty == 0 && altAppearanceDirty) {
reEvaluateAlternateAppearance();
}
else {
if ((envDirty & REEVALUATE_LIGHTS) != 0) {
reEvaluateLights(altAppearanceDirty);
}
else if ((envDirty & REEVALUATE_FOG) != 0)
reEvaluateFog(changedFogs, (changedFogs.size() > 0), altAppearanceDirty);
else if ((envDirty & REEVALUATE_MCLIP) != 0)
reEvaluateModelClip(changedModelClips, (changedModelClips.size() > 0), altAppearanceDirty);
}
// do any pre-update node component screening
if (updateCheckList.size() > 0) {
int size = updateCheckList.size();
for (int k = 0; k < size; k++) {
updateCheckList.get(k).updateNodeComponentCheck();
}
updateCheckList.clear();
}
changedLts.clear();
changedFogs.clear();
changedModelClips.clear();
envDirty = 0;
altAppearanceDirty = false;
view.renderBinReady = true;
VirtualUniverse.mc.sendRunMessage(view,
J3dThread.RENDER_THREAD);
}
void processSwitchChanged(J3dMessage m, long refTime) {
int i;
UnorderList arrList;
int size;
Object[] nodes, nodesArr;
RenderingEnvironmentStructure rdrEnvStr =
universe.renderingEnvironmentStructure;
UpdateTargets targets = (UpdateTargets)m.args[0];
arrList = targets.targetList[Targets.ENV_TARGETS];
if (arrList != null) {
size = arrList.size();
nodesArr = arrList.toArray(false);
for (int h=0; h= 0) {
// Issue 471 - Don't check ATTRIBUTE_VALUE_UPDATE, there is no need
// to do anything to the shader bins when a value changes.
boolean spUpdate =
((component & ShaderAppearanceRetained.SHADER_PROGRAM) != 0);
boolean sasUpdate =
(((component & ShaderAppearanceRetained.SHADER_ATTRIBUTE_SET) != 0) ||
((component & ShaderConstants.ATTRIBUTE_SET_PUT) != 0) ||
((component & ShaderConstants.ATTRIBUTE_SET_REMOVE) != 0) ||
((component & ShaderConstants.ATTRIBUTE_SET_CLEAR) != 0));
if (spUpdate) {
/* TODO : JADA - Sole user logic is incomplete. Will disable for JavaOne */
//if (false && (sApp.mirror.changedFrequent & component) != 0) {
if(false) {
/*
System.err.println("RenderBin : Shader sole user (SHADER_PROGRAM)" +
ra.renderMolecule.textureBin.shaderBin);
*/
ShaderBin sBin;
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
sBin = ra.renderMolecule.textureBin.shaderBin;
if (sBin.componentDirty == 0) {
sBinUpdateList.add(sBin);
sBin.componentDirty |= ShaderBin.SHADER_PROGRAM_DIRTY;
}
}
} else {
/*
System.err.println("RenderBin : not soleUser (SHADER_PROGRAM)" +
ra.renderMolecule.textureBin.shaderBin);
*/
for (i = 0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
AttributeBin attrBin = ra.renderMolecule.textureBin.attributeBin;
ra.renderMolecule.removeRenderAtom(ra);
reInsertShaderBin(attrBin, ra);
}
}
} else if (sasUpdate) {
/* TODO : JADA - Sole user logic is incomplete. Will disable for JavaOne */
//if (false && (sApp.mirror.changedFrequent & component) != 0) {
if(false) {
/*
System.err.println("RenderBin : sole user (SHADER_ATTRIBUTE_SET)" +
ra.renderMolecule.textureBin.shaderBin);
*/
ShaderBin sBin;
for (i = 0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
sBin = ra.renderMolecule.textureBin.shaderBin;
if (sBin.componentDirty == 0) {
sBinUpdateList.add(sBin);
sBin.componentDirty |= ShaderBin.SHADER_ATTRIBUTE_SET_DIRTY;
}
}
} else {
/*
System.err.println("RenderBin :not soleUser (SHADER_ATTRIBUTE_SET) " +
ra.renderMolecule.textureBin.shaderBin);
*/
for (i = 0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
AttributeBin attrBin = ra.renderMolecule.textureBin.attributeBin;
ra.renderMolecule.removeRenderAtom(ra);
reInsertShaderBin(attrBin, ra);
}
}
}
}
}
void processFogChanged(Object[] args) {
FogRetained fog = (FogRetained)args[0];
EnvironmentSet e;
int component = ((Integer)args[1]).intValue();
if ((component &(FogRetained.SCOPE_CHANGED |
FogRetained.BOUNDS_CHANGED |
FogRetained.BOUNDINGLEAF_CHANGED)) != 0){
envDirty |= REEVALUATE_FOG;
}
else {
UnorderList list = fog.mirrorFog.environmentSets;
synchronized (list) {
EnvironmentSet envsets[] = (EnvironmentSet []) list.toArray(false);
int size = list.size();
for (int i = 0; i < size; i++) {
e = envsets[i];
e.canvasDirty |= Canvas3D.FOG_DIRTY;
if (!e.onUpdateList) {
objUpdateList.add(e);
e.onUpdateList = true;
}
}
}
}
}
/**
* This routine get called whenever a component of the appearance
* changes
*/
void processAppearanceChanged(Object[] args){
int component = ((Integer)args[1]).intValue();
int i;
GeometryAtom[] gaArr = (GeometryAtom[] )args[3];
RenderAtom ra = null;
AppearanceRetained app = (AppearanceRetained) args[0];
int TEXTURE_STATE_CHANGED =
AppearanceRetained.TEXTURE_UNIT_STATE |
AppearanceRetained.TEXTURE |
AppearanceRetained.TEXTURE_ATTR |
AppearanceRetained.TEXCOORD_GEN ;
int start = -1;
// Get the first ra that is visible
for (i = 0; (i < gaArr.length && (start < 0)); i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin()) {
continue;
}
else {
start = i;
}
}
if (start >= 0) {
if ((component & TEXTURE_STATE_CHANGED) != 0) {
if (((app.mirror.changedFrequent & TEXTURE_STATE_CHANGED) != 0) &&
((ra.renderMolecule.textureBin.tbFlag &
TextureBin.SOLE_USER) != 0)) {
/*
System.err.println("renderbin. texture state changed tb sole user " +
ra.renderMolecule.textureBin + " tb.tbFlag= " +
ra.renderMolecule.textureBin.tbFlag);
*/
TextureBin tb;
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
tb = ra.renderMolecule.textureBin;
if (tb.soleUserCompDirty == 0) {
tbUpdateList.add(tb);
}
// mark that the texture unit state ref is changed
// also mark that the TextureBin needs to reevaluate
// number of active textures
tb.soleUserCompDirty |=
TextureBin.SOLE_USER_DIRTY_REF;
}
} else {
/*
System.err.println("renderbin. texture state changed tb not sole user " +
ra.renderMolecule.textureBin + " tb.tbFlag= " +
ra.renderMolecule.textureBin.tbFlag);
System.err.println("......tb.soleUser= " +
((ra.renderMolecule.textureBin.tbFlag & TextureBin.SOLE_USER) != 0) +
" app.mirror.changedFrequent= " +
((app.mirror.changedFrequent & TEXTURE_STATE_CHANGED) != 0));
*/
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
ShaderBin sb = ra.renderMolecule.textureBin.shaderBin;
ra.renderMolecule.removeRenderAtom(ra);
reInsertTextureBin(sb, ra);
}
}
} else if ((component & AppearanceRetained.RENDERING) != 0) {
boolean visible = ((Boolean)args[4]).booleanValue();
visGAIsDirty = true;
visQuery = true;
if (!visible) {
// remove all gaAttrs
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
renderAtoms.remove(renderAtoms.indexOf(ra));
removeARenderAtom(ra);
}
}
else {
if ((app.mirror.changedFrequent & component) != 0 &&
ra.renderMolecule.textureBin.attributeBin.soleUser) {
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
AttributeBin aBin = ra.renderMolecule.textureBin.attributeBin;
if ((aBin.onUpdateList & AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST) == 0 ) {
aBinUpdateList.add(aBin);
aBin.onUpdateList |= AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST;
}
}
}
else {
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
EnvironmentSet e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
}
}
else if ((component & (AppearanceRetained.COLOR |
AppearanceRetained.MATERIAL|
AppearanceRetained.TRANSPARENCY|
AppearanceRetained.POLYGON |
AppearanceRetained.LINE|
AppearanceRetained.POINT)) != 0) {
// System.err.println("AppearanceRetained.POINT = "+AppearanceRetained.POINT);
// System.err.println("(app.mirror.changedFrequent & component) != 0 "+app.mirror.changedFrequent );
// System.err.println("ra.renderMolecule.soleUser "+ra.renderMolecule.soleUser);
if ((app.mirror.changedFrequent & component) != 0 &&
ra.renderMolecule.soleUser) {
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
if ((ra.renderMolecule.soleUserCompDirty& RenderMolecule.ALL_DIRTY_BITS) == 0 ) {
rmUpdateList.add(ra.renderMolecule);
}
ra.renderMolecule.soleUserCompDirty |= component;
}
}
else {
for (i = start; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra== null || !ra.inRenderBin())
continue;
TextureBin tb = ra.renderMolecule.textureBin;
ra.renderMolecule.removeRenderAtom(ra);
reInsertRenderAtom(tb, ra);
}
}
}
} else {
// Nothing is visible
if ((component & AppearanceRetained.RENDERING) != 0) {
// Rendering attributes change
visGAIsDirty = true;
visQuery = true;
}
}
}
void processModelClipChanged(Object[] args) {
ModelClipRetained modelClip =
(ModelClipRetained)args[0];
EnvironmentSet e;
int component = ((Integer)args[1]).intValue();
if ((component & (ModelClipRetained.SCOPE_CHANGED |
ModelClipRetained.BOUNDS_CHANGED |
ModelClipRetained.BOUNDINGLEAF_CHANGED)) != 0){
envDirty |= REEVALUATE_MCLIP;
} else if ((component & (ModelClipRetained.ENABLE_CHANGED |
ModelClipRetained.ENABLES_CHANGED)) != 0) {
// need to render modelclip
if (!changedModelClips.contains(modelClip.mirrorModelClip))
changedModelClips.add(modelClip.mirrorModelClip);
// need to reevaluate envset
envDirty |= REEVALUATE_MCLIP;
} else {
UnorderList list = modelClip.mirrorModelClip.environmentSets;
synchronized (list) {
EnvironmentSet envsets[] = (EnvironmentSet []) list.toArray(false);
int size = list.size();
for (int i = 0; i < size; i++) {
e = envsets[i];
e.canvasDirty |= Canvas3D.MODELCLIP_DIRTY;
if (!e.onUpdateList) {
objUpdateList.add(e);
e.onUpdateList = true;
}
}
}
}
}
/**
* This routine get called whenever a region of the boundingleaf
* changes
*/
void processBoundingLeafChanged(Object[] args, long refTime){
// Notify all users of this bounding leaf, it may
// result in the re-evaluation of the lights/fogs/backgrounds
Object[] users = (Object[])(args[3]);
int i;
// XXXX: Handle other object affected by bounding leaf changes
for (i = 0; i < users.length; i++) {
LeafRetained leaf = (LeafRetained)users[i];
switch(leaf.nodeType) {
case NodeRetained.AMBIENTLIGHT:
case NodeRetained.POINTLIGHT:
case NodeRetained.SPOTLIGHT:
case NodeRetained.DIRECTIONALLIGHT:
if (universe.renderingEnvironmentStructure.isLightScopedToThisView(leaf, view))
envDirty |= REEVALUATE_LIGHTS;
break;
case NodeRetained.LINEARFOG:
case NodeRetained.EXPONENTIALFOG:
if (universe.renderingEnvironmentStructure.isFogScopedToThisView(leaf, view))
envDirty |= REEVALUATE_FOG;
break;
case NodeRetained.BACKGROUND:
if (universe.renderingEnvironmentStructure.isBgScopedToThisView(leaf, view))
reEvaluateBg = true;
break;
case NodeRetained.CLIP:
if (universe.renderingEnvironmentStructure.isClipScopedToThisView(leaf, view))
reEvaluateClip = true;
break;
case NodeRetained.MODELCLIP:
if (universe.renderingEnvironmentStructure.isMclipScopedToThisView(leaf, view))
envDirty |= REEVALUATE_MCLIP;
break;
case NodeRetained.ALTERNATEAPPEARANCE:
if (universe.renderingEnvironmentStructure.isAltAppScopedToThisView(leaf, view)) altAppearanceDirty = true;
break;
default:
break;
}
}
}
void processOrientedShape3DChanged(Object[] gaArr) {
RenderAtom ra;
for (int i = 0; i < gaArr.length; i++) {
ra = ((GeometryAtom)gaArr[i]).getRenderAtom(view);
if (ra!= null && ra.inRenderBin() && !ra.inDirtyOrientedRAs()) {
dirtyOrientedRAs.add(ra);
ra.dirtyMask |= RenderAtom.IN_DIRTY_ORIENTED_RAs;
}
}
}
void processShapeChanged(Object[] args, long refTime) {
int component = ((Integer)args[1]).intValue();
int i;
RenderAtom ra;
EnvironmentSet e;
if ((component & Shape3DRetained.APPEARANCE_CHANGED) != 0) {
GeometryAtom[] gaArr = (GeometryAtom[])args[4];
if (gaArr.length > 0) {
if (!gaArr[0].source.appearanceOverrideEnable) {
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin()) {
continue;
}
ra.app = ra.geometryAtom.source.appearance;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
else {
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin()) {
continue;
}
// if its using the alternate appearance continue ..
if (ra.app == ra.geometryAtom.source.otherAppearance)
continue;
ra.app = ra.geometryAtom.source.appearance;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
}
}
else if ((component & Shape3DRetained.GEOMETRY_CHANGED) != 0) {
processDataChanged((Object[])args[2], (Object[])args[3], refTime);
}
else if ((component & Shape3DRetained.APPEARANCEOVERRIDE_CHANGED) != 0) {
AppearanceRetained app, saveApp = null;
Shape3DRetained saveShape = null;
GeometryAtom[] gaArr = (GeometryAtom[])args[4];
Object[] retVal;
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin())
continue;
// Once shape could have many geometryAtoms, add the
// mirrorShape as a user of an appearance only once
if (saveShape != ra.geometryAtom.source) {
saveShape = ra.geometryAtom.source;
if (ra.geometryAtom.source.appearanceOverrideEnable) {
retVal =universe.renderingEnvironmentStructure.getInfluencingAppearance(ra, view);
saveShape.otherAppearance = (AppearanceRetained)retVal[1];
if (retVal[0] == Boolean.TRUE) {
app = (AppearanceRetained)retVal[1];
if (app != null) {
app.sgApp.addAMirrorUser(saveShape);
}
}
else {// use the default
app = ra.geometryAtom.source.appearance;
}
}
else {
// If it were using the alternate appearance
// remove itself as the user
if (ra.app == saveShape.otherAppearance &&
ra.app != null) {
ra.app.sgApp.removeAMirrorUser(saveShape);
}
app = ra.geometryAtom.source.appearance;
saveShape.otherAppearance = null;
}
saveApp = app;
}
else {
app = saveApp;
}
ra.app = app;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
}
/**
* Process a Text3D data change. This involves removing all the
* old geometry atoms in the list, and the creating new ones.
*/
void processDataChanged(Object[] oldGaList,
Object[] newGaList, long referenceTime) {
RenderAtom ra;
int i;
GeometryRetained geo;
GeometryAtom ga;
for (i=0; i 0) {
if (!gaArr[0].source.appearanceOverrideEnable) {
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin()) {
continue;
}
ra.app = ra.geometryAtom.source.appearance;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
else {
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin())
continue;
// if its using the alternate appearance continue ..
if (ra.app == ra.geometryAtom.source.otherAppearance)
continue;
ra.app = ra.geometryAtom.source.appearance;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
}
}
else if ((component & MorphRetained.APPEARANCEOVERRIDE_CHANGED) != 0) {
AppearanceRetained app, saveApp = null;
Shape3DRetained saveShape = null;
GeometryAtom[] gaArr = (GeometryAtom[])args[4];
Object[] retVal;
for (i =0; i < gaArr.length; i++) {
ra = gaArr[i].getRenderAtom(view);
if (ra == null || !ra.inRenderBin())
continue;
// Once shape could have many geometryAtoms, add the
// mirrorShape as a user of an appearance only once
if (saveShape != ra.geometryAtom.source) {
saveShape = ra.geometryAtom.source;
if (ra.geometryAtom.source.appearanceOverrideEnable) {
retVal =universe.renderingEnvironmentStructure.getInfluencingAppearance(ra, view);
saveShape.otherAppearance = (AppearanceRetained)retVal[1];
if (retVal[0] == Boolean.TRUE) {
app = (AppearanceRetained)retVal[1];
if (app != null) {
app.sgApp.addAMirrorUser(saveShape);
}
}
else {// use the default
app = ra.geometryAtom.source.appearance;
}
}
else {
// If it were using the alternate appearance
// remove itself as the user
if (ra.app == saveShape.otherAppearance &&
ra.app != null) {
ra.app.sgApp.removeAMirrorUser(saveShape);
}
app = ra.geometryAtom.source.appearance;
saveShape.otherAppearance = null;
}
saveApp = app;
}
else {
app = saveApp;
}
ra.app = app;
e = ra.renderMolecule.textureBin.environmentSet;
ra.renderMolecule.removeRenderAtom(ra);
reInsertAttributeBin(e, ra);
}
}
}
/**
* This routine gets called whenever the position of the view platform
* has changed.
*/
void updateViewPlatform(ViewPlatformRetained vp, float radius) {
ViewPlatform viewP = view.getViewPlatform();
if (viewP != null && (ViewPlatformRetained)viewP.retained == vp) {
vpcToVworld = vp.getCurrentLocalToVworld(null);
vpcToVworldDirty = true;
synchronized(vp) {
vp.vprDirtyMask |= View.VPR_VIEWPLATFORM_DIRTY;
}
// vp schedSphere is already set and transform in
// BehaviorStructure thread which is run before
// RenderBin using vp.updateActivationRadius()
vpSchedSphereInVworld = vp.schedSphere;
reEvaluateBg = true;
reEvaluateClip = true;
}
}
/**
* This routine removes the GeometryAtoms from RenderBin
*/
void processGeometryAtomsChanged(Object[] gaArr) {
int i;
RenderAtom ra;
for (i = 0; i < gaArr.length; i++) {
ra = ((GeometryAtom)gaArr[i]).getRenderAtom(view);
if (ra != null && ra.inRenderBin()) {
renderAtoms.remove(renderAtoms.indexOf(ra));
removeARenderAtom(ra);
}
}
}
/**
* process Geometry changed, mark the display list
* in which renderMolecule is as dirty
*/
void processGeometryChanged(Object[] args) {
Object[] gaList = (Object[]) args[0];
GeometryRetained g = (GeometryRetained)args[1];
GeometryAtom ga;
int i;
for (i = 0; i < gaList.length; i++) {
ga = ((GeometryAtom)gaList[i]);
RenderAtom renderAtom = ga.getRenderAtom(view);
if (renderAtom == null || !renderAtom.inRenderBin()) {
continue;
}
// Add the renderMolecule to the dirty list so that
// display list will be recreated
int j = 0;
for ( j = 0; j < renderAtom.rListInfo.length; j++) {
if (g == renderAtom.rListInfo[j].geometry())
break;
}
RenderAtomListInfo ra = renderAtom.rListInfo[j];
if ((ra.groupType & RenderAtom.DLIST) != 0)
addDirtyRenderMolecule(ra.renderAtom.renderMolecule);
if ((ra.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) {
addDlistPerRinfo.add(ra);
}
if ((ra.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0)
addGeometryDlist(ra);
// Raster send this message only for setImage()
if (g instanceof RasterRetained) {
Object[] objs = (Object[]) args[2];
Texture2DRetained oldTex = (Texture2DRetained) objs[0];
Texture2DRetained newTex = (Texture2DRetained) objs[1];
RasterRetained geo = (RasterRetained)ra.geometry();
if (oldTex != null) {
addTextureResourceFreeList(oldTex);
ImageComponentRetained oldImage = oldTex.images[0][0];
if (oldImage != null) {
removeNodeComponent(oldImage);
}
}
if (newTex != null) {
ImageComponentRetained newImage = newTex.images[0][0];
if (newImage != null) {
addNodeComponent(newImage);
}
}
}
}
}
void addTextureBin(TextureBin tb) {
textureBinList.add(tb);
}
void removeTextureBin(TextureBin tb) {
textureBinList.remove(tb);
}
void addDirtyRenderMolecule(RenderMolecule rm) {
if ((rm.onUpdateList & RenderMolecule.IN_DIRTY_RENDERMOLECULE_LIST) == 0) {
if (rm.onUpdateList == 0) {
objUpdateList.add(rm);
}
rm.onUpdateList |= RenderMolecule.IN_DIRTY_RENDERMOLECULE_LIST;
dirtyRenderMoleculeList.add(rm);
}
}
void removeDirtyRenderMolecule(RenderMolecule rm) {
if ((rm.onUpdateList & RenderMolecule.IN_DIRTY_RENDERMOLECULE_LIST) != 0) {
rm.onUpdateList &= ~RenderMolecule.IN_DIRTY_RENDERMOLECULE_LIST;
if (rm.onUpdateList == 0) {
objUpdateList.remove(rm);
}
dirtyRenderMoleculeList.remove(dirtyRenderMoleculeList.indexOf(rm));
}
}
void updateDirtyDisplayLists(Canvas3D cv,
ArrayList rmList, ArrayList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy