use std::cell::RefCell;
use std::pin::Pin;
use crate::{
BufferData, BufferDataAccessor, BufferDescriptor, BufferElementType, BufferIndexAccessor,
ByteBuffer, Renderable, ShortIndex, VertexDesc, Vertices,
};
pub struct Buffers<'buffers> {
buffers: RefCell<Vec<Pin<Box<dyn ByteBuffer + 'buffers>>>>,
}
impl<'buffers> Buffers<'buffers> {
pub fn new() -> Self {
let buffers = Vec::new().into();
Self { buffers }
}
pub fn push(&self, buffer: Box<dyn ByteBuffer>) -> usize {
let mut buffers = self.buffers.borrow_mut();
let n = buffers.len();
buffers.push(buffer.into());
n
}
pub fn buffer(&self, n: usize) -> &'buffers dyn ByteBuffer {
let buffers = self.buffers.borrow();
assert!(n < buffers.len(), "Buffer index out of range");
let buffer = buffers[n].as_ref();
unsafe { std::mem::transmute::<&'_ dyn ByteBuffer, &'buffers dyn ByteBuffer>(&*buffer) }
}
}
pub struct DataAccessors<'buffers, R: Renderable> {
data: Vec<Pin<Box<BufferData<'buffers, R>>>>,
descriptors: Vec<Pin<Box<BufferDescriptor<'buffers, R>>>>,
index_accessors: Vec<Pin<Box<BufferIndexAccessor<'buffers, R>>>>,
data_accessors: Vec<Pin<Box<BufferDataAccessor<'buffers, R>>>>,
}
impl<'buffers, R: Renderable> DataAccessors<'buffers, R> {
pub fn new() -> Self {
let data = Vec::new();
let index_accessors = Vec::new();
let descriptors = Vec::new();
let data_accessors = Vec::new();
Self {
data,
descriptors,
data_accessors,
index_accessors,
}
}
pub fn push_buffer_data(
&mut self,
buffers: &Buffers<'buffers>,
buffer_n: usize,
byte_offset: u32,
byte_length: u32,
) -> usize {
let n = self.data.len();
let b = buffers.buffer(buffer_n);
let data = Box::new(BufferData::new(b, byte_offset, byte_length));
self.data.push(data.into());
n
}
pub fn push_index_accessor(
&mut self,
data: usize,
num: u32,
et: BufferElementType,
ofs: u32,
) -> usize {
let n = self.index_accessors.len();
let d = unsafe {
std::mem::transmute::<&BufferData<'_, R>, &'buffers BufferData<'buffers, R>>(
&self.data[data],
)
};
let accessor = Box::new(BufferIndexAccessor::new(d, num, et, ofs));
self.index_accessors.push(accessor.into());
n
}
pub fn push_descriptor(
&mut self,
data: usize,
byte_offset: u32,
mut byte_length: u32,
stride: u32,
) -> usize {
let n = self.data_accessors.len();
let d = unsafe {
std::mem::transmute::<&BufferData<'_, R>, &'buffers BufferData<'buffers, R>>(
&self.data[data],
)
};
if byte_length == 0 {
byte_length = d.byte_length() - byte_offset;
}
let desc = Box::new(BufferDescriptor::new(
d,
byte_offset,
byte_length,
stride,
vec![],
));
self.descriptors.push(desc.into());
n
}
pub fn push_data_accessor(&mut self, desc: usize, vertex_desc: VertexDesc) -> usize
where
<R as Renderable>::Descriptor: Unpin,
{
let n = self.data_accessors.len();
let desc_n = self.descriptors[desc].add_vertex_desc(vertex_desc);
let desc = unsafe {
std::mem::transmute::<&BufferDescriptor<'_, R>, &'buffers BufferDescriptor<'buffers, R>>(
&self.descriptors[desc],
)
};
let accessor = Box::new(BufferDataAccessor::new(desc, desc_n));
self.data_accessors.push(accessor.into());
n
}
pub fn indices(&self, n: Option<usize>) -> Option<&'buffers BufferIndexAccessor<'buffers, R>> {
if let Some(n) = n {
let buffer = self.index_accessors[n].as_ref();
Some(unsafe {
std::mem::transmute::<
&BufferIndexAccessor<'_, R>,
&'buffers BufferIndexAccessor<'buffers, R>,
>(&*buffer)
})
} else {
None
}
}
pub fn data_accessor(&self, n: usize) -> &'buffers BufferDataAccessor<'buffers, R> {
assert!(
n < self.data_accessors.len(),
"Data accessor index out of range"
);
let buffer = self.data_accessors[n].as_ref();
unsafe {
std::mem::transmute::<
&BufferDataAccessor<'_, R>,
&'buffers BufferDataAccessor<'buffers, R>,
>(&*buffer)
}
}
}
pub struct ExampleVertices<'buffers, R: Renderable> {
buffers: Buffers<'buffers>,
accessors: DataAccessors<'buffers, R>,
vertices: Vec<Vertices<'buffers, R>>,
}
impl<'a, R: Renderable> Default for ExampleVertices<'a, R> {
fn default() -> Self {
Self::new()
}
}
impl<'a, R: Renderable> ExampleVertices<'a, R> {
pub fn new() -> Self {
let buffers = Buffers::new();
let accessors = DataAccessors::new();
let vertices = Vec::new();
Self {
buffers,
accessors,
vertices,
}
}
pub fn push_byte_buffer(&mut self, buffer: Box<dyn ByteBuffer>) -> usize {
let buffer_n = self.buffers.push(buffer);
self.accessors
.push_buffer_data(&self.buffers, buffer_n, 0, 0)
}
pub fn push_index_accessor(
&mut self,
data: usize,
num: u32,
et: BufferElementType,
ofs: u32,
) -> usize {
self.accessors.push_index_accessor(data, num, et, ofs)
}
pub fn push_descriptor(
&mut self,
data: usize,
byte_offset: u32,
byte_length: u32,
stride: u32,
) -> usize {
self.accessors
.push_descriptor(data, byte_offset, byte_length, stride)
}
pub fn push_data_accessor(&mut self, desc: usize, vertex_desc: VertexDesc) -> usize
where
<R as Renderable>::Descriptor: Unpin,
{
self.accessors.push_data_accessor(desc, vertex_desc)
}
pub fn push_vertices(
&mut self,
indices: Option<usize>,
positions: usize,
attrs: &[usize],
) -> ShortIndex {
let n = self.vertices.len();
let i = self.accessors.indices(indices);
let v = self.accessors.data_accessor(positions);
let mut vertices = Vertices::new(i, v);
for view_id in attrs {
let v = self.accessors.data_accessor(*view_id);
vertices.add_attr(v);
}
self.vertices.push(vertices);
n.into()
}
pub fn borrow_vertices(&self, vertices: ShortIndex) -> &Vertices<R> {
&self.vertices[vertices.as_usize()]
}
}