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
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
|
|
}
|
|
}
|