use crate::vertex_attributes::{MultiIndexedVertexAttributes, VertexBoneInfluences};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) enum BoneInfluencesPerVertex {
NonUniform(Vec<u8>),
Uniform(u8),
}
impl Default for BoneInfluencesPerVertex {
fn default() -> Self {
BoneInfluencesPerVertex::Uniform(0)
}
}
impl From<Vec<u8>> for BoneInfluencesPerVertex {
fn from(influences: Vec<u8>) -> Self {
BoneInfluencesPerVertex::NonUniform(influences)
}
}
impl MultiIndexedVertexAttributes {
pub(crate) fn set_bone_influences_per_vertex(&mut self, count: u8) {
let mut normalized_group_indices = vec![];
let mut normalized_group_weights = vec![];
let mut current_index: u32 = 0;
if self.bone_influences.is_none() {
return;
}
{
let VertexBoneInfluences {
bones_per_vertex,
bone_indices,
bone_weights,
} = self.bone_influences.as_mut().unwrap();
if let BoneInfluencesPerVertex::NonUniform(bone_influences_per_vertex) =
&bones_per_vertex
{
for group_count in bone_influences_per_vertex.iter() {
let mut vertex_indices = vec![];
let mut vertex_weights = vec![];
for index in current_index..(current_index + *group_count as u32) {
vertex_indices.push(index);
vertex_weights.push(bone_weights[index as usize]);
}
vertex_weights.sort_by(|a, b| b.partial_cmp(a).unwrap());
vertex_indices.sort_by(|a, b| {
bone_weights[*b as usize]
.partial_cmp(&bone_weights[*a as usize])
.unwrap()
});
let mut vertex_indices: Vec<u8> = vertex_indices
.iter()
.map(|i| bone_indices[*i as usize])
.collect();
vertex_indices.resize(count as usize, 0);
vertex_weights.resize(count as usize, 0.0);
normalized_group_indices.append(&mut vertex_indices);
normalized_group_weights.append(&mut vertex_weights);
current_index += *group_count as u32;
}
}
}
let mut bone_influences = self.bone_influences.as_mut().unwrap();
bone_influences.bones_per_vertex = BoneInfluencesPerVertex::Uniform(count);
bone_influences.bone_indices = normalized_group_indices;
bone_influences.bone_weights = normalized_group_weights;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::combine_indices::tests::TodoDeleteMeMultiConverter;
use crate::BlenderMesh;
#[test]
fn set_joints_per_vert() {
let mut start_mesh = BlenderMesh {
multi_indexed_vertex_attributes: TodoDeleteMeMultiConverter {
vertex_group_indices: Some(vec![0, 2, 3, 4, 0, 1, 3, 2]),
bone_influences_per_vertex: Some(vec![1, 3, 4].into()),
vertex_group_weights: Some(vec![1.0, 0.5, 0.2, 0.3, 0.6, 0.15, 0.1, 0.15]),
..TodoDeleteMeMultiConverter::default()
}
.into(),
..BlenderMesh::default()
};
start_mesh
.multi_indexed_vertex_attributes
.set_bone_influences_per_vertex(3);
let three_joints_per_vert = start_mesh;
let expected_mesh = BlenderMesh {
multi_indexed_vertex_attributes: TodoDeleteMeMultiConverter {
vertex_group_indices: Some(vec![0, 0, 0, 2, 4, 3, 0, 1, 2]),
bone_influences_per_vertex: Some(BoneInfluencesPerVertex::Uniform(3)),
vertex_group_weights: Some(vec![1.0, 0.0, 0.0, 0.5, 0.3, 0.2, 0.6, 0.15, 0.15]),
..TodoDeleteMeMultiConverter::default()
}
.into(),
..BlenderMesh::default()
};
assert_eq!(three_joints_per_vert, expected_mesh);
}
}