Use all face vertices to calculate face normal

This ensures correct normals, even for e.g. freeform fins of which the 3 first vertices are concave
This commit is contained in:
SiboVG 2024-02-14 02:19:16 +01:00
parent b3ef442350
commit dfd497b9d1
2 changed files with 34 additions and 4 deletions

View File

@ -355,6 +355,39 @@ public class ObjUtils {
return normalizeVector(crossProduct(u, v));
}
/**
* Calculates the normal vector for a given face of the object.
*
* @param obj The object.
* @param face The face of the object for which to calculate the normal vector.
* @return The calculated normal vector.
*/
public static FloatTuple calculateNormalVector(DefaultObj obj, DefaultObjFace face) {
FloatTuple[] vertices = getVertices(obj, face);
return calculateNormalNewell(vertices);
}
/**
* Calculates the normal of a polygon using the Newell's method.
*
* @param vertices a list of vertices representing the polygon
* @return the normalized normal vector of the polygon
*/
private static FloatTuple calculateNormalNewell(FloatTuple[] vertices) {
float x = 0f;
float y = 0f;
float z = 0f;
for (int i = 0; i < vertices.length; i++) {
FloatTuple current = vertices[i];
FloatTuple next = vertices[(i + 1) % vertices.length];
x += (current.getY() - next.getY()) * (current.getZ() + next.getZ());
y += (current.getZ() - next.getZ()) * (current.getX() + next.getX());
z += (current.getX() - next.getX()) * (current.getY() + next.getY());
}
return normalizeVector(new DefaultFloatTuple(x, y, z));
}
/**
* Subtracts two vectors.
*

View File

@ -69,10 +69,7 @@ public abstract class TriangulationHelper {
Map<Integer, Integer> vertexToTexCoordMap = mapVertexIndicesToTexCoordIndices(face);
// Calculate the face normal
Coordinate normal = vertexToCoordinate(ObjUtils.calculateNormalVector(
obj.getVertex(face.getVertexIndices()[0]),
obj.getVertex(face.getVertexIndices()[1]),
obj.getVertex(face.getVertexIndices()[2])));
Coordinate normal = vertexToCoordinate(ObjUtils.calculateNormalVector(obj, face));
// Project the 3D face to a 2D polygon with only X and Y coordinates.
// This is necessary because the JTS library only works with 2D polygons for triangulation.