diff options
Diffstat (limited to 'src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c')
-rw-r--r-- | src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c b/src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c new file mode 100644 index 0000000..9a8e004 --- /dev/null +++ b/src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* $Id: gl.c 61 2006-11-09 15:31:12Z mmmaddd $ */ | ||
2 | |||
3 | /* | ||
4 | G3DViewer - 3D object viewer | ||
5 | |||
6 | Copyright (C) 2005, 2006 Markus Dahms <mad@automagically.de> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <math.h> | ||
26 | |||
27 | #include <glib.h> | ||
28 | |||
29 | #include <GL/gl.h> | ||
30 | #include <GL/glu.h> | ||
31 | |||
32 | #include <g3d/types.h> | ||
33 | |||
34 | #if 0 | ||
35 | #include "main.h" | ||
36 | #endif | ||
37 | #include "gl.h" | ||
38 | #include "trackball.h" | ||
39 | |||
40 | #if DEBUG > 1 | ||
41 | #define TIMING | ||
42 | #endif | ||
43 | |||
44 | static int _initialized = 0; | ||
45 | |||
46 | #ifdef TIMING | ||
47 | static GTimer *timer = NULL; | ||
48 | static gulong avg_msec = 0; | ||
49 | #endif | ||
50 | |||
51 | GLuint evil; | ||
52 | |||
53 | void gl_init(void) | ||
54 | { | ||
55 | #if DEBUG > 1 | ||
56 | g_printerr("init OpenGL\n"); | ||
57 | #endif | ||
58 | |||
59 | GLfloat light0_pos[4] = { -50.0, 50.0, 0.0, 0.0 }; | ||
60 | GLfloat light0_col[4] = { 0.6, 0.6, 0.6, 1.0 }; | ||
61 | GLfloat light1_pos[4] = { 50.0, 50.0, 0.0, 0.0 }; | ||
62 | GLfloat light1_col[4] = { 0.4, 0.4, 0.4, 1.0 }; | ||
63 | GLfloat ambient_lc[4] = { 0.35, 0.35, 0.35, 1.0 }; | ||
64 | |||
65 | #if 0 | ||
66 | glEnable(GL_CULL_FACE); | ||
67 | #endif | ||
68 | |||
69 | /* transparency and blending */ | ||
70 | #if 0 | ||
71 | glAlphaFunc(GL_GREATER, 0.1); | ||
72 | #endif | ||
73 | glEnable(GL_ALPHA_TEST); | ||
74 | |||
75 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
76 | glEnable(GL_BLEND); | ||
77 | |||
78 | glDepthFunc(GL_LEQUAL); | ||
79 | glEnable(GL_DEPTH_TEST); | ||
80 | |||
81 | #if 0 | ||
82 | glEnable(GL_LINE_SMOOTH); | ||
83 | glEnable(GL_POLYGON_SMOOTH); | ||
84 | #endif | ||
85 | |||
86 | #if 0 | ||
87 | glDisable(GL_DITHER); | ||
88 | #endif | ||
89 | glShadeModel(GL_SMOOTH); | ||
90 | |||
91 | glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); | ||
92 | glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); | ||
93 | glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); | ||
94 | |||
95 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_lc); | ||
96 | glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); | ||
97 | glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); | ||
98 | glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); | ||
99 | |||
100 | glLightfv(GL_LIGHT0, GL_POSITION, light0_pos); | ||
101 | glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_col); | ||
102 | glLightfv(GL_LIGHT1, GL_POSITION, light1_pos); | ||
103 | glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_col); | ||
104 | glLightfv(GL_LIGHT1, GL_SPECULAR, light1_col); | ||
105 | glEnable(GL_LIGHT0); | ||
106 | glEnable(GL_LIGHT1); | ||
107 | glEnable(GL_LIGHTING); | ||
108 | |||
109 | /* colors and materials */ | ||
110 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); | ||
111 | glEnable(GL_COLOR_MATERIAL); | ||
112 | |||
113 | /* texture stuff */ | ||
114 | glEnable(GL_TEXTURE_2D); | ||
115 | |||
116 | #ifdef TIMING | ||
117 | timer = g_timer_new(); | ||
118 | #endif | ||
119 | } | ||
120 | |||
121 | void gl_set_twoside(gboolean twoside) | ||
122 | { | ||
123 | glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, twoside ? 1 : 0); | ||
124 | glColorMaterial( | ||
125 | twoside ? GL_FRONT_AND_BACK : GL_FRONT, | ||
126 | GL_AMBIENT_AND_DIFFUSE); | ||
127 | } | ||
128 | |||
129 | void gl_set_textures(gboolean textures) | ||
130 | { | ||
131 | if(textures) | ||
132 | glEnable(GL_TEXTURE_2D); | ||
133 | else | ||
134 | { | ||
135 | glBindTexture(GL_TEXTURE_2D, 0); | ||
136 | glDisable(GL_TEXTURE_2D); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /* GHFunc */ | ||
141 | void gl_load_texture(gpointer key, gpointer value, gpointer data) | ||
142 | { | ||
143 | G3DImage *image = (G3DImage *)value; | ||
144 | gint32 env; | ||
145 | |||
146 | #if 0 | ||
147 | /* predefined - update object->_tex_images else... */ | ||
148 | glGenTextures(1, &(image->gl_texid)); | ||
149 | #endif | ||
150 | |||
151 | #if DEBUG > 0 | ||
152 | g_print("gl: loading texture '%s' (%dx%dx%d) - id %d\n", | ||
153 | image->name ? image->name : "(null)", | ||
154 | image->width, image->height, image->depth, | ||
155 | image->tex_id); | ||
156 | #endif | ||
157 | |||
158 | glBindTexture(GL_TEXTURE_2D, image->tex_id); | ||
159 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||
160 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | ||
161 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | ||
162 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
163 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | ||
164 | GL_LINEAR_MIPMAP_NEAREST); | ||
165 | |||
166 | switch(image->tex_env) | ||
167 | { | ||
168 | case G3D_TEXENV_BLEND: env = GL_BLEND; break; | ||
169 | case G3D_TEXENV_MODULATE: env = GL_MODULATE; break; | ||
170 | case G3D_TEXENV_DECAL: env = GL_DECAL; break; | ||
171 | case G3D_TEXENV_REPLACE: env = GL_REPLACE; break; | ||
172 | default: env = GL_BLEND; break; | ||
173 | } | ||
174 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); | ||
175 | |||
176 | glTexImage2D( | ||
177 | GL_TEXTURE_2D /* target */, | ||
178 | 0 /* level */, | ||
179 | GL_RGBA /* internalFormat */, | ||
180 | image->width /* width */, | ||
181 | image->height /* height */, | ||
182 | 0 /* border */, | ||
183 | GL_RGBA /* format */, | ||
184 | GL_UNSIGNED_BYTE /* type */, | ||
185 | image->pixeldata /* pixels */); | ||
186 | gluBuild2DMipmaps( | ||
187 | GL_TEXTURE_2D, | ||
188 | GL_RGBA, | ||
189 | image->width, | ||
190 | image->height, | ||
191 | GL_RGBA, | ||
192 | GL_UNSIGNED_BYTE, | ||
193 | image->pixeldata); | ||
194 | } | ||
195 | |||
196 | void gl_update_material(gint32 glflags, G3DMaterial *material) | ||
197 | { | ||
198 | GLenum facetype; | ||
199 | GLfloat normspec[4] = { 0.0, 0.0, 0.0, 1.0 }; | ||
200 | |||
201 | g_return_if_fail(material != NULL); | ||
202 | |||
203 | if(glflags & G3D_FLAG_GL_ALLTWOSIDE) | ||
204 | facetype = GL_FRONT_AND_BACK; | ||
205 | else | ||
206 | facetype = GL_FRONT; | ||
207 | |||
208 | glColor4f( | ||
209 | material->r, | ||
210 | material->g, | ||
211 | material->b, | ||
212 | material->a); | ||
213 | |||
214 | return; | ||
215 | |||
216 | if(glflags & G3D_FLAG_GL_SPECULAR) | ||
217 | glMaterialfv(facetype, GL_SPECULAR, material->specular); | ||
218 | else | ||
219 | glMaterialfv(facetype, GL_SPECULAR, normspec); | ||
220 | |||
221 | if(glflags & G3D_FLAG_GL_SHININESS) | ||
222 | glMaterialf(facetype, GL_SHININESS, material->shininess * 10); | ||
223 | else | ||
224 | glMaterialf(facetype, GL_SHININESS, 0.0); | ||
225 | } | ||
226 | |||
227 | static void gl_draw_face(gint32 glflags, G3DObject *object, gint32 i, | ||
228 | gfloat min_a, gfloat max_a, gboolean *dont_render, gboolean *init) | ||
229 | { | ||
230 | static G3DMaterial *prev_material = NULL; | ||
231 | static guint32 prev_texid = 0; | ||
232 | gint32 j; | ||
233 | |||
234 | if(*init) | ||
235 | { | ||
236 | prev_material = NULL; | ||
237 | prev_texid = 0; | ||
238 | *init = FALSE; | ||
239 | } | ||
240 | |||
241 | /* material check */ | ||
242 | if(prev_material != object->_materials[i]) | ||
243 | { | ||
244 | if((object->_materials[i]->a < min_a) || | ||
245 | (object->_materials[i]->a >= max_a)) | ||
246 | { | ||
247 | *dont_render = TRUE; | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | *dont_render = FALSE; | ||
252 | |||
253 | glEnd(); | ||
254 | gl_update_material(glflags, object->_materials[i]); | ||
255 | glBegin(GL_TRIANGLES); | ||
256 | prev_material = object->_materials[i]; | ||
257 | |||
258 | prev_texid = 0; | ||
259 | } | ||
260 | |||
261 | if(*dont_render) return; | ||
262 | |||
263 | /* texture stuff */ | ||
264 | if((glflags & G3D_FLAG_GL_TEXTURES) && | ||
265 | (object->_flags[i] & G3D_FLAG_FAC_TEXMAP)) | ||
266 | { | ||
267 | /* if texture has changed update to new texture */ | ||
268 | if(object->_tex_images[i] != prev_texid) | ||
269 | { | ||
270 | prev_texid = object->_tex_images[i]; | ||
271 | glEnd(); | ||
272 | glBindTexture(GL_TEXTURE_2D, prev_texid); | ||
273 | glBegin(GL_TRIANGLES); | ||
274 | #if DEBUG > 5 | ||
275 | g_print("gl: binding to texture id %d\n", prev_texid); | ||
276 | #endif | ||
277 | } | ||
278 | } | ||
279 | |||
280 | |||
281 | /* draw triangles */ | ||
282 | for(j = 0; j < 3; j ++) | ||
283 | { | ||
284 | if((glflags & G3D_FLAG_GL_TEXTURES) && | ||
285 | (object->_flags[i] & G3D_FLAG_FAC_TEXMAP)) | ||
286 | { | ||
287 | glTexCoord2f( | ||
288 | object->_tex_coords[(i * 3 + j) * 2 + 0], | ||
289 | object->_tex_coords[(i * 3 + j) * 2 + 1]); | ||
290 | #if DEBUG > 5 | ||
291 | g_print("gl: setting texture coords: %f, %f\n", | ||
292 | object->_tex_coords[(i * 3 + j) * 2 + 0], | ||
293 | object->_tex_coords[(i * 3 + j) * 2 + 1]); | ||
294 | #endif | ||
295 | } | ||
296 | |||
297 | glNormal3f( | ||
298 | object->_normals[(i*3+j)*3+0], | ||
299 | object->_normals[(i*3+j)*3+1], | ||
300 | object->_normals[(i*3+j)*3+2]); | ||
301 | glVertex3f( | ||
302 | object->vertex_data[object->_indices[i*3+j]*3+0], | ||
303 | object->vertex_data[object->_indices[i*3+j]*3+1], | ||
304 | object->vertex_data[object->_indices[i*3+j]*3+2]); | ||
305 | |||
306 | } /* 1 .. 3 */ | ||
307 | } | ||
308 | |||
309 | static void gl_draw_objects(gint32 glflags, GSList *objects, | ||
310 | gfloat min_a, gfloat max_a) | ||
311 | { | ||
312 | GSList *olist; | ||
313 | int i; | ||
314 | G3DObject *object; | ||
315 | gboolean dont_render; | ||
316 | gboolean init = TRUE; | ||
317 | |||
318 | olist = objects; | ||
319 | while(olist != NULL) | ||
320 | { | ||
321 | object = (G3DObject *)olist->data; | ||
322 | olist = olist->next; | ||
323 | |||
324 | dont_render = FALSE; | ||
325 | |||
326 | /* don't render invisible objects */ | ||
327 | if(object->hide) continue; | ||
328 | |||
329 | g_return_if_fail(object != NULL); | ||
330 | #if DEBUG > 3 | ||
331 | g_printerr("name: %s {", object->name); | ||
332 | #endif | ||
333 | |||
334 | #if DEBUG > 2 | ||
335 | g_printerr("new object\n"); | ||
336 | #endif | ||
337 | |||
338 | glPushMatrix(); | ||
339 | |||
340 | if(object->transformation) | ||
341 | { | ||
342 | glMultMatrixf(object->transformation->matrix); | ||
343 | } | ||
344 | |||
345 | glBegin(GL_TRIANGLES); | ||
346 | |||
347 | for(i = 0; i < object->_num_faces; i ++) | ||
348 | { | ||
349 | gl_draw_face(glflags, object, i, min_a, max_a, | ||
350 | &dont_render, &init); | ||
351 | } /* all faces */ | ||
352 | |||
353 | glEnd(); | ||
354 | |||
355 | /* handle sub-objects */ | ||
356 | gl_draw_objects(glflags, object->objects, min_a, max_a); | ||
357 | |||
358 | glPopMatrix(); | ||
359 | |||
360 | } /* while olist != NULL */ | ||
361 | } | ||
362 | |||
363 | void gl_draw(gint32 glflags, gfloat zoom, gfloat aspect, gfloat *bgcolor, | ||
364 | gfloat *quat, G3DModel *model) | ||
365 | { | ||
366 | GLfloat m[4][4]; | ||
367 | static gchar *previous_name = NULL; | ||
368 | static gint32 previous_glflags = -1; | ||
369 | static gint32 dlist = -1; | ||
370 | GLenum error; | ||
371 | gfloat f; | ||
372 | |||
373 | if(! _initialized) | ||
374 | { | ||
375 | gl_init(); | ||
376 | _initialized = 1; | ||
377 | } | ||
378 | |||
379 | /* draw scene... */ | ||
380 | glMatrixMode(GL_PROJECTION); | ||
381 | glLoadIdentity(); | ||
382 | gluPerspective(zoom, aspect, 1, 100); | ||
383 | glMatrixMode(GL_MODELVIEW); | ||
384 | |||
385 | glClearColor( | ||
386 | bgcolor[0], | ||
387 | bgcolor[1], | ||
388 | bgcolor[2], | ||
389 | bgcolor[3]); | ||
390 | glClearDepth(1.0); | ||
391 | glClearIndex(0.3); | ||
392 | glClear( | ||
393 | GL_COLOR_BUFFER_BIT | | ||
394 | GL_DEPTH_BUFFER_BIT | | ||
395 | GL_ACCUM_BUFFER_BIT | | ||
396 | GL_STENCIL_BUFFER_BIT); | ||
397 | |||
398 | glLoadIdentity(); | ||
399 | glTranslatef(0, 0, -30); | ||
400 | build_rotmatrix(m, quat); | ||
401 | glMultMatrixf(&m[0][0]); | ||
402 | |||
403 | /* reset texture */ | ||
404 | glBindTexture (GL_TEXTURE_2D, 0); | ||
405 | |||
406 | if(model == NULL) | ||
407 | return; | ||
408 | |||
409 | #ifdef TIMING | ||
410 | g_timer_start(timer); | ||
411 | #endif | ||
412 | |||
413 | /* FIXME: better detection of new model */ | ||
414 | if((dlist < 0) || (glflags != previous_glflags) || | ||
415 | (previous_name == NULL) || strcmp(previous_name, model->filename)) | ||
416 | { | ||
417 | #if DEBUG > 0 | ||
418 | g_printerr("[gl] creating new display list\n"); | ||
419 | #endif | ||
420 | /* create and execute display list */ | ||
421 | if(dlist >= 0) | ||
422 | glDeleteLists(dlist, 1); | ||
423 | dlist = glGenLists(1); | ||
424 | |||
425 | glNewList(dlist, GL_COMPILE); | ||
426 | /* draw all objects */ | ||
427 | for(f = 1.0; f >= 0.0; f -= 0.2) | ||
428 | gl_draw_objects(glflags, model->objects, f, f + 0.2); | ||
429 | glEndList(); | ||
430 | |||
431 | if(previous_name) g_free(previous_name); | ||
432 | previous_name = g_strdup(model->filename); | ||
433 | previous_glflags = glflags; | ||
434 | } | ||
435 | |||
436 | /* execute display list */ | ||
437 | glCallList(dlist); | ||
438 | |||
439 | error = glGetError(); | ||
440 | if(error != GL_NO_ERROR) | ||
441 | g_printerr("[gl] E: %d\n", error); | ||
442 | |||
443 | #ifdef TIMING /* get time to draw one frame to compare algorithms */ | ||
444 | g_timer_stop(timer); | ||
445 | |||
446 | if(avg_msec == 0) | ||
447 | { | ||
448 | gulong msec; | ||
449 | gdouble sec; | ||
450 | |||
451 | sec = g_timer_elapsed(timer, &msec); | ||
452 | avg_msec = (gulong)sec * 1000000 + msec; | ||
453 | } | ||
454 | else | ||
455 | { | ||
456 | gulong msec, add; | ||
457 | gdouble sec; | ||
458 | |||
459 | sec = g_timer_elapsed(timer, &msec); | ||
460 | add = (gulong)sec * 1000000 + msec; | ||
461 | avg_msec = (avg_msec + add) / 2; | ||
462 | } | ||
463 | |||
464 | g_printerr("average time to render frame: %lu µs\n", avg_msec); | ||
465 | #endif | ||
466 | |||
467 | #if DEBUG > 3 | ||
468 | g_printerr("gl.c: drawn...\n"); | ||
469 | #endif | ||
470 | } | ||
471 | |||