1use super::gli;
2use super::program::Attribute;
3
4pub struct AttributeInfo {
5 normalize: bool,
6 location: u32,
7 offset: i32,
8 size: i32,
9 stride: i32,
10 gl_type: u32,
11}
12
13pub struct Geometry {
14 attributes: Vec<AttributeInfo>,
15 buffer: VertexBuffer,
16 data_length: i32,
17 index: Option<u32>,
18 index_count: i32,
19 total_byte_length: i32,
20 vao: u32,
21 bound: bool,
22}
23
24impl Geometry {
25 pub fn new() -> Geometry {
26 Geometry {
27 attributes: Vec::new(),
28 buffer: VertexBuffer::new(),
29 data_length: 0,
30 index: None,
31 index_count: 0,
32 total_byte_length: 0,
33 vao: gli::create_vertex_array(),
34 bound: false,
35 }
36 }
37
38 fn add_attr(&mut self, attr: &Attribute, normalize: bool) {
39 let (size, gl_type) = gli::get_attribute_size_and_type(attr.gl_type, normalize);
40 let length = gli::size_of_type(gl_type);
41 let info = AttributeInfo {
42 normalize: normalize,
43 location: attr.location,
44 size: size,
45 gl_type: gl_type,
46 offset: self.total_byte_length,
47 stride: length * size,
48 };
49 self.attributes.push(info);
50 self.total_byte_length += length * size;
51 }
52
53 pub fn add_attribute(&mut self, attr: &Attribute) {
54 self.add_attr(attr, false);
55 }
56
57 pub fn add_normalized_attribute(&mut self, attr: &Attribute) {
58 self.add_attr(attr, true);
59 }
60
61 pub fn buffer_data(&mut self, data: &[f32]) {
62 self.data_length = data.len() as i32 * 4;
63 self.buffer.buffer_data(data);
64 }
65
66 fn bind_to_attributes(&self) {
67 for attr in self.attributes.iter() {
68 self.buffer.bind_to_attribute(
69 attr.location,
70 attr.size,
71 attr.gl_type,
72 attr.normalize,
73 self.total_byte_length,
74 attr.offset,
75 );
76 }
77 }
78
79 pub fn draw(&mut self) {
80 gli::bind_vertex_array(self.vao);
81 if !self.bound {
82 self.bind_to_attributes();
83 self.bound = true;
84 }
85 if let Some(index) = self.index {
86 gli::draw_elements_triangles(self.index_count);
87 } else {
88 let count = self.data_length / self.total_byte_length;
89 gli::draw_arrays_triangles(count);
90 }
91 gli::bind_vertex_array(0);
92 }
93}
94
95pub struct VertexBuffer {
96 buffer: u32,
97}
98
99impl VertexBuffer {
100 pub fn new() -> VertexBuffer {
101 let vbo = gli::create_buffer();
102 VertexBuffer {
103 buffer: vbo,
104 }
105 }
106
107 pub fn buffer_data(&self, data: &[f32]) {
108 gli::bind_array_buffer(self.buffer);
109 gli::buffer_array_data(data);
110 }
111
112 pub fn bind_to_attribute(&self, location: u32, size: i32, gl_type: u32, normalized: bool, stride: i32, offset: i32) {
113 gli::bind_array_buffer(self.buffer);
114 gli::vertex_attrib_pointer(location, size, gl_type, normalized, stride, offset);
115 gli::enable_vertex_attrib_array(location);
116 }
117}