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