wip
[hkl.git] / gui / hkl-gui-3d-gl.c
blobf0021cf05f123584a4945e92ef7e084909b7acc0
1 /* $Id: gl.c 127 2009-09-05 19:45:12Z mmmaddd $ */
3 /*
4 G3DViewer - 3D object viewer
6 Copyright (C) 2005, 2006 Markus Dahms <mad@automagically.de>
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.
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.
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
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
27 #include <glib.h>
29 #include <GL/gl.h>
30 #include <GL/glu.h>
32 #include <g3d/types.h>
33 #include <g3d/quat.h>
34 #include <g3d/matrix.h>
35 #include <g3d/vector.h>
36 #include <g3d/face.h>
38 #include "hkl-gui-3d-gl.h"
40 struct _G3DGLRenderState {
41 gint32 gl_dlist, gl_dlist_shadow;
42 G3DMaterial *prev_material;
43 guint32 prev_texid;
46 #if DEBUG > 0
47 #define TIMING
48 #endif
50 #ifdef TIMING
51 static GTimer *timer = NULL;
52 #endif
54 static void gl_init(void)
56 #if DEBUG > 1
57 g_printerr("init OpenGL\n");
58 #endif
61 GLfloat light0_pos[4] = { -50.0, 50.0, 0.0, 0.0 };
62 GLfloat light0_col[4] = { 0.6, 0.6, 0.6, 1.0 };
63 GLfloat light1_pos[4] = { 50.0, 50.0, 0.0, 0.0 };
64 GLfloat light1_col[4] = { 0.4, 0.4, 0.4, 1.0 };
65 GLfloat ambient_lc[4] = { 0.35, 0.35, 0.35, 1.0 };
67 /* transparency and blending */
68 #if 0
69 glAlphaFunc(GL_GREATER, 0.1);
70 #endif
71 glEnable(GL_ALPHA_TEST);
73 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
74 glEnable(GL_BLEND);
76 glEnable(GL_CULL_FACE);
78 /* glClearDepth(1.0f); */
79 glDepthFunc(GL_LEQUAL);
80 glDepthMask(GL_TRUE);
81 glEnable(GL_DEPTH_TEST);
83 #if 0
84 glEnable(GL_LINE_SMOOTH);
85 glEnable(GL_POLYGON_SMOOTH);
86 #endif
88 #if 0
89 glDisable(GL_DITHER);
90 #endif
91 glShadeModel(GL_SMOOTH);
93 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
94 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
95 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
97 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_lc);
98 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
99 #ifdef GL_LIGHT_MODEL_COLOR_CONTROL
100 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
101 #endif
102 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
104 glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
105 glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_col);
106 glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
107 glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_col);
108 glLightfv(GL_LIGHT1, GL_SPECULAR, light1_col);
109 glEnable(GL_LIGHT0);
110 glEnable(GL_LIGHT1);
111 glEnable(GL_LIGHTING);
114 /* colors and materials */
115 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
116 glEnable(GL_COLOR_MATERIAL);
119 /* texture stuff */
120 glEnable(GL_TEXTURE_2D);
123 #ifdef TIMING
124 timer = g_timer_new();
125 #endif
128 void gl_set_twoside(gboolean twoside)
130 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, twoside ? 1 : 0);
131 glColorMaterial(
132 twoside ? GL_FRONT_AND_BACK : GL_FRONT,
133 GL_AMBIENT_AND_DIFFUSE);
136 void gl_set_textures(gboolean textures)
138 if(textures)
139 glEnable(GL_TEXTURE_2D);
140 else
142 glBindTexture(GL_TEXTURE_2D, 0);
143 glDisable(GL_TEXTURE_2D);
147 /* GHFunc */
148 void gl_load_texture(gpointer key, gpointer value, gpointer data)
150 G3DImage *image = (G3DImage *)value;
151 gint32 env;
154 #if 0
155 /* predefined - update object->_tex_images else... */
156 glGenTextures(1, &(image->tex_id));
157 #endif
159 #if DEBUG > 0
160 g_print("gl: loading texture '%s' (%dx%dx%d) - id %d\n",
161 image->name ? image->name : "(null)",
162 image->width, image->height, image->depth,
163 image->tex_id);
164 #endif
166 glBindTexture(GL_TEXTURE_2D, image->tex_id);
167 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
172 GL_LINEAR_MIPMAP_NEAREST);
175 switch(image->tex_env)
177 case G3D_TEXENV_BLEND: env = GL_BLEND; break;
178 case G3D_TEXENV_MODULATE: env = GL_MODULATE; break;
179 case G3D_TEXENV_DECAL: env = GL_DECAL; break;
180 case G3D_TEXENV_REPLACE: env = GL_REPLACE; break;
181 default: env = GL_MODULATE; break;
183 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
184 gluBuild2DMipmaps(
185 GL_TEXTURE_2D,
186 GL_RGBA,
187 image->width,
188 image->height,
189 GL_RGBA,
190 GL_UNSIGNED_BYTE,
191 image->pixeldata);
194 static inline void gl_update_material(G3DGLRenderOptions *options,
195 G3DMaterial *material)
197 GLenum facetype;
198 GLfloat normspec[4] = { 0.0, 0.0, 0.0, 1.0 };
200 g_return_if_fail(material != NULL);
202 if(options->glflags & G3D_FLAG_GL_ALLTWOSIDE)
203 facetype = GL_FRONT_AND_BACK;
204 else
205 facetype = GL_FRONT;
207 if(options->glflags & G3D_FLAG_GL_COLORS)
208 glColor4f(
209 material->r,
210 material->g,
211 material->b,
212 material->a);
213 else
214 glColor4f(0.7, 0.7, 0.7, 1.0);
216 return;
218 if(options->glflags & G3D_FLAG_GL_SPECULAR)
219 glMaterialfv(facetype, GL_SPECULAR, material->specular);
220 else
221 glMaterialfv(facetype, GL_SPECULAR, normspec);
223 if(options->glflags & G3D_FLAG_GL_SHININESS)
224 glMaterialf(facetype, GL_SHININESS, material->shininess * 10);
225 else
226 glMaterialf(facetype, GL_SHININESS, 0.0);
229 static inline void gl_draw_face(G3DGLRenderOptions *options,
230 G3DObject *object, gint32 i, gfloat min_a, gfloat max_a,
231 gboolean *dont_render, gboolean *init, gboolean is_shadow)
233 gint32 j;
235 if(*init)
237 options->state->prev_material = NULL;
238 options->state->prev_texid = 0;
239 *init = FALSE;
242 /* material check */
243 if(!is_shadow && (options->state->prev_material != object->_materials[i]))
245 if((object->_materials[i]->a < min_a) ||
246 (object->_materials[i]->a >= max_a))
248 *dont_render = TRUE;
249 return;
252 *dont_render = FALSE;
254 glEnd();
255 gl_update_material(options, object->_materials[i]);
256 glBegin(GL_TRIANGLES);
257 options->state->prev_material = object->_materials[i];
259 options->state->prev_texid = 0;
262 if(*dont_render) return;
264 /* texture stuff */
265 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
266 (object->_flags[i] & G3D_FLAG_FAC_TEXMAP))
268 /* if texture has changed update to new texture */
269 if(object->_tex_images[i] != options->state->prev_texid) {
270 options->state->prev_texid = object->_tex_images[i];
271 glEnd();
272 glBindTexture(GL_TEXTURE_2D, options->state->prev_texid);
273 glBegin(GL_TRIANGLES);
274 #if DEBUG > 5
275 g_print("gl: binding to texture id %d\n", prev_texid);
276 #endif
280 /* draw triangles */
281 for(j = 0; j < 3; j ++)
283 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
284 (object->_flags[i] & G3D_FLAG_FAC_TEXMAP))
286 glTexCoord2f(
287 object->_tex_coords[(i * 3 + j) * 2 + 0],
288 object->_tex_coords[(i * 3 + j) * 2 + 1]);
289 #if DEBUG > 5
290 g_print("gl: setting texture coords: %f, %f\n",
291 object->_tex_coords[(i * 3 + j) * 2 + 0],
292 object->_tex_coords[(i * 3 + j) * 2 + 1]);
293 #endif
296 glNormal3f(
297 object->_normals[(i*3+j)*3+0],
298 object->_normals[(i*3+j)*3+1],
299 object->_normals[(i*3+j)*3+2]);
300 glVertex3f(
301 object->vertex_data[object->_indices[i*3+j]*3+0],
302 object->vertex_data[object->_indices[i*3+j]*3+1],
303 object->vertex_data[object->_indices[i*3+j]*3+2]);
305 } /* 1 .. 3 */
308 static inline void gl_may_end(gint32 ftype)
310 if(ftype != -1)
311 glEnd();
314 static inline void gl_may_begin(gint32 ftype)
316 if(ftype != -1)
317 glBegin(ftype);
320 static inline void gl_draw_face_list(G3DGLRenderOptions *options,
321 G3DObject *object, gfloat min_a, gfloat max_a,
322 gboolean *init, gboolean is_shadow)
324 GSList *fitem;
325 G3DFace *face;
326 G3DVector nx, ny, nz;
327 gint32 prev_ftype = -1;
328 gint32 index, j, ftype;
330 if(*init) {
331 options->state->prev_material = NULL;
332 options->state->prev_texid = 0;
333 *init = FALSE;
336 for(fitem = object->faces; fitem != NULL; fitem = fitem->next) {
337 face = fitem->data;
338 if(!is_shadow && (options->state->prev_material != face->material)) {
339 if((face->material->a < min_a) || (face->material->a >= max_a)) {
340 return;
343 gl_may_end(prev_ftype);
344 gl_update_material(options, face->material);
345 gl_may_begin(prev_ftype);
347 options->state->prev_material = face->material;
349 options->state->prev_texid = 0;
352 /* texture stuff */
353 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
354 (face->flags & G3D_FLAG_FAC_TEXMAP)) {
355 /* if texture has changed update to new texture */
356 if(face->tex_image) {
357 if(face->tex_image->tex_id != options->state->prev_texid) {
358 options->state->prev_texid = face->tex_image->tex_id;
360 gl_may_end(prev_ftype);
361 glBindTexture(GL_TEXTURE_2D, options->state->prev_texid);
362 gl_may_begin(prev_ftype);
363 #if DEBUG > 5
364 g_print("gl: binding to texture id %d\n", prev_texid);
365 #endif
368 } /* texture stuff */
370 switch(face->vertex_count) {
371 case 3: ftype = GL_TRIANGLES; break;
372 case 4: ftype = GL_QUADS; break;
373 case 2: ftype = GL_LINES; break;
374 default: ftype = GL_POLYGON;
375 #if DEBUG > 0
376 g_debug("face vertex count: %d", face->vertex_count);
377 #endif
378 break;
380 if(ftype != prev_ftype) {
381 gl_may_end(prev_ftype);
382 glBegin(ftype);
383 prev_ftype = ftype;
386 if(!(face->flags & G3D_FLAG_FAC_NORMALS)) {
387 face->normals = g_new0(G3DVector, face->vertex_count * 3);
389 g3d_face_get_normal(face, object, &nx, &ny, &nz);
390 g3d_vector_unify(&nx, &ny, &nz);
392 for(j = 0; j < face->vertex_count; j ++) {
393 face->normals[j * 3 + 0] = nx;
394 face->normals[j * 3 + 1] = ny;
395 face->normals[j * 3 + 2] = nz;
397 face->flags |= G3D_FLAG_FAC_NORMALS;
400 for(j = 0; j < face->vertex_count; j ++) {
401 index = face->vertex_indices[j];
403 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
404 (face->flags & G3D_FLAG_FAC_TEXMAP))
406 glTexCoord2f(
407 face->tex_vertex_data[j * 2 + 0],
408 face->tex_vertex_data[j * 2 + 1]);
411 glNormal3f(
412 face->normals[j * 3 + 0],
413 face->normals[j * 3 + 1],
414 face->normals[j * 3 + 2]);
416 glVertex3f(
417 object->vertex_data[index * 3 + 0],
418 object->vertex_data[index * 3 + 1],
419 object->vertex_data[index * 3 + 2]);
422 } /* face loop */
424 gl_may_end(prev_ftype);
428 static inline void gl_draw_objects(G3DGLRenderOptions *options,
429 GSList *objects, gfloat min_a, gfloat max_a, gboolean is_shadow)
431 GSList *olist;
432 int i;
433 G3DObject *object;
434 gboolean init = TRUE;
436 olist = objects;
437 while(olist != NULL)
439 object = (G3DObject *)olist->data;
440 olist = olist->next;
442 /* don't render invisible objects */
443 if(object->hide) continue;
445 g_return_if_fail(object != NULL);
446 #if DEBUG > 3
447 g_printerr("name: %s {", object->name);
448 #endif
450 #if DEBUG > 2
451 g_printerr("new object\n");
452 #endif
454 glPushMatrix();
456 if(object->transformation)
458 glMultMatrixf(object->transformation->matrix);
461 #define EXPERIMENTAL
462 #ifdef EXPERIMENTAL
463 gl_draw_face_list(options, object, min_a, max_a, &init, is_shadow);
464 #else
465 glBegin(GL_TRIANGLES);
467 for(i = 0; i < object->_num_faces; i ++)
469 gl_draw_face(options, object, i, min_a, max_a,
470 &dont_render, &init, is_shadow);
471 } /* all faces */
473 glEnd();
474 #endif
476 if(!is_shadow && (options->glflags & G3D_FLAG_GL_POINTS)) {
477 glColor4f(0.2, 0.2, 0.2, 1.0);
478 glBegin(GL_POINTS);
479 for(i = 0; i < object->vertex_count; i ++) {
480 glVertex3f(
481 object->vertex_data[i * 3 + 0],
482 object->vertex_data[i * 3 + 1],
483 object->vertex_data[i * 3 + 2]);
485 glEnd();
488 /* handle sub-objects */
489 gl_draw_objects(options, object->objects, min_a, max_a, is_shadow);
491 glPopMatrix();
493 } /* while olist != NULL */
496 static inline void matrix_g3d_to_gl(G3DMatrix *g3dm, GLfloat glm[4][4])
498 guint32 i, j;
500 for(i = 0; i < 4; i ++)
501 for(j = 0; j < 4; j ++)
502 glm[i][j] = g3dm[i * 4 + j];
505 static inline void gl_setup_view(G3DGLRenderOptions *options)
507 GLfloat m[4][4];
508 G3DMatrix *g3dm;
509 G3DFloat w, h;
511 glMatrixMode(GL_PROJECTION);
512 glLoadIdentity();
513 if(options->glflags & G3D_FLAG_GL_ISOMETRIC) {
514 w = 0.5 * options->zoom;
515 h = w / options->aspect;
516 glOrtho(-w / 2.0, w / 2.0, -h / 2.0, h / 2.0, 1, 100);
517 } else {
518 gluPerspective(options->zoom, options->aspect, 1, 100);
520 /* translation of view */
521 glTranslatef(options->offx, options->offy, 0.0);
523 glMatrixMode(GL_MODELVIEW);
525 glClearColor(
526 options->bgcolor[0],
527 options->bgcolor[1],
528 options->bgcolor[2],
529 options->bgcolor[3]);
530 glClearDepth(1.0);
531 glClearIndex(0.3);
532 glClear(
533 GL_COLOR_BUFFER_BIT |
534 GL_DEPTH_BUFFER_BIT |
535 GL_ACCUM_BUFFER_BIT |
536 GL_STENCIL_BUFFER_BIT);
538 glLoadIdentity();
539 glTranslatef(0, 0, -30);
540 g3dm = g3d_matrix_new();
541 g3d_quat_to_matrix(options->quat, g3dm);
542 matrix_g3d_to_gl(g3dm, m);
544 g3d_matrix_free(g3dm);
545 glMultMatrixf(&m[0][0]);
548 static void gl_setup_shadow_matrix(G3DGLRenderOptions *options,
549 G3DVector *l, G3DVector *p, G3DVector *n)
551 G3DDouble c, d;
552 G3DMatrix *m = options->shadow_matrix;
554 d = n[0] * l[0] + n[1] * l[1] + n[2] * l[2];
555 c = p[0] * n[0] + p[1] * n[1] + p[2] * n[2] - d;
557 m[0 * 4 + 0] = l[0] * n[0] + c;
558 m[1 * 4 + 0] = l[0] * n[1];
559 m[2 * 4 + 0] = l[0] * n[2];
560 m[3 * 4 + 0] = - l[0] * c - l[0] * d;
562 m[0 * 4 + 1] = l[1] * n[0];
563 m[1 * 4 + 1] = l[1] * n[1] + c;
564 m[2 * 4 + 1] = l[1] * n[2];
565 m[3 * 4 + 1] = - l[1] * c - l[1] * d;
567 m[0 * 4 + 2] = l[2] * n[0];
568 m[1 * 4 + 2] = l[2] * n[1];
569 m[2 * 4 + 2] = l[2] * n[2] + c;
570 m[3 * 4 + 2] = - l[2] * c - l[2] * d;
572 m[0 * 4 + 3] = n[0];
573 m[1 * 4 + 3] = n[1];
574 m[2 * 4 + 3] = n[2];
575 m[3 * 4 + 3] = -d;
578 void gl_draw_coord_system(G3DGLRenderOptions *options)
580 if(options->glflags & G3D_FLAG_GL_COORD_AXES) {
581 /* x: red */
582 glColor3f(1.0, 0.0, 0.0);
583 glBegin(GL_LINES);
584 glVertex3f(0.0, 0.0, 0.0);
585 glVertex3f(10.0, 0.0, 0.0);
586 glEnd();
587 /* y: green */
588 glColor3f(0.0, 1.0, 0.0);
589 glBegin(GL_LINES);
590 glVertex3f(0.0, 0.0, 0.0);
591 glVertex3f(0.0, 10.0, 0.0);
592 glEnd();
593 /* z: blue */
594 glColor3f(0.0, 0.0, 1.0);
595 glBegin(GL_LINES);
596 glVertex3f(0.0, 0.0, 0.0);
597 glVertex3f(0.0, 0.0, 10.0);
598 glEnd();
602 static G3DFloat gl_min_y(GSList *objects)
604 G3DFloat min_y = 10.0, tmp_y;
605 GSList *oitem;
606 G3DObject *object;
607 gint32 i;
609 for(oitem = objects; oitem != NULL; oitem = oitem->next) {
610 object = oitem->data;
611 for(i = 0; i < object->vertex_count; i ++)
612 if(object->vertex_data[i * 3 + 1] < min_y)
613 min_y = object->vertex_data[i * 3 + 1];
614 tmp_y = gl_min_y(object->objects);
615 if(tmp_y < min_y)
616 min_y = tmp_y;
618 return min_y;
621 static void gl_draw_plane(G3DGLRenderOptions *options)
623 glBegin(GL_QUADS);
624 glNormal3f(0.0, -1.0, 0.0);
625 #define PLANE_MAX 12
626 glVertex3f(-PLANE_MAX, options->min_y - 0.001, PLANE_MAX);
627 glVertex3f( PLANE_MAX, options->min_y - 0.001, PLANE_MAX);
628 glVertex3f( PLANE_MAX, options->min_y - 0.001, -PLANE_MAX);
629 glVertex3f(-PLANE_MAX, options->min_y - 0.001, -PLANE_MAX);
630 #undef PLANE_MAX
631 glEnd();
634 static void gl_setup_floor_stencil(G3DGLRenderOptions *options)
636 glClear(GL_STENCIL_BUFFER_BIT);
637 glDepthMask(GL_FALSE);
638 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
640 glEnable(GL_STENCIL_TEST);
641 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
642 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
644 gl_draw_plane(options);
646 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
647 glDepthMask(GL_TRUE);
649 glStencilFunc(GL_EQUAL, 1, 0xffffffff);
650 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
653 static void gl_setup_shadow_stencil(G3DGLRenderOptions *options)
655 glClear(GL_STENCIL_BUFFER_BIT);
656 glDepthMask(GL_FALSE);
657 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
659 glEnable(GL_STENCIL_TEST);
660 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
661 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
663 glCallList(options->state->gl_dlist_shadow);
665 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
666 glDepthMask(GL_TRUE);
668 glStencilFunc(GL_EQUAL, 1, 0xffffffff);
669 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
672 void gl_draw(G3DGLRenderOptions *options, G3DModel *model)
674 gfloat f;
675 #ifdef TIMING
676 gboolean ignore_timing = FALSE;
677 gulong msec, add;
678 gdouble sec;
679 #endif
680 G3DVector light[3] = { 100.0, 500.0, 20.0 };
681 G3DVector plane[3] = { 0.0, -20.0, 0.0 };
682 G3DVector normal[3] = { 0.0, -1.0, 0.0 };
684 if(!options->initialized)
686 gl_init();
687 options->initialized = TRUE;
688 #ifdef TIMING
689 ignore_timing = TRUE;
690 #endif
693 /* prepare viewport */
694 gl_setup_view(options);
696 /* reset texture */
697 glBindTexture (GL_TEXTURE_2D, 0);
699 if(model == NULL)
700 return;
702 #ifdef TIMING
703 g_timer_start(timer);
704 #endif
706 if(options->updated) {
707 options->updated = FALSE;
708 #ifdef TIMING
709 ignore_timing = TRUE;
710 #endif
711 #if DEBUG > 2
712 g_printerr("[gl] creating new display list\n");
713 #endif
714 options->min_y = gl_min_y(model->objects);
716 /* update render state */
717 if(options->state) {
718 glDeleteLists(options->state->gl_dlist, 1);
719 glDeleteLists(options->state->gl_dlist_shadow, 1);
720 g_free(options->state);
722 options->state = g_new0(G3DGLRenderState, 1);
724 /* create and execute display list */
725 options->state->gl_dlist = glGenLists(1);
726 options->state->gl_dlist_shadow = glGenLists(1);
728 glNewList(options->state->gl_dlist, GL_COMPILE);
729 /* draw all objects */
730 for(f = 1.0; f >= 0.0; f -= 0.2)
731 gl_draw_objects(options, model->objects, f, f + 0.2, FALSE);
732 glEndList();
734 if(options->glflags & G3D_FLAG_GL_SHADOW) {
735 glNewList(options->state->gl_dlist_shadow, GL_COMPILE);
736 gl_draw_objects(options, model->objects, 0.0, 1.0, TRUE);
737 glEndList();
741 g_return_if_fail(options->state != NULL);
743 gl_draw_coord_system(options);
745 if(options->glflags & G3D_FLAG_GL_SHADOW) {
746 plane[1] = options->min_y;
748 /* reflection */
749 glPushMatrix();
750 gl_setup_floor_stencil(options);
751 glTranslatef(0.0, (options->min_y * 2), 0.0);
752 glScalef(1.0, -1.0, 1.0);
753 glCallList(options->state->gl_dlist);
754 glPopMatrix();
756 /* plane */
757 glDisable(GL_LIGHTING);
758 glBindTexture (GL_TEXTURE_2D, 0);
759 glColor4f(0.5, 0.5, 0.5, 0.7);
760 gl_draw_plane(options);
761 glEnable(GL_LIGHTING);
762 /* shadow */
763 glPushMatrix();
764 gl_setup_shadow_matrix(options, light, plane, normal);
765 glBindTexture (GL_TEXTURE_2D, 0);
766 glDisable(GL_LIGHTING);
767 glDisable(GL_DEPTH_TEST);
768 glMultMatrixf(options->shadow_matrix);
769 gl_setup_shadow_stencil(options);
770 glPopMatrix();
771 glPushMatrix();
772 glTranslatef(0.0, 0.001, 0.0);
773 glColor4f(0.3, 0.3, 0.3, 0.7);
774 gl_draw_plane(options);
775 glEnable(GL_DEPTH_TEST);
776 glEnable(GL_LIGHTING);
777 glPopMatrix();
779 glDisable(GL_STENCIL_TEST);
782 /* execute display list */
783 glCallList(options->state->gl_dlist);
785 #ifdef TIMING /* get time to draw one frame to compare algorithms */
786 g_timer_stop(timer);
788 if(!ignore_timing) {
789 if(options->avg_msec == 0) {
790 sec = g_timer_elapsed(timer, &msec);
791 options->avg_msec = (gulong)sec * 1000000 + msec;
792 } else {
793 sec = g_timer_elapsed(timer, &msec);
794 add = (gulong)sec * 1000000 + msec;
795 options->avg_msec = (options->avg_msec + add) / 2;
798 #endif
800 #if DEBUG > 3
801 g_printerr("gl.c: drawn...\n");
802 #endif