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}