From bac0f818536d9e575fc423033fa68aa9df1bf9a1 Mon Sep 17 00:00:00 2001 From: shadowislord Date: Sun, 8 Feb 2015 18:16:35 -0500 Subject: [PATCH] Fix scene graph update corruption due to earlier optimizations. The update optimization will not visit child nodes unless the parent has any refresh flags set. However if a "partial update" occurs which only clears some of the flags (e.g. getWorldBound()), then a situation could occur where a child node has refresh flags set but not its parent, thus causing the aformentioned issue. To allieviate this, we must always propagate the specific flag required, regardless of whether or not the parent has some other flags already set. --- .../src/main/java/com/jme3/scene/Node.java | 13 --------- .../src/main/java/com/jme3/scene/Spatial.java | 29 ++++++++++++++++++- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/scene/Node.java b/jme3-core/src/main/java/com/jme3/scene/Node.java index 84ef6d0a3..69c9bd018 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Node.java +++ b/jme3-core/src/main/java/com/jme3/scene/Node.java @@ -137,19 +137,6 @@ public class Node extends Spatial implements Savable { child.setLightListRefresh(); } - - // Make sure next updateGeometricState() visits this branch - // to update lights. - Spatial p = parent; - while (p != null) { - if (p.refreshFlags != 0) { - // any refresh flag is sufficient, - // as each propagates to the root Node - return; - } - p.refreshFlags |= RF_CHILD_LIGHTLIST; - p = p.parent; - } } @Override diff --git a/jme3-core/src/main/java/com/jme3/scene/Spatial.java b/jme3-core/src/main/java/com/jme3/scene/Spatial.java index 242aaf288..1fe68d730 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Spatial.java +++ b/jme3-core/src/main/java/com/jme3/scene/Spatial.java @@ -269,6 +269,33 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab protected void setLightListRefresh() { refreshFlags |= RF_LIGHTLIST; + + // Make sure next updateGeometricState() visits this branch + // to update lights. + Spatial p = parent; + while (p != null) { + //if (p.refreshFlags != 0) { + // any refresh flag is sufficient, + // as each propagates to the root Node + + // 2015/2/8: + // This is not true, because using e.g. getWorldBound() + // or getWorldTransform() activates a "partial refresh" + // which does not update the lights but does clear + // the refresh flags on the ancestors! + + // return; + //} + + if ((p.refreshFlags & RF_CHILD_LIGHTLIST) != 0) { + // The parent already has this flag, + // so must all ancestors. + return; + } + + p.refreshFlags |= RF_CHILD_LIGHTLIST; + p = p.parent; + } } /** @@ -808,7 +835,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab if ((refreshFlags & RF_BOUND) != 0) { updateWorldBound(); } - + assert refreshFlags == 0; }