mod3d_base/example_objects/
example_vertices.rs

1//a Imports
2use std::cell::RefCell;
3use std::pin::Pin;
4
5use crate::{
6    BufferData, BufferDataAccessor, BufferDescriptor, BufferElementType, BufferIndexAccessor,
7    ByteBuffer, Renderable, ShortIndex, VertexDesc, Vertices,
8};
9
10//a ExampleBuffers
11//tp ExampleBuffers
12/// This is a monotonically increasing [Vec] of buffers, which are immutable once added to the struct
13///
14/// It allows the buffers to be borrowed (immutably) for the lifetime
15/// of the structure, even if later more buffers are added to the Vec
16pub struct Buffers<'buffers> {
17    buffers: RefCell<Vec<Pin<Box<dyn ByteBuffer + 'buffers>>>>,
18}
19
20//ip Buffers
21impl<'buffers> Buffers<'buffers> {
22    //fp new
23    /// Create a new empty [Buffers]
24    pub fn new() -> Self {
25        let buffers = Vec::new().into();
26        Self { buffers }
27    }
28
29    //mp push
30    /// Push a new [ByteBuffer] implementation and return its index
31    pub fn push(&self, buffer: Box<dyn ByteBuffer>) -> usize {
32        let mut buffers = self.buffers.borrow_mut();
33        let n = buffers.len();
34        buffers.push(buffer.into());
35        n
36    }
37
38    //ap Borrow a buffer
39    /// Get a reference to one of the buffers held by self;
40    pub fn buffer(&self, n: usize) -> &'buffers dyn ByteBuffer {
41        let buffers = self.buffers.borrow();
42        assert!(n < buffers.len(), "Buffer index out of range");
43        let buffer = buffers[n].as_ref();
44        // Safety:
45        //
46        // Extending the lifetime of the reference to the ByteBuffer to
47        // that of self is safe as each element of self.buffers is not
48        // able to move (they are Pinned) and this reference cannot
49        // outlive self.buffers, and the references are guaranteed not to
50        // be used during the drop of Self
51        unsafe { std::mem::transmute::<&'_ dyn ByteBuffer, &'buffers dyn ByteBuffer>(&*buffer) }
52    }
53}
54
55//a DataAccessors
56//tp DataAccessors
57/// This structure helps for objects; the data is
58pub struct DataAccessors<'buffers, R: Renderable> {
59    data: Vec<Pin<Box<BufferData<'buffers, R>>>>,
60    descriptors: Vec<Pin<Box<BufferDescriptor<'buffers, R>>>>,
61    index_accessors: Vec<Pin<Box<BufferIndexAccessor<'buffers, R>>>>,
62    data_accessors: Vec<Pin<Box<BufferDataAccessor<'buffers, R>>>>,
63}
64
65//ip DataAccessors
66impl<'buffers, R: Renderable> DataAccessors<'buffers, R> {
67    //fp new
68    /// Create a new [DataAccessors]
69    pub fn new() -> Self {
70        let data = Vec::new();
71        let index_accessors = Vec::new();
72        let descriptors = Vec::new();
73        let data_accessors = Vec::new();
74        Self {
75            data,
76            descriptors,
77            data_accessors,
78            index_accessors,
79        }
80    }
81
82    //fp push_buffer_data
83    /// Push a new [BufferData] that is a portion of a Buffer
84    pub fn push_buffer_data(
85        &mut self,
86        buffers: &Buffers<'buffers>,
87        buffer_n: usize,
88        byte_offset: u32,
89        byte_length: u32,
90    ) -> usize {
91        let n = self.data.len();
92        let b = buffers.buffer(buffer_n);
93        let data = Box::new(BufferData::new(b, byte_offset, byte_length));
94        self.data.push(data.into());
95        n
96    }
97
98    //fp push_index_accessor
99    /// Create a new [BufferIndexAccessor] on a particular [BufferData] instance that has already been pushed
100    pub fn push_index_accessor(
101        &mut self,
102        data: usize,
103        num: u32,
104        et: BufferElementType,
105        ofs: u32,
106    ) -> usize {
107        let n = self.index_accessors.len();
108        // Safety:
109        //
110        // Extending the lifetime of the reference to BufferIndexAccessor to
111        // that of self is safe as each element of self.descriptors is not
112        // able to move (they are Pinned) and this reference cannot
113        // outlive self.index_accessors, and the references are guaranteed not to
114        // be used during the drop of Self
115        let d = unsafe {
116            std::mem::transmute::<&BufferData<'_, R>, &'buffers BufferData<'buffers, R>>(
117                &self.data[data],
118            )
119        };
120        let accessor = Box::new(BufferIndexAccessor::new(d, num, et, ofs));
121        self.index_accessors.push(accessor.into());
122        n
123    }
124
125    //fp push_descriptor
126    /// Create a new [BufferDescriptor<] on a particular [BufferData]
127    /// instance that has already been pushed
128    pub fn push_descriptor(
129        &mut self,
130        data: usize,
131        byte_offset: u32,
132        mut byte_length: u32,
133        stride: u32,
134    ) -> usize {
135        let n = self.data_accessors.len();
136        // Safety:
137        //
138        // Extending the lifetime of the reference to BufferData to
139        // that of self is safe as each element of self.data is not
140        // able to move (they are Pinned) and this reference cannot
141        // outlive self.data, and the references are guaranteed not to
142        // be used during the drop of Self
143        let d = unsafe {
144            std::mem::transmute::<&BufferData<'_, R>, &'buffers BufferData<'buffers, R>>(
145                &self.data[data],
146            )
147        };
148        if byte_length == 0 {
149            byte_length = d.byte_length() - byte_offset;
150        }
151        let desc = Box::new(BufferDescriptor::new(
152            d,
153            byte_offset,
154            byte_length,
155            stride,
156            vec![],
157        ));
158        self.descriptors.push(desc.into());
159        n
160    }
161
162    //fp push_data_accessor
163    /// Create a new [BufferAccessor] on a particular [BufferData] instance that has already been pushed
164    pub fn push_data_accessor(&mut self, desc: usize, vertex_desc: VertexDesc) -> usize
165    where
166        <R as Renderable>::Descriptor: Unpin,
167    {
168        let n = self.data_accessors.len();
169        let desc_n = self.descriptors[desc].add_vertex_desc(vertex_desc);
170        // Safety:
171        //
172        // Extending the lifetime of the reference to BufferDescriptor to
173        // that of self is safe as each element of self.descriptors is not
174        // able to move (they are Pinned) and this reference cannot
175        // outlive self.descriptors, and the references are guaranteed not to
176        // be used during the drop of Self
177        let desc = unsafe {
178            std::mem::transmute::<&BufferDescriptor<'_, R>, &'buffers BufferDescriptor<'buffers, R>>(
179                &self.descriptors[desc],
180            )
181        };
182        let accessor = Box::new(BufferDataAccessor::new(desc, desc_n));
183        self.data_accessors.push(accessor.into());
184        n
185    }
186
187    //ap indices
188    /// Get a buffer-lifetime reference to a buffer-lifetime [BufferIndexAccessor]
189    pub fn indices(&self, n: Option<usize>) -> Option<&'buffers BufferIndexAccessor<'buffers, R>> {
190        if let Some(n) = n {
191            let buffer = self.index_accessors[n].as_ref();
192            // Safety:
193            //
194            // Extending the lifetime of the reference to BufferIndexAccessor to
195            // that of self is safe as each element of self.index_accessors is not
196            // able to move (they are Pinned) and this reference cannot
197            // outlive self.index_accessors, and the references are guaranteed not to
198            // be used during the drop of Self
199            Some(unsafe {
200                std::mem::transmute::<
201                    &BufferIndexAccessor<'_, R>,
202                    &'buffers BufferIndexAccessor<'buffers, R>,
203                >(&*buffer)
204            })
205        } else {
206            None
207        }
208    }
209    //ap data_accessor
210    /// Get a buffer-lifetime reference to a buffer-lifetime [BufferDataAccessor]
211    pub fn data_accessor(&self, n: usize) -> &'buffers BufferDataAccessor<'buffers, R> {
212        assert!(
213            n < self.data_accessors.len(),
214            "Data accessor index out of range"
215        );
216        let buffer = self.data_accessors[n].as_ref();
217        // Safety:
218        //
219        // Extending the lifetime of the reference to BufferDataAccessor to
220        // that of self is safe as each element of self.data_accessors is not
221        // able to move (they are Pinned) and this reference cannot
222        // outlive self.data_accessors, and the references are guaranteed not to
223        // be used during the drop of Self
224        unsafe {
225            std::mem::transmute::<
226                &BufferDataAccessor<'_, R>,
227                &'buffers BufferDataAccessor<'buffers, R>,
228            >(&*buffer)
229        }
230    }
231}
232
233//a ExampleVertices
234//tp ExampleVertices
235/// This structure provides for creating example objects, particularly with regard to their vertices
236///
237/// It uses arrays of [Pin]ned data structures so that the data can be safely self-referential
238pub struct ExampleVertices<'buffers, R: Renderable> {
239    buffers: Buffers<'buffers>,
240    accessors: DataAccessors<'buffers, R>,
241    vertices: Vec<Vertices<'buffers, R>>,
242}
243
244//ip Default for ExampleVertices
245impl<'a, R: Renderable> Default for ExampleVertices<'a, R> {
246    fn default() -> Self {
247        Self::new()
248    }
249}
250
251//ip ExampleVertices
252impl<'a, R: Renderable> ExampleVertices<'a, R> {
253    //fp new
254    /// Create a new [ExampleVertices]
255    ///
256    /// This should probably not be Pin<Box<>>
257    pub fn new() -> Self {
258        let buffers = Buffers::new();
259        let accessors = DataAccessors::new();
260        let vertices = Vec::new();
261        Self {
262            buffers,
263            accessors,
264            vertices,
265        }
266    }
267
268    //fp push_byte_buffer
269    /// Push a new [ByteBuffer] implementation and return its index
270    pub fn push_byte_buffer(&mut self, buffer: Box<dyn ByteBuffer>) -> usize {
271        let buffer_n = self.buffers.push(buffer);
272        self.accessors
273            .push_buffer_data(&self.buffers, buffer_n, 0, 0)
274    }
275
276    //fp push_index_accessor
277    /// Create a new [BufferAccessor] on a particular [ByteBuffer] instance that has already been pushed
278    pub fn push_index_accessor(
279        &mut self,
280        data: usize,
281        num: u32,
282        et: BufferElementType,
283        ofs: u32,
284    ) -> usize {
285        self.accessors.push_index_accessor(data, num, et, ofs)
286    }
287
288    //fp push_descriptor
289    /// Create a new [BufferDescriptor<] on a particular [BufferData]
290    /// instance that has already been pushed
291    pub fn push_descriptor(
292        &mut self,
293        data: usize,
294        byte_offset: u32,
295        byte_length: u32,
296        stride: u32,
297    ) -> usize {
298        self.accessors
299            .push_descriptor(data, byte_offset, byte_length, stride)
300    }
301
302    //fp push_data_accessor
303    /// Create a new [BufferAccessor] on a particular [ByteBuffer] instance that has already been pushed
304    pub fn push_data_accessor(&mut self, desc: usize, vertex_desc: VertexDesc) -> usize
305    where
306        <R as Renderable>::Descriptor: Unpin,
307    {
308        self.accessors.push_data_accessor(desc, vertex_desc)
309    }
310
311    //fp push_vertices
312    /// Create a new [Vertices] using a set of indices and positions
313    ///
314    /// This extends the life of the BufferAccessor to that of the ExampleVertices
315    ///
316    /// This is safe as the BufferAccessor's are in the Vec for ExampleVertices
317    pub fn push_vertices(
318        &mut self,
319        indices: Option<usize>,
320        positions: usize,
321        attrs: &[usize],
322    ) -> ShortIndex {
323        let n = self.vertices.len();
324        let i = self.accessors.indices(indices);
325        let v = self.accessors.data_accessor(positions);
326        let mut vertices = Vertices::new(i, v);
327        for view_id in attrs {
328            let v = self.accessors.data_accessor(*view_id);
329            vertices.add_attr(v);
330        }
331        self.vertices.push(vertices);
332        n.into()
333    }
334
335    //fp borrow_vertices
336    /// Borrow a set of vertices; this would allow (if mut!) the vertices to have attributes added
337    pub fn borrow_vertices(&self, vertices: ShortIndex) -> &Vertices<R> {
338        &self.vertices[vertices.as_usize()]
339    }
340}