You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
4.2 KiB
Rust

use crate::types::TypeDescriptor;
use std::ffi::c_void;
use std::ops::Range;
pub struct StaticBufferNonIndexed {
pub vao: u32,
pub attributes: Vec<Attribute>,
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<Attribute>,
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<Attribute>,
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<D>
where
D: VertexData,
{
fn get_amount(&self) -> usize;
fn get_list(&self) -> &[D];
fn create_ptr(&self, interleaved: bool, range: Option<Range<usize>>) -> 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::<Vec<(&usize, &*const c_void)>>();
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<D: VertexData> VertexDataCollection<D> for Vec<D> {
fn get_amount(&self) -> usize {
self.len()
}
fn get_list(&self) -> &[D] {
&self
}
}
impl<D: VertexData> VertexDataCollection<D> for &[D] {
fn get_amount(&self) -> usize {
self.len()
}
fn get_list(&self) -> &[D] {
self
}
}
impl<D: VertexData> VertexDataCollection<D> for Box<[D]> {
fn get_amount(&self) -> usize {
self.len()
}
fn get_list(&self) -> &[D] {
&self
}
}
impl<D: VertexData> VertexDataCollection<D> for [D] {
fn get_amount(&self) -> usize {
self.len()
}
fn get_list(&self) -> &[D] {
&self
}
}