use byteorder::{LittleEndian, ReadBytesExt}; use std::cmp; use std::convert::TryInto; use std::ffi::c_void; use std::io::Cursor; // Only contains f32 floats pub struct VertexBuffer { id: u32, // Not bytes. len: usize, } impl VertexBuffer { pub fn from_slice (slice: &[f32]) -> Self { const FLOAT_SIZE: usize = 4; let id = { let mut id = 0; unsafe { gl::GenBuffers (1, &mut id); gl::BindBuffer (gl::ARRAY_BUFFER, id); gl::BufferData (gl::ARRAY_BUFFER, (slice.len () * FLOAT_SIZE).try_into ().unwrap (), &slice [0] as *const f32 as *const c_void, gl::STATIC_DRAW); } assert! (id != 0); id }; Self { id, len: slice.len (), } } pub fn bind (&self) { unsafe { gl::BindBuffer (gl::ARRAY_BUFFER, self.id); } } } impl Drop for VertexBuffer { fn drop (&mut self) { if self.id == 0 { return; } unsafe { gl::DeleteBuffers (1, &self.id); } self.id = 0; } } pub struct IndexBuffer { id: u32, // Not bytes. Number of indexes. len: usize, max: u32, } impl IndexBuffer { pub fn from_slice (slice: &[u8]) -> Self { let mut rdr = Cursor::new (slice); let mut max = None; const IDX_SIZE: usize = 4; assert_eq! (slice.len () % IDX_SIZE, 0); for _ in 0..slice.len () / IDX_SIZE { let idx = rdr.read_u32:: ().unwrap (); max = match max { None => Some (idx), Some (max) => Some (cmp::max (max, idx)), }; } let id = { let mut id = 0; unsafe { gl::GenBuffers (1, &mut id); gl::BindBuffer (gl::ELEMENT_ARRAY_BUFFER, id); gl::BufferData (gl::ELEMENT_ARRAY_BUFFER, slice.len ().try_into ().unwrap (), &slice [0] as *const u8 as *const c_void, gl::STATIC_DRAW); } assert! (id != 0); id }; Self { id, len: slice.len () / IDX_SIZE, max: max.unwrap (), } } pub fn bind (&self) { unsafe { gl::BindBuffer (gl::ELEMENT_ARRAY_BUFFER, self.id); } } pub fn max (&self) -> u32 { self.max } } impl Drop for IndexBuffer { fn drop (&mut self) { if self.id == 0 { return; } unsafe { gl::DeleteBuffers (1, &self.id); } self.id = 0; } }