fix invalid bone weights (#8316)

# Objective

when a mesh uses zero for all bone weights, vertices end up in the
middle of the screen.

## Solution

we can address this by explicitly setting the first bone weight to 1
when the weights are given as zero. this is the approach taken by
[unity](https://forum.unity.com/threads/whats-the-problem-with-this-import-fbx-warning.133736/)
(although that also sets the bone index to zero) and
[three.js](94c1a4b86f/src/objects/SkinnedMesh.js (L98)),
and likely other engines.

## Alternatives

it does add a bit of overhead, and users can always fix this themselves,
though it's a bit awkward particularly with gltfs.

(note - this is for work so my sme status shouldn't apply)

---------

Co-authored-by: ira <JustTheCoolDude@gmail.com>
This commit is contained in:
robtfm 2023-04-10 08:49:53 +01:00 committed by GitHub
parent be0ca7f168
commit cc8f023b3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -110,7 +110,7 @@ impl Mesh {
attribute: MeshVertexAttribute,
values: impl Into<VertexAttributeValues>,
) {
let values = values.into();
let mut values = values.into();
let values_format = VertexFormat::from(&values);
if values_format != attribute.format {
panic!(
@ -119,6 +119,17 @@ impl Mesh {
);
}
// validate attributes
if attribute.id == Self::ATTRIBUTE_JOINT_WEIGHT.id {
let VertexAttributeValues::Float32x4(ref mut values) = values else {
unreachable!() // we confirmed the format above
};
for value in values.iter_mut().filter(|v| *v == &[0.0, 0.0, 0.0, 0.0]) {
// zero weights are invalid
value[0] = 1.0;
}
}
self.attributes
.insert(attribute.id, MeshAttributeData { attribute, values });
}