Skip to content

Commit 2b35f28

Browse files
committed
MPO: implement propagation and add test
Conflicts: jme3-core/src/main/java/com/jme3/scene/Node.java jme3-core/src/main/java/com/jme3/scene/Spatial.java
1 parent 280733c commit 2b35f28

5 files changed

Lines changed: 477 additions & 63 deletions

File tree

jme3-core/src/main/java/com/jme3/material/MatParamOverride.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
import com.jme3.shader.VarType;
3535

3636
public final class MatParamOverride extends MatParam {
37-
37+
38+
public MatParamOverride() {
39+
super();
40+
}
41+
3842
public MatParamOverride(VarType type, String name, Object value) {
3943
super(type, name, value);
4044
}

jme3-core/src/main/java/com/jme3/scene/Node.java

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ public class Node extends Spatial {
7575
* requiresUpdate() method.
7676
*/
7777
private SafeArrayList<Spatial> updateList = null;
78-
7978
/**
8079
* False if the update list requires rebuilding. This is Node.class
8180
* specific and therefore not included as part of the Spatial update flags.
@@ -100,7 +99,6 @@ public Node() {
10099
*/
101100
public Node(String name) {
102101
super(name);
103-
104102
// For backwards compatibility, only clear the "requires
105103
// update" flag if we are not a subclass of Node.
106104
// This prevents subclass from silently failing to receive
@@ -141,10 +139,21 @@ protected void setLightListRefresh(){
141139
}
142140
}
143141

142+
@Override
143+
protected void setMatParamOverrideRefresh() {
144+
super.setMatParamOverrideRefresh();
145+
for (Spatial child : children.getArray()) {
146+
if ((child.refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
147+
continue;
148+
}
149+
150+
child.setMatParamOverrideRefresh();
151+
}
152+
}
153+
144154
@Override
145155
protected void updateWorldBound(){
146156
super.updateWorldBound();
147-
148157
// for a node, the world bound is a combination of all it's children
149158
// bounds
150159
BoundingVolume resultBound = null;
@@ -239,19 +248,20 @@ public void updateGeometricState(){
239248
// This branch has no geometric state that requires updates.
240249
return;
241250
}
242-
243251
if ((refreshFlags & RF_LIGHTLIST) != 0){
244252
updateWorldLightList();
245253
}
246254

255+
if ((refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
256+
updateMatParamOverrides();
257+
}
247258
if ((refreshFlags & RF_TRANSFORM) != 0){
248259
// combine with parent transforms- same for all spatial
249260
// subclasses.
250261
updateWorldTransforms();
251262
}
252263

253264
refreshFlags &= ~RF_CHILD_LIGHTLIST;
254-
255265
if (!children.isEmpty()) {
256266
// the important part- make sure child geometric state is refreshed
257267
// first before updating own world bound. This saves
@@ -287,7 +297,6 @@ public int getTriangleCount() {
287297

288298
return count;
289299
}
290-
291300
/**
292301
* <code>getVertexCount</code> returns the number of vertices contained
293302
* in all sub-branches of this node that contain geometry.
@@ -321,7 +330,6 @@ public int getVertexCount() {
321330
public int attachChild(Spatial child) {
322331
return attachChildAt(child, children.size());
323332
}
324-
325333
/**
326334
*
327335
* <code>attachChildAt</code> attaches a child to this node at an index. This node
@@ -345,20 +353,18 @@ public int attachChildAt(Spatial child, int index) {
345353
}
346354
child.setParent(this);
347355
children.add(index, child);
348-
349356
// XXX: Not entirely correct? Forces bound update up the
350357
// tree stemming from the attached child. Also forces
351358
// transform update down the tree-
352359
child.setTransformRefresh();
353360
child.setLightListRefresh();
361+
child.setMatParamOverrideRefresh();
354362
if (logger.isLoggable(Level.FINE)) {
355363
logger.log(Level.FINE,"Child ({0}) attached to this node ({1})",
356364
new Object[]{child.getName(), getName()});
357365
}
358-
359366
invalidateUpdateList();
360367
}
361-
362368
return children.size();
363369
}
364370

@@ -433,7 +439,8 @@ public Spatial detachChildAt(int index) {
433439
child.setTransformRefresh();
434440
// lights are also inherited from parent
435441
child.setLightListRefresh();
436-
442+
child.setMatParamOverrideRefresh();
443+
437444
invalidateUpdateList();
438445
}
439446
return child;
@@ -519,7 +526,6 @@ public Spatial getChild(String name) {
519526
}
520527
return null;
521528
}
522-
523529
/**
524530
* determines if the provided Spatial is contained in the children list of
525531
* this node.
@@ -567,39 +573,32 @@ public void setLodLevel(int lod){
567573

568574
public int collideWith(Collidable other, CollisionResults results){
569575
int total = 0;
570-
571576
// optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children
572577
// number 4 in condition is somewhat arbitrary. When there is only one child, the boundingVolume test is redundant at all.
573578
// The idea is when there are few children, it can be too expensive to test boundingVolume first.
574579
/*
575580
I'm removing this change until some issues can be addressed and I really
576581
think it needs to be implemented a better way anyway.
577-
578582
First, it causes issues for anyone doing collideWith() with BoundingVolumes
579583
and expecting it to trickle down to the children. For example, children
580584
with BoundingSphere bounding volumes and collideWith(BoundingSphere). Doing
581585
a collision check at the parent level then has to do a BoundingSphere to BoundingBox
582586
collision which isn't resolved. (Having to come up with a collision point in that
583587
case is tricky and the first sign that this is the wrong approach.)
584-
585588
Second, the rippling changes this caused to 'optimize' collideWith() for this
586589
special use-case are another sign that this approach was a bit dodgy. The whole
587590
idea of calculating a full collision just to see if the two shapes collide at all
588591
is very wasteful.
589-
590592
A proper implementation should support a simpler boolean check that doesn't do
591593
all of that calculation. For example, if 'other' is also a BoundingVolume (ie: 99.9%
592594
of all non-Ray cases) then a direct BV to BV intersects() test can be done. So much
593595
faster. And if 'other' _is_ a Ray then the BV.intersects(Ray) call can be done.
594-
595596
I don't have time to do it right now but I'll at least un-break a bunch of peoples'
596597
code until it can be 'optimized' properly. Hopefully it's not too late to back out
597598
the other dodgy ripples this caused. -pspeed (hindsight-expert ;))
598-
599599
Note: the code itself is relatively simple to implement but I don't have time to
600600
a) test it, and b) see if '> 4' is still a decent check for it. Could be it's fast
601601
enough to do all the time for > 1.
602-
603602
if (children.size() > 4)
604603
{
605604
BoundingVolume bv = this.getWorldBound();
@@ -692,7 +691,6 @@ public Node clone(boolean cloneMaterials){
692691
// Reset the fields of the clone that should be in a 'new' state.
693692
nodeClone.updateList = null;
694693
nodeClone.updateListValid = false; // safe because parent is nulled out in super.clone()
695-
696694
return nodeClone;
697695
}
698696

@@ -732,7 +730,6 @@ public void cloneFields( Cloner cloner, Object original ) {
732730
// cloning this list is fine.
733731
this.updateList = cloner.clone(updateList);
734732
}
735-
736733
@Override
737734
public void write(JmeExporter e) throws IOException {
738735
super.write(e);
@@ -744,7 +741,6 @@ public void read(JmeImporter e) throws IOException {
744741
// XXX: Load children before loading itself!!
745742
// This prevents empty children list if controls query
746743
// it in Control.setSpatial().
747-
748744
children = new SafeArrayList( Spatial.class,
749745
e.getCapsule(this).readSavableArrayList("children", null) );
750746

@@ -754,7 +750,6 @@ public void read(JmeImporter e) throws IOException {
754750
child.parent = this;
755751
}
756752
}
757-
758753
super.read(e);
759754
}
760755

@@ -775,15 +770,13 @@ public void updateModelBound() {
775770
}
776771
}
777772
}
778-
779773
@Override
780774
public void depthFirstTraversal(SceneGraphVisitor visitor) {
781775
for (Spatial child : children.getArray()) {
782776
child.depthFirstTraversal(visitor);
783777
}
784778
visitor.visit(this);
785779
}
786-
787780
@Override
788781
protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue) {
789782
queue.addAll(children);

0 commit comments

Comments
 (0)