[SOLVED] GeometryBatchFactory breaks Shadows?

Hello,



I load many blender scenes in my project, attached them to rootNode and then put the line :



[java]GeometryBatchFactory.optimize(rootNode);[/java]



From now, Parallel-Split Shadow Map does not work anymore. (Work nice if i remove the batch line).

I’ve certainly missed something but no idea at all :x

Ty in advance for your help

Ok nvm, i found solution -_-

It would be nice if you could describe what was the issue and how you solved it in case others run ino the same issue or make the same mistake.

1 Like

I also noticed that GeometryBatchFactory does not show PhysicsDebugShape of batched geometries.





Code example (but debug shape is not shown if i use GeometryBatchFactory):

[java]



for (int i=0; i<numClones; i++) {



Geometry gm = geom.clone(false);

gm.setName("instance"+i);



CollisionShape colShape = new MeshCollisionShape(gm.getMesh());

colShape.setMargin(0.005f);

RigidBodyControl rigControl = new RigidBodyControl(colShape, 0);



gm.addControl(rigControl);



bulletAppState.getPhysicsSpace().add(gm);



instNodes.attachChild(gm);



}



GeometryBatchFactory.optimize(instNodes); // fps optimization

rootNode.attachChild(instNodes);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);



[/java]





Is it ok?

@normen said:
It would be nice if you could describe what was the issue and how you solved it in case others run ino the same issue or make the same mistake.


Ok sry. GeometryBatchFactory.optimize() seams to set the ShadowMode var of each batched Spatial to its default value (ShadowMode.OFF).

So i had to set this param AFTER using this optimization, by adding the following loop :

[java]
// adding spatials to myNode (blender scenes in my case)
myNode.attachChild(myScene)

// optimization of myNode
GeometryBatchFactory.optimize(myNode);

// setting of ShadowMode of each scene
for (Spatial s:myNode) {
s.setShadowMode(ShadowMode.Received);
}[/java]

and everything works well.

@kriss4realms thanks for the tip. The same is for debugShapes. I added physics after GeometryBatchFactory and the debugShapes are seen.



[java]

GeometryBatchFactory.optimize(instNodes); // fps optimization

rootNode.attachChild(instNodes);



// setting physics

for (Spatial s : instNodes.getChildren()) {

Geometry geo = (Geometry) s;

CollisionShape colShape = new MeshCollisionShape(geo.getMesh());

colShape.setMargin(0.005f);

RigidBodyControl rigControl = new RigidBodyControl(colShape, 0);



geo.addControl(rigControl);



bulletAppState.getPhysicsSpace().add(geo);

}

[/java]

@mifth: nonsense

@normen Is it possible that batching geometries strips out all the RigidBodyControl out of them? If I comment the GeometryBatchFactory.optimize(node); line everything works perfectly and when it’s uncommented, it crashes at the point I’m trying to access the node’s RigidBodyControl. It is in fact NULL at that point.

@.Ben. said: @normen Is it possible that batching geometries strips out all the RigidBodyControl out of them? If I comment the GeometryBatchFactory.optimize(node); line everything works perfectly and when it's uncommented, it crashes at the point I'm trying to access the node's RigidBodyControl. It is in fact NULL at that point.

GeometryBatchFactory
-takes in a set of spatials
-destroys them and copies their data into a single object
-produces that object

…so yeah, I think individual ‘stuff’ attached to the now gone spatials is probably also gone.

Edit: note, not trying to sound snarky… but I’m hoping if anyone thinks that it actually should work then they can explain how many rigid body controls become one rigid body control in the batched version.

1 Like

However if you use the BatchNode instead of the GeometryBatchFactory yous should still be able to keep individual controls on geometries while they are batched

1 Like

Wow, thank you @pspeed and @nehon for this useful information. I had misunderstood what GeometryBatchFactory did. But Paul, I was not thinking as if that factory would batch the rigid body controls together, I was thinking that it would leave them detached and only link all those geometries into one array which is clear now that is not its job to do that and when I read the actions list that factory does, it makes sense that it wouldn’t work like that either. What kind of application would this factory be good for? I guess only the applications without physics at all, meaning no rigid body controls and nothing else but plain geometries?

@nehon (and/or whoever wants to answer this) :

  1. Does BatchNode provide us with the kind of performance boost GeometryBatchFactory gives on let’s say 1000 physics enabled objects?
  2. If I had static geometries (no physics) would I be right to say that I’d be better to use GeometryBatchFactory vs BatchNode to save RAM and still have the same performance gain over the other method or would that assumption be wrong?

Thank you so much for your time guys. I gave you +1 to both for efforts.

  1. Well there can be some overhead compared to GeometrybatchFactory, but you gain the ability to keep all sub geometries as if they were not batched. But that’s about the same kind of performance boost compared to 1000 unbatched object in the scene. There is an example of batch node with physics https://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/batching/TestBatchNodeTower.java
  2. Yes if you have static geoms (not moving at all not only with no physic), geometryBatchFactory is the way to go. Note that a batched geometries with GBF can still be moved or have physics interactions as a whole with other objects.

@nehon Hi again, I tried the BatchNode class implementation to replace the GeometryBatchFactory since I needed the linked RigidBodyControl to stay after the batching and obviously the GeometryBatchFactory does not do that. I did this:

[java]
// In the class header…
private BatchNode batchnode_placed_cubes;
// --------------------------

// In my init function…
batchnode_placed_cubes = new BatchNode(“Placed Cubes”);
rayTraceablesRootNode.attachChild(batchnode_placed_cubes);

// Create a cube
Box boxMesh = new Box(1,1,1);
Geometry boxGeo = new Geometry("Collected Cube " + batchnode_placed_cubes.getChildren().size(), boxMesh);
Material boxMat = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);
boxMat.setBoolean(“UseMaterialColors”, true);
boxMat.setColor(“Ambient”, ColorRGBA.Pink);
boxMat.setColor(“Diffuse”, ColorRGBA.Pink);
boxGeo.setMaterial(boxMat);
boxGeo.setLocalTranslation(ghostCubeMark.getLocalTranslation());

// Physics (without gravity at the moment)
RigidBodyControl r = new RigidBodyControl(0);
boxGeo.addControl®;
bulletAppState.getPhysicsSpace().add®;

// Batch optimization
batchnode_placed_cubes.attachChild(boxGeo);
batchnode_placed_cubes.batch();

// Do whatever based on the cubes’ mass…
for(Spatial child : batchnode_placed_cubes.getChildren()) { // It goes in OK
if(child.getControl(RigidBodyControl.class).getMass() == 0){ // Exception thrown, getMass() is NULL <------
// Whatever here works without batching but now does not…
}
}
[/java]

…as you can see, I get a NULL exception on child.getControl(RigidBodyControl.class).getMass() whereas if I did not optimize at all with BatchNode it would not throw any exception and execute perfectly. Any idea why? Is it normal? I control-clicked the getChildren() function to see if your class returns a BatchNode instead of a Spatial, but you implemented a standard Node so this function is the same one used in Node (so it returns a Spatial like it did before I try batching anyways).

Any ideas? :-/

BatchNode will create some of its own children… you cannot expect every child to be just yours anymore. Your child will be there but so will others.

1 Like

Yeah the BatchNode will create some children geometries of its own (batches…). Just test if the child has a RigidBodyControl before testing the mass and it should be fine.

1 Like

Ohh… I see! I would have thought it would attach the additional nodes as subnodes of each child tough, but I understand. Thanks I’ll test this out! :smiley: +1 guys again! Thx

EDIT: In the logs I now see this if I println() the placed cubes names. For every cube I put in the batchnode, one additional node gets created. If I were to optimize even further, should I detach the original non batched nodes (like in this example, called Collected Cube [0,2,4,6,8]) and is it normal that there is one separate batch node for every node I attached? Something tells me this is incorrect and I should only see 5 nodes + 1 in the logs. I wonder if this is supposed to be like this. The story is that everytime I attach a new node I run the batch() method, should I do cleanup before calling the batch() method multiple times?

[java]
Console:

Collected Cube 0
Placed Cubes-batch0
Collected Cube 2
Placed Cubes-batch1
Collected Cube 4
Placed Cubes-batch2
Collected Cube 6
Placed Cubes-batch3
Collected Cube 8
Placed Cubes-batch4
[/java]

Thx :smiley: