rev |
line source |
nuclear@8
|
1 #include <string.h>
|
nuclear@8
|
2 #include "mesh.h"
|
nuclear@8
|
3 #include "opengl.h"
|
nuclear@8
|
4
|
nuclear@8
|
5 Mesh::Mesh()
|
nuclear@8
|
6 {
|
nuclear@8
|
7 set_primitive(GL_TRIANGLES);
|
nuclear@8
|
8
|
nuclear@8
|
9 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
|
nuclear@8
|
10 attrib[i].nelems = 3;
|
nuclear@8
|
11 attrib[i].sdrloc = -1;
|
nuclear@8
|
12 attrib[i].vbo = 0;
|
nuclear@8
|
13 attrib[i].vbo_valid = false;
|
nuclear@8
|
14 }
|
nuclear@8
|
15 num_verts = 0;
|
nuclear@8
|
16
|
nuclear@8
|
17 num_idx = 0;
|
nuclear@8
|
18 ibo = 0;
|
nuclear@8
|
19 ibo_size = 0;
|
nuclear@8
|
20 ibo_valid = false;
|
nuclear@8
|
21
|
nuclear@8
|
22 vbo_usage = ibo_usage = GL_STATIC_DRAW;
|
nuclear@8
|
23 }
|
nuclear@8
|
24
|
nuclear@8
|
25 Mesh::~Mesh()
|
nuclear@8
|
26 {
|
nuclear@8
|
27 clear();
|
nuclear@8
|
28
|
nuclear@8
|
29 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
|
nuclear@8
|
30 if(attrib[i].vbo) {
|
nuclear@8
|
31 glDeleteBuffers(1, &attrib[i].vbo);
|
nuclear@8
|
32 }
|
nuclear@8
|
33 }
|
nuclear@8
|
34 if(ibo) {
|
nuclear@8
|
35 glDeleteBuffers(1, &ibo);
|
nuclear@8
|
36 }
|
nuclear@8
|
37 }
|
nuclear@8
|
38
|
nuclear@8
|
39 void Mesh::clear()
|
nuclear@8
|
40 {
|
nuclear@8
|
41 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
|
nuclear@8
|
42 attrib[i].vbo_valid = false;
|
nuclear@8
|
43 attrib[i].data.clear();
|
nuclear@8
|
44
|
nuclear@8
|
45 }
|
nuclear@8
|
46 ibo_valid = false;
|
nuclear@8
|
47 index.clear();
|
nuclear@8
|
48 }
|
nuclear@8
|
49
|
nuclear@8
|
50 void Mesh::set_primitive(int prim)
|
nuclear@8
|
51 {
|
nuclear@8
|
52 if(prim == -1) {
|
nuclear@8
|
53 this->prim = GL_TRIANGLES;
|
nuclear@8
|
54 } else {
|
nuclear@8
|
55 this->prim = prim;
|
nuclear@8
|
56 }
|
nuclear@8
|
57
|
nuclear@8
|
58 switch(this->prim) {
|
nuclear@8
|
59 case GL_TRIANGLES:
|
nuclear@8
|
60 prim_verts = 3;
|
nuclear@8
|
61 break;
|
nuclear@8
|
62
|
nuclear@8
|
63 case GL_QUADS:
|
nuclear@8
|
64 prim_verts = 4;
|
nuclear@8
|
65 break;
|
nuclear@8
|
66
|
nuclear@8
|
67 case GL_LINES:
|
nuclear@8
|
68 prim_verts = 2;
|
nuclear@8
|
69 break;
|
nuclear@8
|
70
|
nuclear@8
|
71 case GL_POINTS:
|
nuclear@8
|
72 prim_verts = 1;
|
nuclear@8
|
73 break;
|
nuclear@8
|
74
|
nuclear@8
|
75 default:
|
nuclear@8
|
76 break;
|
nuclear@8
|
77 }
|
nuclear@8
|
78 }
|
nuclear@8
|
79
|
nuclear@8
|
80 void Mesh::set_attrib_location(int attr, int loc)
|
nuclear@8
|
81 {
|
nuclear@8
|
82 attrib[attr].sdrloc = loc;
|
nuclear@8
|
83 }
|
nuclear@8
|
84
|
nuclear@8
|
85 float *Mesh::set_vertex_data(int attr, int nelem, int count, float *data)
|
nuclear@8
|
86 {
|
nuclear@8
|
87 attrib[attr].data.resize(count * nelem);
|
nuclear@8
|
88 if(data) {
|
nuclear@8
|
89 memcpy(&attrib[attr].data[0], data, nelem * count * sizeof(float));
|
nuclear@8
|
90 }
|
nuclear@8
|
91
|
nuclear@8
|
92 attrib[attr].nelems = nelem;
|
nuclear@8
|
93 attrib[attr].vbo_valid = false;
|
nuclear@8
|
94
|
nuclear@8
|
95 num_verts = count;
|
nuclear@8
|
96
|
nuclear@8
|
97 return &attrib[attr].data[0];
|
nuclear@8
|
98 }
|
nuclear@8
|
99
|
nuclear@8
|
100 unsigned int *Mesh::set_index_data(int count, unsigned int *data)
|
nuclear@8
|
101 {
|
nuclear@8
|
102 index.resize(count);
|
nuclear@8
|
103 if(data) {
|
nuclear@8
|
104 memcpy(&index[0], data, count * sizeof(unsigned int));
|
nuclear@8
|
105 }
|
nuclear@8
|
106
|
nuclear@8
|
107 num_idx = count;
|
nuclear@8
|
108 ibo_valid = false;
|
nuclear@8
|
109
|
nuclear@8
|
110 return &index[0];
|
nuclear@8
|
111 }
|
nuclear@8
|
112
|
nuclear@8
|
113 int Mesh::get_vertex_count() const
|
nuclear@8
|
114 {
|
nuclear@8
|
115 return num_verts;
|
nuclear@8
|
116 }
|
nuclear@8
|
117
|
nuclear@8
|
118 float *Mesh::get_vertex_data(int attr)
|
nuclear@8
|
119 {
|
nuclear@8
|
120 if(attrib[attr].data.empty()) {
|
nuclear@8
|
121 return 0;
|
nuclear@8
|
122 }
|
nuclear@8
|
123 return &attrib[attr].data[0];
|
nuclear@8
|
124 }
|
nuclear@8
|
125
|
nuclear@8
|
126 const float *Mesh::get_vertex_data(int attr) const
|
nuclear@8
|
127 {
|
nuclear@8
|
128 if(attrib[attr].data.empty()) {
|
nuclear@8
|
129 return 0;
|
nuclear@8
|
130 }
|
nuclear@8
|
131 return &attrib[attr].data[0];
|
nuclear@8
|
132 }
|
nuclear@8
|
133
|
nuclear@8
|
134 int Mesh::get_index_count() const
|
nuclear@8
|
135 {
|
nuclear@8
|
136 return num_idx;
|
nuclear@8
|
137 }
|
nuclear@8
|
138
|
nuclear@8
|
139 unsigned int *Mesh::get_index_data()
|
nuclear@8
|
140 {
|
nuclear@8
|
141 if(index.empty()) {
|
nuclear@8
|
142 return 0;
|
nuclear@8
|
143 }
|
nuclear@8
|
144 return &index[0];
|
nuclear@8
|
145 }
|
nuclear@8
|
146
|
nuclear@8
|
147 const unsigned int *Mesh::get_index_data() const
|
nuclear@8
|
148 {
|
nuclear@8
|
149 if(index.empty()) {
|
nuclear@8
|
150 return 0;
|
nuclear@8
|
151 }
|
nuclear@8
|
152 return &index[0];
|
nuclear@8
|
153 }
|
nuclear@8
|
154
|
nuclear@8
|
155 int Mesh::get_face_count() const
|
nuclear@8
|
156 {
|
nuclear@8
|
157 if(index.empty()) {
|
nuclear@8
|
158 return get_vertex_count() / prim_verts;
|
nuclear@8
|
159 }
|
nuclear@8
|
160 return get_index_count() / prim_verts;
|
nuclear@8
|
161 }
|
nuclear@8
|
162
|
nuclear@8
|
163 MeshFace Mesh::get_face(int idx) const
|
nuclear@8
|
164 {
|
nuclear@8
|
165 MeshFace face;
|
nuclear@8
|
166 face.vcount = prim_verts;
|
nuclear@8
|
167
|
nuclear@8
|
168 int nfaces = get_face_count();
|
nuclear@8
|
169 if(idx < 0 || idx >= nfaces) {
|
nuclear@8
|
170 return face;
|
nuclear@8
|
171 }
|
nuclear@8
|
172
|
nuclear@8
|
173 const Vector3 *verts = (const Vector3*)&attrib[MESH_VERTEX].data[0];
|
nuclear@8
|
174
|
nuclear@8
|
175 if(index.empty()) {
|
nuclear@8
|
176 for(int i=0; i<3; i++) {
|
nuclear@8
|
177 face.v[i] = verts[idx * 3 + i];
|
nuclear@8
|
178 }
|
nuclear@8
|
179
|
nuclear@8
|
180 } else {
|
nuclear@8
|
181 for(int i=0; i<3; i++) {
|
nuclear@8
|
182 int vidx = index[idx * 3 + i];
|
nuclear@8
|
183 face.v[i] = verts[vidx];
|
nuclear@8
|
184 }
|
nuclear@8
|
185 }
|
nuclear@8
|
186
|
nuclear@8
|
187 return face;
|
nuclear@8
|
188 }
|
nuclear@8
|
189
|
nuclear@8
|
190
|
nuclear@8
|
191 void Mesh::begin(int prim)
|
nuclear@8
|
192 {
|
nuclear@8
|
193 if(prim == -1) {
|
nuclear@8
|
194 this->prim = GL_TRIANGLES;
|
nuclear@8
|
195 } else {
|
nuclear@8
|
196 this->prim = prim;
|
nuclear@8
|
197 }
|
nuclear@8
|
198
|
nuclear@8
|
199 clear();
|
nuclear@8
|
200
|
nuclear@8
|
201 cur_norm_valid = false;
|
nuclear@8
|
202 cur_tc_valid = false;
|
nuclear@8
|
203 cur_tang_valid = false;
|
nuclear@8
|
204 }
|
nuclear@8
|
205
|
nuclear@8
|
206 void Mesh::end()
|
nuclear@8
|
207 {
|
nuclear@8
|
208 }
|
nuclear@8
|
209
|
nuclear@8
|
210 void Mesh::vertex(float x, float y, float z)
|
nuclear@8
|
211 {
|
nuclear@8
|
212 if(cur_norm_valid) {
|
nuclear@8
|
213 attrib[MESH_NORMAL].data.push_back(cur_norm.x);
|
nuclear@8
|
214 attrib[MESH_NORMAL].data.push_back(cur_norm.y);
|
nuclear@8
|
215 attrib[MESH_NORMAL].data.push_back(cur_norm.z);
|
nuclear@8
|
216 }
|
nuclear@8
|
217 if(cur_tc_valid) {
|
nuclear@8
|
218 attrib[MESH_TEXCOORD].data.push_back(cur_tc.x);
|
nuclear@8
|
219 attrib[MESH_TEXCOORD].data.push_back(cur_tc.y);
|
nuclear@8
|
220 }
|
nuclear@8
|
221 if(cur_tang_valid) {
|
nuclear@8
|
222 attrib[MESH_TANGENT].data.push_back(cur_tang.x);
|
nuclear@8
|
223 attrib[MESH_TANGENT].data.push_back(cur_tang.y);
|
nuclear@8
|
224 attrib[MESH_TANGENT].data.push_back(cur_tang.z);
|
nuclear@8
|
225 }
|
nuclear@8
|
226 attrib[MESH_VERTEX].data.push_back(x);
|
nuclear@8
|
227 attrib[MESH_VERTEX].data.push_back(y);
|
nuclear@8
|
228 attrib[MESH_VERTEX].data.push_back(z);
|
nuclear@8
|
229 }
|
nuclear@8
|
230
|
nuclear@8
|
231 void Mesh::normal(float x, float y, float z)
|
nuclear@8
|
232 {
|
nuclear@8
|
233 cur_norm = Vector3(x, y, z);
|
nuclear@8
|
234 cur_norm_valid = true;
|
nuclear@8
|
235 }
|
nuclear@8
|
236
|
nuclear@8
|
237 void Mesh::texcoord(float x, float y)
|
nuclear@8
|
238 {
|
nuclear@8
|
239 cur_tc = Vector2(x, y);
|
nuclear@8
|
240 cur_tc_valid = true;
|
nuclear@8
|
241 }
|
nuclear@8
|
242
|
nuclear@8
|
243 void Mesh::tangent(float x, float y, float z)
|
nuclear@8
|
244 {
|
nuclear@8
|
245 cur_tang = Vector3(x, y, z);
|
nuclear@8
|
246 cur_tang_valid = true;
|
nuclear@8
|
247 }
|
nuclear@8
|
248
|
nuclear@8
|
249 void Mesh::draw() const
|
nuclear@8
|
250 {
|
nuclear@8
|
251 if(attrib[MESH_VERTEX].data.empty()) {
|
nuclear@8
|
252 return;
|
nuclear@8
|
253 }
|
nuclear@8
|
254
|
nuclear@8
|
255 bool use_norm = !attrib[MESH_NORMAL].data.empty();
|
nuclear@8
|
256 bool use_tc = !attrib[MESH_TEXCOORD].data.empty();
|
nuclear@8
|
257 bool use_tang = !attrib[MESH_TANGENT].data.empty();
|
nuclear@8
|
258 int norm_loc, tc_loc, tang_loc;
|
nuclear@8
|
259
|
nuclear@8
|
260 const float *ptr = &attrib[MESH_VERTEX].data[0];
|
nuclear@8
|
261 int loc = attrib[MESH_VERTEX].sdrloc;
|
nuclear@8
|
262 if(loc == -1) {
|
nuclear@8
|
263 glEnableClientState(GL_VERTEX_ARRAY);
|
nuclear@8
|
264 glVertexPointer(attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, ptr);
|
nuclear@8
|
265 } else {
|
nuclear@8
|
266 glEnableVertexAttribArray(loc);
|
nuclear@8
|
267 glVertexAttribPointer(loc, attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0, ptr);
|
nuclear@8
|
268 }
|
nuclear@8
|
269
|
nuclear@8
|
270 if(use_norm) {
|
nuclear@8
|
271 const float *ptr = &attrib[MESH_NORMAL].data[0];
|
nuclear@8
|
272 norm_loc = attrib[MESH_NORMAL].sdrloc;
|
nuclear@8
|
273 if(norm_loc == -1) {
|
nuclear@8
|
274 glEnableClientState(GL_NORMAL_ARRAY);
|
nuclear@8
|
275 glNormalPointer(GL_FLOAT, 0, ptr);
|
nuclear@8
|
276 } else {
|
nuclear@8
|
277 glEnableVertexAttribArray(norm_loc);
|
nuclear@8
|
278 glVertexAttribPointer(norm_loc, attrib[MESH_NORMAL].nelems, GL_FLOAT, 0, 0, ptr);
|
nuclear@8
|
279 }
|
nuclear@8
|
280 }
|
nuclear@8
|
281
|
nuclear@8
|
282 if(use_tc) {
|
nuclear@8
|
283 const float *ptr = &attrib[MESH_TEXCOORD].data[0];
|
nuclear@8
|
284 tc_loc = attrib[MESH_TEXCOORD].sdrloc;
|
nuclear@8
|
285 if(tc_loc == -1) {
|
nuclear@8
|
286 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@8
|
287 glTexCoordPointer(attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, ptr);
|
nuclear@8
|
288 } else {
|
nuclear@8
|
289 glEnableVertexAttribArray(tc_loc);
|
nuclear@8
|
290 glVertexAttribPointer(tc_loc, attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0, ptr);
|
nuclear@8
|
291 }
|
nuclear@8
|
292 }
|
nuclear@8
|
293
|
nuclear@8
|
294 if(!attrib[MESH_TANGENT].data.empty()) {
|
nuclear@8
|
295 const float *ptr = &attrib[MESH_TANGENT].data[0];
|
nuclear@8
|
296 tang_loc = attrib[MESH_TANGENT].sdrloc;
|
nuclear@8
|
297 if(tang_loc != -1) {
|
nuclear@8
|
298 glEnableVertexAttribArray(tang_loc);
|
nuclear@8
|
299 glVertexAttribPointer(tang_loc, attrib[MESH_TANGENT].nelems, GL_FLOAT, 0, 0, ptr);
|
nuclear@8
|
300 }
|
nuclear@8
|
301 }
|
nuclear@8
|
302
|
nuclear@8
|
303 if(!index.empty()) {
|
nuclear@8
|
304 glDrawElements(prim, num_idx, GL_UNSIGNED_INT, &index[0]);
|
nuclear@8
|
305 } else {
|
nuclear@8
|
306 glDrawArrays(prim, 0, num_verts * 3);
|
nuclear@8
|
307 }
|
nuclear@8
|
308
|
nuclear@8
|
309 if(use_norm) {
|
nuclear@8
|
310 if(norm_loc == -1) {
|
nuclear@8
|
311 glDisableClientState(GL_NORMAL_ARRAY);
|
nuclear@8
|
312 } else {
|
nuclear@8
|
313 glDisableVertexAttribArray(norm_loc);
|
nuclear@8
|
314 }
|
nuclear@8
|
315 }
|
nuclear@8
|
316 if(use_tc) {
|
nuclear@8
|
317 if(tc_loc == -1) {
|
nuclear@8
|
318 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@8
|
319 } else {
|
nuclear@8
|
320 glDisableVertexAttribArray(tc_loc);
|
nuclear@8
|
321 }
|
nuclear@8
|
322 }
|
nuclear@8
|
323 if(use_tang) {
|
nuclear@8
|
324 if(tang_loc != -1) {
|
nuclear@8
|
325 glDisableVertexAttribArray(tang_loc);
|
nuclear@8
|
326 }
|
nuclear@8
|
327 }
|
nuclear@8
|
328 }
|