mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
normalize joint weights (#10539)
# Objective allow automatic fixing of bad joint weights. fix #10447 ## Solution - remove automatic normalization of vertexes with all zero joint weights. - add `Mesh::normalize_joint_weights` which fixes zero joint weights, and also ensures that all weights sum to 1. this is a manual call as it may be slow to apply to large skinned meshes, and is unnecessary if you have control over the source assets. note: this became a more significant problem with 0.12, as weights that are close to, but not exactly 1 now seem to use `Vec3::ZERO` for the unspecified weight, where previously they used the entity translation.
This commit is contained in:
parent
a955d65ffa
commit
b35b9e5005
1 changed files with 26 additions and 12 deletions
|
@ -213,7 +213,7 @@ impl Mesh {
|
|||
attribute: MeshVertexAttribute,
|
||||
values: impl Into<VertexAttributeValues>,
|
||||
) {
|
||||
let mut values = values.into();
|
||||
let values = values.into();
|
||||
let values_format = VertexFormat::from(&values);
|
||||
if values_format != attribute.format {
|
||||
panic!(
|
||||
|
@ -222,17 +222,6 @@ 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 });
|
||||
}
|
||||
|
@ -630,6 +619,31 @@ impl Mesh {
|
|||
pub fn morph_target_names(&self) -> Option<&[String]> {
|
||||
self.morph_target_names.as_deref()
|
||||
}
|
||||
|
||||
/// Normalize joint weights so they sum to 1.
|
||||
pub fn normalize_joint_weights(&mut self) {
|
||||
if let Some(joints) = self.attribute_mut(Self::ATTRIBUTE_JOINT_WEIGHT) {
|
||||
let VertexAttributeValues::Float32x4(ref mut joints) = joints else {
|
||||
panic!("unexpected joint weight format");
|
||||
};
|
||||
|
||||
for weights in joints.iter_mut() {
|
||||
// force negative weights to zero
|
||||
weights.iter_mut().for_each(|w| *w = w.max(0.0));
|
||||
|
||||
let sum: f32 = weights.iter().sum();
|
||||
if sum == 0.0 {
|
||||
// all-zero weights are invalid
|
||||
weights[0] = 1.0;
|
||||
} else {
|
||||
let recip = sum.recip();
|
||||
for weight in weights.iter_mut() {
|
||||
*weight *= recip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
Loading…
Reference in a new issue