aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/SwitchRetained.java
diff options
context:
space:
mode:
authorHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
committerHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
commit7a2e20caac9db6f789a7b3fab344b9758af45335 (patch)
treeb5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/SwitchRetained.java
parentf76ce302c4bb2a9f03bbee571ec5d05c29633023 (diff)
j3dcore: flatten the directory structure a bit
Signed-off-by: Harvey Harrison <[email protected]>
Diffstat (limited to 'src/javax/media/j3d/SwitchRetained.java')
-rw-r--r--src/javax/media/j3d/SwitchRetained.java957
1 files changed, 957 insertions, 0 deletions
diff --git a/src/javax/media/j3d/SwitchRetained.java b/src/javax/media/j3d/SwitchRetained.java
new file mode 100644
index 0000000..eac2cb6
--- /dev/null
+++ b/src/javax/media/j3d/SwitchRetained.java
@@ -0,0 +1,957 @@
+/*
+ * Copyright 1996-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.BitSet;
+
+/**
+ * The switch node controls which one of its children will be rendered.
+ */
+
+class SwitchRetained extends GroupRetained implements TargetsInterface
+{
+ static final int GEO_NODES = 0x0001;
+ static final int ENV_NODES = 0x0002;
+ static final int BEHAVIOR_NODES = 0x0004;
+ static final int SOUND_NODES = 0x0008;
+ static final int BOUNDINGLEAF_NODES = 0x0010;
+
+ /**
+ * The value specifing which child to render.
+ */
+ int whichChild = Switch.CHILD_NONE;
+
+ /**
+ * The BitSet specifying which children are to be selected for
+ * rendering. This is used ONLY if whichChild is set to CHILD_MASK.
+ */
+ BitSet childMask = new BitSet();
+
+ /**
+ * The childmask bitset used for rendering
+ */
+ BitSet renderChildMask = new BitSet();
+
+ // A boolean indication that something changed
+ boolean isDirty = true;
+
+// switchLevel per key, used in traversing switch children
+ArrayList<Integer> switchLevels = new ArrayList<Integer>(1);
+
+ // key which identifies a unique path from a locale to this switch link
+ HashKey switchKey = new HashKey();
+
+ // switch index counter to identify specific children
+ int switchIndexCount = 0;
+
+ // for message processing
+ UpdateTargets updateTargets = null;
+
+ArrayList<ArrayList<SwitchState>> childrenSwitchStates = null;
+
+ SwitchRetained() {
+ this.nodeType = NodeRetained.SWITCH;
+ }
+
+ /**
+ * Sets which child should be drawn.
+ * @param whichChild the child to choose during a render operation
+ */
+ // synchronized with clearLive
+ synchronized void setWhichChild(int whichChild, boolean updateAlways) {
+
+ int i, nchildren;
+
+ this.whichChild = whichChild;
+ isDirty = true;
+
+ if (source != null && source.isLive()) {
+ updateTargets = new UpdateTargets();
+ ArrayList<SwitchState> updateList = new ArrayList<SwitchState>(1);
+ nchildren = children.size();
+ switch (whichChild) {
+ case Switch.CHILD_ALL:
+ for (i=0; i<nchildren; i++) {
+ if (renderChildMask.get(i) == false || updateAlways) {
+ renderChildMask.set(i);
+ updateSwitchChild(i, true, updateList);
+ }
+ }
+ break;
+ case Switch.CHILD_NONE:
+ for (i=0; i<nchildren; i++) {
+ if (renderChildMask.get(i) == true || updateAlways) {
+ renderChildMask.clear(i);
+ updateSwitchChild(i, false, updateList);
+ }
+ }
+ break;
+ case Switch.CHILD_MASK:
+ for (i=0; i<nchildren; i++) {
+ if (childMask.get(i) == true) {
+ if (renderChildMask.get(i) == false || updateAlways) {
+ renderChildMask.set(i);
+ updateSwitchChild(i, true, updateList);
+ }
+ } else {
+ if (renderChildMask.get(i) == true || updateAlways) {
+ renderChildMask.clear(i);
+ updateSwitchChild(i, false, updateList);
+ }
+ }
+ }
+ break;
+ default:
+ for (i=0; i<nchildren; i++) {
+ if (i == whichChild) {
+ if (renderChildMask.get(i) == false || updateAlways) {
+ renderChildMask.set(i);
+ updateSwitchChild(i, true, updateList);
+ }
+ } else {
+ if (renderChildMask.get(i) == true || updateAlways) {
+ renderChildMask.clear(i);
+ updateSwitchChild(i, false, updateList);
+ }
+ }
+ }
+ break;
+ }
+ sendMessage(updateList);
+ }
+ dirtyBoundsCache();
+ }
+
+ /**
+ * Returns the index of the current child.
+ * @return the default child's index
+ */
+ int getWhichChild() {
+ return this.whichChild;
+ }
+
+ /**
+ * Sets current childMask.
+ * @param childMask a BitSet to select the children for rendering
+ */
+ // synchronized with clearLive
+ synchronized final void setChildMask(BitSet childMask) {
+ int i, nbits, nchildren;
+
+ if (childMask.size() > this.childMask.size()) {
+ nbits = childMask.size();
+ } else {
+ nbits = this.childMask.size();
+ }
+
+ for (i=0; i<nbits; i++) {
+ if (childMask.get(i)) {
+ this.childMask.set(i);
+ } else {
+ this.childMask.clear(i);
+ }
+ }
+ this.isDirty = true;
+ if (source != null && source.isLive() &&
+ whichChild == Switch.CHILD_MASK) {
+ updateTargets = new UpdateTargets();
+ ArrayList<SwitchState> updateList = new ArrayList<SwitchState>(1);
+ nchildren = children.size();
+ for (i=0; i<nchildren; i++) {
+ if (childMask.get(i) == true) {
+ if (renderChildMask.get(i) == false) {
+ renderChildMask.set(i);
+ updateSwitchChild(i, true, updateList);
+ }
+ } else {
+ if (renderChildMask.get(i) == true) {
+ renderChildMask.clear(i);
+ updateSwitchChild(i, false, updateList);
+ }
+ }
+ }
+ sendMessage(updateList);
+ }
+ dirtyBoundsCache();
+ }
+
+void sendMessage(ArrayList<SwitchState> updateList) {
+
+ J3dMessage m ;
+ int i,j,size,threads;
+ Object[] nodesArr, nodes;
+
+ threads = updateTargets.computeSwitchThreads();
+
+ if (threads > 0) {
+
+ m = new J3dMessage();
+ m.type = J3dMessage.SWITCH_CHANGED;
+ m.universe = universe;
+ m.threads = threads;
+ m.args[0] = updateTargets;
+ m.args[2] = updateList;
+ UnorderList blnList =
+ updateTargets.targetList[Targets.BLN_TARGETS];
+
+ if (blnList != null) {
+ BoundingLeafRetained mbleaf;
+ size = blnList.size();
+
+ Object[] boundingLeafUsersArr = new Object[size];
+ nodesArr = blnList.toArray(false);
+ for (j=0; j<size; j++) {
+ nodes = (Object[])nodesArr[j];
+ Object[] boundingLeafUsers = new Object[nodes.length];
+ boundingLeafUsersArr[j] = boundingLeafUsers;
+ for (i=0; i<nodes.length; i++) {
+ mbleaf = (BoundingLeafRetained) nodes[i];
+ boundingLeafUsers[i] = mbleaf.users.toArray();
+ }
+ }
+ m.args[1] = boundingLeafUsersArr;
+ }
+ VirtualUniverse.mc.processMessage(m);
+ }
+
+ UnorderList vpList = updateTargets.targetList[Targets.VPF_TARGETS];
+ if (vpList != null) {
+ ViewPlatformRetained vp;
+ size = vpList.size();
+
+ nodesArr = vpList.toArray(false);
+ for (j=0; j<size; j++) {
+ nodes = (Object[])nodesArr[j];
+ for (i=0; i<nodes.length; i++) {
+ vp = (ViewPlatformRetained)nodes[i];
+ vp.processSwitchChanged();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the current childMask.
+ * @return the current childMask
+ */
+ final BitSet getChildMask() {
+ return (BitSet)this.childMask.clone();
+ }
+
+ /**
+ * Returns the current child.
+ * @return the current child
+ */
+ Node currentChild() {
+ if ((whichChild < 0) || (whichChild >= children.size()))
+ return null;
+ else
+ return getChild(whichChild);
+ }
+
+void updateSwitchChild(int child, boolean switchOn, ArrayList<SwitchState> updateList) {
+ int i;
+ int switchLevel;
+
+ if (inSharedGroup) {
+ for (i=0; i<localToVworldKeys.length; i++) {
+ switchLevel = switchLevels.get(i).intValue();
+ traverseSwitchChild(child, localToVworldKeys[i], i, this,
+ false, false, switchOn, switchLevel, updateList);
+ }
+ } else {
+ switchLevel = switchLevels.get(0).intValue();
+ traverseSwitchChild(child, null, 0, this, false, false,
+ switchOn, switchLevel, updateList);
+ }
+ }
+
+ // Switch specific data at SetLive.
+ @Override
+ void setAuxData(SetLiveState s, int index, int hkIndex) {
+ int size;
+ ArrayList<SwitchState> switchStates;
+
+ // Group's setAuxData()
+ super.setAuxData(s, index, hkIndex);
+ switchLevels.add(new Integer(s.switchLevels[index]));
+ int nchildren = children.size();
+ for (int i=0; i<nchildren; i++) {
+ switchStates = childrenSwitchStates.get(i);
+ switchStates.add(hkIndex, new SwitchState(true));
+ }
+ }
+
+ @Override
+ void setNodeData(SetLiveState s) {
+ super.setNodeData(s);
+ // add this node to parent's childSwitchLink
+ if (s.childSwitchLinks != null) {
+ if(!inSharedGroup ||
+ // only add if not already added in sharedGroup
+ !s.childSwitchLinks.contains(this)) {
+ s.childSwitchLinks.add(this);
+ }
+ }
+ // Note that s.childSwitchLinks is updated in super.setLive
+ s.parentSwitchLink = this;
+
+ if (!inSharedGroup) {
+ setAuxData(s, 0, 0);
+ } else {
+ // For inSharedGroup case.
+ int j, hkIndex;
+
+ s.hashkeyIndex = new int[s.keys.length];
+ for(j=0; j<s.keys.length; j++) {
+ hkIndex = s.keys[j].equals(localToVworldKeys, 0,
+ localToVworldKeys.length);
+ if(hkIndex >= 0) {
+ setAuxData(s, j, hkIndex);
+ } else {
+ MasterControl.getCoreLogger().severe("Can't Find matching hashKey in setNodeData.");
+ }
+ s.hashkeyIndex[j] = hkIndex;
+ }
+ }
+ }
+
+ @Override
+ void setLive(SetLiveState s) {
+ int i,j,k;
+ boolean switchOn;
+ SwitchRetained switchRoot;
+ int size;
+
+ // save setLiveState
+ Targets[] savedSwitchTargets = s.switchTargets;
+ ArrayList<SwitchState> savedSwitchStates = s.switchStates;
+ SwitchRetained[] savedClosestSwitchParents = s.closestSwitchParents;
+ int[] savedClosestSwitchIndices = s.closestSwitchIndices;
+ ArrayList<NodeRetained> savedChildSwitchLinks = s.childSwitchLinks;
+ GroupRetained savedParentSwitchLink = s.parentSwitchLink;
+ int[] savedHashkeyIndex = s.hashkeyIndex;
+
+ // update setLiveState for this node
+ s.closestSwitchParents = (SwitchRetained[])
+ savedClosestSwitchParents.clone();
+ s.closestSwitchIndices = Arrays.copyOf(savedClosestSwitchIndices, savedClosestSwitchIndices.length);
+
+ // Note that s.containsNodesList is updated in super.setLive
+ // Note that s.closestSwitchIndices is updated in super.setLive
+ for (i=0; i< s.switchLevels.length; i++) {
+ s.switchLevels[i]++;
+ s.closestSwitchParents[i] = this;
+ }
+
+ super.doSetLive(s);
+
+ initRenderChildMask();
+
+ // update switch leaves' compositeSwitchMask
+ // and update switch leaves' switchOn flag if this is top level switch
+ if (inSharedGroup) {
+ for (i=0; i<s.keys.length; i++) {
+ j = s.hashkeyIndex[i];
+ // j is index in ContainNodes
+ if (j < localToVworldKeys.length) {
+ switchRoot = (s.switchLevels[i] == 0)? this : null;
+ size = children.size();
+ for (k=0; k<size; k++) {
+ switchOn = renderChildMask.get(k);
+ traverseSwitchChild(k, s.keys[i], j, switchRoot, true, false,
+ switchOn, s.switchLevels[i], null);
+ }
+ }
+ }
+ } else {
+ switchRoot = (s.switchLevels[0] == 0)? this : null;
+ size = children.size();
+ for (i=0; i<size; i++) {
+ switchOn = renderChildMask.get(i);
+ traverseSwitchChild(i, null, 0, switchRoot, true, false,
+ switchOn, s.switchLevels[0], null);
+ }
+ }
+
+ // restore setLiveState
+ s.switchTargets = savedSwitchTargets;
+ s.switchStates = savedSwitchStates;
+ s.closestSwitchParents = savedClosestSwitchParents;
+ s.closestSwitchIndices = savedClosestSwitchIndices;
+ for (i=0; i< s.switchLevels.length; i++) {
+ s.switchLevels[i]--;
+ }
+ s.childSwitchLinks = savedChildSwitchLinks;
+ s.parentSwitchLink = savedParentSwitchLink;
+ s.hashkeyIndex = savedHashkeyIndex;
+ super.markAsLive();
+ }
+
+
+ @Override
+ void removeNodeData(SetLiveState s) {
+
+ int numChildren = children.size();
+ int i, j;
+ ArrayList<SwitchState> switchStates;
+
+ if (refCount <= 0) {
+ // remove this node from parentSwitchLink's childSwitchLinks
+ // clear childSwitchLinks
+ if (parentSwitchLink != null) {
+ for(i=0; i<parentSwitchLink.childrenSwitchLinks.size();i++) {
+ ArrayList<NodeRetained> switchLinks = parentSwitchLink.childrenSwitchLinks.get(i);
+ if (switchLinks.contains(this)) {
+ switchLinks.remove(this);
+ break;
+ }
+ }
+ }
+ for (j=0; j<numChildren; j++) {
+ switchStates = childrenSwitchStates.get(j);
+ switchStates.clear();
+ }
+ switchLevels.remove(0);
+ } else {
+ // remove children dependent data
+ int hkIndex;
+
+ // Must be in reverse, to preserve right indexing.
+ for (i = s.keys.length-1; i >= 0; i--) {
+ hkIndex = s.keys[i].equals(localToVworldKeys, 0,
+ localToVworldKeys.length);
+ if(hkIndex >= 0) {
+ for (j=0; j<numChildren; j++) {
+ switchStates = childrenSwitchStates.get(j);
+ switchStates.remove(hkIndex);
+ }
+ switchLevels.remove(hkIndex);
+ }
+ }
+ }
+
+ super.removeNodeData(s);
+ }
+
+
+
+ // synchronized with setWhichChild and setChildMask
+ @Override
+ synchronized void clearLive(SetLiveState s) {
+ Targets[] savedSwitchTargets = s.switchTargets;
+ s.switchTargets = null;
+ super.clearLive(s);
+ s.switchTargets = savedSwitchTargets;
+ }
+
+ void initRenderChildMask() {
+ int i, nchildren;
+ nchildren = children.size();
+ switch(whichChild) {
+ case Switch.CHILD_ALL:
+ for (i=0; i<nchildren; i++) {
+ renderChildMask.set(i);
+ }
+ break;
+ case Switch.CHILD_NONE:
+ for (i=0; i<nchildren; i++) {
+ renderChildMask.clear(i);
+ }
+ break;
+ case Switch.CHILD_MASK:
+ for (i=0; i<nchildren; i++) {
+ if (childMask.get(i) == true) {
+ renderChildMask.set(i);
+ } else {
+ renderChildMask.clear(i);
+ }
+ }
+ break;
+ default:
+ for (i=0; i<nchildren; i++) {
+
+ if (i == whichChild) {
+ renderChildMask.set(i);
+ } else {
+ renderChildMask.clear(i);
+ }
+ }
+ }
+ }
+
+ void traverseSwitchChild(int child, HashKey key, int index,
+ SwitchRetained switchRoot, boolean init,
+ boolean swChanged, boolean switchOn,
+ int switchLevel, ArrayList<SwitchState> updateList) {
+ int i,j,k;
+ SwitchRetained sw;
+ LinkRetained ln;
+ Object obj;
+
+ boolean newSwChanged = false;
+ ArrayList<SwitchState> childSwitchStates = childrenSwitchStates.get(child);
+ SwitchState switchState = childSwitchStates.get(index);
+ switchState.updateCompositeSwitchMask(switchLevel, switchOn);
+
+ if (switchRoot != null) {
+ if (init) {
+ if (!switchState.initialized) {
+ switchState.initSwitchOn();
+ }
+ } else {
+ boolean compositeSwitchOn = switchState.evalCompositeSwitchOn();
+ if (switchState.cachedSwitchOn != compositeSwitchOn) {
+ switchState.updateCachedSwitchOn();
+
+ switchRoot.updateTargets.addCachedTargets(
+ switchState.cachedTargets);
+ newSwChanged = true;
+ updateList.add(switchState);
+ }
+ }
+ }
+
+
+ ArrayList<NodeRetained> childSwitchLinks = childrenSwitchLinks.get(child);
+ int cslSize =childSwitchLinks.size();
+ for (i=0; i<cslSize; i++) {
+
+ obj = childSwitchLinks.get(i);
+ if (obj instanceof SwitchRetained) {
+ sw = (SwitchRetained)obj;
+ int swSize = sw.children.size();
+ for(j=0; j<swSize; j++) {
+ sw.traverseSwitchChild(j, key, index, switchRoot, init,
+ newSwChanged, switchOn, switchLevel,
+ updateList);
+ }
+ } else { // LinkRetained
+ ln = (LinkRetained)obj;
+ if (key == null) {
+ switchKey.reset();
+ switchKey.append(locale.nodeId);
+ } else {
+ switchKey.set(key);
+ }
+ switchKey.append(LinkRetained.plus).append(ln.nodeId);
+
+ if ((ln.sharedGroup != null) &&
+ (ln.sharedGroup.localToVworldKeys != null)) {
+
+ j = switchKey.equals(ln.sharedGroup.localToVworldKeys,0,
+ ln.sharedGroup.localToVworldKeys.length);
+ if(j < 0) {
+ System.err.println("SwitchRetained : Can't find hashKey");
+ }
+
+ if (j<ln.sharedGroup.localToVworldKeys.length) {
+ int lscSize = ln.sharedGroup.children.size();
+ for(k=0; k<lscSize; k++) {
+ ln.sharedGroup.traverseSwitchChild(k, ln.sharedGroup.
+ localToVworldKeys[j],
+ j, switchRoot,
+ init, newSwChanged,
+ switchOn, switchLevel, updateList);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void traverseSwitchParent() {
+ boolean switchOn;
+ int switchLevel;
+ SwitchRetained switchRoot;
+ int i,j;
+ int size;
+
+ // first traverse this node's child
+ if (inSharedGroup) {
+ for (j=0; j<localToVworldKeys.length; j++) {
+ switchLevel = switchLevels.get(j).intValue();
+ switchRoot = (switchLevel == 0)? this : null;
+ size = children.size();
+ for (i=0; i<size; i++) {
+ switchOn = renderChildMask.get(i);
+ traverseSwitchChild(i, localToVworldKeys[j], j, switchRoot,
+ true, false, switchOn, switchLevel, null);
+ }
+ }
+ } else {
+ switchLevel = switchLevels.get(0).intValue();
+ switchRoot = (switchLevel == 0)? this : null;
+ size = children.size();
+ for (i=0; i<size; i++) {
+ switchOn = renderChildMask.get(i);
+ traverseSwitchChild(i, null, 0, switchRoot,
+ true, false, switchOn, switchLevel, null);
+ }
+ }
+
+ // now traverse this node's parent
+ if (parentSwitchLink != null) {
+ if (parentSwitchLink instanceof SwitchRetained) {
+ ((SwitchRetained)parentSwitchLink).traverseSwitchParent();
+ } else if (parentSwitchLink instanceof SharedGroupRetained) {
+ ((SharedGroupRetained)parentSwitchLink).traverseSwitchParent();
+ }
+ }
+ }
+
+
+ @Override
+ void computeCombineBounds(Bounds bounds) {
+ if (boundsAutoCompute) {
+ if (!VirtualUniverse.mc.cacheAutoComputedBounds) {
+ if (whichChild == Switch.CHILD_ALL) {
+ for (int i = 0; i < children.size(); i++) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(bounds);
+ }
+ }
+ } else if (whichChild == Switch.CHILD_MASK) {
+ for (int i = 0; i < children.size(); i++) {
+ if (childMask.get(i)) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(bounds);
+ }
+ }
+ }
+ } else if (whichChild != Switch.CHILD_NONE) {
+ if (whichChild < children.size()) {
+ NodeRetained child = children.get(whichChild);
+ if (child != null) {
+ child.computeCombineBounds(bounds);
+ }
+ }
+ }
+ } else {
+ // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
+ if (!validCachedBounds) {
+ validCachedBounds = true;
+
+ // Issue 544
+ if (VirtualUniverse.mc.useBoxForGroupBounds) {
+ cachedBounds = new BoundingBox((Bounds) null);
+ } else {
+ cachedBounds = new BoundingSphere((Bounds)null);
+ }
+ if (whichChild == Switch.CHILD_ALL) {
+ for (int i = 0; i < children.size(); i++) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(cachedBounds);
+ }
+ }
+ } else if (whichChild == Switch.CHILD_MASK) {
+ for (int i = 0; i < children.size(); i++) {
+ if (childMask.get(i)) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(cachedBounds);
+ }
+ }
+ }
+ } else if (whichChild != Switch.CHILD_NONE) {
+ if (whichChild < children.size()) {
+ NodeRetained child = children.get(whichChild);
+ if (child != null) {
+ child.computeCombineBounds(cachedBounds);
+ }
+ }
+ }
+ }
+ bounds.combine(cachedBounds);
+ }
+ } else {
+ // Should this be lock too ? ( MT safe ? )
+ synchronized (localBounds) {
+ bounds.combine(localBounds);
+ }
+ }
+ }
+
+
+ /**
+ * Gets the bounding object of a node.
+ * @return the node's bounding object
+ */
+ @Override
+ Bounds getBounds() {
+ if (boundsAutoCompute) {
+ // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
+ if (validCachedBounds) {
+ return (Bounds) cachedBounds.clone();
+ }
+
+ // issue 544
+ Bounds boundingObject = null;
+ if (VirtualUniverse.mc.useBoxForGroupBounds) {
+ boundingObject = new BoundingBox((Bounds) null);
+ } else {
+ boundingObject = new BoundingSphere((Bounds)null);
+ }
+
+ if (whichChild == Switch.CHILD_ALL) {
+ for (int i = 0; i < children.size(); i++) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(boundingObject);
+ }
+ }
+ } else if (whichChild == Switch.CHILD_MASK) {
+ for (int i = 0; i < children.size(); i++) {
+ if (childMask.get(i)) {
+ NodeRetained child = children.get(i);
+ if (child != null) {
+ child.computeCombineBounds(boundingObject);
+ }
+ }
+ }
+ } else if (whichChild != Switch.CHILD_NONE &&
+ whichChild >= 0 &&
+ whichChild < children.size()) {
+
+ NodeRetained child = children.get(whichChild);
+ if (child != null) {
+ child.computeCombineBounds(boundingObject);
+ }
+ }
+
+ return boundingObject;
+ } else {
+ return super.getBounds();
+ }
+ }
+
+
+ /*
+ void compile(CompileState compState) {
+ setCompiled();
+ compState.startGroup(null); // don't merge at this level
+ compileChildren(compState);
+ compState.endGroup();
+ }
+ */
+
+ /**
+ * Compiles the children of the switch, preventing shape merging at
+ * this level or above
+ */
+ @Override
+ void compile(CompileState compState) {
+
+
+ super.compile(compState);
+
+ // don't remove this group node
+ mergeFlag = SceneGraphObjectRetained.DONT_MERGE;
+
+ if (J3dDebug.devPhase && J3dDebug.debug) {
+ compState.numSwitches++;
+ }
+ }
+
+ @Override
+ void insertChildrenData(int index) {
+ if (childrenSwitchStates == null) {
+ childrenSwitchStates = new ArrayList<ArrayList<SwitchState>>(1);
+ childrenSwitchLinks = new ArrayList<ArrayList<NodeRetained>>(1);
+ }
+
+ childrenSwitchLinks.add(index, new ArrayList<NodeRetained>(1));
+
+ ArrayList<SwitchState> switchStates = new ArrayList<SwitchState>(1);
+ childrenSwitchStates.add(index, switchStates);
+ if (source != null && source.isLive()) {
+ for (int i=0; i<localToVworld.length; i++) {
+ switchStates.add(new SwitchState(true));
+ }
+ }
+ }
+
+ @Override
+ void appendChildrenData() {
+ if (childrenSwitchStates == null) {
+ childrenSwitchStates = new ArrayList<ArrayList<SwitchState>>(1);
+ childrenSwitchLinks = new ArrayList<ArrayList<NodeRetained>>(1);
+ }
+ childrenSwitchLinks.add(new ArrayList<NodeRetained>(1));
+
+ ArrayList<SwitchState> switchStates = new ArrayList<SwitchState>(1);
+ childrenSwitchStates.add(switchStates);
+ if (source != null && source.isLive()) {
+ for (int i=0; i<localToVworld.length; i++) {
+ switchStates.add(new SwitchState(true));
+ }
+ }
+ }
+
+ @Override
+ void removeChildrenData(int index) {
+ ArrayList<SwitchState> oldSwitchStates = childrenSwitchStates.get(index);
+ oldSwitchStates.clear();
+ childrenSwitchStates.remove(index);
+
+ ArrayList<NodeRetained> oldSwitchLinks = childrenSwitchLinks.get(index);
+ oldSwitchLinks.clear();
+ childrenSwitchLinks.remove(index);
+ }
+
+ @Override
+ void childDoSetLive(NodeRetained child, int childIndex, SetLiveState s) {
+
+ int numPaths = (inSharedGroup)? s.keys.length : 1;
+ s.childSwitchLinks = childrenSwitchLinks.get(childIndex);
+ for (int j=0; j< numPaths; j++) {
+ s.closestSwitchIndices[j] = switchIndexCount;
+ s.closestSwitchParents[j] = this;
+ }
+ // use switchIndexCount instead of child index to avoid
+ // reordering due to add/remove child later
+ switchIndexCount++;
+
+ Targets[] newTargets = new Targets[numPaths];
+ for(int i=0; i<numPaths; i++) {
+ newTargets[i] = new Targets();
+ }
+ s.switchTargets = newTargets;
+ s.switchStates = childrenSwitchStates.get(childIndex);
+
+ if(child!=null)
+ child.setLive(s);
+
+ CachedTargets cachedTargets;
+ SwitchState switchState;
+ if (! inSharedGroup) {
+ cachedTargets = s.switchTargets[0].snapShotInit();
+ switchState = s.switchStates.get(0);
+ switchState.cachedTargets = cachedTargets;
+ } else {
+ for(int i=0; i<numPaths; i++) {
+ cachedTargets = s.switchTargets[i].snapShotInit();
+ switchState = s.switchStates.get(s.hashkeyIndex[i]);
+ switchState.cachedTargets = cachedTargets;
+ }
+ }
+ }
+
+ // ***************************
+ // TargetsInterface methods
+ // ***************************
+
+ @Override
+ TargetsInterface getClosestTargetsInterface(int type) {
+ return (type == TargetsInterface.SWITCH_TARGETS)?
+ (TargetsInterface)this:
+ (TargetsInterface)parentTransformLink;
+ }
+
+ @Override
+ public CachedTargets getCachedTargets(int type, int index, int child) {
+ if (type == TargetsInterface.SWITCH_TARGETS) {
+ ArrayList<SwitchState> switchStates = childrenSwitchStates.get(child);
+ if (index < switchStates.size()) {
+ SwitchState switchState = switchStates.get(index);
+ return switchState.cachedTargets;
+ } else {
+ return null;
+ }
+ } else {
+ System.err.println("getCachedTargets: wrong arguments");
+ return null;
+ }
+ }
+
+ @Override
+ public void resetCachedTargets(int type,
+ CachedTargets[] newCtArr, int child) {
+ if (type == TargetsInterface.SWITCH_TARGETS) {
+ ArrayList<SwitchState> switchStates = childrenSwitchStates.get(child);
+ if (newCtArr.length != switchStates.size()) {
+ System.err.println("resetCachedTargets: unmatched length!" +
+ newCtArr.length + " " + switchStates.size());
+ System.err.println(" resetCachedTargets: " + this);
+ }
+ SwitchState switchState;
+ for (int i=0; i<newCtArr.length; i++) {
+ switchState = switchStates.get(i);
+ switchState.cachedTargets = newCtArr[i];
+ }
+ } else {
+ System.err.println("resetCachedTargets: wrong arguments");
+ }
+ }
+
+@Override
+public ArrayList<SwitchState> getTargetsData(int type, int child) {
+ if (type == TargetsInterface.SWITCH_TARGETS) {
+ return childrenSwitchStates.get(child);
+ }
+ else {
+ System.err.println("getTargetsData: wrong arguments");
+ return null;
+ }
+}
+
+ @Override
+ public int getTargetThreads(int type) {
+ System.err.println("getTargetsThreads: wrong arguments");
+ return -1;
+ }
+
+ @Override
+ public void updateCachedTargets(int type, CachedTargets[] newCt) {
+ System.err.println("updateCachedTarget: wrong arguments");
+ }
+
+ @Override
+ public void computeTargetThreads(int type, CachedTargets[] newCt) {
+ System.err.println("computeTargetThreads: wrong arguments");
+ }
+
+ @Override
+ public void updateTargetThreads(int type, CachedTargets[] newCt) {
+ System.err.println("updateTargetThreads: wrong arguments");
+ }
+
+ @Override
+ public void propagateTargetThreads(int type, int newTargetThreads) {
+ System.err.println("propagateTargetThreads: wrong arguments");
+ }
+
+ @Override
+ public void copyCachedTargets(int type, CachedTargets[] newCt) {
+ System.err.println("copyCachedTarget: wrong arguments");
+ }
+}