Well after a bit more research, it turns out that my initial patch was wrong. I wasn't pushing the correct indexes to ODE.
My patch is following your initial suggestion, and modifies updateData (TriMesh mesh). Basically, when copying geometry to ODE now all batches are being used.
This is the patched updateData that I am using (and so far working):
/**
* Recreates ODE vertices and indices lists for a given jME TriMesh object.
* @param mesh The TriMesh to be built in ODE.
*/
public void updateData( TriMesh mesh ) {
int totalVerticesLength = 0;
int totalIndicesLength = 0;
// Walk batches and count indices and vertices
for (int batchIndex = 0; batchIndex < mesh.getBatchCount(); batchIndex++) {
TriangleBatch batch = mesh.getBatch (batchIndex);
totalVerticesLength += (batch.getVertexCount() * 3);
totalIndicesLength += (batch.getTriangleCount() * 3);
}
// Create vertices buffer
if ( odeVertices != null ) {
Ode.delete_floatArray( odeVertices );
odeVertices = null;
}
odeVertices = Odejava.createSwigFloatArray( totalVerticesLength );
// Create indices buffer
if ( odeIndices != null ) {
Ode.delete_intArray( odeIndices );
odeIndices = null;
}
SWIGTYPE_p_int result = Ode.new_intArray( totalIndicesLength );
// Retrieve mesh scale to bake vertex data
float[] scale = {mesh.getWorldScale().x, mesh.getWorldScale().y, mesh.getWorldScale().z};
// Walk batches and fill in vertices and index data
int vertexOffset = 0;
int indexOffset = 0;
for (int batchIndex = 0; batchIndex < mesh.getBatchCount(); batchIndex++) {
TriangleBatch batch = mesh.getBatch (batchIndex);
IntBuffer indices = batch.getIndexBuffer();
indices.rewind();
FloatBuffer vertices = batch.getVertexBuffer();
vertices.rewind();
int partialVertexOffset = vertexOffset / 3;
int verticesLength = batch.getVertexCount() * 3;
for ( int i = 0; i < verticesLength / 3; i++ ) {
Ode.floatArray_setitem( odeVertices, vertexOffset, vertices.get() * scale[0] );
Ode.floatArray_setitem( odeVertices, vertexOffset + 1, vertices.get() * scale[1] );
Ode.floatArray_setitem( odeVertices, vertexOffset + 2, vertices.get() * scale[2] );
vertexOffset += 3;
}
int indicesLength = batch.getTriangleCount() * 3;
for ( int i = 0; i < indicesLength / 3; i++ ) {
Ode.intArray_setitem( result, indexOffset, indices.get() + partialVertexOffset);
Ode.intArray_setitem( result, indexOffset + 1, indices.get() + partialVertexOffset);
Ode.intArray_setitem( result, indexOffset + 2, indices.get() + partialVertexOffset);
indexOffset += 3;
}
}
odeIndices = result;
// Send to ODE
Ode.dGeomTriMeshDataBuildSingle1( data, odeVertices.getVoidPointer(), 12,
totalVerticesLength / 3, odeIndices.getVoidPointer(), totalIndicesLength, 12, null );
if ( geomId != null ) { Ode.dGeomTriMeshSetData( geomId, data ); }
}
Now, this doesn't seem to require any special action for shared meshes, since all vertex and index data is copied ( :?).
There is, however, something that is fooling me. Mainly because of my lack of understanding I guess. Have a look at function:
PhysicsCollisionGeometry
PhysicsNode.generatePhysicsGeometry( Spatial spatial, Vector3f translation, Quaternion rotation, Vector3f scale, boolean useTriangleAccurateGeometries )
It contains a similar TODO note, and a hardcoded getBatch(0). This leads to a difficult situation: if the geometry with multiple batches is a TriMesh and triangle accuracy is required, then everything seems to work because ultimately createPhysicsGeometry is called and it will copy data (calling the patched function above).
However, this would probably fail for geometry with multiple batches if the Geometry is a Box, Sphere, etc. I think jME never builds those primitives using multiple batches but if it did, the code at generatePhysicsGeometry should be patched too to take multiple batches into account.
I know all this is a mess. Sorry for the fuzz.
According to renanse, I guess in the future will be easier to modify the Collada importer so it never uses batches. That way everything should work. @irrisor, I don't know what the target of a SharedMesh is :s (I have no clue about shared things, vbos, etc.., and I know I have to face that soon), but the updateData function seems to work just fine even if the mesh is a shared mesh (vertices and indices can be copied with no changes).