use crate::types::TypeDescriptor; use std::ffi::c_void; use std::ops::Range; pub struct StaticBufferNonIndexed { pub vao: u32, pub attributes: Vec, pub elements: usize, } impl StaticBufferNonIndexed { pub fn bind(&self) { unsafe { gl::BindVertexArray(self.vao); } } pub fn draw(&self) { self.bind(); unsafe { gl::DrawArrays(gl::TRIANGLES, 0, self.elements as i32) } } } pub struct StaticBuffer { pub vao: u32, pub attributes: Vec, pub ebo: u32, pub indices: usize, } impl StaticBuffer { pub fn bind(&self) { unsafe { gl::BindVertexArray(self.vao); gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo); } } pub fn draw(&self) { self.bind(); unsafe { gl::DrawElements( gl::TRIANGLES, self.indices as i32, gl::UNSIGNED_INT, 0 as *const c_void, ) } } } impl Drop for StaticBuffer { fn drop(&mut self) { unsafe { gl::DeleteVertexArrays(1, [self.vao].as_ptr()) } } } pub struct Attributes { mem: Box<[u8]>, pub attributes: Vec, pub size: usize, pub elements: usize, } impl Attributes { pub fn as_ptr(&self) -> *const c_void { self.mem.as_ptr() as *const c_void } } pub struct Attribute { pub amount: usize, pub stride: usize, pub offset: usize, pub gl_type: u32, } pub trait VertexData { fn get_sizes() -> Box<[usize]>; fn get_types() -> Box<[TypeDescriptor]>; fn get_pointers(&self) -> Box<[*const c_void]>; } pub trait VertexDataCollection where D: VertexData, { fn get_amount(&self) -> usize; fn get_list(&self) -> &[D]; fn create_ptr(&self, interleaved: bool, range: Option>) -> Attributes { let sizes = D::get_sizes(); let struct_size = sizes.clone().iter().sum(); let range = range.unwrap_or(0..self.get_amount()); let amount = range.end - range.start; let mut list = vec![0u8; struct_size * amount]; let items = self.get_list(); for i in range.clone() { let item = &items[i]; let pointers = item.get_pointers(); let sizes_and_pointers = sizes .iter() .zip(pointers.iter()) .collect::>(); let mut offset = 0; for (size, ptr) in sizes_and_pointers { let index = if interleaved { offset + (struct_size * (i - range.start)) } else { (offset * amount) + size * i }; unsafe { std::ptr::copy(ptr.cast(), list.as_mut_ptr().add(index), *size); } offset += size; } } let mut attributes = vec![]; let mut offset = 0; for (size, type_desc) in sizes.iter().zip(D::get_types().iter()) { attributes.push(Attribute { amount: type_desc.amount as usize, gl_type: type_desc.gl_type, stride: if interleaved { struct_size } else { *size }, offset: if interleaved { offset } else { offset * amount }, }); offset += *size; } Attributes { mem: list.into_boxed_slice(), attributes, size: struct_size * amount, elements: items.len(), } } } impl VertexDataCollection for Vec { fn get_amount(&self) -> usize { self.len() } fn get_list(&self) -> &[D] { &self } } impl VertexDataCollection for &[D] { fn get_amount(&self) -> usize { self.len() } fn get_list(&self) -> &[D] { self } } impl VertexDataCollection for Box<[D]> { fn get_amount(&self) -> usize { self.len() } fn get_list(&self) -> &[D] { &self } } impl VertexDataCollection for [D] { fn get_amount(&self) -> usize { self.len() } fn get_list(&self) -> &[D] { &self } }