Hi,
I’m trying to use BatchNode in my project and I’m getting a BufferUnderflowException with the following stacktrace:
java.nio.BufferUnderflowException
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.rewind();
bindBufPos.get(tmpFloat, 0, length);
if (bindBufNorm != null) {
bindBufNorm.rewind();
bindBufNorm.get(tmpFloatN, 0, length);
}
if (bindBufTangents != null) {
bindBufTangents.rewind();
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