/* * 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.Arrays; import java.util.HashMap; import javax.vecmath.Vector3d; /** * A rendering environment structure is an object that organizes lights, * fogs, backgrounds, clips, and model clips. */ class RenderingEnvironmentStructure extends J3dStructure implements ObjectUpdate { /** * The list of light nodes */ ArrayList<LightRetained> nonViewScopedLights = new ArrayList<LightRetained>(); HashMap<View, ArrayList<LightRetained>> viewScopedLights = new HashMap<View, ArrayList<LightRetained>>(); int numberOfLights = 0; /** * The list of fog nodes */ ArrayList<FogRetained> nonViewScopedFogs = new ArrayList<FogRetained>(); HashMap<View, ArrayList<FogRetained>> viewScopedFogs = new HashMap<View, ArrayList<FogRetained>>(); int numberOfFogs = 0; /** * The list of alternate app nodes */ ArrayList<AlternateAppearanceRetained> nonViewScopedAltAppearances = new ArrayList<AlternateAppearanceRetained>(); HashMap<View, ArrayList<AlternateAppearanceRetained>> viewScopedAltAppearances = new HashMap<View, ArrayList<AlternateAppearanceRetained>>(); int numberOfAltApps = 0; /** * The list of model clip nodes */ ArrayList<ModelClipRetained> nonViewScopedModelClips = new ArrayList<ModelClipRetained>(); HashMap<View, ArrayList<ModelClipRetained>> viewScopedModelClips = new HashMap<View, ArrayList<ModelClipRetained>>(); int numberOfModelClips = 0; /** * The list of background nodes */ ArrayList<BackgroundRetained> nonViewScopedBackgrounds = new ArrayList<BackgroundRetained>(); HashMap<View, ArrayList<BackgroundRetained>> viewScopedBackgrounds = new HashMap<View, ArrayList<BackgroundRetained>>(); int numberOfBgs = 0; /** * The list of clip nodes */ ArrayList<ClipRetained> nonViewScopedClips = new ArrayList<ClipRetained>(); HashMap<View, ArrayList<ClipRetained>> viewScopedClips = new HashMap<View, ArrayList<ClipRetained>>(); int numberOfClips = 0; // For closest Background selection BackgroundRetained[] intersectedBacks = new BackgroundRetained[1]; // For closest Clip selection ClipRetained[] intersectedClips = new ClipRetained[1]; // For closest Background, Clip, Fog selection Bounds[] intersectedBounds = new Bounds[1]; Transform3D localeXform = new Transform3D(); Vector3d localeTranslation = new Vector3d(); // For closest Fog selection FogRetained[] intersectedFogs = new FogRetained[1]; // for closest alternate appearance selection AlternateAppearanceRetained[] intersectedAltApps = new AlternateAppearanceRetained[1]; // For closest ModelClip selection ModelClipRetained[] intersectedModelClips = new ModelClipRetained[1]; // Back clip distance in V world double backClipDistance; // ArrayList of leafRetained object whose mirrorObjects // should be updated ArrayList<Object[]> objList = new ArrayList<Object[]>(); // ArrayList of leafRetained object whose boundingleaf xform // should be updated ArrayList<LeafRetained> xformChangeList = new ArrayList<LeafRetained>(); // freelist management of objects private final ArrayList<Object[]> objFreeList = new ArrayList<Object[]>(); LightRetained[] retlights = new LightRetained[5]; // variables used for processing transform messages boolean transformMsg = false; UpdateTargets targets = null; ArrayList blUsers = null; Integer ogInsert = new Integer(J3dMessage.ORDERED_GROUP_INSERTED); Integer ogRemove = new Integer(J3dMessage.ORDERED_GROUP_REMOVED); // Used to lock the intersectedBounds {used by fog, mclip etc} // Can used intersectedBounds itself, since this may be realloced Object lockObj = new Object(); /** * Constructs a RenderingEnvironmentStructure object in the specified * virtual universe. */ RenderingEnvironmentStructure(VirtualUniverse u) { super(u, J3dThread.UPDATE_RENDERING_ENVIRONMENT); } /** * Returns a object array of length 5 to save the 5 objects in the message list. */ Object[] getObjectArray() { int size = objFreeList.size(); if (size == 0) return new Object[5]; return objFreeList.remove(size - 1); } void addObjArrayToFreeList(Object[] objs) { Arrays.fill(objs, null); objFreeList.add(objs); } @Override public void updateObject() { int size; size = objList.size(); for (int i = 0; i < size; i++) { Object[] args = objList.get(i); LeafRetained leaf = (LeafRetained)args[0]; leaf.updateMirrorObject(args); addObjArrayToFreeList(args); } objList.clear(); size = xformChangeList.size(); for (int i = 0; i < size; i++) { xformChangeList.get(i).updateTransformChange(); } xformChangeList.clear(); } @Override void processMessages(long referenceTime) { J3dMessage[] messages = getMessages(referenceTime);; J3dMessage m; int nMsg = getNumMessage(); if (nMsg <= 0) { return; } for (int i=0; i < nMsg; i++) { m = messages[i]; switch (m.type) { case J3dMessage.INSERT_NODES: insertNodes(m); break; case J3dMessage.REMOVE_NODES: removeNodes(m); break; case J3dMessage.LIGHT_CHANGED: updateLight(m.args); break; case J3dMessage.BOUNDINGLEAF_CHANGED: updateBoundingLeaf(m.args); break; case J3dMessage.FOG_CHANGED: updateFog(m.args); break; case J3dMessage.ALTERNATEAPPEARANCE_CHANGED: updateAltApp(m.args); break; case J3dMessage.SHAPE3D_CHANGED: updateShape3D(m.args); break; case J3dMessage.ORIENTEDSHAPE3D_CHANGED: updateOrientedShape3D(m.args); break; case J3dMessage.MORPH_CHANGED: updateMorph(m.args); break; case J3dMessage.TRANSFORM_CHANGED: transformMsg = true; break; case J3dMessage.SWITCH_CHANGED: processSwitchChanged(m); // may need to process dirty switched-on transform if (universe.transformStructure.getLazyUpdate()) { transformMsg = true; } break; case J3dMessage.MODELCLIP_CHANGED: updateModelClip(m.args); break; case J3dMessage.BACKGROUND_CHANGED: updateBackground(m.args); break; case J3dMessage.CLIP_CHANGED: updateClip(m.args); break; case J3dMessage.ORDERED_GROUP_INSERTED: updateOrderedGroupInserted(m); break; case J3dMessage.ORDERED_GROUP_REMOVED: updateOrderedGroupsRemoved(m); break; case J3dMessage.VIEWSPECIFICGROUP_CHANGED: updateViewSpecificGroupChanged(m); break; case J3dMessage.VIEWSPECIFICGROUP_INIT: initViewSpecificInfo(m); break; case J3dMessage.VIEWSPECIFICGROUP_CLEAR: clearViewSpecificInfo(m); break; } m.decRefcount(); } if (transformMsg) { updateTransformChange(); transformMsg = false; } VirtualUniverse.mc.addMirrorObject(this); Arrays.fill(messages, 0, nMsg, null); } void updateOrderedGroupInserted(J3dMessage m) { Object[] ogList = (Object[])m.args[0]; Object[] ogChildIdList = (Object[])m.args[1]; Object[] ogOrderedIdList = (Object[])m.args[2]; OrderedGroupRetained og; for (int n = 0; n < ogList.length; n++) { og = (OrderedGroupRetained)ogList[n]; og.updateChildIdTableInserted(((Integer) ogChildIdList[n]).intValue(), ((Integer) ogOrderedIdList[n]).intValue()); og.incrChildCount(); } } void updateOrderedGroupsRemoved(J3dMessage m) { Object[] ogList = (Object[])m.args[0]; Object[] ogChildIdList = (Object[])m.args[1]; OrderedGroupRetained og; for (int n = 0; n < ogList.length; n++) { og = (OrderedGroupRetained)ogList[n]; og.updateChildIdTableRemoved(((Integer) ogChildIdList[n]).intValue()); og.decrChildCount(); } } /** * This processes a switch change. */ void processSwitchChanged(J3dMessage m) { int i; UnorderList arrList; int size; Object[] nodes, nodesArr; LeafRetained leaf; UpdateTargets targets = (UpdateTargets)m.args[0]; arrList = targets.targetList[Targets.BLN_TARGETS]; if (arrList != null) { BoundingLeafRetained mbleaf; Object[] objArr = (Object[])m.args[1]; Object[] obj; size = arrList.size(); nodesArr = arrList.toArray(false); for (int h=0; h<size; h++) { nodes = (Object[])nodesArr[h]; obj = (Object[])objArr[h]; for (i=0; i<nodes.length; i++) { Object[] users = (Object[])obj[i]; mbleaf = (BoundingLeafRetained)nodes[i]; //mbleaf.switchState.updateCurrentSwitchOn(); for (int j = 0; j < users.length; j++) { leaf = (LeafRetained)users[j]; if (leaf instanceof FogRetained || leaf instanceof LightRetained || leaf instanceof ModelClipRetained || leaf instanceof ClipRetained || leaf instanceof AlternateAppearanceRetained || leaf instanceof BackgroundRetained) { leaf.updateBoundingLeaf(); } } } } } } void insertNodes(J3dMessage m) { Object[] nodes = (Object[])m.args[0]; ArrayList<NodeRetained> viewScopedNodes = (ArrayList<NodeRetained>)m.args[3]; ArrayList<ArrayList<View>> scopedNodesViewList = (ArrayList<ArrayList<View>>)m.args[4]; int i; for (i=0; i<nodes.length; i++) { Object n = nodes[i]; if (n instanceof LightRetained) { LightRetained lt = (LightRetained)n; numberOfLights++; // If this particulat light is not scoped, added it // to all the views if (lt.inBackgroundGroup) lt.geometryBackground.lights.add(lt); else nonViewScopedLights.add(lt); } else if (n instanceof FogRetained) { FogRetained fg = (FogRetained)n; numberOfFogs++; // If the fog is scoped to a view , then .. if (fg.inBackgroundGroup) { fg.geometryBackground.fogs.add(fg); } else { nonViewScopedFogs.add(fg); } } else if (n instanceof AlternateAppearanceRetained) { AlternateAppearanceRetained altApp = (AlternateAppearanceRetained)n; numberOfAltApps++; nonViewScopedAltAppearances.add(altApp); } else if (n instanceof BackgroundRetained) { BackgroundRetained bg = (BackgroundRetained)n; numberOfBgs++; nonViewScopedBackgrounds.add(bg); } else if (n instanceof ClipRetained) { ClipRetained cl = (ClipRetained)n; numberOfClips++; nonViewScopedClips.add(cl); } else if (n instanceof ModelClipRetained) { ModelClipRetained mc = (ModelClipRetained)n; numberOfModelClips++; nonViewScopedModelClips.add(mc); } } if (viewScopedNodes != null) { int size = viewScopedNodes.size(); int vlsize; for (i = 0; i < size; i++) { NodeRetained n = viewScopedNodes.get(i); ArrayList<View> vl = scopedNodesViewList.get(i); if (n instanceof LightRetained) { LightRetained lt = (LightRetained) n; lt.isViewScoped = true; numberOfLights++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<LightRetained> list = viewScopedLights.get(view); if (list == null) { list = new ArrayList<LightRetained>(); viewScopedLights.put(view, list); } list.add(lt); } } else if (n instanceof FogRetained) { FogRetained ft = (FogRetained) n; ft.isViewScoped = true; numberOfFogs++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<FogRetained> list = viewScopedFogs.get(view); if (list == null) { list = new ArrayList<FogRetained>(); viewScopedFogs.put(view, list); } list.add(ft); } } else if (n instanceof AlternateAppearanceRetained) { AlternateAppearanceRetained aart = (AlternateAppearanceRetained) n; aart.isViewScoped = true; numberOfAltApps++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<AlternateAppearanceRetained> list = viewScopedAltAppearances .get(view); if (list == null) { list = new ArrayList<AlternateAppearanceRetained>(); viewScopedAltAppearances.put(view, list); } list.add(aart); } } else if (n instanceof BackgroundRetained) { BackgroundRetained bt = (BackgroundRetained) n; bt.isViewScoped = true; numberOfBgs++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<BackgroundRetained> list = viewScopedBackgrounds .get(view); if (list == null) { list = new ArrayList<BackgroundRetained>(); viewScopedBackgrounds.put(view, list); } list.add(bt); } } else if (n instanceof ClipRetained) { ClipRetained ct = (ClipRetained) n; ct.isViewScoped = true; numberOfClips++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<ClipRetained> list = viewScopedClips.get(view); if (list == null) { list = new ArrayList<ClipRetained>(); viewScopedClips.put(view, list); } list.add(ct); } } else if (n instanceof ModelClipRetained) { ModelClipRetained mt = (ModelClipRetained)n; mt.isViewScoped = true; numberOfModelClips++; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<ModelClipRetained> list = viewScopedModelClips.get(view); if (list == null) { list = new ArrayList<ModelClipRetained>(); viewScopedModelClips.put(view, list); } list.add(mt); } } } } if (numberOfLights > retlights.length) retlights = new LightRetained[numberOfLights]; if (intersectedFogs.length < numberOfFogs) intersectedFogs = new FogRetained[numberOfFogs]; if (intersectedAltApps.length < numberOfAltApps) intersectedAltApps = new AlternateAppearanceRetained[numberOfAltApps]; if (intersectedBacks.length < numberOfBgs) intersectedBacks = new BackgroundRetained[numberOfBgs]; if (intersectedClips.length < numberOfClips) intersectedClips = new ClipRetained[numberOfClips]; if (intersectedModelClips.length < numberOfModelClips) intersectedModelClips = new ModelClipRetained[numberOfModelClips]; } @Override void removeNodes(J3dMessage m) { Object[] nodes = (Object[])m.args[0]; ArrayList<NodeRetained> viewScopedNodes = (ArrayList<NodeRetained>)m.args[3]; ArrayList<ArrayList<View>> scopedNodesViewList = (ArrayList<ArrayList<View>>)m.args[4]; int i; GeometryAtom ga; LeafRetained oldsrc = null; // System.err.println("RE : removeNodes message " + m); // System.err.println("RE : removeNodes m.args[0] " + m.args[0]); for (i=0; i<nodes.length; i++) { Object n = nodes[i]; if (n instanceof LightRetained) { LightRetained lt = (LightRetained)n; if (lt.inBackgroundGroup) { lt.geometryBackground.lights.remove(lt); } else { nonViewScopedLights.remove(lt); } numberOfLights--; } else if (n instanceof FogRetained) { numberOfFogs--; FogRetained fg = (FogRetained)n; if (fg.inBackgroundGroup) { fg.geometryBackground.fogs.remove(fg); } else { nonViewScopedFogs.remove(nonViewScopedFogs.indexOf(n)); } } else if (n instanceof AlternateAppearanceRetained) { numberOfAltApps--; nonViewScopedAltAppearances.remove(nonViewScopedAltAppearances.indexOf(n)); }else if (n instanceof BackgroundRetained) { numberOfBgs--; nonViewScopedBackgrounds.remove(nonViewScopedBackgrounds.indexOf(n)); } else if (n instanceof ClipRetained) { numberOfClips--; nonViewScopedClips.remove(nonViewScopedClips.indexOf(n)); } else if (n instanceof ModelClipRetained) { ModelClipRetained mc = (ModelClipRetained)n; numberOfModelClips--; nonViewScopedModelClips.remove(mc); } else if (n instanceof GeometryAtom) { ga = (GeometryAtom)n; // Check that we have not already cleared the mirrorobject // since mant geometry atoms could be generated for one // mirror shape if (ga.source != oldsrc) { ga.source.clearMirrorShape(); oldsrc = ga.source; } } else if (n instanceof OrderedGroupRetained) { // Clear the orderedBins for this orderedGroup ((OrderedGroupRetained)n).clearDerivedDataStructures(); } } if (viewScopedNodes != null) { int size = viewScopedNodes.size(); int vlsize; for (i = 0; i < size; i++) { NodeRetained n = viewScopedNodes.get(i); ArrayList<View> vl = scopedNodesViewList.get(i); if (n instanceof LightRetained) { LightRetained lt = (LightRetained) n; lt.isViewScoped = false; numberOfLights--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<LightRetained> list = viewScopedLights.get(view); list.remove(lt); if (list.size() == 0) { viewScopedLights.remove(view); } } } else if (n instanceof FogRetained) { FogRetained ft = (FogRetained)n; ft.isViewScoped = false; numberOfFogs--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<FogRetained> list = viewScopedFogs.get(view); list.remove(ft); if (list.size() == 0) { viewScopedFogs.remove(view); } } } else if (n instanceof AlternateAppearanceRetained) { AlternateAppearanceRetained aart = (AlternateAppearanceRetained) n; aart.isViewScoped = false; numberOfAltApps--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<AlternateAppearanceRetained> list = viewScopedAltAppearances .get(view); list.remove(aart); if (list.size() == 0) { viewScopedAltAppearances.remove(view); } } } else if (n instanceof BackgroundRetained) { BackgroundRetained bt = (BackgroundRetained)n; bt.isViewScoped = false; numberOfBgs--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<BackgroundRetained> list = viewScopedBackgrounds.get(view); list.remove(bt); if (list.size() == 0) { viewScopedBackgrounds.remove(view); } } } else if (n instanceof ClipRetained) { ClipRetained ct = (ClipRetained) n; ct.isViewScoped = false; numberOfClips--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<ClipRetained> list = viewScopedClips.get(view); list.remove(ct); if (list.size() == 0) { viewScopedClips.remove(view); } } } else if (n instanceof ModelClipRetained) { ModelClipRetained mt = (ModelClipRetained)n; mt.isViewScoped = false; numberOfModelClips--; vlsize = vl.size(); for (int k = 0; k < vlsize; k++) { View view = vl.get(k); ArrayList<ModelClipRetained> list = viewScopedModelClips.get(view); list.remove(mt); if (list.size() == 0) { viewScopedModelClips.remove(view); } } } } } } LightRetained[] getInfluencingLights(RenderAtom ra, View view) { LightRetained[] lightAry = null; int i, j; // Need to lock retlights, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized (retlights) { ArrayList<LightRetained> globalLights; int numLights = 0; if (ra.geometryAtom.source.inBackgroundGroup) { globalLights = ra.geometryAtom.source.geometryBackground.lights; numLights = processLights(globalLights, ra, numLights); } else { if ((globalLights = viewScopedLights.get(view)) != null) { numLights = processLights(globalLights, ra, numLights); } // now process the common lights numLights = processLights(nonViewScopedLights, ra, numLights); } boolean newLights = false; if (ra.lights != null && ra.lights.length == numLights) { for (i=0; i<ra.lights.length; i++) { for (j=0; j<numLights; j++) { if (ra.lights[i] == retlights[j]) { break; } } if (j==numLights) { newLights = true; break; } } } else { newLights = true; } if (newLights) { lightAry = new LightRetained[numLights]; for (i = 0; i < numLights; i++) { lightAry[i] = retlights[i]; } return (lightAry); } else { return(ra.lights); } } } // Called while holding the retlights lock private int processLights(ArrayList<LightRetained> globalLights, RenderAtom ra, int numLights) { LightRetained[] shapeScopedLt; Bounds bounds; int i, j, n; bounds = ra.localeVwcBounds; int size = globalLights.size(); if (size > 0) { for (i=0; i<size; i++) { LightRetained light = globalLights.get(i); // System.err.println("vwcBounds = "+bounds); // System.err.println("light.region = "+light.region); // System.err.println("Intersected = "+bounds.intersect(light.region)); // System.err.println(""); // if ((light.viewList != null && light.viewList.contains(view)) && // Treat lights in background geo as having infinite bounds if (light.lightOn && light.switchState.currentSwitchOn && (ra.geometryAtom.source.inBackgroundGroup || bounds.intersect(light.region))){ // Get the mirror Shape3D node n = ra.geometryAtom.source.numlights; shapeScopedLt = ra.geometryAtom.source.lights; // System.err.println("numLights per shape= "+n); // scoped Fog/light is kept in the original // shape3D node, what happens if this list changes // while accessing them?. So, Lock. if (light.isScoped) { for (j = 0; j < n; j++) { // then check if the light is scoped to // this group if (light == shapeScopedLt[j]) { retlights[numLights++] = light; break; } } } else { retlights[numLights++] = light; } } } } return numLights; } FogRetained getInfluencingFog(RenderAtom ra, View view) { FogRetained fog = null; int j, nfogs; Bounds closestBounds; // Need to lock lockObj, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized(lockObj) { nfogs = 0; Bounds bounds = ra.localeVwcBounds; if (intersectedBounds.length < numberOfFogs) intersectedBounds = new Bounds[numberOfFogs]; ArrayList<FogRetained> globalFogs; if (ra.geometryAtom.source.inBackgroundGroup) { globalFogs = ra.geometryAtom.source.geometryBackground.fogs; nfogs = processFogs(globalFogs, ra, nfogs); // If background, then nfogs > 1, take the first one if (nfogs >= 1) fog = intersectedFogs[0]; } else { if ((globalFogs = viewScopedFogs.get(view)) != null) { nfogs = processFogs(globalFogs, ra, nfogs); } // now process the common fogs nfogs = processFogs(nonViewScopedFogs, ra, nfogs); if (nfogs == 1) fog = intersectedFogs[0]; else if (nfogs > 1) { closestBounds = bounds.closestIntersection(intersectedBounds); for (j= 0; j < nfogs; j++) { if (intersectedBounds[j] == closestBounds) { fog = intersectedFogs[j]; break; } } } } return (fog); } } // Called while holding lockObj lock int processFogs(ArrayList<FogRetained> globalFogs, RenderAtom ra, int numFogs) { int size = globalFogs.size(); FogRetained fog; int i, k, n; Bounds bounds = ra.localeVwcBounds; FogRetained[] shapeScopedFog; if (globalFogs.size() > 0) { for (i = 0 ; i < size; i++) { fog = globalFogs.get(i); // Note : There is no enable check for fog if (fog.region != null && fog.switchState.currentSwitchOn && (ra.geometryAtom.source.inBackgroundGroup || fog.region.intersect(bounds))) { n = ra.geometryAtom.source.numfogs; shapeScopedFog = ra.geometryAtom.source.fogs; if (fog.isScoped) { for (k = 0; k < n; k++) { // then check if the Fog is scoped to // this group if (fog == shapeScopedFog[k]) { intersectedBounds[numFogs] = fog.region; intersectedFogs[numFogs++] = fog; break; } } } else { intersectedBounds[numFogs] = fog.region; intersectedFogs[numFogs++] = fog; } } } } return numFogs; } ModelClipRetained getInfluencingModelClip(RenderAtom ra, View view) { if (ra.geometryAtom.source.inBackgroundGroup) return null; // Need to lock lockObj, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized (lockObj) { Bounds bounds = ra.localeVwcBounds; int nModelClips = 0; if (intersectedBounds.length < numberOfModelClips) intersectedBounds = new Bounds[numberOfModelClips]; ArrayList<ModelClipRetained> globalModelClips = viewScopedModelClips.get(view); if (globalModelClips != null) nModelClips = processModelClips(globalModelClips, ra, nModelClips); // now process the common clips nModelClips = processModelClips(nonViewScopedModelClips, ra, nModelClips); ModelClipRetained modelClip = null; if (nModelClips == 1) modelClip = intersectedModelClips[0]; else if (nModelClips > 1) { Bounds closestBounds = bounds.closestIntersection(intersectedBounds); for (int j = 0; j < nModelClips; j++) { if (intersectedBounds[j] == closestBounds) { modelClip = intersectedModelClips[j]; break; } } } return modelClip; } } int processModelClips(ArrayList<ModelClipRetained> globalModelClips, RenderAtom ra, int nModelClips) { int size = globalModelClips.size(); int i, k, n; ModelClipRetained modelClip; Bounds bounds = ra.localeVwcBounds; ModelClipRetained[] shapeScopedModelClip; if (size > 0) { for (i = 0; i < size; i++) { modelClip = globalModelClips.get(i); if (modelClip.enableFlag == true && modelClip.region != null && modelClip.switchState.currentSwitchOn) { if (modelClip.region.intersect(bounds) == true) { n = ra.geometryAtom.source.numModelClips; shapeScopedModelClip = ra.geometryAtom.source.modelClips; if (modelClip.isScoped) { for (k = 0; k < n; k++) { // then check if the modelClip is scoped to // this group if (shapeScopedModelClip[k] == modelClip) { intersectedBounds[nModelClips] = modelClip.region; intersectedModelClips[nModelClips++] = modelClip; break; } } } else { intersectedBounds[nModelClips] = modelClip.region; intersectedModelClips[nModelClips++] = modelClip; } } } } } return nModelClips; } BackgroundRetained getApplicationBackground(BoundingSphere bounds, Locale viewLocale, View view) { BackgroundRetained bg = null; Bounds closestBounds; int j = 0; int nbacks; // Need to lock lockObj, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized(lockObj) { nbacks = 0; if (intersectedBounds.length < numberOfBgs) intersectedBounds = new Bounds[numberOfBgs]; ArrayList<BackgroundRetained> globalBgs = viewScopedBackgrounds.get(view); if (globalBgs != null) nbacks = processBgs(globalBgs, bounds, nbacks, viewLocale); nbacks = processBgs(nonViewScopedBackgrounds, bounds, nbacks, viewLocale); // If there are no intersections, set to black. if (nbacks == 1) { bg = intersectedBacks[0]; } else if (nbacks > 1) { closestBounds = bounds.closestIntersection(intersectedBounds); for (j=0; j<nbacks; j++) { if (intersectedBounds[j] == closestBounds) { bg = intersectedBacks[j]; //System.err.println("matched " + closestBounds); break; } } } return (bg); } } // Called while holding lockObj lock int processBgs(ArrayList<BackgroundRetained> globalBgs, BoundingSphere bounds, int nbacks, Locale viewLocale) { int size = globalBgs.size(); for (int i = 0; i < size; i++) { BackgroundRetained back = globalBgs.get(i); if (back.transformedRegion == null || !back.switchState.currentSwitchOn) continue; if (back.cachedLocale != viewLocale) { Bounds localeBounds = (Bounds)back.transformedRegion.clone(); // Translate the transformed region back.cachedLocale.hiRes.difference(viewLocale.hiRes, localeTranslation); localeXform.setIdentity(); localeXform.setTranslation(localeTranslation); localeBounds.transform(localeXform); if (localeBounds.intersect(bounds) == true) { intersectedBounds[nbacks] = localeBounds; intersectedBacks[nbacks++] = back; } } else { if (back.transformedRegion.intersect(bounds) == true) { intersectedBounds[nbacks] = back.transformedRegion; intersectedBacks[nbacks++] = back; } } } return nbacks; } double[] backClipDistanceInVworld (BoundingSphere bounds, View view) { int j; Bounds closestBounds; boolean backClipActive; double[] backClipDistance; double distance; // Need to lock intersectedBounds, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized(lockObj) { backClipDistance = null; backClipActive = false; int nclips = 0; distance = 0.0; if (intersectedBounds.length < numberOfClips) intersectedBounds = new Bounds[numberOfClips]; ArrayList<ClipRetained> globalClips = viewScopedClips.get(view); if (globalClips != null) nclips = processClips(globalClips, bounds, nclips); nclips = processClips(nonViewScopedClips, bounds, nclips); if (nclips == 1) { distance = intersectedClips[0].backDistanceInVworld; backClipActive = true; } else if (nclips > 1) { closestBounds = bounds.closestIntersection(intersectedBounds); for (j=0; j < nclips; j++) { if (intersectedBounds[j] == closestBounds) { distance = intersectedClips[j].backDistanceInVworld; backClipActive = true; break; } } } if (backClipActive) { backClipDistance = new double[1]; backClipDistance[0] = distance; } return (backClipDistance); } } int processClips(ArrayList<ClipRetained> globalClips, BoundingSphere bounds, int nclips) { int size = globalClips.size(); for (int i = 0; i < size; i++) { ClipRetained clip = globalClips.get(i); if (clip.transformedRegion != null && clip.transformedRegion.intersect(bounds) == true && clip.switchState.currentSwitchOn) { intersectedBounds[nclips] = clip.transformedRegion; intersectedClips[nclips++] = clip; } } return nclips; } void updateLight(Object[] args) { Object[] objs; LightRetained light = (LightRetained)args[0]; int component = ((Integer)args[1]).intValue(); // Store the value to be updated during object update // If its an ambient light, then if color changed, update immediately if ((component & (LightRetained.INIT_MIRROR)) != 0) { light.initMirrorObject(args); } if (light instanceof AmbientLightRetained && ((component & LightRetained.COLOR_CHANGED) != 0)) { light.updateImmediateMirrorObject(args); } else if ((component & (LightRetained.COLOR_CHANGED| LightRetained.INIT_MIRROR | PointLightRetained.POSITION_CHANGED | PointLightRetained.ATTENUATION_CHANGED| DirectionalLightRetained.DIRECTION_CHANGED | SpotLightRetained.DIRECTION_CHANGED | SpotLightRetained.CONCENTRATION_CHANGED | SpotLightRetained.ANGLE_CHANGED)) != 0) { objs = getObjectArray(); objs[0] = args[0]; objs[1] = args[1]; objs[2] = args[2]; objs[3] = args[3]; objs[4] = args[4]; objList.add(objs); } else if ((component & LightRetained.CLEAR_MIRROR) != 0) { light.clearMirrorObject(args); } else { light.updateImmediateMirrorObject(args); } } void updateBackground(Object[] args) { BackgroundRetained bg = (BackgroundRetained)args[0]; bg.updateImmediateMirrorObject(args); } void updateFog(Object[] args) { Object[] objs; FogRetained fog = (FogRetained)args[0]; int component = ((Integer)args[1]).intValue(); if ((component & FogRetained.INIT_MIRROR) != 0) { fog.initMirrorObject(args); // Color, distance et all should be updated when renderer // is not running .. objs = getObjectArray(); objs[0] = args[0]; objs[1] = args[1]; objs[2] = args[2]; objs[3] = args[3]; objs[4] = args[4]; objList.add(objs); } else if ((component & FogRetained.CLEAR_MIRROR) != 0) { fog.clearMirrorObject(args); // Store the value to be updated during object update } else if ((component & (FogRetained.COLOR_CHANGED | LinearFogRetained.FRONT_DISTANCE_CHANGED| LinearFogRetained.BACK_DISTANCE_CHANGED | ExponentialFogRetained.DENSITY_CHANGED)) != 0) { objs = getObjectArray(); objs[0] = args[0]; objs[1] = args[1]; objs[2] = args[2]; objs[3] = args[3]; objs[4] = args[4]; objList.add(objs); } else { fog.updateImmediateMirrorObject(args); } } void updateAltApp(Object[] args) { AlternateAppearanceRetained altApp = (AlternateAppearanceRetained)args[0]; int component = ((Integer)args[1]).intValue(); if ((component & AlternateAppearanceRetained.INIT_MIRROR) != 0) { AlternateAppearanceRetained altapp = (AlternateAppearanceRetained)args[0]; altapp.initMirrorObject(args); } else if ((component & AlternateAppearanceRetained.CLEAR_MIRROR) != 0) { AlternateAppearanceRetained altapp = (AlternateAppearanceRetained)args[0]; altapp.clearMirrorObject(args); } else { altApp.updateImmediateMirrorObject(args); } } void updateClip(Object[] args) { ClipRetained clip = (ClipRetained)args[0]; clip.updateImmediateMirrorObject(args); } void updateModelClip(Object[] args) { ModelClipRetained modelClip = (ModelClipRetained)args[0]; Object[] objs; int component = ((Integer)args[1]).intValue(); if ((component & ModelClipRetained.INIT_MIRROR) != 0) { modelClip.initMirrorObject(args); } if ((component & ModelClipRetained.CLEAR_MIRROR) != 0) { modelClip.clearMirrorObject(args); } else if ((component & (ModelClipRetained.PLANES_CHANGED | ModelClipRetained.INIT_MIRROR | ModelClipRetained.PLANE_CHANGED)) != 0) { objs = getObjectArray(); objs[0] = args[0]; objs[1] = args[1]; objs[2] = args[2]; objs[3] = args[3]; objs[4] = args[4]; objList.add(objs); } else { modelClip.updateImmediateMirrorObject(args); } } void updateBoundingLeaf(Object[] args) { BoundingLeafRetained bl = (BoundingLeafRetained)args[0]; Object[] users = (Object[])(args[3]); bl.updateImmediateMirrorObject(args); // Now update all users of this bounding leaf object for (int i = 0; i < users.length; i++) { LeafRetained mLeaf = (LeafRetained)users[i]; mLeaf.updateBoundingLeaf(); } } void updateShape3D(Object[] args) { Shape3DRetained shape = (Shape3DRetained)args[0]; shape.updateImmediateMirrorObject(args); } void updateOrientedShape3D(Object[] args) { OrientedShape3DRetained shape = (OrientedShape3DRetained)args[4]; shape.updateImmediateMirrorObject(args); } void updateMorph(Object[] args) { MorphRetained morph = (MorphRetained)args[0]; morph.updateImmediateMirrorObject(args); } void updateTransformChange() { int i,j; Object[] nodes, nodesArr; BoundingLeafRetained bl; UnorderList arrList; int size; targets = universe.transformStructure.getTargetList(); blUsers = universe.transformStructure.getBlUsers(); // process misc environment nodes arrList = targets.targetList[Targets.ENV_TARGETS]; if (arrList != null) { size = arrList.size(); nodesArr = arrList.toArray(false); for (j = 0; j < size; j++) { nodes = (Object[])nodesArr[j]; for (i = 0; i < nodes.length; i++) { if (nodes[i] instanceof LightRetained) { LightRetained ml = (LightRetained)nodes[i]; ml.updateImmediateTransformChange(); xformChangeList.add(ml); } else if (nodes[i] instanceof FogRetained) { FogRetained mfog = (FogRetained) nodes[i]; mfog.updateImmediateTransformChange(); xformChangeList.add(mfog); } else if (nodes[i] instanceof AlternateAppearanceRetained){ AlternateAppearanceRetained mAltApp = (AlternateAppearanceRetained) nodes[i]; mAltApp.updateImmediateTransformChange(); xformChangeList.add(mAltApp); } else if (nodes[i] instanceof BackgroundRetained) { BackgroundRetained bg = (BackgroundRetained) nodes[i]; bg.updateImmediateTransformChange(); } else if (nodes[i] instanceof ModelClipRetained) { ModelClipRetained mc = (ModelClipRetained) nodes[i]; mc.updateImmediateTransformChange(); } } } } // process BoundingLeaf nodes arrList = targets.targetList[Targets.BLN_TARGETS]; if (arrList != null) { size = arrList.size(); nodesArr = arrList.toArray(false); for (j = 0; j < size; j++) { nodes = (Object[])nodesArr[j]; for (i = 0; i < nodes.length; i++) { bl = (BoundingLeafRetained)nodes[i]; bl.updateImmediateTransformChange(); } } } // Now notify the list of all users of bounding leaves // to update its boundingleaf transformed region if (blUsers != null) { for (i = 0; i < blUsers.size(); i++) { LeafRetained leaf = (LeafRetained) blUsers.get(i); leaf.updateBoundingLeaf(); } } targets = null; blUsers = null; } // The first element is TRUE, if alternate app is in effect // The second element return the appearance that should be used // Note , I can't just return null for app, then I don't know // if the appearance is null or if the alternate app in not // in effect Object[] getInfluencingAppearance(RenderAtom ra, View view) { int j; Bounds closestBounds; Bounds bounds; Object[] retVal; retVal = new Object[2]; if (ra.geometryAtom.source.inBackgroundGroup) { retVal[0] = Boolean.FALSE; return retVal; } // Need to lock lockObj, since on a multi-processor // system with 2 views on a single universe, there might // be councurrent access synchronized(lockObj) { int nAltApp = 0; bounds = ra.localeVwcBounds; if (intersectedBounds.length < numberOfAltApps) intersectedBounds = new Bounds[numberOfAltApps]; ArrayList<AlternateAppearanceRetained> globalAltApps = viewScopedAltAppearances.get(view); if (globalAltApps != null) nAltApp = processAltApps(globalAltApps, ra, nAltApp); nAltApp = processAltApps(nonViewScopedAltAppearances, ra, nAltApp); AlternateAppearanceRetained altApp = null; if (nAltApp == 1) altApp = intersectedAltApps[0]; else if (nAltApp > 1) { closestBounds = bounds.closestIntersection(intersectedBounds); for (j= 0; j < nAltApp; j++) { if (intersectedBounds[j] == closestBounds) { altApp = intersectedAltApps[j]; break; } } } if (altApp == null) { retVal[0] = Boolean.FALSE; return retVal; } else { retVal[0] = Boolean.TRUE; retVal[1] = altApp.appearance; return retVal; } } } // Called while holding lockObj lock int processAltApps(ArrayList<AlternateAppearanceRetained> globalAltApps, RenderAtom ra, int nAltApp) { int size = globalAltApps.size(); Bounds bounds = ra.localeVwcBounds; AlternateAppearanceRetained[] shapeScopedAltApp; if (size == 0) return nAltApp; for (int i = 0; i < size; i++) { AlternateAppearanceRetained altApp = globalAltApps.get(i); // System.err.println("altApp.region = "+altApp.region+" altApp.switchState.currentSwitchOn = "+altApp.switchState.currentSwitchOn+" intersect = "+altApp.region.intersect(ra.geometryAtom.vwcBounds)); // System.err.println("altApp.isScoped = "+altApp.isScoped); // Note : There is no enable check for fog if (altApp.region == null || !altApp.switchState.currentSwitchOn) continue; if (altApp.region.intersect(bounds) == true) { int n = ra.geometryAtom.source.numAltApps; shapeScopedAltApp = ra.geometryAtom.source.altApps; if (altApp.isScoped) { for (int k = 0; k < n; k++) { // then check if the light is scoped to // this group if (altApp == shapeScopedAltApp[k]) { intersectedBounds[nAltApp] = altApp.region; intersectedAltApps[nAltApp++] = altApp; break; } } } else { intersectedBounds[nAltApp] = altApp.region; intersectedAltApps[nAltApp++] = altApp; } } } return nAltApp; } void initViewSpecificInfo(J3dMessage m) { int[] keys = (int[])m.args[2]; ArrayList<ArrayList<View>> vlists = (ArrayList<ArrayList<View>>)m.args[1]; ArrayList<ViewSpecificGroupRetained> vsgs = (ArrayList<ViewSpecificGroupRetained>)m.args[0]; if (vsgs != null) { // System.err.println("===> non null Vsg"); int size = vsgs.size(); for (int i = 0; i < size; i++) { ViewSpecificGroupRetained v = vsgs.get(i); ArrayList<View> l = vlists.get(i); int index = keys[i]; // System.err.println("v = "+v+" index = "+index+" l = "+l); v.cachedViewList.add(index, l); /* for (int k = 0; k < v.cachedViewList.size(); k++) { System.err.println("v = "+v+" k = "+k+" v.cachedViewList.get(k) = "+v.cachedViewList.get(k)); } */ } } } void clearViewSpecificInfo(J3dMessage m) { int[] keys = (int[])m.args[1]; ArrayList<ViewSpecificGroupRetained> vsgs = (ArrayList<ViewSpecificGroupRetained>)m.args[0]; if (vsgs != null) { int size = vsgs.size(); for (int i = 0; i < size; i++) { ViewSpecificGroupRetained v = vsgs.get(i); int index = keys[i]; if (index == -1) { int csize = v.cachedViewList.size(); for (int j = 0; j < csize; j++) { v.cachedViewList.get(j).clear(); } v.cachedViewList.clear(); } else { v.cachedViewList.remove(index).clear(); } } } } void updateViewSpecificGroupChanged(J3dMessage m) { int component = ((Integer)m.args[0]).intValue(); Object[] objAry = (Object[])m.args[1]; ArrayList<LightRetained> ltList = null; ArrayList<FogRetained> fogList = null; ArrayList<ModelClipRetained> mclipList = null; ArrayList<AlternateAppearanceRetained> altAppList = null; ArrayList<BackgroundRetained> bgList = null; ArrayList<ClipRetained> clipList = null; if (((component & ViewSpecificGroupRetained.ADD_VIEW) != 0) || ((component & ViewSpecificGroupRetained.SET_VIEW) != 0)) { int i; Object obj; View view = (View)objAry[0]; ArrayList vsgList = (ArrayList)objAry[1]; ArrayList leafList = (ArrayList)objAry[2]; int[] keyList = (int[])objAry[3]; int size = vsgList.size(); // Don't add null views if (view != null) { for (i = 0; i < size; i++) { ViewSpecificGroupRetained vsg = (ViewSpecificGroupRetained)vsgList.get(i); int index = keyList[i]; vsg.updateCachedInformation(ViewSpecificGroupRetained.ADD_VIEW, view, index); } size = leafList.size(); // Leaves is non-null only for the top VSG if (size > 0) { // Now process the list of affected leaved for( i = 0; i < size; i++) { obj = leafList.get(i); if (obj instanceof LightRetained) { LightRetained lt = (LightRetained)obj; lt.isViewScoped = true; numberOfLights++; if (ltList == null) { if ((ltList = viewScopedLights.get(view)) == null) { ltList = new ArrayList<LightRetained>(); viewScopedLights.put(view, ltList); } } ltList.add(lt); } if (obj instanceof FogRetained) { FogRetained ft = (FogRetained)obj; ft.isViewScoped = true; numberOfFogs++; if (fogList == null) { if ((fogList = viewScopedFogs.get(view)) == null) { fogList = new ArrayList<FogRetained>(); viewScopedFogs.put(view, fogList); } } fogList.add(ft); } if (obj instanceof ModelClipRetained) { ModelClipRetained mc = (ModelClipRetained)obj; mc.isViewScoped = true; numberOfModelClips++; if (mclipList == null) { if ((mclipList = viewScopedModelClips.get(view)) == null) { mclipList = new ArrayList<ModelClipRetained>(); viewScopedModelClips.put(view, mclipList); } } mclipList.add(mc); } if (obj instanceof AlternateAppearanceRetained) { AlternateAppearanceRetained aart = (AlternateAppearanceRetained)obj; aart.isViewScoped = true; numberOfAltApps++; if (altAppList == null) { if ((altAppList = viewScopedAltAppearances .get(view)) == null) { altAppList = new ArrayList<AlternateAppearanceRetained>(); viewScopedAltAppearances.put(view, altAppList); } } altAppList.add(aart); } if (obj instanceof ClipRetained) { ClipRetained ct = (ClipRetained) obj; ct.isViewScoped = true; numberOfClips++; if (clipList == null) { if ((clipList = viewScopedClips.get(view)) == null) { clipList = new ArrayList<ClipRetained>(); viewScopedClips.put(view, clipList); } } clipList.add(ct); } if (obj instanceof BackgroundRetained) { BackgroundRetained bg = (BackgroundRetained) obj; bg.isViewScoped = true; numberOfBgs++; if (bgList == null) { if ((bgList = viewScopedBackgrounds.get(view)) == null) { bgList = new ArrayList<BackgroundRetained>(); viewScopedBackgrounds.put(view, bgList); } } bgList.add(bg); } } if (numberOfLights > retlights.length) retlights = new LightRetained[numberOfLights]; if (intersectedFogs.length < numberOfFogs) intersectedFogs = new FogRetained[numberOfFogs]; if (intersectedAltApps.length < numberOfAltApps) intersectedAltApps = new AlternateAppearanceRetained[numberOfAltApps]; if (intersectedBacks.length < numberOfBgs) intersectedBacks = new BackgroundRetained[numberOfBgs]; if (intersectedClips.length < numberOfClips) intersectedClips = new ClipRetained[numberOfClips]; if (intersectedModelClips.length < numberOfModelClips) intersectedModelClips = new ModelClipRetained[numberOfModelClips]; } } } if (((component & ViewSpecificGroupRetained.REMOVE_VIEW) != 0)|| ((component & ViewSpecificGroupRetained.SET_VIEW) != 0)) { int i; Object obj; ArrayList vsgList; ArrayList leafList; int[] keyList; View view; if ((component & ViewSpecificGroupRetained.REMOVE_VIEW) != 0) { view = (View)objAry[0]; vsgList = (ArrayList)objAry[1]; leafList = (ArrayList)objAry[2]; keyList = (int[])objAry[3]; } else { view = (View)objAry[4]; vsgList = (ArrayList)objAry[5]; leafList = (ArrayList)objAry[6]; keyList = (int[])objAry[7]; } // Don't add null views if (view != null) { int size = vsgList.size(); for (i = 0; i < size; i++) { ViewSpecificGroupRetained vsg = (ViewSpecificGroupRetained)vsgList.get(i); int index = keyList[i]; vsg.updateCachedInformation(ViewSpecificGroupRetained.REMOVE_VIEW, view, index); } size = leafList.size(); // Leaves is non-null only for the top VSG if (size > 0) { // Now process the list of affected leaved for( i = 0; i < size; i++) { obj = leafList.get(i); if (obj instanceof LightRetained) { ((LightRetained)obj).isViewScoped = false; numberOfLights--; if (ltList == null) { ltList = viewScopedLights.get(view); } ltList.remove(obj); } if (obj instanceof FogRetained) { ((FogRetained)obj).isViewScoped = false; numberOfFogs--; if (fogList == null) { fogList = viewScopedFogs.get(view); } fogList.remove(obj); } if (obj instanceof ModelClipRetained) { ((ModelClipRetained)obj).isViewScoped = false; numberOfModelClips--; if (mclipList == null) { mclipList = viewScopedModelClips.get(view); } mclipList.remove(obj); } if (obj instanceof AlternateAppearanceRetained) { ((AlternateAppearanceRetained)obj).isViewScoped = false; numberOfAltApps--; if (altAppList == null) { altAppList = viewScopedAltAppearances.get(view); } altAppList.remove(obj); } if (obj instanceof ClipRetained) { ((ClipRetained)obj).isViewScoped = false; numberOfClips--; if (clipList == null) { clipList = viewScopedClips.get(view); } clipList.remove(obj); } if (obj instanceof BackgroundRetained) { ((BackgroundRetained)obj).isViewScoped = false; numberOfBgs++; if (bgList == null) { bgList = viewScopedBackgrounds.get(view); } bgList.remove(obj); } } // If there are no more lights scoped to the view, // remove the mapping if (ltList != null && ltList.size() == 0) viewScopedLights.remove(view); if (fogList != null && fogList.size() == 0) viewScopedFogs.remove(view); if (mclipList != null && mclipList.size() == 0) viewScopedModelClips.remove(view); if (altAppList != null && altAppList.size() == 0) viewScopedAltAppearances.remove(view); if (clipList != null && clipList.size() == 0) viewScopedClips.remove(view); if (bgList != null && bgList.size() == 0) viewScopedBackgrounds.remove(view); } } } } boolean isLightScopedToThisView(Object obj, View view) { LightRetained light = (LightRetained)obj; if (light.isViewScoped) { ArrayList<LightRetained> l = viewScopedLights.get(view); // If this is a scoped lights, but has no views then .. if (l == null || !l.contains(light)) return false; } return true; } boolean isFogScopedToThisView(Object obj, View view) { FogRetained fog = (FogRetained)obj; if (fog.isViewScoped) { ArrayList<FogRetained> l = viewScopedFogs.get(view); // If this is a scoped fog, but has no views then .. if (l == null || !l.contains(fog)) return false; } return true; } boolean isAltAppScopedToThisView(Object obj, View view) { AlternateAppearanceRetained altApp = (AlternateAppearanceRetained)obj; if (altApp.isViewScoped) { ArrayList<AlternateAppearanceRetained> l = viewScopedAltAppearances.get(view); // If this is a scoped altapp, but has no views then .. if (l == null || !l.contains(altApp)) return false; } return true; } boolean isBgScopedToThisView(Object obj, View view) { BackgroundRetained bg = (BackgroundRetained)obj; if (bg.isViewScoped) { ArrayList<BackgroundRetained> l = viewScopedBackgrounds.get(view); // If this is a scoped bg, but has no views then .. if (l == null || !l.contains(bg)) return false; } return true; } boolean isClipScopedToThisView(Object obj, View view) { ClipRetained clip = (ClipRetained)obj; if (clip.isViewScoped) { ArrayList<ClipRetained> l = viewScopedClips.get(view); // If this is a scoped clip, but has no views then .. if (l == null || !l.contains(clip)) return false; } return true; } boolean isMclipScopedToThisView(Object obj, View view) { ModelClipRetained mclip = (ModelClipRetained)obj; if (mclip.isViewScoped) { ArrayList<ModelClipRetained> l = viewScopedModelClips.get(view); // If this is a scoped mclip, but has no views then .. if (l == null || !l.contains(mclip)) return false; } return true; } @Override void cleanup() {} }