1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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);
}
}