mirror of
https://github.com/Redot-Engine/redot-engine.git
synced 2025-12-06 15:21:56 -05:00
Fix jolt_physics soft body vertex normal calculation
The code previously iterated through each face and set all vertices to that face's normal. This resulted in each vertex getting the normal from just one face that it belonged to (whichever face was last in this array). This caused weird shading artifacts. This fixes the code so that the vertex normal is now the average normal of all faces that it belongs to. This results in "smooth shading" behavior for soft body meshes. This is still somewhat undesirable if the input mesh was using flat shading, but it looks less bad than the previous behavior of picking a normal at random from one attached face. This matches the behavior of GodotPhysicsServer3D. Fixes #107831.
This commit is contained in:
@@ -628,8 +628,13 @@ void JoltSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHandl
|
||||
|
||||
const int physics_vertex_count = (int)physics_vertices.size();
|
||||
|
||||
normals.clear();
|
||||
normals.resize(physics_vertex_count);
|
||||
|
||||
// Compute vertex normals using smooth-shading:
|
||||
// Each vertex should use the average normal of all faces it is a part of.
|
||||
// Iterate over each face, and add the face normal to each of the face vertices.
|
||||
// By the end of the loop, each vertex normal will be the sum of all face normals it belongs to.
|
||||
for (const SoftBodyFace &physics_face : physics_faces) {
|
||||
// Jolt uses a different winding order, so we swap the indices to account for that.
|
||||
|
||||
@@ -643,9 +648,18 @@ void JoltSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHandl
|
||||
|
||||
const Vector3 normal = (v2 - v0).cross(v1 - v0).normalized();
|
||||
|
||||
normals[i0] = normal;
|
||||
normals[i1] = normal;
|
||||
normals[i2] = normal;
|
||||
normals[i0] += normal;
|
||||
normals[i1] += normal;
|
||||
normals[i2] += normal;
|
||||
}
|
||||
// Normalize the vertex normals to have length 1.0
|
||||
for (Vector3 &n : normals) {
|
||||
real_t len = n.length();
|
||||
// Some normals may have length 0 if the face was degenerate,
|
||||
// so don't divide by zero.
|
||||
if (len > CMP_EPSILON) {
|
||||
n /= len;
|
||||
}
|
||||
}
|
||||
|
||||
const int mesh_vertex_count = shared->mesh_to_physics.size();
|
||||
|
||||
Reference in New Issue
Block a user