blender_mesh/vertex_attributes/mod.rs
1mod vertex_attribute;
2
3pub use self::vertex_attribute::{BoneAttributes, VertexAttribute};
4use crate::bone::BoneInfluencesPerVertex;
5
6mod single_indexed;
7pub use self::single_indexed::*;
8
9/// Points to the data for each vertex.
10///
11/// Typically by the time a `MeshIr` has been prepared for rendering it will have every 3 indices
12/// correspond to one face - but this is not a requirement.
13///
14/// You could - for example - have 4 indices correspond to a face.
15///
16/// These can also be mixed. When exporting from Blender, for example, you might have
17/// `VertexIndices` that are grouped by 3 sometimes and 4 other times and even more other times -
18/// all within the same vector.
19///
20/// You can decipher this by referencing the [`vertices_in_each_face`]
21///
22/// ## A visualization
23///
24/// So way we have `VertexIndices` that correspond to a `vertex_uvs: (Vec<f32>, 2)`.
25///
26/// Say our `VertexIndices` and `vertex_uvs` look like the following:
27///
28/// ```rust,no_run
29/// let vertex_indices = vec![0, 1, 2, 0, 2, 3];
30/// let vertex_positions = vec![
31/// 0., 0.,
32/// 1., 0.,
33/// 1., 1.,
34/// 0., 1.,
35/// ];
36/// ```
37///
38/// In this case every vertex index corresponds to 3 vertex position floats.
39///
40/// | Index | Uv |
41/// | --- | --- |
42/// | 0 | &[0., 0.,] |
43/// | 1 | &[1., 0.,] |
44/// | 2 | &[1., 1.,] |
45/// | 3 | &[0., 1.,] |
46///
47/// When referenced in conjunction with `vertices_in_each_face` you can determine the
48/// positions of the vertices in each face.
49///
50/// For example, if `vertices_in_each_face: [3, 4, 3]`, then the first three position indices
51/// give you the positions for the triangle for the first face, then the next 4 position indices
52/// give you the quad for the next face, then the next three give you positions for the next
53/// triangle.
54///
55/// [`vertices_in_each_face`]: struct.MultiIndexVertexData.html#method.vertices_in_each_face
56pub type VertexIndices = Vec<u16>;
57
58/// Per vertex data from the BlenderMesh.
59///
60/// When exporting from Blender there data is exported with multiple indices,
61/// then after running `combine_vertex_indices` there will be one single index
62/// for all of the vertex data.
63#[derive(Debug, Serialize, Deserialize, PartialEq)]
64pub enum VertexAttributes {
65 /// The data has multiple indices per vertex, such as one for position data, uvs and normals,
66 /// etc.
67 Multi(MultiIndexedVertexAttributes),
68 /// The data has one single index per vertex
69 Single(SingleIndexedVertexAttributes),
70}
71
72impl Default for VertexAttributes {
73 fn default() -> Self {
74 VertexAttributes::Multi(MultiIndexedVertexAttributes::default())
75 }
76}
77
78/// Vertex data with multiple indices - not suited for OpenGL and other single index rendering
79/// pipelines, but good for on disk storage as their is less data duplicated when there are
80/// multiple indices.
81///
82/// TODO: A HashMap so that we can have arbitrary vertex attributes
83#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
84pub struct MultiIndexedVertexAttributes {
85 // The number of vertices that comprise each face of the mesh.
86 //
87 // For example, [3, 4, 4, 3, 3, 4] would mean that the first face has 3 vertices (triangle),
88 // the next face has 4 (quad), then the next face has 4, etc.
89 //
90 // ## Example Use Cases
91 //
92 // - Triangulation, where faces with more than 3 vertices need to be split into triangles.
93 //
94 // - Calculating vertex tangents, where all vertices in the same face will have the same
95 // tangent.
96 pub(crate) vertices_in_each_face: Vec<u8>,
97 pub(crate) positions: IndexedAttribute,
98 pub(crate) normals: Option<IndexedAttribute>,
99 pub(crate) uvs: Option<IndexedAttribute>,
100 pub(crate) bone_influences: Option<VertexBoneInfluences>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
104pub struct IndexedAttribute {
105 pub(crate) indices: VertexIndices,
106 pub(crate) attribute: VertexAttribute<f32>,
107}
108
109#[allow(missing_docs)]
110impl IndexedAttribute {
111 pub fn new(indices: VertexIndices, attribute: VertexAttribute<f32>) -> Self {
112 IndexedAttribute { indices, attribute }
113 }
114}
115
116impl From<(VertexIndices, VertexAttribute<f32>)> for IndexedAttribute {
117 fn from(v: (VertexIndices, VertexAttribute<f32>)) -> Self {
118 Self {
119 indices: v.0,
120 attribute: v.1,
121 }
122 }
123}
124
125impl From<MultiIndexedVertexAttributes> for VertexAttributes {
126 fn from(m: MultiIndexedVertexAttributes) -> Self {
127 VertexAttributes::Multi(m)
128 }
129}
130impl From<SingleIndexedVertexAttributes> for VertexAttributes {
131 fn from(s: SingleIndexedVertexAttributes) -> Self {
132 VertexAttributes::Single(s)
133 }
134}
135
136/// The amount that each bone in the mesh's parent armature influences each vertex.
137///
138/// For example, if `bone_indices = [0, 1, 2, 2, 5]` and
139/// `bone_weights = [0.2, 0.4, 0.2, 0.5, 0.5]` and `bones_per_vertex = [3, 2]` then
140/// the first vertex is influenced by bone 0 by 0.2, bone 1 by 0.4 and bone 2 by 0.2.
141///
142/// Then the second vertex is influenced by bone 2 by 0.5 and bone 5 by 0.5
143///
144/// TODO: Remove this and use VertexAttribute with something like attribute_size: Varies(vec![])
145/// this allows us to handle all attributes the same way.
146#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
147pub struct VertexBoneInfluences {
148 /// The number of bones that affect each vertex.
149 ///
150 /// Example: [3, 5, 2] would mean that the first vertex is influenced by 3 bones, second by
151 /// 5, and third by 2
152 pub(crate) bones_per_vertex: BoneInfluencesPerVertex,
153 /// The indices of the bones that affect each vertex.
154 pub(crate) bone_indices: Vec<u8>,
155 /// The corresponding weights of each bone index
156 pub(crate) bone_weights: Vec<f32>,
157}