bevy/crates/bevy_mesh/src
Shane Celis f375422ddd
Compute better smooth normals for cheaper, maybe (#16050)
# Objective

Avoid a premature normalize operation and get better smooth normals for
it.

## Inspiration

@IceSentry suggested `face_normal()` could have its normalize removed
based on [this article](https://iquilezles.org/articles/normals/) in PR
#16039.

## Solution

I did not want to change `face_normal()` to return a vector that's not
normalized. The name "normal" implies it'll be normalized. Instead I
added the `face_area_normal()` function, whose result is not normalized.
Its magnitude is equal two times the triangle's area. I've noted why
this is the case in its doc comment.

I changed `compute_smooth_normals()` from computing normals from
adjacent faces with equal weight to use the area of the faces as a
weight. This has the benefit of being cheaper computationally and
hopefully produces better normals.

The `compute_flat_normals()` is unchanged and still uses
`face_normal()`.

## Testing

One test was added which shows the bigger triangle having an effect on
the normal, but the previous test that uses the same size triangles is
unchanged.

**WARNING:** No visual test has been done yet. No example exists that
demonstrates the compute_smooth_normals(). Perhaps there's a good model
to demonstrate what the differences are. I would love to have some input
on this.

I'd suggest @IceSentry and @stepancheg to review this PR.

## Further Considerations

It's possible weighting normals by their area is not definitely better
than unweighted. It's possible there may be aesthetic reasons to prefer
one over the other. In such a case, we could offer two variants:
weighted or unweighted. Or we could offer another function perhaps like
this: `compute_smooth_normals_with_weights(|normal, area| 1.0)` which
would restore the original unweighted sum of normals.

---

## Showcase

Smooth normal calculation now weights adjacent face normals by their
area.

## Migration Guide
2024-12-03 17:25:10 +00:00
..
primitives Use en-us locale for typos (#16037) 2024-10-20 18:55:17 +00:00
conversions.rs Remove thiserror from bevy_mesh (#15768) 2024-10-09 14:24:54 +00:00
index.rs Indices::extend (#16023) 2024-10-31 16:39:32 +00:00
lib.rs Split out bevy_mesh from bevy_render (#15666) 2024-10-06 14:18:11 +00:00
mesh.rs Compute better smooth normals for cheaper, maybe (#16050) 2024-12-03 17:25:10 +00:00
mikktspace.rs Remove thiserror from bevy_mesh (#15768) 2024-10-09 14:24:54 +00:00
morph.rs Fix *most* clippy lints (#15906) 2024-10-14 20:52:35 +00:00
skinning.rs Split out bevy_mesh from bevy_render (#15666) 2024-10-06 14:18:11 +00:00
vertex.rs Compute better smooth normals for cheaper, maybe (#16050) 2024-12-03 17:25:10 +00:00