1pub mod obj;
2
3use fere_common::*;
4use gl::types::*;
5
6#[derive(Debug, Default)]
7pub struct MeshData {
8 pub name: String,
9
10 pub pos: Vec<Vec3>,
11 pub normal: Vec<Vec3>,
12 pub uv: Vec<Vec2>,
13 pub tan: Vec<Vec3>,
14
15 pub minmax: Option<(Vec3, Vec3)>,
16}
17
18impl MeshData {
19 pub fn merge(meshes: Vec<MeshData>) -> Self {
20 let init = MeshData {
21 name: "".to_owned(),
22 pos: Vec::new(),
23 normal: Vec::new(),
24 uv: Vec::new(),
25 tan: Vec::new(),
26 minmax: None,
27 };
28 meshes.into_iter().fold(init, |mut acc, mut x| {
29 acc.name += &x.name;
30 acc.pos.append(&mut x.pos);
31 acc.normal.append(&mut x.normal);
32 acc.uv.append(&mut x.uv);
33 acc.tan.append(&mut x.tan);
34 acc
35 })
36 }
37
38 pub fn create_description(&self) -> MeshDescription {
39 let mean_pos = self.pos.iter().sum::<Vec3>() / self.pos.len() as f32;
40 MeshDescription { mean_pos }
41 }
42}
43
44#[derive(Debug)]
45pub struct MeshDescription {
46 pub mean_pos: Vec3,
47}
48
49#[derive(Debug)]
50pub struct Mesh {
51 pub name: String,
52 pub path: Option<String>,
54 pub size: usize,
55
56 data: Option<MeshData>,
58 description: MeshDescription,
59
60 vao: GLuint,
62 vbo: GLuint,
63}
64
65impl Mesh {
66 pub fn new(path: Option<String>, data: MeshData) -> Self {
67 let description = data.create_description();
68 Mesh {
69 name: data.name.clone(),
70 path,
71 size: data.pos.len(),
72 data: Some(data),
73 vao: 0,
74 vbo: 0,
75 description,
76 }
77 }
78
79 pub fn description(&self) -> &MeshDescription {
80 &self.description
81 }
82
83 pub fn buffer(&mut self) {
84 unsafe {
85 gl::GenVertexArrays(1, &mut self.vao);
86 gl::BindVertexArray(self.vao);
87 gl::GenBuffers(1, &mut self.vbo);
88 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
89
90 self.size = self.data.as_ref().unwrap().pos.len();
91 if self.size == 0 {
92 return;
93 }
94
95 let data = self.data.take().unwrap();
96 let f = 4; let n = self.size as isize;
98
99 gl::BufferData(
100 gl::ARRAY_BUFFER,
101 f * (n * 3 + n * 3 + n * 2 + n * 3),
102 std::ptr::null(),
103 gl::STATIC_DRAW,
104 );
105 gl::BufferSubData(
106 gl::ARRAY_BUFFER,
107 0,
108 f * (n * 3),
109 data.pos[0].as_ptr().cast(),
110 );
111 gl::BufferSubData(
112 gl::ARRAY_BUFFER,
113 f * (n * 3),
114 f * (n * 3),
115 data.normal[0].as_ptr().cast(),
116 );
117
118 if !data.uv.is_empty() {
119 gl::BufferSubData(
120 gl::ARRAY_BUFFER,
121 f * (n * 6),
122 f * (n * 2),
123 data.uv[0].as_ptr().cast(),
124 );
125 }
126 if !data.tan.is_empty() {
127 gl::BufferSubData(
128 gl::ARRAY_BUFFER,
129 f * (n * 8),
130 f * (n * 3),
131 data.tan[0].as_ptr().cast(),
132 );
133 }
134
135 gl::EnableVertexAttribArray(0);
136 gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 0, std::ptr::null::<u8>().cast());
137 gl::EnableVertexAttribArray(1);
138 gl::VertexAttribPointer(
139 1,
140 3,
141 gl::FLOAT,
142 gl::FALSE,
143 0,
144 ((f * 3 * n) as *const u8).cast(),
145 );
146 if !data.uv.is_empty() {
147 gl::EnableVertexAttribArray(2);
148 gl::VertexAttribPointer(
149 2,
150 2,
151 gl::FLOAT,
152 gl::FALSE,
153 0,
154 ((f * 6 * n) as *const u8).cast(),
155 );
156 }
157 if !data.tan.is_empty() {
158 gl::EnableVertexAttribArray(3);
159 gl::VertexAttribPointer(
160 3,
161 3,
162 gl::FLOAT,
163 gl::FALSE,
164 0,
165 ((f * 8 * n) as *const u8).cast(),
166 );
167 }
168 }
169 }
170
171 pub fn bind(&self) {
172 debug_assert!(self.data.is_none(), "bind() on an unbufferd mesh");
173 unsafe { gl::BindVertexArray(self.vao) }
174 }
175
176 pub fn bind_or_buffer(&mut self) {
177 if self.data.is_some() {
178 self.buffer();
179 }
180 unsafe { gl::BindVertexArray(self.vao) }
181 }
182
183 pub fn draw(&self) {
184 unsafe { gl::DrawArrays(gl::TRIANGLES, 0, self.size as i32) }
185 }
186
187 pub fn draw_line(&self) {
189 unsafe { gl::DrawArrays(gl::LINES, 0, 2) }
190 }
191
192 pub fn draw_wireframe(&self) {
193 unsafe {
194 gl::Disable(gl::CULL_FACE);
195 gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
196 gl::DrawArrays(gl::TRIANGLES, 0, self.size as i32);
197 gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL);
198 gl::Enable(gl::CULL_FACE);
199 }
200 }
201}
202
203impl Drop for Mesh {
204 fn drop(&mut self) {
205 if self.data.is_none() {
206 unsafe {
207 gl::DeleteVertexArrays(1, &self.vao);
208 gl::DeleteBuffers(1, &self.vbo);
209 }
210 }
211 }
212}