reverie_engine_opengl/vao/
buffer.rs

1//! 頂点の情報を動的に追加・削除するためのバッファ
2
3use std::marker::PhantomData;
4use std::mem;
5
6use crate::gl;
7use crate::gl::types::{GLenum, GLint};
8use crate::gl::{types::GLfloat, Gl};
9use crate::vao::Vao;
10use crate::vao::VaoConfig;
11use crate::vao::VertexType;
12
13/// 頂点の情報を動的に追加・削除するためのバッファ
14#[derive(Debug)]
15pub struct VaoBuffer<V: VertexType> {
16    vertex_size: usize,
17    num_attributes: usize,
18    attribute_types: &'static [GLenum],
19    attribute_sizes: &'static [GLint],
20    buffer: Vec<f32>,
21    vertex_num: i32,
22    _phantom: PhantomData<V>,
23}
24
25impl<V: VertexType> Default for VaoBuffer<V> {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl<V: VertexType> VaoBuffer<V> {
32    /// 空の[`VaoBuffer`]を作る
33    pub fn new() -> Self {
34        Self {
35            buffer: Vec::<f32>::new(),
36            vertex_num: 0,
37            vertex_size: V::vertex_size(),
38            num_attributes: V::attribute_sizes().len(),
39            attribute_sizes: V::attribute_sizes(),
40            attribute_types: V::attribute_types(),
41            _phantom: PhantomData,
42        }
43    }
44
45    /// 初期のバッファーサイズを指定して[`VaoBuffer`]を作る
46    ///
47    /// `num_vertex_to_reserve`個の頂点が確保できるだけの初期容量になる。
48    pub fn with_num_vertex(num_vertex_to_reserve: usize) -> Self {
49        let vertex_size = V::vertex_size();
50        Self {
51            buffer: Vec::<f32>::with_capacity(num_vertex_to_reserve * vertex_size),
52            vertex_num: 0,
53            vertex_size,
54            num_attributes: V::attribute_sizes().len(),
55            attribute_types: V::attribute_types(),
56            attribute_sizes: V::attribute_sizes(),
57            _phantom: PhantomData,
58        }
59    }
60
61    /// 頂点群を追加する
62    ///
63    /// * `v` - 頂点の情報がフラットに繰り返される`Vec`。したがって`v.len()`は[`VertexType::vertex_size()`]の倍数になる。※頂点情報の仕様については[`VertexType::vertex_size()`]を参照
64    pub fn append(&mut self, v: &mut Vec<f32>) {
65        debug_assert_eq!(v.len() % self.vertex_size, 0);
66        self.vertex_num += (v.len() / self.vertex_size) as i32;
67        self.buffer.append(v);
68    }
69
70    /// すべての頂点を削除する
71    pub fn clear(&mut self) {
72        self.buffer.clear();
73        self.vertex_num = self.buffer.len() as i32;
74    }
75
76    /// バッファの余分な容量をできるだけ縮める
77    pub fn shrink(&mut self) {
78        self.buffer.shrink_to_fit();
79    }
80
81    /// バッファの容量を予め確保する
82    ///
83    /// 少なくとも`additional_num_vertex`個の頂点が格納できるように確保する。
84    pub fn reserve(&mut self, additional_num_vertex: usize) {
85        self.buffer
86            .reserve(additional_num_vertex * self.vertex_size);
87    }
88
89    /// 先頭の`num_vertex_to_preserve`個の頂点以外の頂点を削除する
90    pub fn clear_preserving_first(&mut self, num_vertex_to_preserve: usize) {
91        self.buffer
92            .truncate(num_vertex_to_preserve * self.vertex_size);
93    }
94
95    /// 現在のバッファの内容をもとに[`Vao`]を作る
96    pub fn build<'a>(&self, gl: &Gl, config: &'a VaoConfig) -> Vao<'a> {
97        unsafe {
98            Vao::new(
99                gl.clone(),
100                (self.buffer.len() * mem::size_of::<GLfloat>()) as _,
101                self.buffer.as_ptr() as _,
102                gl::STATIC_DRAW,
103                self.num_attributes,
104                self.attribute_types,
105                self.attribute_sizes,
106                ((3 + 3 + 2) * mem::size_of::<GLfloat>()) as _,
107                self.vertex_num,
108                config,
109            )
110        }
111    }
112}