diff options
author | paulby <[email protected]> | 2007-04-20 00:54:41 +0000 |
---|---|---|
committer | paulby <[email protected]> | 2007-04-20 00:54:41 +0000 |
commit | e5728c258119acd9f42c2168b67561fb48602f56 (patch) | |
tree | 0465faab64b7d1bdbc393da96726c0bdacacb84e /src/classes | |
parent | 993cbb3af21cd9d67d5a23eef0f1f08f95c7f682 (diff) |
Issue 480. Cache getBounds() results
Issue number:
Obtained from:
Submitted by:
Reviewed by:
git-svn-id: https://svn.java.net/svn/j3d-core~svn/trunk@825 ba19aa83-45c5-6ac9-afd3-db810772062c
Diffstat (limited to 'src/classes')
10 files changed, 251 insertions, 88 deletions
diff --git a/src/classes/share/javax/media/j3d/BranchGroupRetained.java b/src/classes/share/javax/media/j3d/BranchGroupRetained.java index 568f04b..7607f5b 100644 --- a/src/classes/share/javax/media/j3d/BranchGroupRetained.java +++ b/src/classes/share/javax/media/j3d/BranchGroupRetained.java @@ -55,6 +55,7 @@ class BranchGroupRetained extends GroupRetained { * Detaches this BranchGroup from its parent. */ void detach() { + dirtyBoundsCache(); if (universe != null) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { diff --git a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java index 005f654..ad543cd 100644 --- a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java @@ -414,6 +414,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // System.err.println("computeBoundingBox ...."); + if (boundsDirty && VirtualUniverse.mc.cacheAutoComputedBounds) { + for(ArrayList<Shape3DRetained> users : userLists) { + for(Shape3DRetained shape : users) + shape.dirtyBoundsCache(); + } + } + if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { // by copy computeBoundingBox(initialVertexIndex, vertexData); @@ -444,6 +451,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ //System.err.println("vertexType & PD"); computeBoundingBox(doubleRefCoords); } + } diff --git a/src/classes/share/javax/media/j3d/GeometryRetained.java b/src/classes/share/javax/media/j3d/GeometryRetained.java index 4fc68ee..a57cb22 100644 --- a/src/classes/share/javax/media/j3d/GeometryRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryRetained.java @@ -81,7 +81,7 @@ abstract class GeometryRetained extends NodeComponentRetained { // A list of ArrayLists which contain all the Shape3DRetained objects // refering to this geometry. Each list corresponds to the universe // above. - ArrayList userLists = new ArrayList(); + ArrayList<ArrayList<Shape3DRetained>> userLists = new ArrayList(); // true if color not specified with alpha channel boolean noAlpha = false; diff --git a/src/classes/share/javax/media/j3d/GroupRetained.java b/src/classes/share/javax/media/j3d/GroupRetained.java index 3e99f79..4caf826 100644 --- a/src/classes/share/javax/media/j3d/GroupRetained.java +++ b/src/classes/share/javax/media/j3d/GroupRetained.java @@ -199,6 +199,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } } + dirtyBoundsCache(); } // The method that does the work once the lock is acquired. @@ -295,6 +296,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } } + dirtyBoundsCache(); } // The method that does the work once the lock is acquired. @@ -345,6 +347,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } } + dirtyBoundsCache(); } /** @@ -476,6 +479,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } } + dirtyBoundsCache(); } // The method that does the work once the lock is acquired. @@ -499,6 +503,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } void moveTo(BranchGroup bg) { + ((GroupRetained)bg.retained).dirtyBoundsCache(); if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { @@ -519,6 +524,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } } + dirtyBoundsCache(); } // The method that does the work once the lock is acquired. @@ -2218,7 +2224,6 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { s.fogs = savedScopedFogs; s.altAppearances = savedScopedAltApps; s.modelClips = savedScopedMclips; - } void setScopingInfo(SetLiveState s) { @@ -2419,19 +2424,42 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } void computeCombineBounds(Bounds bounds) { - - if (boundsAutoCompute) { - for (int i=children.size()-1; i>=0; i--) { - NodeRetained child = (NodeRetained)children.get(i); - if(child != null) - child.computeCombineBounds(bounds); - } - } else { - // Should this be lock too ? ( MT safe ? ) - synchronized(localBounds) { - bounds.combine(localBounds); - } - } + if (!VirtualUniverse.mc.cacheAutoComputedBounds) { + if (boundsAutoCompute) { + for (int i=children.size()-1; i>=0; i--) { + NodeRetained child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(bounds); + } + } else { + // Should this be lock too ? ( MT safe ? ) + synchronized(localBounds) { + bounds.combine(localBounds); + } + } + } else { + if (cachedBounds!=null && boundsAutoCompute) { + bounds.combine(cachedBounds); + return; + } + + if (boundsAutoCompute) { + cachedBounds = new BoundingSphere(); + ((BoundingSphere)cachedBounds).setRadius(-1); + for (int i=children.size()-1; i>=0; i--) { + NodeRetained child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(cachedBounds); + } + bounds.combine(cachedBounds); + } else { + // Should this be lock too ? ( MT safe ? ) + synchronized(localBounds) { + bounds.combine(localBounds); + } + } + } + } @@ -2442,6 +2470,10 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { Bounds getBounds() { if ( boundsAutoCompute) { + if (cachedBounds!=null) { + return (Bounds) cachedBounds.clone(); + } + BoundingSphere boundingSphere = new BoundingSphere(); boundingSphere.setRadius(-1.0); diff --git a/src/classes/share/javax/media/j3d/MasterControl.java b/src/classes/share/javax/media/j3d/MasterControl.java index c0b1ae6..c503697 100644 --- a/src/classes/share/javax/media/j3d/MasterControl.java +++ b/src/classes/share/javax/media/j3d/MasterControl.java @@ -472,6 +472,10 @@ class MasterControl { //Set as true if you have memory leaks after disposing Canvas3D. //Default false value does affect Java3D View dispose behavior. boolean forceReleaseView = false; + + // Issue 480: Cache the bounds of nodes so that getBounds does not + // recompute the boounds of the entire graph per call + boolean cacheAutoComputedBounds = false; /** * Constructs a new MasterControl object. Note that there is @@ -661,7 +665,13 @@ class MasterControl { disableXinerama = true; } - // Initialize the native J3D library + // Issue 480 : Cache bounds returned by getBounds() + cacheAutoComputedBounds = + getBooleanProperty("j3d.cacheAutoComputeBounds", + cacheAutoComputedBounds, + "Cache AutoCompute Bounds, accelerates getBounds()"); + + // Initialize the native J3D library if (!Pipeline.getPipeline().initializeJ3D(disableXinerama)) { throw new RuntimeException(J3dI18N.getString("MasterControl0")); } diff --git a/src/classes/share/javax/media/j3d/NodeRetained.java b/src/classes/share/javax/media/j3d/NodeRetained.java index fe8f0c6..6978854 100644 --- a/src/classes/share/javax/media/j3d/NodeRetained.java +++ b/src/classes/share/javax/media/j3d/NodeRetained.java @@ -140,6 +140,8 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { // Bounds set by the API Bounds apiBounds; + protected Bounds cachedBounds=null; // Cached auto compute bounds, could we use localBounds ? + /** * Each element, p, of branchGroupPaths is a list of BranchGroup from * root of the tree to this. @@ -275,7 +277,12 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { * of bounds */ void setBoundsAutoCompute(boolean autoCompute) { + if (this.boundsAutoCompute==autoCompute) { + return; + } + this.boundsAutoCompute = autoCompute; + dirtyBoundsCache(); } /** @@ -941,5 +948,20 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { } void searchGeometryAtoms(UnorderList list) {} + + /** + * Make the boundsCache of this node and all its parents dirty + */ + void dirtyBoundsCache() { + // Possible optimisation is to not traverse up the tree + // if the cachedBounds==null. However this is not the case + // if the node is the child of a SharedGroup + if (VirtualUniverse.mc.cacheAutoComputedBounds) { + cachedBounds = null; + if (parent!=null) { + parent.dirtyBoundsCache(); + } + } + } } diff --git a/src/classes/share/javax/media/j3d/Shape3DRetained.java b/src/classes/share/javax/media/j3d/Shape3DRetained.java index 2b82163..b4ec88c 100644 --- a/src/classes/share/javax/media/j3d/Shape3DRetained.java +++ b/src/classes/share/javax/media/j3d/Shape3DRetained.java @@ -286,7 +286,7 @@ class Shape3DRetained extends LeafRetained { geometryList.add(null); } } - + dirtyBoundsCache(); } /** @@ -350,6 +350,7 @@ class Shape3DRetained extends LeafRetained { geometryList.set(index,null); } } + dirtyBoundsCache(); } /** @@ -396,7 +397,8 @@ class Shape3DRetained extends LeafRetained { } else { geometryList.add(index,null); } - } + } + dirtyBoundsCache(); } /** @@ -435,7 +437,7 @@ class Shape3DRetained extends LeafRetained { geometryList.remove(index); } - + dirtyBoundsCache(); } @@ -838,7 +840,9 @@ class Shape3DRetained extends LeafRetained { if(boundsAutoCompute) { // System.err.println("getBounds ---- localBounds is " + localBounds); - + if (cachedBounds!=null) { + return (Bounds) cachedBounds.clone(); + } if(geometryList != null) { BoundingBox bbox = new BoundingBox((Bounds) null); @@ -880,43 +884,66 @@ class Shape3DRetained extends LeafRetained { */ void computeCombineBounds(Bounds bounds) { - if(boundsAutoCompute) { - - if(geometryList != null) { - GeometryRetained geometry; - BoundingBox bbox = null; - - if (staticTransform != null) { - bbox = new BoundingBox((BoundingBox) null); - } - - for(int i=0; i<geometryList.size(); i++) { - geometry = (GeometryRetained) geometryList.get(i); - if ((geometry != null) && - (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) { - geometry.computeBoundingBox(); - // Should this be lock too ? ( MT safe ? ) - synchronized(geometry.geoBounds) { - if (staticTransform != null) { - bbox.set(geometry.geoBounds); - bbox.transform(staticTransform.transform); - bounds.combine((Bounds)bbox); - } else { - bounds.combine((Bounds)geometry.geoBounds); - } - } - } - } - } - - } else { - - // Should this be lock too ? ( MT safe ? ) - synchronized(localBounds) { - bounds.combine((Bounds) localBounds); - } - } - } + if(boundsAutoCompute) { + if(geometryList != null) { + GeometryRetained geometry; + BoundingBox bbox = null; + + if (staticTransform != null) { + bbox = new BoundingBox((BoundingBox) null); + } + + if (!VirtualUniverse.mc.cacheAutoComputedBounds) { + for(int i=0; i<geometryList.size(); i++) { + geometry = (GeometryRetained) geometryList.get(i); + if ((geometry != null) && + (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) { + geometry.computeBoundingBox(); + // Should this be lock too ? ( MT safe ? ) + synchronized(geometry.geoBounds) { + if (staticTransform != null) { + bbox.set(geometry.geoBounds); + bbox.transform(staticTransform.transform); + bounds.combine((Bounds)bbox); + } else { + bounds.combine((Bounds)geometry.geoBounds); + } + } + } + } + } else { + if (cachedBounds==null) { + cachedBounds = new BoundingBox((BoundingBox) null); + + for(int i=0; i<geometryList.size(); i++) { + geometry = (GeometryRetained) geometryList.get(i); + if ((geometry != null) && + (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) { + geometry.computeBoundingBox(); + // Should this be lock too ? ( MT safe ? ) + synchronized(geometry.geoBounds) { + if (staticTransform != null) { + bbox.set(geometry.geoBounds); + bbox.transform(staticTransform.transform); + cachedBounds.combine((Bounds)bbox); + } else { + cachedBounds.combine((Bounds)geometry.geoBounds); + } + } + } + } + } + bounds.combine(cachedBounds); + } + } + } else { + + // Should this be lock too ? ( MT safe ? ) + synchronized(localBounds) { + bounds.combine((Bounds) localBounds); + } + } + } /** * assign a name to this node when it is made live. @@ -2700,6 +2727,7 @@ class Shape3DRetained extends LeafRetained { geometryList.remove(index); } } + dirtyBoundsCache(); } boolean willRemainOpaque(int geoType) { diff --git a/src/classes/share/javax/media/j3d/SharedGroupRetained.java b/src/classes/share/javax/media/j3d/SharedGroupRetained.java index ac4036c..7c0be0a 100644 --- a/src/classes/share/javax/media/j3d/SharedGroupRetained.java +++ b/src/classes/share/javax/media/j3d/SharedGroupRetained.java @@ -873,4 +873,25 @@ class SharedGroupRetained extends GroupRetained implements TargetsInterface { s.parentTransformLink = this; child.setLive(s); } + + /** + * Make the boundsCache of this node and all its parents dirty + */ + void dirtyBoundsCache() { + // Possible optimisation is to not traverse up the tree + // if the cachedBounds==null. However this is not the case + // if the node is the child of a SharedGroup + if (VirtualUniverse.mc.cacheAutoComputedBounds) { + cachedBounds = null; + synchronized(parents) { + Enumeration e = parents.elements(); + while(e.hasMoreElements()) { + LinkRetained parent = (LinkRetained) e.nextElement(); + if (parent!=null) { + parent.dirtyBoundsCache(); + } + } + } + } + } } diff --git a/src/classes/share/javax/media/j3d/SwitchRetained.java b/src/classes/share/javax/media/j3d/SwitchRetained.java index 4f99c26..3156d58 100644 --- a/src/classes/share/javax/media/j3d/SwitchRetained.java +++ b/src/classes/share/javax/media/j3d/SwitchRetained.java @@ -130,6 +130,7 @@ class SwitchRetained extends GroupRetained implements TargetsInterface } sendMessage(updateList); } + dirtyBoundsCache(); } /** @@ -182,6 +183,7 @@ class SwitchRetained extends GroupRetained implements TargetsInterface } sendMessage(updateList); } + dirtyBoundsCache(); } void sendMessage(ArrayList updateList) { @@ -614,37 +616,62 @@ class SwitchRetained extends GroupRetained implements TargetsInterface NodeRetained child; if(boundsAutoCompute) { - - if(whichChild == Switch.CHILD_ALL) { - for(i=0; i<children.size(); i++) { - child = (NodeRetained)children.get(i); - if(child != null) - child.computeCombineBounds(bounds); - } - } - else if(whichChild == Switch.CHILD_MASK) { - for(i=0; i<children.size(); i++) { - if(childMask.get(i)) { - child = (NodeRetained)children.get(i); - if(child != null) - child.computeCombineBounds(bounds); - } - } - } - else if(whichChild != Switch.CHILD_NONE) { - if (whichChild < children.size()) { - child = (NodeRetained)children.get(whichChild); - if(child != null) - child.computeCombineBounds(bounds); - } - } - + if (!VirtualUniverse.mc.cacheAutoComputedBounds) { + if(whichChild == Switch.CHILD_ALL) { + for(i=0; i<children.size(); i++) { + child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(bounds); + } + } else if(whichChild == Switch.CHILD_MASK) { + for(i=0; i<children.size(); i++) { + if(childMask.get(i)) { + child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(bounds); + } + } + } else if(whichChild != Switch.CHILD_NONE) { + if (whichChild < children.size()) { + child = (NodeRetained)children.get(whichChild); + if(child != null) + child.computeCombineBounds(bounds); + } + } + } else { + if (cachedBounds==null) { + cachedBounds = new BoundingSphere(); + ((BoundingSphere)cachedBounds).setRadius(-1); + if(whichChild == Switch.CHILD_ALL) { + for(i=0; i<children.size(); i++) { + child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(cachedBounds); + } + } else if(whichChild == Switch.CHILD_MASK) { + for(i=0; i<children.size(); i++) { + if(childMask.get(i)) { + child = (NodeRetained)children.get(i); + if(child != null) + child.computeCombineBounds(cachedBounds); + } + } + } else if(whichChild != Switch.CHILD_NONE) { + if (whichChild < children.size()) { + child = (NodeRetained)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); + } } - else - // Should this be lock too ? ( MT safe ? ) - synchronized(localBounds) { - bounds.combine(localBounds); - } } @@ -658,6 +685,10 @@ class SwitchRetained extends GroupRetained implements TargetsInterface NodeRetained child; if(boundsAutoCompute) { + if (cachedBounds!=null) { + return (Bounds) cachedBounds.clone(); + } + BoundingSphere boundingSphere = new BoundingSphere(); boundingSphere.setRadius(-1.0); diff --git a/src/classes/share/javax/media/j3d/TransformGroupRetained.java b/src/classes/share/javax/media/j3d/TransformGroupRetained.java index f51a5fd..3ef24af 100644 --- a/src/classes/share/javax/media/j3d/TransformGroupRetained.java +++ b/src/classes/share/javax/media/j3d/TransformGroupRetained.java @@ -147,6 +147,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface //System.err.println("TransformGroupRetained --- TRANSFORM_CHANGED " + this); VirtualUniverse.mc.processMessage(tchangeMessage); } + dirtyBoundsCache(); } /** @@ -768,10 +769,16 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface void computeCombineBounds(Bounds bounds) { + + if (cachedBounds!=null && boundsAutoCompute) { + bounds.combine(cachedBounds); + return; + } + NodeRetained child; BoundingSphere boundingSphere = new BoundingSphere(); boundingSphere.setRadius(-1.0); - + if(boundsAutoCompute) { for (int i=children.size()-1; i>=0; i--) { child = (NodeRetained)children.get(i); @@ -794,6 +801,9 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface } bounds.combine(boundingSphere); + if (boundsAutoCompute && VirtualUniverse.mc.cacheAutoComputedBounds) { + cachedBounds = boundingSphere; + } } void processChildLocalToVworld(ArrayList dirtyTransformGroups, |