three_d/core/buffer/
element_buffer.rs

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