[SOLVED] BatchNode BufferUnderflowException


I’m trying to use BatchNode in my project and I’m getting a BufferUnderflowException with the following stacktrace:

at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:271)
at com.jme3.scene.BatchNode.doTransforms(BatchNode.java:556)
at com.jme3.scene.BatchNode.updateSubBatch(BatchNode.java:152)
at com.jme3.scene.BatchNode.onTransformChange(BatchNode.java:104)
at com.jme3.scene.Geometry.updateWorldTransforms(Geometry.java:326)
at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:905)
at com.jme3.scene.Node.updateGeometricState(Node.java:271)
at com.jme3.scene.Node.updateGeometricState(Node.java:271)
at com.jme3.scene.Node.updateGeometricState(Node.java:271)

Getting into BatchNode code, the doTransforms method:

private void doTransforms(FloatBuffer bindBufPos, FloatBuffer bindBufNorm, FloatBuffer bindBufTangents, FloatBuffer bufPos, FloatBuffer bufNorm, FloatBuffer bufTangents, int start, int end, Matrix4f transform) {

        TempVars vars = TempVars.get();
        Vector3f pos = vars.vect1;
        Vector3f norm = vars.vect2;
        Vector3f tan = vars.vect3;

        int length = (end - start) * 3;
        int tanLength = (end - start) * 4;

        // offset is given in element units
        // convert to be in component units
        int offset = start * 3;
        int tanOffset = start * 4;

        bindBufPos.get(tmpFloat, 0, length);

        if (bindBufNorm != null) {
            bindBufNorm.get(tmpFloatN, 0, length);

        if (bindBufTangents != null) {
            bindBufTangents.get(tmpFloatT, 0, tanLength); // This is the line producing the exception


In my case, this batch has 2544 vertices which results in vertices3 buffer except from tmpFloatT having size of vertices4 while bindBufTangents is vertices*3 causing the buffer underflow.

Tangents for all geometries added to the BatchNode before running batch() are created using the TangentBinormalGenerator generate method which getting into the code generates a buffer of size vertices*3 :

    private static void processTriangleData(Mesh mesh, VertexData[] vertices,
            boolean approxTangent)
        FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();

        FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.length * 3);

In adition to that, as far as I undertand, the 4th position for each vertex is not used or set. Also from BatchNode.doTransforms:

            if (bindBufTangents != null) {
                tanIndex1 = tanIndex + 1;
                tanIndex2 = tanIndex + 2;
                tan.x = tmpFloatT[tanIndex];
                tan.y = tmpFloatT[tanIndex1];
                tan.z = tmpFloatT[tanIndex2];
                transform.multNormal(tan, tan);
                tmpFloatT[tanIndex] = tan.x;
                tmpFloatT[tanIndex1] = tan.y;
                tmpFloatT[tanIndex2] = tan.z;
                tanIndex += 4;

Maybe tangents should be created using 4 floats for each vertex, maybe BatchNode should use vertices*3 temp tangent buffer, maybe I’m missing something…

Thank you for your answers :wink:

1 Like

OK, it was completely something I was missing. I started this project long ago with jme3 alpha2 and back then, if I remember correctly, the tangentBinormalGenerator didn’t work properly or I had some issues with it, so I forked it inside my project, so the code using just 3 coordinates per vertex is the old code back then creating the issue :confused: :man_facepalming:

I removed it from the project and changed the imports to use the current generator and it works as expected :stuck_out_tongue:

1 Like