blender_mesh/vertex_attributes/single_indexed/
interleave.rs1use crate::vertex_attributes::VertexAttribute;
2use crate::SingleIndexedVertexAttributes;
3
4#[derive(Debug, thiserror::Error)]
6pub enum InterleaveError {
7 #[error("Only {num_provided} buffers were provided so there is nothing to interleave.")]
9 RequiresAtLeastTwoBuffers { num_provided: usize },
10 #[error("The length of each attribute should correspond to the same number of vertices")]
13 MismatchedLengths,
14}
15
16impl SingleIndexedVertexAttributes {
17 pub fn interleave<T: Copy>(attribs: &[&VertexAttribute<T>]) -> Result<Vec<T>, InterleaveError> {
34 if attribs.len() < 2 {
35 return Err(InterleaveError::RequiresAtLeastTwoBuffers {
36 num_provided: attribs.len(),
37 });
38 }
39
40 let vertex_count = attribs[0].data.len() as f32 / attribs[0].attribute_size as f32;
41
42 if !attribs
43 .iter()
44 .all(|attrib| attrib.len() as f32 / attrib.attribute_size as f32 == vertex_count)
45 {
46 return Err(InterleaveError::MismatchedLengths);
47 }
48
49 let vertex_count = vertex_count as usize;
50
51 let mut interleaved = vec![];
56
57 for vertex in 0..vertex_count {
58 for attrib in attribs {
59 let attribuze_size = attrib.attribute_size as usize;
60 let index = vertex * attribuze_size;
61 for idx in index..index + attribuze_size {
62 interleaved.push(attrib.data[idx]);
63 }
64 }
65 }
66
67 Ok(interleaved)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
77 fn combine_two_attributes() {
78 let positions = VertexAttribute::new(vec![0., 1., 2., 3., 4., 5.], 3).unwrap();
79 let uvs = VertexAttribute::new(vec![50., 51., 52., 53.], 2).unwrap();
80
81 let combined = SingleIndexedVertexAttributes::interleave(&[&positions, &uvs]).unwrap();
82
83 assert_eq!(combined, vec![0., 1., 2., 50., 51., 3., 4., 5., 52., 53.]);
84 }
85
86 #[test]
88 fn only_one_buffer_provided() {
89 let positions = VertexAttribute::new(vec![0., 1., 2., 3., 4., 5.], 3).unwrap();
90 match SingleIndexedVertexAttributes::interleave(&[&positions]) {
91 Err(InterleaveError::RequiresAtLeastTwoBuffers { num_provided: 1 }) => {}
92 _ => unreachable!(),
93 };
94 }
95
96 #[test]
98 fn error_if_incompatible_lengths() {
99 let positions = VertexAttribute::new(vec![0.], 3).unwrap();
100 let uvs = VertexAttribute::new(vec![50., 51., 52., 53.], 2).unwrap();
101
102 match SingleIndexedVertexAttributes::interleave(&[&positions, &uvs]) {
103 Err(InterleaveError::MismatchedLengths {}) => {}
104 _ => unreachable!(),
105 };
106 }
107}