Attached you will find a method to corrects seams between squared meshes which will result by having different normals. Can be called after loading the mesh and ev. before you generate tangents. Works only on squared meshes in the x, z plane.
screenshot shows seams on the left (no fix) and no seams on the right (fix applied):
code (java button didn’t work for me):
/**
- Fix the normals of vertices lying on the edge of a tile to face a direction ON the edge. The result will be
- that two tiles corrected by this way will do not have seams on adjecant vertices.
- The algorithm works by moving the normal x and z values to 0 if the vertex is on the corresponding border.
-
@param mesh The mesh, normals should be fixed
-
@param borderDistance The distance from the center to one border, asuming all 4 borders at same distance
-
@param borderTolerance The positive tolerance value for checks if a vertex is on the border. Anything vertex within that distance to a border will be fixed.
*/
public static void fixTileNormals(Mesh mesh, float borderDistance, float borderTolerance){
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
FloatBuffer normals = BufferUtils.createFloatBuffer(vertexBuffer.capacity());
Vector3f v = new Vector3f();
Vector3f n = new Vector3f();
//just loop over all values, whatever type it is, a vertex has its normal at the corresponding index
for (int i = 0; i < vertexBuffer.capacity()/3; i++) {
populateFromBuffer(v, vertexBuffer, i);
populateFromBuffer(n, normalBuffer, i);
//on left or right border, the set x comp of normal to 0
if(FastMath.abs(v.x+borderDistance) <=borderTolerance) n.x = 0f;
else if(FastMath.abs(-v.x+borderDistance) <=borderTolerance) n.x = 0f;
//on top or bottom border, the set z comp of normal to 0
if(FastMath.abs(v.z+borderDistance) <=borderTolerance) n.z = 0f;
else if(FastMath.abs(-v.z+borderDistance) <=borderTolerance) n.z = 0f;
n.normalizeLocal();
normals.put(n.x);
normals.put(n.y);
normals.put(n.z);
}
mesh.clearBuffer(Type.Normal);
mesh.setBuffer(Type.Normal, 3, normals);
}