aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/g3dviewer-0.2.99.4/src/gl.c
diff options
context:
space:
mode:
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.c471
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
44static int _initialized = 0;
45
46#ifdef TIMING
47static GTimer *timer = NULL;
48static gulong avg_msec = 0;
49#endif
50
51GLuint evil;
52
53void 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
121void 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
129void 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 */
141void 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
196void 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
227static 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
309static 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
363void 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