/* * 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 nonViewScopedLights = new ArrayList(); HashMap> viewScopedLights = new HashMap>(); int numberOfLights = 0; /** * The list of fog nodes */ ArrayList nonViewScopedFogs = new ArrayList(); HashMap> viewScopedFogs = new HashMap>(); int numberOfFogs = 0; /** * The list of alternate app nodes */ ArrayList nonViewScopedAltAppearances = new ArrayList(); HashMap> viewScopedAltAppearances = new HashMap>(); int numberOfAltApps = 0; /** * The list of model clip nodes */ ArrayList nonViewScopedModelClips = new ArrayList(); HashMap> viewScopedModelClips = new HashMap>(); int numberOfModelClips = 0; /** * The list of background nodes */ ArrayList nonViewScopedBackgrounds = new ArrayList(); HashMap> viewScopedBackgrounds = new HashMap>(); int numberOfBgs = 0; /** * The list of clip nodes */ ArrayList nonViewScopedClips = new ArrayList(); HashMap> viewScopedClips = new HashMap>(); 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 objList = new ArrayList(); // ArrayList of leafRetained object whose boundingleaf xform // should be updated ArrayList xformChangeList = new ArrayList(); // freelist management of objects private final ArrayList objFreeList = new ArrayList(); 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 viewScopedNodes = (ArrayList)m.args[3]; ArrayList> scopedNodesViewList = (ArrayList>)m.args[4]; int i; for (i=0; i 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 list = viewScopedLights.get(view); if (list == null) { list = new ArrayList(); 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 list = viewScopedFogs.get(view); if (list == null) { list = new ArrayList(); 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 list = viewScopedAltAppearances .get(view); if (list == null) { list = new ArrayList(); 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 list = viewScopedBackgrounds .get(view); if (list == null) { list = new ArrayList(); 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 list = viewScopedClips.get(view); if (list == null) { list = new ArrayList(); 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 list = viewScopedModelClips.get(view); if (list == null) { list = new ArrayList(); 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 viewScopedNodes = (ArrayList)m.args[3]; ArrayList> scopedNodesViewList = (ArrayList>)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 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 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 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 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 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 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 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 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 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 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 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 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 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 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> vlists = (ArrayList>)m.args[1]; ArrayList vsgs = (ArrayList)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 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 vsgs = (ArrayList)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 ltList = null; ArrayList fogList = null; ArrayList mclipList = null; ArrayList altAppList = null; ArrayList bgList = null; ArrayList 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(); 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(); 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(); 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(); 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(); 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(); 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 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 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 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 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 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 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() {} }