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.
experimental
shadowislord 10 years ago
parent e19be328a7
commit bac0f81853
  1. 13
      jme3-core/src/main/java/com/jme3/scene/Node.java
  2. 29
      jme3-core/src/main/java/com/jme3/scene/Spatial.java

@ -137,19 +137,6 @@ public class Node extends Spatial implements Savable {
child.setLightListRefresh(); 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 @Override

@ -269,6 +269,33 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
protected void setLightListRefresh() { protected void setLightListRefresh() {
refreshFlags |= RF_LIGHTLIST; 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) { if ((refreshFlags & RF_BOUND) != 0) {
updateWorldBound(); updateWorldBound();
} }
assert refreshFlags == 0; assert refreshFlags == 0;
} }

Loading…
Cancel
Save