spitfire_core/
lib.rs

1use bytemuck::{Pod, Zeroable};
2use std::{ops::Range, vec::Drain};
3
4#[derive(Debug, Copy, Clone, Pod, Zeroable)]
5#[repr(C)]
6pub struct Triangle {
7    pub a: u32,
8    pub b: u32,
9    pub c: u32,
10}
11
12impl Default for Triangle {
13    fn default() -> Self {
14        Self { a: 0, b: 1, c: 2 }
15    }
16}
17
18impl Triangle {
19    pub fn offset(mut self, offset: usize) -> Self {
20        self.a += offset as u32;
21        self.b += offset as u32;
22        self.c += offset as u32;
23        self
24    }
25}
26
27#[derive(Debug, Clone, Copy)]
28pub struct VertexStreamToken {
29    vertices: usize,
30    triangles: usize,
31    batches: usize,
32}
33
34pub struct VertexStream<V: Pod, B> {
35    vertices: Vec<V>,
36    triangles: Vec<Triangle>,
37    batches: Vec<(B, Range<usize>)>,
38    resize_count: usize,
39}
40
41impl<V: Pod, B> Default for VertexStream<V, B> {
42    fn default() -> Self {
43        Self {
44            vertices: Vec::with_capacity(1024),
45            triangles: Vec::with_capacity(1024),
46            batches: Vec::with_capacity(1024),
47            resize_count: 1024,
48        }
49    }
50}
51
52impl<V: Pod, B> VertexStream<V, B> {
53    pub fn new(resize_count: usize) -> Self {
54        Self {
55            vertices: Vec::with_capacity(resize_count),
56            triangles: Vec::with_capacity(resize_count),
57            batches: Vec::with_capacity(resize_count),
58            resize_count,
59        }
60    }
61
62    pub fn fork(&self) -> Self {
63        Self::new(self.resize_count)
64    }
65
66    pub fn token(&self) -> VertexStreamToken {
67        VertexStreamToken {
68            vertices: self.vertices.len(),
69            triangles: self.triangles.len(),
70            batches: self.batches.len(),
71        }
72    }
73
74    /// # Safety
75    /// By extracting part of stream, you might make this and new stream invalid!
76    pub unsafe fn extract(&mut self, token: VertexStreamToken) -> Self {
77        let VertexStreamToken {
78            vertices,
79            triangles,
80            batches,
81        } = token;
82        let mut result = self.fork();
83        unsafe {
84            result.extend_vertices(self.vertices.drain(vertices..));
85            result.extend_triangles(
86                false,
87                self.triangles.drain(triangles..).map(|mut triangle| {
88                    triangle.a -= vertices as u32;
89                    triangle.b -= vertices as u32;
90                    triangle.c -= vertices as u32;
91                    triangle
92                }),
93            );
94            result.extend_batches(self.batches.drain(batches..).map(|(batch, mut range)| {
95                range.start -= triangles;
96                range.end -= triangles;
97                (batch, range)
98            }));
99        }
100        result
101    }
102
103    pub fn transformed(
104        &mut self,
105        mut f: impl FnMut(&mut Self),
106        mut t: impl FnMut(&mut V),
107    ) -> &mut Self {
108        let start = self.vertices.len();
109        f(self);
110        let end = self.vertices.len();
111        for vertex in &mut self.vertices[start..end] {
112            t(vertex);
113        }
114        self
115    }
116
117    pub fn triangle(&mut self, vertices: [V; 3]) -> &mut Self {
118        self.ensure_capacity();
119        let offset = self.vertices.len();
120        self.vertices.extend(vertices);
121        self.triangles.push(Triangle::default().offset(offset));
122        self
123    }
124
125    pub fn triangle_fan(&mut self, vertices: impl IntoIterator<Item = V>) -> &mut Self {
126        self.ensure_capacity();
127        let start = self.vertices.len() as u32;
128        self.vertices.extend(vertices);
129        let end = self.vertices.len() as u32;
130        let count = (end - start).saturating_sub(2);
131        let mut offset = start + 1;
132        for _ in 0..count {
133            self.triangles.push(Triangle {
134                a: start,
135                b: offset,
136                c: offset + 1,
137            });
138            offset += 1;
139        }
140        self
141    }
142
143    pub fn triangle_strip(&mut self, vertices: impl IntoIterator<Item = V>) -> &mut Self {
144        self.ensure_capacity();
145        let start = self.vertices.len() as u32;
146        self.vertices.extend(vertices);
147        let end = self.vertices.len() as u32;
148        let count = (end - start).saturating_sub(2);
149        let mut offset = start;
150        let mut flip = false;
151        for _ in 0..count {
152            self.triangles.push(if flip {
153                Triangle {
154                    a: offset + 1,
155                    b: offset,
156                    c: offset + 2,
157                }
158            } else {
159                Triangle {
160                    a: offset,
161                    b: offset + 1,
162                    c: offset + 2,
163                }
164            });
165            offset += 1;
166            flip = !flip;
167        }
168        self
169    }
170
171    pub fn quad(&mut self, vertices: [V; 4]) -> &mut Self {
172        self.ensure_capacity();
173        let offset = self.vertices.len();
174        self.vertices.extend(vertices);
175        self.triangles
176            .push(Triangle { a: 0, b: 1, c: 2 }.offset(offset));
177        self.triangles
178            .push(Triangle { a: 2, b: 3, c: 0 }.offset(offset));
179        self
180    }
181
182    pub fn extend(
183        &mut self,
184        vertices: impl IntoIterator<Item = V>,
185        triangles: impl IntoIterator<Item = Triangle>,
186    ) -> &mut Self {
187        self.ensure_capacity();
188        let offset = self.vertices.len();
189        self.vertices.extend(vertices);
190        self.triangles.extend(
191            triangles
192                .into_iter()
193                .map(|triangle| triangle.offset(offset)),
194        );
195        self
196    }
197
198    /// # Safety
199    /// By writing raw vertices you might produce invalid renderables!
200    pub unsafe fn extend_vertices(&mut self, iter: impl IntoIterator<Item = V>) -> &Self {
201        self.vertices.extend(iter);
202        self
203    }
204
205    /// # Safety
206    /// By writing raw triangles you might produce invalid renderables!
207    pub unsafe fn extend_triangles(
208        &mut self,
209        relative: bool,
210        iter: impl IntoIterator<Item = Triangle>,
211    ) -> &Self {
212        if relative {
213            let offset = self.vertices.len();
214            self.triangles
215                .extend(iter.into_iter().map(|triangle| triangle.offset(offset)));
216        } else {
217            self.triangles.extend(iter);
218        }
219        self
220    }
221
222    /// # Safety
223    /// By writing raw batches you might produce invalid renderables!
224    pub unsafe fn extend_batches(
225        &mut self,
226        iter: impl IntoIterator<Item = (B, Range<usize>)>,
227    ) -> &Self {
228        self.batches.extend(iter);
229        self
230    }
231
232    pub fn append(&mut self, other: &mut Self) {
233        let offset = self.triangles.len();
234        self.extend(other.vertices.drain(..), other.triangles.drain(..));
235        self.batches.extend(
236            other
237                .batches
238                .drain(..)
239                .map(|(data, range)| (data, (range.start + offset)..(range.end + offset))),
240        );
241    }
242
243    pub fn append_cloned(&mut self, other: &Self)
244    where
245        B: Clone,
246    {
247        let offset = self.triangles.len();
248        self.extend(
249            other.vertices.iter().copied(),
250            other.triangles.iter().copied(),
251        );
252        self.batches.extend(
253            other
254                .batches
255                .iter()
256                .map(|(data, range)| (data.clone(), (range.start + offset)..(range.end + offset))),
257        );
258    }
259
260    pub fn clear(&mut self) {
261        self.vertices.clear();
262        self.triangles.clear();
263        self.batches.clear();
264    }
265
266    pub fn batch(&mut self, data: B) {
267        if self.batches.len() == self.batches.capacity() {
268            self.batches.reserve_exact(self.resize_count);
269        }
270        self.batch_end();
271        let start = self.triangles.len();
272        self.batches.push((data, start..start))
273    }
274
275    pub fn batch_optimized(&mut self, data: B)
276    where
277        B: PartialEq,
278    {
279        if let Some(last) = self.batches.last_mut() {
280            if last.0 == data {
281                last.1.end = self.triangles.len();
282                return;
283            }
284        }
285        self.batch(data);
286    }
287
288    pub fn batch_end(&mut self) {
289        if let Some(last) = self.batches.last_mut() {
290            last.1.end = self.triangles.len();
291        }
292    }
293
294    pub fn render<R: VertexStreamRenderer<V, B>>(
295        &mut self,
296        renderer: &mut R,
297    ) -> Result<(), R::Error> {
298        self.batch_end();
299        renderer.render(self)
300    }
301
302    pub fn vertices(&self) -> &[V] {
303        &self.vertices
304    }
305
306    pub fn triangles(&self) -> &[Triangle] {
307        &self.triangles
308    }
309
310    pub fn batches(&self) -> &[(B, Range<usize>)] {
311        &self.batches
312    }
313
314    #[allow(clippy::type_complexity)]
315    pub fn drain(&mut self) -> (Drain<V>, Drain<Triangle>, Drain<(B, Range<usize>)>) {
316        self.batch_end();
317        (
318            self.vertices.drain(..),
319            self.triangles.drain(..),
320            self.batches.drain(..),
321        )
322    }
323
324    fn ensure_capacity(&mut self) {
325        if self.vertices.len() == self.vertices.capacity() {
326            self.vertices.reserve_exact(self.resize_count);
327        }
328        if self.triangles.len() == self.triangles.capacity() {
329            self.triangles.reserve_exact(self.resize_count);
330        }
331    }
332}
333
334pub trait VertexStreamRenderer<V: Pod, B> {
335    type Error;
336
337    fn render(&mut self, stream: &mut VertexStream<V, B>) -> Result<(), Self::Error>;
338}
339
340impl<V: Pod, B> VertexStreamRenderer<V, B> for () {
341    type Error = ();
342
343    fn render(&mut self, _: &mut VertexStream<V, B>) -> Result<(), Self::Error> {
344        Ok(())
345    }
346}