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
use crate::vertex_attributes::VertexAttribute;
use crate::SingleIndexedVertexAttributes;
#[derive(Debug, thiserror::Error)]
pub enum InterleaveError {
#[error("Only {num_provided} buffers were provided so there is nothing to interleave.")]
RequiresAtLeastTwoBuffers { num_provided: usize },
#[error("The length of each attribute should correspond to the same number of vertices")]
MismatchedLengths,
}
impl SingleIndexedVertexAttributes {
pub fn interleave<T: Copy>(attribs: &[&VertexAttribute<T>]) -> Result<Vec<T>, InterleaveError> {
if attribs.len() < 2 {
return Err(InterleaveError::RequiresAtLeastTwoBuffers {
num_provided: attribs.len(),
});
}
let vertex_count = attribs[0].data.len() as f32 / attribs[0].attribute_size as f32;
if !attribs
.iter()
.all(|attrib| attrib.len() as f32 / attrib.attribute_size as f32 == vertex_count)
{
return Err(InterleaveError::MismatchedLengths);
}
let vertex_count = vertex_count as usize;
let mut interleaved = vec![];
for vertex in 0..vertex_count {
for attrib in attribs {
let attribuze_size = attrib.attribute_size as usize;
let index = vertex * attribuze_size;
for idx in index..index + attribuze_size {
interleaved.push(attrib.data[idx]);
}
}
}
Ok(interleaved)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn combine_two_attributes() {
let positions = VertexAttribute::new(vec![0., 1., 2., 3., 4., 5.], 3).unwrap();
let uvs = VertexAttribute::new(vec![50., 51., 52., 53.], 2).unwrap();
let combined = SingleIndexedVertexAttributes::interleave(&[&positions, &uvs]).unwrap();
assert_eq!(combined, vec![0., 1., 2., 50., 51., 3., 4., 5., 52., 53.]);
}
#[test]
fn only_one_buffer_provided() {
let positions = VertexAttribute::new(vec![0., 1., 2., 3., 4., 5.], 3).unwrap();
match SingleIndexedVertexAttributes::interleave(&[&positions]) {
Err(InterleaveError::RequiresAtLeastTwoBuffers { num_provided: 1 }) => {}
_ => unreachable!(),
};
}
#[test]
fn error_if_incompatible_lengths() {
let positions = VertexAttribute::new(vec![0.], 3).unwrap();
let uvs = VertexAttribute::new(vec![50., 51., 52., 53.], 2).unwrap();
match SingleIndexedVertexAttributes::interleave(&[&positions, &uvs]) {
Err(InterleaveError::MismatchedLengths {}) => {}
_ => unreachable!(),
};
}
}