appy/utils/
array_buffer.rs

1use crate::gl;
2
3/// Abstraction for an OpenGL array buffer.
4///
5/// This array buffer can hold a number of floating point components.
6/// It is set as a flat array, but should be thought of as a two
7/// dimensional array. The number of components is the number of
8/// columns in the array. The array buffer can be bound to several
9/// attribute locations, with each attribute location using one or
10/// more components.
11pub struct ArrayBuffer {
12    vao: gl::types::GLuint,
13    vbo: gl::types::GLuint,
14    components: u32,
15    len: usize,
16}
17
18impl ArrayBuffer {
19    /// Create an [`ArrayBuffer`] with a specified number of components.
20    pub fn new(components: u32) -> Self {
21        let mut vao: gl::types::GLuint = 0;
22        unsafe {
23            gl::GenVertexArrays(1, &mut vao);
24            gl::BindVertexArray(vao);
25        }
26
27        let mut vbo: gl::types::GLuint = 0;
28        unsafe {
29            gl::GenBuffers(1, &mut vbo);
30        }
31
32        Self {
33            vao,
34            vbo,
35            components,
36            len: 0,
37        }
38    }
39
40    /// Get the number of items in the array.
41    pub fn len(&self) -> usize {
42        self.len
43    }
44
45    /*pub fn is_empty(&self) -> bool {
46        self.len == 0
47    }*/
48
49    /// Set data.
50    ///
51    /// The vertices array is a flat array, but should be thought of
52    /// as a two dimensional array. The length of the [`ArrayBuffer`] will
53    /// be the lenght of the array divided by the number of components.
54    pub fn set_data(&mut self, vertices: Vec<f32>) {
55        self.len = vertices.len() / self.components as usize;
56
57        unsafe {
58            gl::BindVertexArray(self.vao);
59            gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
60            gl::BufferData(
61                gl::ARRAY_BUFFER,                                                       // target
62                (vertices.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
63                vertices.as_ptr() as *const gl::types::GLvoid, // pointer to data
64                gl::STATIC_DRAW,                               // usage
65            );
66        }
67    }
68
69    /// Bind array buffer to an attribute location.
70    ///
71    /// The `offs` parameter specifies the first component to bind, and `num`
72    /// specifies the number of compontns to bind.
73    pub fn bind(&self, attrib_location: i32, offs: usize, num: u32) {
74        unsafe {
75            gl::BindVertexArray(self.vao);
76            gl::EnableVertexAttribArray(attrib_location as u32); // this is "layout (location = 0)" in vertex shader
77            gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
78            gl::VertexAttribPointer(
79                attrib_location as u32, // index of the generic vertex attribute ("layout (location = 0)")
80                num as i32,             // the number of components per generic vertex attribute
81                gl::FLOAT,              // data type
82                gl::FALSE,              // normalized (int-to-float conversion)
83                ((self.components as usize) * std::mem::size_of::<f32>()) as gl::types::GLint, // stride (byte offset between consecutive attributes)
84                (offs * std::mem::size_of::<f32>()) as *const _, // offset of the first component
85            );
86        }
87    }
88}