three_d/core/buffer/element_buffer.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use std::marker::PhantomData;
use crate::core::*;
/// The basic data type used for each index in an element buffer.
pub trait ElementBufferDataType: data_type::DataType {
///
/// Converts the index to `u32`.
///
fn as_u32(&self) -> u32;
}
impl ElementBufferDataType for u8 {
fn as_u32(&self) -> u32 {
*self as u32
}
}
impl ElementBufferDataType for u16 {
fn as_u32(&self) -> u32 {
*self as u32
}
}
impl ElementBufferDataType for u32 {
fn as_u32(&self) -> u32 {
*self
}
}
///
/// A buffer containing 3 indices for each triangle to be rendered, which is why it is also known as an index buffer.
/// The three indices refer to three places in a set of [VertexBuffer] where the data (position, normal etc.) is found for the three vertices of the triangle.
/// See for example [Program::draw_elements] to use this for drawing.
///
pub struct ElementBuffer<T: ElementBufferDataType> {
context: Context,
id: crate::context::Buffer,
count: u32,
_d: PhantomData<T>,
}
impl<T: ElementBufferDataType> ElementBuffer<T> {
///
/// Creates a new empty element buffer.
///
pub fn new(context: &Context) -> Self {
let id = unsafe { context.create_buffer().expect("Failed creating buffer") };
Self {
context: context.clone(),
id,
count: 0,
_d: PhantomData,
}
}
///
/// Creates a new element buffer and fills it with the given indices which must be divisable by 3.
///
pub fn new_with_data(context: &Context, data: &[T]) -> Self {
let mut buffer = Self::new(context);
if !data.is_empty() {
buffer.fill(data);
}
buffer
}
///
/// Fills the buffer with the given indices which must be divisable by 3.
/// This function will resize the buffer to have the same size as the indices array, if that is not desired, use [fill_subset](Self::fill_subset) instead.
///
pub fn fill(&mut self, indices: &[T]) {
self.bind();
unsafe {
self.context.buffer_data_u8_slice(
crate::context::ELEMENT_ARRAY_BUFFER,
to_byte_slice(indices),
crate::context::STATIC_DRAW,
);
self.context
.bind_buffer(crate::context::ELEMENT_ARRAY_BUFFER, None);
}
self.count = indices.len() as u32;
}
///
/// Fills the buffer with the given indices starting at the given offset.
/// This will increase the size of the buffer if there's not enough room. Otherwise, the size will remain unchanged.
///
pub fn fill_subset(&mut self, offset: u32, indices: &[T]) {
self.bind();
unsafe {
self.context.buffer_sub_data_u8_slice(
crate::context::ELEMENT_ARRAY_BUFFER,
offset as i32,
to_byte_slice(indices),
);
self.context
.bind_buffer(crate::context::ELEMENT_ARRAY_BUFFER, None);
}
self.count = (offset as u32 + indices.len() as u32).max(self.count);
}
///
/// The number of values in the buffer.
///
pub fn count(&self) -> u32 {
self.count
}
///
/// The number of triangles in the buffer.
///
pub fn triangle_count(&self) -> u32 {
self.count / 3
}
pub(crate) fn bind(&self) {
unsafe {
self.context
.bind_buffer(crate::context::ELEMENT_ARRAY_BUFFER, Some(self.id));
}
}
}
impl<T: ElementBufferDataType> Drop for ElementBuffer<T> {
fn drop(&mut self) {
unsafe {
self.context.delete_buffer(self.id);
}
}
}