BatchNode and NullPointerException with same material nodes

Hi, I’m trying to use BatchNode.

The process I use is:

  1. I create the BatchNode: batchNode = new BatchNode("Batchy");
  2. I add some nodes with geometries to the batchNode: for(Spatial s : spatials) batchNode.attachChild(spat);
  3. I batch the node: batchNode.batch()

On the 3rd step I get:

java.lang.NullPointerException
	at com.jme3.scene.BatchNode.mergeGeometries(BatchNode.java:584)
	at com.jme3.scene.BatchNode.doBatch(BatchNode.java:232)
	at com.jme3.scene.BatchNode.batch(BatchNode.java:187)

I made a lot of tests with it, and if I put different materials to each node (so to the containing geometries) It doesn’t fire an exception but it only batches per node (obviously).
The scengraph is:

---- BATCH NODE ----
Batchy (BatchNode)
-null (Node) - (362t, 784v)
–MODEL0 (Node) - (362t, 784v)
—structure1 (Geometry)(customMaterial) - (362t, 784v)
-null (Node) - (110t, 129v)
–MODEL1 (Node) - (110t, 129v)
—Cube-ogremesh (Node) - (110t, 129v)
----rotH (Node) - (110t, 129v)
-----rotV (Node) - (82t, 81v)
------tube1 (Geometry)(customMaterial2) - (82t, 81v)
-----lateral1 (Geometry)(customMaterial2) - (28t, 48v)

I use code to print the graph so I’m sure is fine.

With different materials I get the two extra batches at the end of the previous graph (looking at the triangles and vertex I can say that is done as it must):

-Batchy-batch0 (Geometry)(null) - (362t, 784v)
-Batchy-batch1 (Geometry)(null) - (110t, 129v)

But if I replace customMaterial2 by customMaterial, is when I get the previous nullPointer. I would like to know if I’m doing it wrong (what I already checked for hours, even comparing with the jme3test.batching examples) or if this is, actually, a bug.

Thanks in advance for any help.

What are your spatials? Are they custom meshes?

Yes, some of them are imported from blender and others are from the world forge asset pack. I removed all their textures and I changed their material.

Do you have a test case?
the NPE occurs on a null vertex buffer…and that’s pretty weird.

i had this kind of problem when there was no normal in my meshes.
BatchNode seemsto be sensible to this.

Here you have it.

ok thanks.
The problem is that one of the geometry (named “CURTAIN”) doesn’t have a Color buffer, whereas the other have.

All your geometries should have the same vertex buffers set on.
At the very least, batchNode should crash more elegantly, with a proper error, I’ll add this.

To make it more reliable, a color buffer could be generated (with just white color) so that those models could be batched.

Thanks for your help.

I think this is a more user friendly way than throwing any error :wink:

Actually, based on the OpenGL spec, the default attribute value when the attribute is not set on the shader is 0,0,0,1. So perhaps the correct behavior is to create a buffer filled with 0,0,0,1 to be consistent with the OpenGL spec.

But then if you had one model that uses vertex color and one that didn’t, they would have different materials. What this means, is that you have vertex color data and you’re not using it - so perhaps you should unset it?

I just removed the buffers (actually two of them: VertexBuffer.Type.Color and VertexBuffer.Type.TexCoord2) from all geometries to test it (now, all of the geometries have the same buffers) but it throws:

java.nio.BufferUnderflowException
	at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:265)
	at com.jme3.scene.BatchNode.doTransformsTangents(BatchNode.java:663)
	at com.jme3.scene.BatchNode.updateSubBatch(BatchNode.java:169)
	at com.jme3.scene.Geometry.updateWorldTransforms(Geometry.java:286)
	at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:713)
	at com.jme3.scene.Node.updateGeometricState(Node.java:175)
	at com.jme3.scene.BatchNode.updateGeometricState(BatchNode.java:120)
	at com.jme3.scene.BatchNode.batch(BatchNode.java:193)

I thought about it but, I don’t really like that.What default values to use? here it’s the color buffer, but it could be any kind of buffer. using 0,0,0,1 for the color buffer seems dumb to be honest because it will result in a black color on the geometry of the inColor is used…
Silently “fixing” it may cause more issues later in the game that will be way less easy to detect…
That’s why a plain exception is IMO better for the user.

Did you generate the tangents on all the sub geoms?

Based on the OpenGL specification, 0,0,0,1 is used if the attribute is not specified. Therefore, if you have the case such that:

  • The model uses the attribute in the shader
  • The attribute’s VertexBuffer is not specified on the Mesh object

Then there would be no difference between batching the model and generating a 0,0,0,1 buffer for it vs. not batching the model at all.

Well, here we have a typical case where it’s dumb to do it. Through that error the user realized that he didn’t need those buffers on the mesh. With this kind of safegard, we would have silently add clutter on top of the models clutter…

I’d rather keep an exception and provide a utility class that would take a bunch of geomatries and add the missing buffers with default values. This way the user would be aware of the problem and would deliberatlely choose to “align” all the meshes’ buffers.

1 Like

Ok, I just did and it worked fine, thanks.

Totally agreed :smiley:

By the way, is there a graphical way to modify the vertex buffers?, or the only current way is by code?.

Nope only by code.