1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | #include <math.h> |
29 | #include <stdio.h> |
30 | #include <stdint.h> |
31 | |
32 | #include "GLES/gl.h" |
33 | #include <GLES/glext.h> |
34 | #include "EGL/egl.h" |
35 | #include "EGL/eglext.h" |
36 | #include "models.h" |
37 | |
38 | #define VMCS_RESOURCE(a,b) (b) |
39 | |
40 | /****************************************************************************** |
41 | Private typedefs, macros and constants |
42 | ******************************************************************************/ |
43 | |
44 | enum {VBO_VERTEX, VBO_NORMAL, VBO_TEXTURE, VBO_MAX}; |
45 | #define MAX_MATERIALS 4 |
46 | #define MAX_MATERIAL_NAME 32 |
47 | |
48 | typedef struct wavefront_material_s { |
49 | GLuint vbo[VBO_MAX]; |
50 | int numverts; |
51 | char name[MAX_MATERIAL_NAME]; |
52 | GLuint texture; |
53 | } WAVEFRONT_MATERIAL_T; |
54 | |
55 | typedef struct wavefront_model_s { |
56 | WAVEFRONT_MATERIAL_T material[MAX_MATERIALS]; |
57 | int num_materials; |
58 | GLuint texture; |
59 | } WAVEFRONT_MODEL_T; |
60 | |
61 | |
62 | /****************************************************************************** |
63 | Static Data |
64 | ******************************************************************************/ |
65 | |
66 | /****************************************************************************** |
67 | Static Function Declarations |
68 | ******************************************************************************/ |
69 | |
70 | /****************************************************************************** |
71 | Static Function Definitions |
72 | ******************************************************************************/ |
73 | |
74 | static void create_vbo(GLenum type, GLuint *vbo, int size, void *data) |
75 | { |
76 | glGenBuffers(1, vbo); |
77 | vc_assert(*vbo); |
78 | glBindBuffer(type, *vbo); |
79 | glBufferData(type, size, data, GL_STATIC_DRAW); |
80 | glBindBuffer(type, 0); |
81 | } |
82 | |
83 | |
84 | static void destroy_vbo(GLuint *vbo) |
85 | { |
86 | glDeleteBuffers(1, vbo); |
87 | *vbo = 0; |
88 | } |
89 | |
90 | #define MAX_VERTICES 100000 |
91 | static void *allocbuffer(int size) |
92 | { |
93 | return malloc(size); |
94 | } |
95 | |
96 | static void freebuffer(void *p) |
97 | { |
98 | free (p); |
99 | } |
100 | |
101 | static void centre_and_rescale(float *verts, int numvertices) |
102 | { |
103 | float cx=0.0f, cy=0.0f, cz=0.0f, scale=0.0f; |
104 | float minx=0.0f, miny=0.0f, minz=0.0f; |
105 | float maxx=0.0f, maxy=0.0f, maxz=0.0f; |
106 | int i; |
107 | float *v = verts; |
108 | minx = maxx = verts[0]; |
109 | miny = maxy = verts[1]; |
110 | minz = maxz = verts[2]; |
111 | for (i=0; i<numvertices; i++) { |
112 | float x = *v++; |
113 | float y = *v++; |
114 | float z = *v++; |
115 | minx = vcos_min(minx, x); |
116 | miny = vcos_min(miny, y); |
117 | minz = vcos_min(minz, z); |
118 | maxx = vcos_max(maxx, x); |
119 | maxy = vcos_max(maxy, y); |
120 | maxz = vcos_max(maxz, z); |
121 | cx += x; |
122 | cy += y; |
123 | cz += z; |
124 | } |
125 | cx /= (float)numvertices; |
126 | cy /= (float)numvertices; |
127 | cz /= (float)numvertices; |
128 | scale = 3.0f / (maxx-minx + maxy-miny + maxz-minz); |
129 | v = verts; |
130 | for (i=0; i<numvertices; i++) { |
131 | *v = (*v-cx) * scale; v++; |
132 | *v = (*v-cy) * scale; v++; |
133 | *v = (*v-cz) * scale; v++; |
134 | } |
135 | } |
136 | |
137 | static void renormalise(float *verts, int numvertices) |
138 | { |
139 | int i; |
140 | float *v = verts; |
141 | for (i=0;i<numvertices; i++) { |
142 | float x = v[0]; |
143 | float y = v[1]; |
144 | float z = v[2]; |
145 | float scale = 1.0f/sqrtf(x*x + y*y + z*z); |
146 | *v++ = x * scale; |
147 | *v++ = y * scale; |
148 | *v++ = z * scale; |
149 | } |
150 | } |
151 | |
152 | static void deindex(float *dst, const float *src, const unsigned short *indexes, GLsizei size, GLsizei count) |
153 | { |
154 | int i; |
155 | for (i=0; i<count; i++) { |
156 | int ind = size * (indexes[0]-1); |
157 | *dst++ = src[ind + 0]; |
158 | *dst++ = src[ind + 1]; |
159 | // todo: optimise - move out of loop |
160 | if (size >= 3) *dst++ = src[ind + 2]; |
161 | indexes += 3; |
162 | } |
163 | } |
164 | |
165 | int draw_wavefront(MODEL_T m, GLuint texture) |
166 | { |
167 | int i; |
168 | WAVEFRONT_MODEL_T *model = (WAVEFRONT_MODEL_T *)m; |
169 | |
170 | for (i=0; i<model->num_materials; i++) { |
171 | WAVEFRONT_MATERIAL_T *mat = model->material + i; |
172 | if (mat->texture == -1) continue; |
173 | |
174 | if (mat->texture) |
175 | glBindTexture(GL_TEXTURE_2D, mat->texture); |
176 | else |
177 | glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); |
178 | |
179 | if (mat->vbo[VBO_VERTEX]) { |
180 | glBindBuffer(GL_ARRAY_BUFFER, mat->vbo[VBO_VERTEX]); |
181 | glVertexPointer(3, GL_FLOAT, 0, NULL); |
182 | } |
183 | if (mat->vbo[VBO_NORMAL]) { |
184 | glEnableClientState(GL_NORMAL_ARRAY); |
185 | glBindBuffer(GL_ARRAY_BUFFER, mat->vbo[VBO_NORMAL]); |
186 | glNormalPointer(GL_FLOAT, 0, NULL); |
187 | } else { |
188 | glDisableClientState(GL_NORMAL_ARRAY); |
189 | } |
190 | if (mat->vbo[VBO_TEXTURE]) { |
191 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
192 | glBindBuffer(GL_ARRAY_BUFFER, mat->vbo[VBO_TEXTURE]); |
193 | glTexCoordPointer(2, GL_FLOAT, 0, NULL); |
194 | } else { |
195 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
196 | } |
197 | glDrawArrays(GL_TRIANGLES, 0, mat->numverts); |
198 | } |
199 | glBindBuffer(GL_ARRAY_BUFFER, 0); |
200 | return 0; |
201 | } |
202 | |
203 | struct wavefront_model_loading_s { |
204 | unsigned short material_index[MAX_MATERIALS]; |
205 | int num_materials; |
206 | int numv, numt, numn, numf; |
207 | unsigned int data[0]; |
208 | }; |
209 | |
210 | static int load_wavefront_obj(const char *modelname, WAVEFRONT_MODEL_T *model, struct wavefront_model_loading_s *m) |
211 | { |
212 | char line[256+1]; |
213 | unsigned short pp[54+1]; |
214 | FILE *fp; |
215 | int i, valid; |
216 | float *qv = (float *)m->data; |
217 | float *qt = (float *)m->data + 3 * MAX_VERTICES; |
218 | float *qn = (float *)m->data + (3+2) * MAX_VERTICES; |
219 | unsigned short *qf = (unsigned short *)((float *)m->data + (3+2+3) * MAX_VERTICES); |
220 | float *pv = qv, *pt = qt, *pn = qn; |
221 | unsigned short *pf = qf; |
222 | fp = fopen(modelname, "r" ); |
223 | if (!fp) return -1; |
224 | |
225 | m->num_materials = 0; |
226 | m->material_index[0] = 0; |
227 | |
228 | valid = fread(line, 1, sizeof(line)-1, fp); |
229 | |
230 | while (valid > 0) { |
231 | char *s, *end = line; |
232 | |
233 | while((end-line < valid) && *end != '\n' && *end != '\r') |
234 | end++; |
235 | *end++ = 0; |
236 | |
237 | if((end-line < valid) && *end != '\n' && *end != '\r') |
238 | *end++ = 0; |
239 | |
240 | s = line; |
241 | |
242 | if (s[strlen(s)-1] == 10) s[strlen(s)-1]=0; |
243 | switch (s[0]) { |
244 | case '#': break; // comment |
245 | case '\r': case '\n': case '\0': break; // blank line |
246 | case 'm': vc_assert(strncmp(s, "mtllib" , sizeof "mtllib" -1)==0); break; |
247 | case 'o': break; |
248 | case 'u': |
249 | if (sscanf(s, "usemtl %s" , /*MAX_MATERIAL_NAME-1, */model->material[m->num_materials].name) == 1) { |
250 | if (m->num_materials < MAX_MATERIALS) { |
251 | if (m->num_materials > 0 && ((pf-qf)/3 == m->material_index[m->num_materials-1] || strcmp(model->material[m->num_materials-1].name, model->material[m->num_materials].name)==0)) { |
252 | strcpy(model->material[m->num_materials-1].name, model->material[m->num_materials].name); |
253 | m->num_materials--; |
254 | } else |
255 | m->material_index[m->num_materials] = (pf-qf)/3; |
256 | m->num_materials++; |
257 | } |
258 | } else { printf("%s" , s); vc_assert(0); } |
259 | break; |
260 | case 'g': vc_assert(strncmp(s, "g " , sizeof "g " -1)==0); break; |
261 | case 's': vc_assert(strncmp(s, "s " , sizeof "s " -1)==0); break; |
262 | case 'v': case 'f': |
263 | if (sscanf(s, "v %f %f %f" , pv+0, pv+1, pv+2) == 3) { |
264 | pv += 3; |
265 | } else if (sscanf(s, "vt %f %f" , pt+0, pt+1) == 2) { |
266 | pt += 2; |
267 | } else if (sscanf(s, "vn %f %f %f" , pn+0, pn+1, pn+2) == 3) { |
268 | pn += 3; |
269 | } else if (i = sscanf(s, "f" " %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu" |
270 | " %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu" |
271 | " %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu//%hu %hu" , |
272 | pp+ 0, pp+ 1, pp+ 2, pp+ 3, pp+ 4, pp+ 5, pp+ 6, pp+ 7, pp+ 8, pp+ 9, pp+10, pp+11, |
273 | pp+12, pp+13, pp+14, pp+15, pp+16, pp+17, pp+18, pp+19, pp+20, pp+21, pp+22, pp+23, |
274 | pp+24, pp+25, pp+26, pp+27, pp+28, pp+29, pp+30, pp+32, pp+32, pp+33, pp+34, pp+35, pp+36), i >= 6) { |
275 | int poly = i/2; |
276 | //vc_assert(i < countof(pp)); // may need to increment poly count and pp array |
277 | for (i=1; i<poly-1; i++) { |
278 | *pf++ = pp[0]; *pf++ = 0; *pf++ = pp[1]; |
279 | *pf++ = pp[2*i+0]; *pf++ = 0; *pf++ = pp[2*i+1]; |
280 | *pf++ = pp[2*(i+1)+0]; *pf++ = 0; *pf++ = pp[2*(i+1)+1]; |
281 | } |
282 | } else if (i = sscanf(s, "f" " %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu" |
283 | " %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu" |
284 | " %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu/%hu %hu" , |
285 | pp+ 0, pp+ 1, pp+ 2, pp+ 3, pp+ 4, pp+ 5, pp+ 6, pp+ 7, pp+ 8, pp+ 9, pp+10, pp+11, |
286 | pp+12, pp+13, pp+14, pp+15, pp+16, pp+17, pp+18, pp+19, pp+20, pp+21, pp+22, pp+23, |
287 | pp+24, pp+25, pp+26, pp+27, pp+28, pp+29, pp+30, pp+32, pp+32, pp+33, pp+34, pp+35, pp+36), i >= 6) { |
288 | int poly = i/2; |
289 | //vc_assert(i < countof(pp); // may need to increment poly count and pp array |
290 | for (i=1; i<poly-1; i++) { |
291 | *pf++ = pp[0]; *pf++ = pp[1]; *pf++ = 0; |
292 | *pf++ = pp[2*i+0]; *pf++ = pp[2*i+1]; *pf++ = 0; |
293 | *pf++ = pp[2*(i+1)+0]; *pf++ = pp[2*(i+1)+1]; *pf++ = 0; |
294 | } |
295 | } else if (i = sscanf(s, "f" " %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu" |
296 | " %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu" |
297 | " %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu %hu" , |
298 | pp+ 0, pp+ 1, pp+ 2, pp+ 3, pp+ 4, pp+ 5, pp+ 6, pp+ 7, pp+ 8, pp+ 9, pp+10, pp+11, pp+12, pp+13, pp+14, pp+15, pp+16, pp+17, |
299 | pp+18, pp+19, pp+20, pp+21, pp+22, pp+23, pp+24, pp+25, pp+26, pp+27, pp+28, pp+29, pp+30, pp+32, pp+32, pp+33, pp+34, pp+35, |
300 | pp+36, pp+37, pp+38, pp+39, pp+40, pp+41, pp+42, pp+43, pp+44, pp+45, pp+46, pp+47, pp+48, pp+49, pp+50, pp+51, pp+52, pp+53, pp+54), i >= 9) { |
301 | int poly = i/3; |
302 | //vc_assert(i < countof(pp); // may need to increment poly count and pp array |
303 | for (i=1; i<poly-1; i++) { |
304 | *pf++ = pp[0]; *pf++ = pp[1]; *pf++ = pp[2]; |
305 | *pf++ = pp[3*i+0]; *pf++ = pp[3*i+1]; *pf++ = pp[3*i+2]; |
306 | *pf++ = pp[3*(i+1)+0]; *pf++ = pp[3*(i+1)+1]; *pf++ = pp[3*(i+1)+2]; |
307 | } |
308 | } else { printf("%s" , s); vc_assert(0); } |
309 | break; |
310 | default: |
311 | printf("%02x %02x %s" , s[0], s[1], s); vc_assert(0); break; |
312 | } |
313 | |
314 | // shift down read characters and read some more into the end |
315 | // if we didn't find a newline, then end is one off the end of our |
316 | // line, so end-line will be valid+1 |
317 | i = end-line > valid ? valid : end-line; |
318 | memmove(line, end, valid - i); |
319 | valid -= i; |
320 | valid += fread(line+valid, 1, sizeof(line)-1-valid, fp); |
321 | } |
322 | fclose(fp); |
323 | |
324 | if (m->num_materials==0) m->material_index[m->num_materials++] = 0; |
325 | |
326 | centre_and_rescale(qv, (pv-qv)/3); |
327 | renormalise(qn, (pn-qn)/3); |
328 | //centre_and_rescale2(qt, (pt-qt)/2); |
329 | |
330 | m->numv = pv-qv; |
331 | m->numt = pt-qt; |
332 | m->numn = pn-qn; |
333 | m->numf = pf-qf; |
334 | |
335 | // compress array |
336 | //memcpy((float *)m->data, (float *)m->data, m->numv * sizeof *qv); - nop |
337 | memcpy((float *)m->data + m->numv, (float *)m->data + 3 * MAX_VERTICES, m->numt * sizeof *qt); |
338 | memcpy((float *)m->data + m->numv + m->numt,(float *) m->data + (3 + 2) * MAX_VERTICES, m->numn * sizeof *qn); |
339 | memcpy((float *)m->data + m->numv + m->numt + m->numn, (float *)m->data + (3 + 2 + 3) * MAX_VERTICES, m->numf * sizeof *qf); |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static int load_wavefront_dat(const char *modelname, WAVEFRONT_MODEL_T *model, struct wavefront_model_loading_s *m) |
345 | { |
346 | FILE *fp; |
347 | int s; |
348 | const int size = sizeof *m + |
349 | sizeof(float)*(3+2+3)*MAX_VERTICES + // 3 vertices + 2 textures + 3 normals |
350 | sizeof(unsigned short)*3*MAX_VERTICES; //each face has 9 vertices |
351 | |
352 | fp = fopen(modelname, "r" ); |
353 | if (!fp) return -1; |
354 | s = fread(m, 1, size, fp); |
355 | if (s < 0) return -1; |
356 | fclose(fp); |
357 | return 0; |
358 | } |
359 | |
360 | MODEL_T load_wavefront(const char *modelname, const char *texturename) |
361 | { |
362 | WAVEFRONT_MODEL_T *model; |
363 | float *temp, *qv, *qt, *qn; |
364 | unsigned short *qf; |
365 | int i; |
366 | int numverts = 0, offset = 0; |
367 | struct wavefront_model_loading_s *m; |
368 | int s=-1; |
369 | char modelname_obj[128]; |
370 | model = malloc(sizeof *model); |
371 | if (!model || !modelname) return NULL; |
372 | memset (model, 0, sizeof *model); |
373 | model->texture = 0; //load_texture(texturename); |
374 | m = allocbuffer(sizeof *m + |
375 | sizeof(float)*(3+2+3)*MAX_VERTICES + // 3 vertices + 2 textures + 3 normals |
376 | sizeof(unsigned short)*3*MAX_VERTICES); //each face has 9 vertices |
377 | if (!m) return 0; |
378 | |
379 | if (strlen(modelname) + 5 <= sizeof modelname_obj) { |
380 | strcpy(modelname_obj, modelname); |
381 | strcat(modelname_obj, ".dat" ); |
382 | s = load_wavefront_dat(modelname_obj, model, m); |
383 | } |
384 | if (s==0) {} |
385 | else if (strncmp(modelname + strlen(modelname) - 4, ".obj" , 4) == 0) { |
386 | #ifdef DUMP_OBJ_DAT |
387 | int size; |
388 | FILE *fp; |
389 | #endif |
390 | s = load_wavefront_obj(modelname, model, m); |
391 | #ifdef DUMP_OBJ_DAT |
392 | strcpy(modelname_obj, modelname); |
393 | strcat(modelname_obj, ".dat" ); |
394 | size = sizeof *m + |
395 | sizeof(float)*(3*m->numv+2*m->numt+3*m->numn) + // 3 vertices + 2 textures + 3 normals |
396 | sizeof(unsigned short)*3*m->numf; //each face has 9 vertices |
397 | fp = host_file_open(modelname_obj, "w" ); |
398 | fwrite(m, 1, size, fp); |
399 | fclose(fp); |
400 | #endif |
401 | } else if (strncmp(modelname + strlen(modelname) - 4, ".dat" , 4) == 0) { |
402 | s = load_wavefront_dat(modelname, model, m); |
403 | } |
404 | if (s != 0) return 0; |
405 | |
406 | qv = (float *)(m->data); |
407 | qt = (float *)(m->data + m->numv); |
408 | qn = (float *)(m->data + m->numv + m->numt); |
409 | qf = (unsigned short *)(m->data + m->numv + m->numt + m->numn); |
410 | |
411 | numverts = m->numf/3; |
412 | vc_assert(numverts <= MAX_VERTICES); |
413 | |
414 | temp = allocbuffer(3*numverts*sizeof *temp); |
415 | for (i=0; i<m->num_materials; i++) { |
416 | WAVEFRONT_MATERIAL_T *mat = model->material + i; |
417 | mat->numverts = i < m->num_materials-1 ? m->material_index[i+1]-m->material_index[i] : numverts - m->material_index[i]; |
418 | // vertex, texture, normal |
419 | deindex(temp, qv, qf+3*offset+0, 3, mat->numverts); |
420 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_VERTEX, 3 * mat->numverts * sizeof *qv, temp); // 3 |
421 | |
422 | deindex(temp, qt, qf+3*offset+1, 2, mat->numverts); |
423 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_TEXTURE, 2 * mat->numverts * sizeof *qt, temp); // 2 |
424 | |
425 | deindex(temp, qn, qf+3*offset+2, 3, mat->numverts); |
426 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_NORMAL, 3 * mat->numverts * sizeof *qn, temp); // 3 |
427 | offset += mat->numverts; |
428 | mat->texture = model->texture; |
429 | } |
430 | model->num_materials = m->num_materials; |
431 | vc_assert(offset == numverts); |
432 | freebuffer(temp); |
433 | freebuffer(m); |
434 | return (MODEL_T)model; |
435 | } |
436 | |
437 | void unload_wavefront(MODEL_T m) |
438 | { |
439 | WAVEFRONT_MODEL_T *model = (WAVEFRONT_MODEL_T *)m; |
440 | int i; |
441 | for (i=0; i<model->num_materials; i++) { |
442 | WAVEFRONT_MATERIAL_T *mat = model->material + i; |
443 | if (mat->vbo[VBO_VERTEX]) |
444 | destroy_vbo(mat->vbo+VBO_VERTEX); |
445 | if (mat->vbo[VBO_TEXTURE]) |
446 | destroy_vbo(mat->vbo+VBO_TEXTURE); |
447 | if (mat->vbo[VBO_NORMAL]) |
448 | destroy_vbo(mat->vbo+VBO_NORMAL); |
449 | } |
450 | } |
451 | |
452 | // create a cube model that looks like a wavefront model, |
453 | MODEL_T cube_wavefront(void) |
454 | { |
455 | static const float qv[] = { |
456 | -0.5f, -0.5f, 0.5f, |
457 | -0.5f, -0.5f, -0.5f, |
458 | 0.5f, -0.5f, -0.5f, |
459 | 0.5f, -0.5f, 0.5f, |
460 | -0.5f, 0.5f, 0.5f, |
461 | 0.5f, 0.5f, 0.5f, |
462 | 0.5f, 0.5f, -0.5f, |
463 | -0.5f, 0.5f, -0.5f, |
464 | }; |
465 | |
466 | static const float qn[] = { |
467 | 0.0f, -1.0f, -0.0f, |
468 | 0.0f, 1.0f, -0.0f, |
469 | 0.0f, 0.0f, 1.0f, |
470 | 1.0f, 0.0f, -0.0f, |
471 | 0.0f, 0.0f, -1.0f, |
472 | -1.0f, 0.0f, -0.0f, |
473 | }; |
474 | |
475 | static const float qt[] = { |
476 | 1.0f, 0.0f, |
477 | 1.0f, 1.0f, |
478 | 0.0f, 1.0f, |
479 | 0.0f, 0.0f, |
480 | }; |
481 | |
482 | static const unsigned short qf[] = { |
483 | 1,1,1, 2,2,1, 3,3,1, |
484 | 3,3,1, 4,4,1, 1,1,1, |
485 | 5,4,2, 6,1,2, 7,2,2, |
486 | 7,2,2, 8,3,2, 5,4,2, |
487 | 1,4,3, 4,1,3, 6,2,3, |
488 | 6,2,3, 5,3,3, 1,4,3, |
489 | 4,4,4, 3,1,4, 7,2,4, |
490 | 7,2,4, 6,3,4, 4,4,4, |
491 | 3,4,5, 2,1,5, 8,2,5, |
492 | 8,2,5, 7,3,5, 3,4,5, |
493 | 2,4,6, 1,1,6, 5,2,6, |
494 | 5,2,6, 8,3,6, 2,4,6, |
495 | }; |
496 | WAVEFRONT_MODEL_T *model = malloc(sizeof *model); |
497 | if (model) { |
498 | WAVEFRONT_MATERIAL_T *mat = model->material; |
499 | float *temp; |
500 | const int offset = 0; |
501 | memset(model, 0, sizeof *model); |
502 | |
503 | temp = allocbuffer(3*MAX_VERTICES*sizeof *temp); |
504 | mat->numverts = countof(qf)/3; |
505 | // vertex, texture, normal |
506 | deindex(temp, qv, qf+3*offset+0, 3, mat->numverts); |
507 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_VERTEX, 3 * mat->numverts * sizeof *qv, temp); // 3 |
508 | |
509 | deindex(temp, qt, qf+3*offset+1, 2, mat->numverts); |
510 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_TEXTURE, 2 * mat->numverts * sizeof *qt, temp); // 2 |
511 | |
512 | deindex(temp, qn, qf+3*offset+2, 3, mat->numverts); |
513 | create_vbo(GL_ARRAY_BUFFER, mat->vbo+VBO_NORMAL, 3 * mat->numverts * sizeof *qn, temp); // 3 |
514 | |
515 | freebuffer(temp); |
516 | model->num_materials = 1; |
517 | } |
518 | return (MODEL_T)model; |
519 | } |
520 | |
521 | |
522 | |