diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java index cfc4168c..d11dd6a9 100644 --- a/src/java/com/threerings/jme/model/Model.java +++ b/src/java/com/threerings/jme/model/Model.java @@ -794,7 +794,8 @@ public class Model extends ModelNode getWorldTranslation(), getWorldScale(), worldBound); } else { - super.updateGeometricState(_accum, initiator); + super.updateGeometricState(_shouldAccumulate ? _accum : time, + initiator); _accum = 0f; } } @@ -847,7 +848,9 @@ public class Model extends ModelNode // initialize the controllers for (Object ctrl : getControllers()) { if (ctrl instanceof ModelController) { - ((ModelController)ctrl).init(this); + ModelController mctrl = (ModelController)ctrl; + mctrl.init(this); + _shouldAccumulate |= mctrl.shouldAccumulate(); } } } @@ -1004,6 +1007,9 @@ public class Model extends ModelNode /** The amount of update time accumulated while outside of view frustum. */ protected float _accum; + /** Whether or not we should accumulate update time while out of view. */ + protected boolean _shouldAccumulate; + /** The child node that contains the model's emissions in world space. */ protected Node _emissionNode; diff --git a/src/java/com/threerings/jme/model/ModelController.java b/src/java/com/threerings/jme/model/ModelController.java index f129c7f7..e3d8b18d 100644 --- a/src/java/com/threerings/jme/model/ModelController.java +++ b/src/java/com/threerings/jme/model/ModelController.java @@ -84,6 +84,16 @@ public abstract class ModelController extends Controller } } + /** + * Determines whether the controller updates should include time + * accumulated while the model was out of sight. Accumulating will + * be turned off only if all controllers are non-accumulating. + */ + public boolean shouldAccumulate () + { + return true; + } + /** * Creates or populates and returns a clone of this object using the given * clone properties. diff --git a/src/java/com/threerings/jme/model/ModelNode.java b/src/java/com/threerings/jme/model/ModelNode.java index 9af6b79e..10478582 100644 --- a/src/java/com/threerings/jme/model/ModelNode.java +++ b/src/java/com/threerings/jme/model/ModelNode.java @@ -107,9 +107,8 @@ public class ModelNode extends Node @Override // documentation inherited public void updateWorldBound () { - // if the node is culled, there are no mesh descendants and thus no - // bounds - if (cullMode != CULL_ALWAYS) { + // don't bother updating if we know there are no visible descendants + if (_hasVisibleDescendants) { super.updateWorldBound(); } } @@ -171,6 +170,7 @@ public class ModelNode extends Node ((ModelSpatial)child).putClone(null, properties)); } } + mstore._hasVisibleDescendants = _hasVisibleDescendants; return mstore; } @@ -327,16 +327,15 @@ public class ModelNode extends Node */ protected boolean cullInvisibleNodes () { - boolean hasVisibleDescendants = false; for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { Spatial child = getChild(ii); if (!(child instanceof ModelNode) || ((ModelNode)child).cullInvisibleNodes()) { - hasVisibleDescendants = true; + _hasVisibleDescendants = true; } } - setCullMode(hasVisibleDescendants ? CULL_INHERIT : CULL_ALWAYS); - return hasVisibleDescendants; + setCullMode(_hasVisibleDescendants ? CULL_INHERIT : CULL_ALWAYS); + return _hasVisibleDescendants; } /** @@ -403,5 +402,8 @@ public class ModelNode extends Node protected Matrix4f _localTransform = new Matrix4f(), _modelTransform = new Matrix4f(); + /** Whether or not this node has mesh descendants. */ + protected boolean _hasVisibleDescendants; + private static final long serialVersionUID = 1; }