[hkl] remove a bunch of warnings.
[hkl.git] / gui / hkl-gui-3d-gl.c
blobe185fb3718c51b105c82df7ee682a82e0a828ce2
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 glDepthFunc(GL_LEQUAL);
77 glDepthMask(GL_TRUE);
78 glEnable(GL_DEPTH_TEST);
81 #if 0
82 glEnable(GL_LINE_SMOOTH);
83 glEnable(GL_POLYGON_SMOOTH);
84 #endif
86 #if 0
87 glDisable(GL_DITHER);
88 #endif
89 glShadeModel(GL_SMOOTH);
91 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
92 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
93 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
95 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_lc);
96 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
97 #ifdef GL_LIGHT_MODEL_COLOR_CONTROL
98 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
99 #endif
100 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
102 glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
103 glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_col);
104 glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
105 glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_col);
106 glLightfv(GL_LIGHT1, GL_SPECULAR, light1_col);
107 glEnable(GL_LIGHT0);
108 glEnable(GL_LIGHT1);
109 glEnable(GL_LIGHTING);
112 /* colors and materials */
113 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
114 glEnable(GL_COLOR_MATERIAL);
117 /* texture stuff */
118 glEnable(GL_TEXTURE_2D);
121 #ifdef TIMING
122 timer = g_timer_new();
123 #endif
126 void gl_set_twoside(gboolean twoside)
128 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, twoside ? 1 : 0);
129 glColorMaterial(
130 twoside ? GL_FRONT_AND_BACK : GL_FRONT,
131 GL_AMBIENT_AND_DIFFUSE);
134 void gl_set_textures(gboolean textures)
136 if(textures)
137 glEnable(GL_TEXTURE_2D);
138 else
140 glBindTexture(GL_TEXTURE_2D, 0);
141 glDisable(GL_TEXTURE_2D);
145 /* GHFunc */
146 void gl_load_texture(gpointer key, gpointer value, gpointer data)
148 G3DImage *image = (G3DImage *)value;
149 gint32 env;
152 #if 0
153 /* predefined - update object->_tex_images else... */
154 glGenTextures(1, &(image->tex_id));
155 #endif
157 #if DEBUG > 0
158 g_print("gl: loading texture '%s' (%dx%dx%d) - id %d\n",
159 image->name ? image->name : "(null)",
160 image->width, image->height, image->depth,
161 image->tex_id);
162 #endif
164 glBindTexture(GL_TEXTURE_2D, image->tex_id);
165 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
169 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
170 GL_LINEAR_MIPMAP_NEAREST);
173 switch(image->tex_env)
175 case G3D_TEXENV_BLEND: env = GL_BLEND; break;
176 case G3D_TEXENV_MODULATE: env = GL_MODULATE; break;
177 case G3D_TEXENV_DECAL: env = GL_DECAL; break;
178 case G3D_TEXENV_REPLACE: env = GL_REPLACE; break;
179 default: env = GL_MODULATE; break;
181 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
182 gluBuild2DMipmaps(
183 GL_TEXTURE_2D,
184 GL_RGBA,
185 image->width,
186 image->height,
187 GL_RGBA,
188 GL_UNSIGNED_BYTE,
189 image->pixeldata);
192 static inline void gl_update_material(G3DGLRenderOptions *options,
193 G3DMaterial *material)
195 GLenum facetype;
196 GLfloat normspec[4] = { 0.0, 0.0, 0.0, 1.0 };
198 g_return_if_fail(material != NULL);
200 if(options->glflags & G3D_FLAG_GL_ALLTWOSIDE)
201 facetype = GL_FRONT_AND_BACK;
202 else
203 facetype = GL_FRONT;
205 if(options->glflags & G3D_FLAG_GL_COLORS)
206 glColor4f(
207 material->r,
208 material->g,
209 material->b,
210 material->a);
211 else
212 glColor4f(0.7, 0.7, 0.7, 1.0);
214 return;
216 if(options->glflags & G3D_FLAG_GL_SPECULAR)
217 glMaterialfv(facetype, GL_SPECULAR, material->specular);
218 else
219 glMaterialfv(facetype, GL_SPECULAR, normspec);
221 if(options->glflags & G3D_FLAG_GL_SHININESS)
222 glMaterialf(facetype, GL_SHININESS, material->shininess * 10);
223 else
224 glMaterialf(facetype, GL_SHININESS, 0.0);
227 static inline void gl_draw_face(G3DGLRenderOptions *options,
228 G3DObject *object, gint32 i, gfloat min_a, gfloat max_a,
229 gboolean *dont_render, gboolean *init, gboolean is_shadow)
231 gint32 j;
233 if(*init)
235 options->state->prev_material = NULL;
236 options->state->prev_texid = 0;
237 *init = FALSE;
240 /* material check */
241 if(!is_shadow && (options->state->prev_material != object->_materials[i]))
243 if((object->_materials[i]->a < min_a) ||
244 (object->_materials[i]->a >= max_a))
246 *dont_render = TRUE;
247 return;
250 *dont_render = FALSE;
252 glEnd();
253 gl_update_material(options, object->_materials[i]);
254 glBegin(GL_TRIANGLES);
255 options->state->prev_material = object->_materials[i];
257 options->state->prev_texid = 0;
260 if(*dont_render) return;
262 /* texture stuff */
263 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
264 (object->_flags[i] & G3D_FLAG_FAC_TEXMAP))
266 /* if texture has changed update to new texture */
267 if(object->_tex_images[i] != options->state->prev_texid) {
268 options->state->prev_texid = object->_tex_images[i];
269 glEnd();
270 glBindTexture(GL_TEXTURE_2D, options->state->prev_texid);
271 glBegin(GL_TRIANGLES);
272 #if DEBUG > 5
273 g_print("gl: binding to texture id %d\n", prev_texid);
274 #endif
278 /* draw triangles */
279 for(j = 0; j < 3; j ++)
281 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
282 (object->_flags[i] & G3D_FLAG_FAC_TEXMAP))
284 glTexCoord2f(
285 object->_tex_coords[(i * 3 + j) * 2 + 0],
286 object->_tex_coords[(i * 3 + j) * 2 + 1]);
287 #if DEBUG > 5
288 g_print("gl: setting texture coords: %f, %f\n",
289 object->_tex_coords[(i * 3 + j) * 2 + 0],
290 object->_tex_coords[(i * 3 + j) * 2 + 1]);
291 #endif
294 glNormal3f(
295 object->_normals[(i*3+j)*3+0],
296 object->_normals[(i*3+j)*3+1],
297 object->_normals[(i*3+j)*3+2]);
298 glVertex3f(
299 object->vertex_data[object->_indices[i*3+j]*3+0],
300 object->vertex_data[object->_indices[i*3+j]*3+1],
301 object->vertex_data[object->_indices[i*3+j]*3+2]);
303 } /* 1 .. 3 */
306 static inline void gl_may_end(gint32 ftype)
308 if(ftype != -1)
309 glEnd();
312 static inline void gl_may_begin(gint32 ftype)
314 if(ftype != -1)
315 glBegin(ftype);
318 static inline void gl_draw_face_list(G3DGLRenderOptions *options,
319 G3DObject *object, gfloat min_a, gfloat max_a,
320 gboolean *init, gboolean is_shadow)
322 GSList *fitem;
323 G3DFace *face;
324 G3DVector nx, ny, nz;
325 gint32 prev_ftype = -1;
326 gint32 index, j, ftype;
328 if(*init) {
329 options->state->prev_material = NULL;
330 options->state->prev_texid = 0;
331 *init = FALSE;
334 for(fitem = object->faces; fitem != NULL; fitem = fitem->next) {
335 face = fitem->data;
336 if(!is_shadow && (options->state->prev_material != face->material)) {
337 if((face->material->a < min_a) || (face->material->a >= max_a)) {
338 return;
341 gl_may_end(prev_ftype);
342 gl_update_material(options, face->material);
343 gl_may_begin(prev_ftype);
345 options->state->prev_material = face->material;
347 options->state->prev_texid = 0;
350 /* texture stuff */
351 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
352 (face->flags & G3D_FLAG_FAC_TEXMAP)) {
353 /* if texture has changed update to new texture */
354 if(face->tex_image) {
355 if(face->tex_image->tex_id != options->state->prev_texid) {
356 options->state->prev_texid = face->tex_image->tex_id;
358 gl_may_end(prev_ftype);
359 glBindTexture(GL_TEXTURE_2D, options->state->prev_texid);
360 gl_may_begin(prev_ftype);
361 #if DEBUG > 5
362 g_print("gl: binding to texture id %d\n", prev_texid);
363 #endif
366 } /* texture stuff */
368 switch(face->vertex_count) {
369 case 3: ftype = GL_TRIANGLES; break;
370 case 4: ftype = GL_QUADS; break;
371 case 2: ftype = GL_LINES; break;
372 default: ftype = GL_POLYGON;
373 #if DEBUG > 0
374 g_debug("face vertex count: %d", face->vertex_count);
375 #endif
376 break;
378 if(ftype != prev_ftype) {
379 gl_may_end(prev_ftype);
380 glBegin(ftype);
381 prev_ftype = ftype;
384 if(!(face->flags & G3D_FLAG_FAC_NORMALS)) {
385 face->normals = g_new0(G3DVector, face->vertex_count * 3);
387 g3d_face_get_normal(face, object, &nx, &ny, &nz);
388 g3d_vector_unify(&nx, &ny, &nz);
390 for(j = 0; j < face->vertex_count; j ++) {
391 face->normals[j * 3 + 0] = nx;
392 face->normals[j * 3 + 1] = ny;
393 face->normals[j * 3 + 2] = nz;
395 face->flags |= G3D_FLAG_FAC_NORMALS;
398 for(j = 0; j < face->vertex_count; j ++) {
399 index = face->vertex_indices[j];
401 if(!is_shadow && (options->glflags & G3D_FLAG_GL_TEXTURES) &&
402 (face->flags & G3D_FLAG_FAC_TEXMAP))
404 glTexCoord2f(
405 face->tex_vertex_data[j * 2 + 0],
406 face->tex_vertex_data[j * 2 + 1]);
409 glNormal3f(
410 face->normals[j * 3 + 0],
411 face->normals[j * 3 + 1],
412 face->normals[j * 3 + 2]);
414 glVertex3f(
415 object->vertex_data[index * 3 + 0],
416 object->vertex_data[index * 3 + 1],
417 object->vertex_data[index * 3 + 2]);
420 } /* face loop */
422 gl_may_end(prev_ftype);
426 static inline void gl_draw_objects(G3DGLRenderOptions *options,
427 GSList *objects, gfloat min_a, gfloat max_a, gboolean is_shadow)
429 GSList *olist;
430 int i;
431 G3DObject *object;
432 gboolean dont_render;
433 gboolean init = TRUE;
435 olist = objects;
436 while(olist != NULL)
438 object = (G3DObject *)olist->data;
439 olist = olist->next;
441 dont_render = FALSE;
443 /* don't render invisible objects */
444 if(object->hide) continue;
446 g_return_if_fail(object != NULL);
447 #if DEBUG > 3
448 g_printerr("name: %s {", object->name);
449 #endif
451 #if DEBUG > 2
452 g_printerr("new object\n");
453 #endif
455 glPushMatrix();
457 if(object->transformation)
459 glMultMatrixf(object->transformation->matrix);
462 #define EXPERIMENTAL
463 #ifdef EXPERIMENTAL
464 gl_draw_face_list(options, object, min_a, max_a, &init, is_shadow);
465 #else
466 glBegin(GL_TRIANGLES);
468 for(i = 0; i < object->_num_faces; i ++)
470 gl_draw_face(options, object, i, min_a, max_a,
471 &dont_render, &init, is_shadow);
472 } /* all faces */
474 glEnd();
475 #endif
477 if(!is_shadow && (options->glflags & G3D_FLAG_GL_POINTS)) {
478 glColor4f(0.2, 0.2, 0.2, 1.0);
479 glBegin(GL_POINTS);
480 for(i = 0; i < object->vertex_count; i ++) {
481 glVertex3f(
482 object->vertex_data[i * 3 + 0],
483 object->vertex_data[i * 3 + 1],
484 object->vertex_data[i * 3 + 2]);
486 glEnd();
489 /* handle sub-objects */
490 gl_draw_objects(options, object->objects, min_a, max_a, is_shadow);
492 glPopMatrix();
494 } /* while olist != NULL */
497 static inline void matrix_g3d_to_gl(G3DMatrix *g3dm, GLfloat glm[4][4])
499 guint32 i, j;
501 for(i = 0; i < 4; i ++)
502 for(j = 0; j < 4; j ++)
503 glm[i][j] = g3dm[i * 4 + j];
506 static inline void gl_setup_view(G3DGLRenderOptions *options)
508 GLfloat m[4][4];
509 G3DMatrix *g3dm;
510 G3DFloat w, h;
512 glMatrixMode(GL_PROJECTION);
513 glLoadIdentity();
514 if(options->glflags & G3D_FLAG_GL_ISOMETRIC) {
515 w = 0.5 * options->zoom;
516 h = w / options->aspect;
517 glOrtho(-w / 2.0, w / 2.0, -h / 2.0, h / 2.0, 1, 100);
518 } else {
519 gluPerspective(options->zoom, options->aspect, 1, 100);
521 /* translation of view */
522 glTranslatef(options->offx, options->offy, 0.0);
524 glMatrixMode(GL_MODELVIEW);
526 glClearColor(
527 options->bgcolor[0],
528 options->bgcolor[1],
529 options->bgcolor[2],
530 options->bgcolor[3]);
531 glClearDepth(1.0);
532 glClearIndex(0.3);
533 glClear(
534 GL_COLOR_BUFFER_BIT |
535 GL_DEPTH_BUFFER_BIT |
536 GL_ACCUM_BUFFER_BIT |
537 GL_STENCIL_BUFFER_BIT);
539 glLoadIdentity();
540 glTranslatef(0, 0, -30);
541 g3dm = g3d_matrix_new();
542 g3d_quat_to_matrix(options->quat, g3dm);
543 matrix_g3d_to_gl(g3dm, m);
545 g3d_matrix_free(g3dm);
546 glMultMatrixf(&m[0][0]);
549 static void gl_setup_shadow_matrix(G3DGLRenderOptions *options,
550 G3DVector *l, G3DVector *p, G3DVector *n)
552 G3DDouble c, d;
553 G3DMatrix *m = options->shadow_matrix;
555 d = n[0] * l[0] + n[1] * l[1] + n[2] * l[2];
556 c = p[0] * n[0] + p[1] * n[1] + p[2] * n[2] - d;
558 m[0 * 4 + 0] = l[0] * n[0] + c;
559 m[1 * 4 + 0] = l[0] * n[1];
560 m[2 * 4 + 0] = l[0] * n[2];
561 m[3 * 4 + 0] = - l[0] * c - l[0] * d;
563 m[0 * 4 + 1] = l[1] * n[0];
564 m[1 * 4 + 1] = l[1] * n[1] + c;
565 m[2 * 4 + 1] = l[1] * n[2];
566 m[3 * 4 + 1] = - l[1] * c - l[1] * d;
568 m[0 * 4 + 2] = l[2] * n[0];
569 m[1 * 4 + 2] = l[2] * n[1];
570 m[2 * 4 + 2] = l[2] * n[2] + c;
571 m[3 * 4 + 2] = - l[2] * c - l[2] * d;
573 m[0 * 4 + 3] = n[0];
574 m[1 * 4 + 3] = n[1];
575 m[2 * 4 + 3] = n[2];
576 m[3 * 4 + 3] = -d;
579 void gl_draw_coord_system(G3DGLRenderOptions *options)
581 if(options->glflags & G3D_FLAG_GL_COORD_AXES) {
582 /* x: red */
583 glColor3f(1.0, 0.0, 0.0);
584 glBegin(GL_LINES);
585 glVertex3f(0.0, 0.0, 0.0);
586 glVertex3f(10.0, 0.0, 0.0);
587 glEnd();
588 /* y: green */
589 glColor3f(0.0, 1.0, 0.0);
590 glBegin(GL_LINES);
591 glVertex3f(0.0, 0.0, 0.0);
592 glVertex3f(0.0, 10.0, 0.0);
593 glEnd();
594 /* z: blue */
595 glColor3f(0.0, 0.0, 1.0);
596 glBegin(GL_LINES);
597 glVertex3f(0.0, 0.0, 0.0);
598 glVertex3f(0.0, 0.0, 10.0);
599 glEnd();
603 static G3DFloat gl_min_y(GSList *objects)
605 G3DFloat min_y = 10.0, tmp_y;
606 GSList *oitem;
607 G3DObject *object;
608 gint32 i;
610 for(oitem = objects; oitem != NULL; oitem = oitem->next) {
611 object = oitem->data;
612 for(i = 0; i < object->vertex_count; i ++)
613 if(object->vertex_data[i * 3 + 1] < min_y)
614 min_y = object->vertex_data[i * 3 + 1];
615 tmp_y = gl_min_y(object->objects);
616 if(tmp_y < min_y)
617 min_y = tmp_y;
619 return min_y;
622 static void gl_draw_plane(G3DGLRenderOptions *options)
624 glBegin(GL_QUADS);
625 glNormal3f(0.0, -1.0, 0.0);
626 #define PLANE_MAX 12
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 glVertex3f(-PLANE_MAX, options->min_y - 0.001, -PLANE_MAX);
631 #undef PLANE_MAX
632 glEnd();
635 static void gl_setup_floor_stencil(G3DGLRenderOptions *options)
637 glClear(GL_STENCIL_BUFFER_BIT);
638 glDepthMask(GL_FALSE);
639 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
641 glEnable(GL_STENCIL_TEST);
642 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
643 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
645 gl_draw_plane(options);
647 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
648 glDepthMask(GL_TRUE);
650 glStencilFunc(GL_EQUAL, 1, 0xffffffff);
651 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
654 static void gl_setup_shadow_stencil(G3DGLRenderOptions *options)
656 glClear(GL_STENCIL_BUFFER_BIT);
657 glDepthMask(GL_FALSE);
658 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
660 glEnable(GL_STENCIL_TEST);
661 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
662 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
664 glCallList(options->state->gl_dlist_shadow);
666 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
667 glDepthMask(GL_TRUE);
669 glStencilFunc(GL_EQUAL, 1, 0xffffffff);
670 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
673 void gl_draw(G3DGLRenderOptions *options, G3DModel *model)
675 gfloat f;
676 #ifdef TIMING
677 gboolean ignore_timing = FALSE;
678 gulong msec, add;
679 gdouble sec;
680 #endif
681 G3DVector light[3] = { 100.0, 500.0, 20.0 };
682 G3DVector plane[3] = { 0.0, -20.0, 0.0 };
683 G3DVector normal[3] = { 0.0, -1.0, 0.0 };
685 if(!options->initialized)
687 gl_init();
688 options->initialized = TRUE;
689 #ifdef TIMING
690 ignore_timing = TRUE;
691 #endif
694 /* prepare viewport */
695 gl_setup_view(options);
697 /* reset texture */
698 glBindTexture (GL_TEXTURE_2D, 0);
700 if(model == NULL)
701 return;
703 #ifdef TIMING
704 g_timer_start(timer);
705 #endif
707 if(options->updated) {
708 options->updated = FALSE;
709 #ifdef TIMING
710 ignore_timing = TRUE;
711 #endif
712 #if DEBUG > 2
713 g_printerr("[gl] creating new display list\n");
714 #endif
715 options->min_y = gl_min_y(model->objects);
717 /* update render state */
718 if(options->state) {
719 glDeleteLists(options->state->gl_dlist, 1);
720 glDeleteLists(options->state->gl_dlist_shadow, 1);
721 g_free(options->state);
723 options->state = g_new0(G3DGLRenderState, 1);
725 /* create and execute display list */
726 options->state->gl_dlist = glGenLists(1);
727 options->state->gl_dlist_shadow = glGenLists(1);
729 glNewList(options->state->gl_dlist, GL_COMPILE);
730 /* draw all objects */
731 for(f = 1.0; f >= 0.0; f -= 0.2)
732 gl_draw_objects(options, model->objects, f, f + 0.2, FALSE);
733 glEndList();
735 if(options->glflags & G3D_FLAG_GL_SHADOW) {
736 glNewList(options->state->gl_dlist_shadow, GL_COMPILE);
737 gl_draw_objects(options, model->objects, 0.0, 1.0, TRUE);
738 glEndList();
742 g_return_if_fail(options->state != NULL);
744 gl_draw_coord_system(options);
746 if(options->glflags & G3D_FLAG_GL_SHADOW) {
747 plane[1] = options->min_y;
749 /* reflection */
750 glPushMatrix();
751 gl_setup_floor_stencil(options);
752 glTranslatef(0.0, (options->min_y * 2), 0.0);
753 glScalef(1.0, -1.0, 1.0);
754 glCallList(options->state->gl_dlist);
755 glPopMatrix();
757 /* plane */
758 glDisable(GL_LIGHTING);
759 glBindTexture (GL_TEXTURE_2D, 0);
760 glColor4f(0.5, 0.5, 0.5, 0.7);
761 gl_draw_plane(options);
762 glEnable(GL_LIGHTING);
763 /* shadow */
764 glPushMatrix();
765 gl_setup_shadow_matrix(options, light, plane, normal);
766 glBindTexture (GL_TEXTURE_2D, 0);
767 glDisable(GL_LIGHTING);
768 glDisable(GL_DEPTH_TEST);
769 glMultMatrixf(options->shadow_matrix);
770 gl_setup_shadow_stencil(options);
771 glPopMatrix();
772 glPushMatrix();
773 glTranslatef(0.0, 0.001, 0.0);
774 glColor4f(0.3, 0.3, 0.3, 0.7);
775 gl_draw_plane(options);
776 glEnable(GL_DEPTH_TEST);
777 glEnable(GL_LIGHTING);
778 glPopMatrix();
780 glDisable(GL_STENCIL_TEST);
783 /* execute display list */
784 glCallList(options->state->gl_dlist);
786 #ifdef TIMING /* get time to draw one frame to compare algorithms */
787 g_timer_stop(timer);
789 if(!ignore_timing) {
790 if(options->avg_msec == 0) {
791 sec = g_timer_elapsed(timer, &msec);
792 options->avg_msec = (gulong)sec * 1000000 + msec;
793 } else {
794 sec = g_timer_elapsed(timer, &msec);
795 add = (gulong)sec * 1000000 + msec;
796 options->avg_msec = (options->avg_msec + add) / 2;
799 #endif
801 #if DEBUG > 3
802 g_printerr("gl.c: drawn...\n");
803 #endif