I’m probably doing something wrong but I can’t figure out what it is. My code, which is quite messy sorry for that, takes a mesh with shared vertices (which has an index buffer) and then makes the vertices unshared with a flat normal according to the triangle. Here are two images to demonstrate what I’m trying to do :
The first image depicts my bug. For some reason, when changing loaded model’s buffers, this happens. The model is the teapot in jme3-testdata.
Here’s my code :
private static final int VERTICES_PER_TRIANGLE = 3;
public static <T extends Mesh> T computeNormals(T mesh, boolean containsSharedVertices) {
VertexBuffer positionVertexBuffer = mesh.getBuffer(Type.Position);
FloatBuffer positionFloatBuffer = (FloatBuffer) positionVertexBuffer.getData();
positionFloatBuffer.rewind();
VertexBuffer normalVertexBuffer = mesh.getBuffer(Type.Normal);
FloatBuffer normalFloatBuffer = (FloatBuffer) normalVertexBuffer.getData();
normalFloatBuffer.rewind();
Vector3f[] triangleVertices = new Vector3f[VERTICES_PER_TRIANGLE];
for (int i = 0; i < triangleVertices.length; ++i)
triangleVertices[i] = new Vector3f();
if (!containsSharedVertices) {
// Not important ...
} else {
VertexBuffer indexVertexBuffer = mesh.getBuffer(Type.Index);
ShortBuffer indexShortBuffer = (ShortBuffer) indexVertexBuffer.getData();
int targetVertexCount = indexShortBuffer.limit();
int targetTriangleCout = targetVertexCount / VERTICES_PER_TRIANGLE;
indexShortBuffer.rewind();
FloatBuffer positionNewFloatBuffer = (FloatBuffer) VertexBuffer.createBuffer(Format.Float, positionVertexBuffer.getNumComponents(), targetVertexCount);
FloatBuffer normalNewFloatBuffer = (FloatBuffer) VertexBuffer.createBuffer(Format.Float, normalVertexBuffer.getNumComponents(), targetVertexCount);
for (int triangleIndex = 0; triangleIndex < targetTriangleCout; ++triangleIndex) {
for (int triangleVertexIndex = 0; triangleVertexIndex < VERTICES_PER_TRIANGLE; ++triangleVertexIndex) {
positionFloatBuffer.position(indexShortBuffer.get() * positionVertexBuffer.getNumComponents());
for (int vertexComponentIndex = 0; vertexComponentIndex < positionVertexBuffer.getNumComponents(); ++vertexComponentIndex) {
float vertexComponent = positionFloatBuffer.get();
triangleVertices[triangleVertexIndex].set(vertexComponentIndex, vertexComponent);
positionNewFloatBuffer.put(vertexComponent);
}
}
Vector3f normal = computeTriangleNormal(triangleVertices);
for (int normalIndex = 0; normalIndex < VERTICES_PER_TRIANGLE; ++normalIndex)
for (int normalComponentIndex = 0; normalComponentIndex < normalVertexBuffer.getNumComponents(); ++normalComponentIndex)
normalNewFloatBuffer.put(normal.get(normalComponentIndex));
}
positionNewFloatBuffer.flip();
normalNewFloatBuffer.flip();
mesh.clearBuffer(Type.Index);
positionVertexBuffer.updateData(positionNewFloatBuffer);
normalVertexBuffer.updateData(normalNewFloatBuffer);
// TODO
}
mesh.updateCounts();
mesh.updateBound();
return mesh;
}
public static boolean mayNotShareVertices(Mesh mesh) {
return mesh.getMode() == Mode.Triangles;
}
public static Vector3f computeTriangleNormal(Vector3f[] vertices) {
return computeTriangleNormal(vertices[0], vertices[1], vertices[2]);
}
public static Vector3f computeTriangleNormal(Vector3f p1, Vector3f p2, Vector3f p3) {
return p2.subtract(p1).cross(p3.subtract(p1)).normalizeLocal();
}