1 /*
2 Copyright (C) 2003 Cedric Cellier, Dominique Lavault
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <math.h>
21 #include <assert.h>
22 #include "opengl.h"
23 #include "draw.h"
24 #include "csg.h"
25 #include "data.h"
26 #include "main.h"
27 #include "memspool.h"
28 #include "log.h"
29 #include "geom.h"
30
31 static int stencil_size; /* in bits */
32
33 PFNGLNEWBUFFERREGIONPROC glNewBufferRegion = NULL;
34 PFNGLDELETEBUFFERREGIONPROC glDeleteBufferRegion = NULL;
35 PFNGLREADBUFFERREGIONPROC glReadBufferRegion = NULL;
36 PFNGLDRAWBUFFERREGIONPROC glDrawBufferRegion = NULL;
37 PFNGLBUFFERREGIONENABLEDPROC glBufferRegionEnabled = NULL;
38
39 #ifdef _WIN32
40 PFNWGLCREATEBUFFERREGIONARBPROC wglCreateBufferRegionARB = NULL;
41 PFNWGLDELETEBUFFERREGIONARBPROC wglDeleteBufferRegionARB = NULL;
42 PFNWGLSAVEBUFFERREGIONARBPROC wglSaveBufferRegionARB = NULL;
43 PFNWGLRESTOREBUFFERREGIONARBPROC wglRestoreBufferRegionARB = NULL;
44 static HANDLE wgl_region;
45
wgl_free()46 void wgl_free()
47 {
48 wglDeleteBufferRegionARB(wgl_region);
49 }
50 #endif
51
52 static GLuint ktx_region;
53 static char ktx_ok, wgl_ok;
54
55 #ifdef __APPLE__
56 #import <mach-o/dyld.h>
57 #import <string.h>
NSGLGetProcAddress(const char * name)58 static void *NSGLGetProcAddress(const char *name)
59 {
60 NSSymbol symbol;
61 char *symbolName;
62 // Prepend a '_' for the Unix C symbol mangling convention
63 symbolName = malloc (strlen (name) + 2);
64 strcpy(symbolName + 1, name);
65 symbolName[0] = '_';
66 symbol = NULL;
67 if (NSIsSymbolNameDefined (symbolName))
68 symbol = NSLookupAndBindSymbol (symbolName);
69 free (symbolName);
70 return symbol ? NSAddressOfSymbol (symbol) : NULL;
71 }
72 #endif
73
lglGetProcAddress(const char * name)74 static void *lglGetProcAddress(const char *name)
75 {
76 #ifdef _WIN32
77 void *t = (void*)wglGetProcAddress(name);
78 if (t == 0)
79 gltv_log_warning(GLTV_LOG_MUSTSEE, "wglGetProcAddress know nothing about '%s'", name);
80 return NULL;
81 #elif __APPLE__
82 void *t = (void*)NSGLGetProcAddress(name);
83 if (t == 0)
84 gltv_log_warning(GLTV_LOG_MUSTSEE, "NSGLGetProcAddress know nothing about '%s'", name);
85 return t;
86 #else
87 void *t = (void*)glXGetProcAddressARB(name);
88 if (t == 0)
89 gltv_log_warning(GLTV_LOG_MUSTSEE, "glXGetProcAddress know nothing about '%s'", name);
90 return t;
91 #endif
92 }
93
ktx_free()94 void ktx_free()
95 {
96 glDeleteBufferRegion(ktx_region);
97 }
98
99 Display *display;
100 GLXPbuffer pbuffer;
101 GLXDrawable current_read, current_draw;
102 GLXContext current_context;
pbuffer_free()103 void pbuffer_free()
104 {
105 glXDestroyPbuffer(display, pbuffer);
106 }
107
108 int with_ktx = 0, with_wgl = 0;
draw_init()109 void draw_init()
110 {
111 GLTV_WARN_LEVEL level = GLTV_LOG_OPTIONAL;
112 /* general info about opengl */
113 gltv_log_warning(GLTV_LOG_OPTIONAL, "OpenGl Vendor : %s", glGetString(GL_VENDOR));
114 gltv_log_warning(GLTV_LOG_OPTIONAL, "OpenGl Renderer : %s", glGetString(GL_RENDERER));
115 gltv_log_warning(GLTV_LOG_OPTIONAL, "OpenGl Version : %s", glGetString(GL_VERSION));
116 gltv_log_warning(GLTV_LOG_OPTIONAL, "OpenGl Extensions : %s", glGetString(GL_EXTENSIONS));
117 /* draw specific reset */
118 glEnable(GL_CULL_FACE);
119 glEnable(GL_DEPTH_TEST);
120 glGetIntegerv(GL_STENCIL_BITS, &stencil_size);
121 glClearDepth((GLfloat)1);
122 if (stencil_size<4) level = GLTV_LOG_MUSTSEE;
123 gltv_log_warning(level, "Stencil size : %d bits\n", stencil_size);
124 ktx_ok = 0;
125 if (with_ktx) {
126 /* get KTX functions */
127 glNewBufferRegion = (PFNGLNEWBUFFERREGIONPROC)lglGetProcAddress("glNewBufferRegion");
128 glDeleteBufferRegion = (PFNGLDELETEBUFFERREGIONPROC)lglGetProcAddress("glDeleteBufferRegion");
129 glReadBufferRegion = (PFNGLREADBUFFERREGIONPROC)lglGetProcAddress("glReadBufferRegion");
130 glDrawBufferRegion = (PFNGLDRAWBUFFERREGIONPROC)lglGetProcAddress("glDrawBufferRegion");
131 glBufferRegionEnabled = (PFNGLBUFFERREGIONENABLEDPROC)lglGetProcAddress("glBufferRegionEnabled");
132 if (glNewBufferRegion && glDeleteBufferRegion && glReadBufferRegion && glDrawBufferRegion && glBufferRegionEnabled) {
133 if (glBufferRegionEnabled()) {
134 gltv_log_warning(GLTV_LOG_MUSTSEE, "KTX extention in use :-)");
135 ktx_region = glNewBufferRegion(GL_KTX_Z_REGION);
136 atexit(ktx_free);
137 ktx_ok = 1;
138 } else {
139 gltv_log_warning(GLTV_LOG_MUSTSEE, "KTX extention not usable :'(");
140 ktx_ok = 0;
141 }
142 } else {
143 gltv_log_warning(GLTV_LOG_MUSTSEE, "KTX extention not supported");
144 ktx_ok = 0;
145 }
146 #ifdef _WIN32
147 } else if (with_wgl) {
148 wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC) lglGetProcAddress("wglCreateBufferRegionARB");
149 wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC) lglGetProcAddress("wglDeleteBufferRegionARB");
150 wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC) lglGetProcAddress("wglSaveBufferRegionARB");
151 wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC) lglGetProcAddress("wglRestoreBufferRegionARB");
152 if (wglCreateBufferRegionARB && wglDeleteBufferRegionARB && wglSaveBufferRegionARB && wglRestoreBufferRegionARB) {
153 gltv_log_warning(GLTV_LOG_MUSTSEE, "WGL extention in use :-)");
154 wgl_region = wglCreateBufferRegionARB(wglGetCurrentDC(), 0, WGL_DEPTH_BUFFER_BIT_ARB);
155 atexit(wgl_free);
156 wgl_ok = 1;
157 } else {
158 gltv_log_warning(GLTV_LOG_MUSTSEE, "WGL extention not in use :'(");
159 }
160 #endif
161 }
162 }
163
draw_primitive(primitive * prim)164 void draw_primitive(primitive *prim)
165 {
166 glEnableClientState(GL_VERTEX_ARRAY);
167 glVertexPointer(3, GL_FLOAT, 0, prim->points);
168 if (NULL!=prim->norms) {
169 glEnableClientState(GL_NORMAL_ARRAY);
170 glNormalPointer(GL_FLOAT, 0, prim->norms);
171 }
172 glDrawElements(GL_TRIANGLES, (int)prim->nb_faces*3, GL_UNSIGNED_INT, (void*)prim->faces);
173 }
174
draw_mesh(mesh * m)175 void draw_mesh(mesh *m)
176 {
177 if (NULL!=m->texture && NULL!=m->uv_coord) {
178 glBindTexture(GL_TEXTURE_2D, m->texture->binding);
179 glEnable(GL_TEXTURE_2D);
180 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
181 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
182 glTexCoordPointer(2, GL_FLOAT, 0, (void*)m->uv_coord->c);
183 } else {
184 glDisable(GL_TEXTURE_2D);
185 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
186 }
187 draw_primitive(m->prim);
188 }
189
draw_node(csg_node * node)190 static void draw_node(csg_node *node)
191 {
192 /* draw the primitive, at the location */
193 assert(node->type == CSG_PRIM);
194 glPushMatrix();
195 glMultMatrixf(node->u.prim.m->pos->c);
196 draw_mesh(node->u.prim.m);
197 glPopMatrix();
198 }
199
200 static GLfloat *depth_buffer = NULL;
201 static unsigned buffer_size = 0;
202 static char buffer_region_succeeded;
203 GLfloat *depthSave = NULL;
204 GLubyte *stencilSave = NULL;
205 GLubyte *colorSave = NULL;
206
free_buffers()207 static void free_buffers()
208 {
209 if (depth_buffer) gltv_memspool_unregister(depth_buffer);
210 if (depthSave) gltv_memspool_unregister(depthSave);
211 if (stencilSave) gltv_memspool_unregister(stencilSave);
212 if (colorSave) gltv_memspool_unregister(colorSave);
213 }
214
push_ortho_view(float left,float right,float bottom,float top,float znear,float zfar)215 void push_ortho_view(float left, float right, float bottom, float top, float znear, float zfar)
216 {
217 glPushMatrix();
218 glLoadIdentity();
219 glMatrixMode(GL_PROJECTION);
220 glPushMatrix();
221 glLoadIdentity();
222 glOrtho(left, right, bottom, top, znear, zfar);
223 }
224
pop_view(void)225 void pop_view(void)
226 {
227 glPopMatrix();
228 glMatrixMode(GL_MODELVIEW);
229 glPopMatrix();
230 }
231
zbuffer_save(b_box_2d * region)232 static void zbuffer_save(b_box_2d *region)
233 {
234 unsigned needed_size;
235 if (region->vide) return;
236 if (ktx_ok) {
237 glReadBufferRegion(ktx_region, region->xmin, region->ymin, region->xmax-region->xmin, region->ymax-region->ymin);
238 return;
239 #ifdef _WIN32
240 } else if (wgl_ok) {
241 if (GL_TRUE==wglSaveBufferRegionARB(wgl_region, region->xmin, region->ymin, region->xmax-region->xmin, region->ymax-region->ymin)) {
242 buffer_region_succeeded = 1;
243 return;
244 } else {
245 buffer_region_succeeded = 0;
246 }
247 #endif
248 }
249 needed_size = (region->xmax-region->xmin)*(region->ymax-region->ymin)*sizeof(GLuint);
250 if (NULL == depth_buffer) {
251 depth_buffer = gltv_memspool_alloc(needed_size);
252 if (!depth_buffer) gltv_log_fatal("Cannot get memory for saving depth buffer");
253 buffer_size = needed_size;
254 atexit(free_buffers);
255 } else if (buffer_size<needed_size) {
256 depth_buffer = gltv_memspool_realloc(depth_buffer, needed_size);
257 if (!depth_buffer) gltv_log_fatal("Cannot get memory for saving depth buffer");
258 buffer_size = needed_size;
259 }
260 glReadPixels(region->xmin, region->ymin, region->xmax-region->xmin, region->ymax-region->ymin, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depth_buffer);
261 }
262
zbuffer_restore(b_box_2d * region)263 void zbuffer_restore(b_box_2d *region)
264 {
265 if (region->vide) return;
266 if (ktx_ok) {
267 glDrawBufferRegion(ktx_region, region->xmin, region->ymin, region->xmax-region->xmin, region->ymax-region->ymin, region->xmin, region->ymin);
268 return;
269 #ifdef _WIN32
270 } else if (wgl_ok && buffer_region_succeeded) {
271 wglRestoreBufferRegionARB(wgl_region, region->xmin, region->ymin, region->xmax-region->xmin, region->ymax-region->ymin, region->xmin, region->ymin);
272 return;
273 #endif
274 }
275 glDisable(GL_STENCIL_TEST);
276 glColorMask(0, 0, 0, 0);
277 glDepthMask(1);
278 glEnable(GL_DEPTH_TEST);
279 glDepthFunc(GL_ALWAYS);
280 push_ortho_view(0., (float)glut_fenLong, 0., (float)glut_fenHaut, 0., 1.);
281 glRasterPos3f(region->xmin, region->ymin, -.5);
282 glDrawPixels(region->xmax-region->xmin, region->ymax-region->ymin, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depth_buffer);
283 /* glColorMask(1,1,1,1);
284 glBegin(GL_LINE_STRIP);
285 glColor3f(1,1,1);
286 glVertex3f(region->xmin, region->ymin, -.5);
287 glVertex3f(region->xmax, region->ymin, -.5);
288 glVertex3f(region->xmax, region->ymax, -.5);
289 glVertex3f(region->xmin, region->ymax, -.5);
290 glVertex3f(region->xmin, region->ymin, -.5);
291 glEnd();
292 glColorMask(0,0,0,0);*/
293 pop_view();
294 glDepthFunc(GL_LESS);
295 glEnable(GL_STENCIL_TEST);
296 }
297
zbuffer_clear(b_box_2d * region)298 void zbuffer_clear(b_box_2d *region)
299 {
300 if (region->vide) return;
301 push_ortho_view(0., (float)glut_fenLong, 0., (float)glut_fenHaut, 0., 1.);
302 glBegin(GL_QUADS);
303 glVertex3f(region->xmin, region->ymax, -1);
304 glVertex3f(region->xmax, region->ymax, -1);
305 glVertex3f(region->xmax, region->ymin, -1);
306 glVertex3f(region->xmin, region->ymin, -1);
307 glEnd();
308 pop_view();
309 }
310
311 #ifndef NDEBUG
copyDepthToColor()312 void copyDepthToColor()
313 {
314 int x, y;
315 GLfloat max, min;
316 GLint previousColorBuffer;
317 unsigned needed_size = glut_fenLong*glut_fenHaut*sizeof(GLfloat);
318 static unsigned size = 0;
319 int winWidth = glut_fenLong, winHeight=glut_fenHaut;
320 if (depthSave==NULL) {
321 depthSave = gltv_memspool_alloc(needed_size);
322 size = needed_size;
323 } else if (needed_size>size) {
324 depthSave = gltv_memspool_realloc(depthSave, needed_size);
325 size = needed_size;
326 }
327 glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depthSave);
328 /* I'm sure this could be done much better with OpenGL */
329 max = 0;
330 min = 1;
331 for(y = 0; y < winHeight; y++)
332 for(x = 0; x < winWidth; x++) {
333 if(depthSave[winWidth * y + x] < min)
334 min = depthSave[winWidth * y + x];
335 if(depthSave[winWidth * y + x] > max)// && depthSave[winWidth * y + x] < .999)
336 max = depthSave[winWidth * y + x];
337 }
338 for(y = 0; y < winHeight; y++)
339 for(x = 0; x < winWidth; x++) {
340 if(depthSave[winWidth * y + x] <= max)
341 depthSave[winWidth * y + x] = 1 - (depthSave[winWidth * y + x] - min) / (max - min);
342 else
343 depthSave[winWidth * y + x] = 0;
344 }
345 push_ortho_view(0., 1., 0., 1., 0., 1.);
346 glRasterPos3f(0, 0, -.5);
347 glDisable(GL_DEPTH_TEST);
348 glDisable(GL_STENCIL_TEST);
349 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
350 glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
351 glDrawBuffer(GL_BACK);
352 glDrawPixels(winWidth, winHeight, GL_LUMINANCE , GL_FLOAT, depthSave);
353 glDrawBuffer(previousColorBuffer);
354 glEnable(GL_STENCIL_TEST);
355 glEnable(GL_DEPTH_TEST);
356 pop_view();
357 }
358
359 unsigned char stencilValueToColorMap[][3] = {
360 {255, 0, 0},
361 {255, 218, 250},
362 {72, 255, 0},
363 {0, 255, 145},
364 {0, 145, 255},
365 {255, 255, 255},
366 {255, 0, 218}
367 };
368
copyStencilToColor()369 void copyStencilToColor()
370 {
371 int x, y;
372 GLint previousColorBuffer;
373 int winWidth = glut_fenLong, winHeight=glut_fenHaut;
374 unsigned needed_size = glut_fenLong*glut_fenHaut*sizeof(*stencilSave);
375 static unsigned size = 0;
376 if (stencilSave==NULL) {
377 stencilSave = gltv_memspool_alloc(needed_size);
378 size = needed_size;
379 colorSave = gltv_memspool_alloc(winWidth * winHeight * 4 * sizeof(GLubyte));
380 } else if (needed_size>size) {
381 stencilSave = gltv_memspool_realloc(stencilSave, needed_size);
382 size = needed_size;
383 colorSave = gltv_memspool_realloc(colorSave, winWidth * winHeight * 4 * sizeof(GLubyte));
384 }
385 glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilSave);
386 /* I'm sure this could be done much better with OpenGL */
387 for(y = 0; y < winHeight; y++)
388 for(x = 0; x < winWidth; x++) {
389 int stencilValue;
390 stencilValue = stencilSave[winWidth * y + x];
391 /* if (stencilValue&16) {
392 colorSave[(winWidth * y + x) * 3 + 0]=250;
393 colorSave[(winWidth * y + x) * 3 + 1]=250;
394 colorSave[(winWidth * y + x) * 3 + 2]=250;
395 } else {
396 colorSave[(winWidth * y + x) * 3 + 0]=0;
397 colorSave[(winWidth * y + x) * 3 + 1]=0;
398 colorSave[(winWidth * y + x) * 3 + 2]=0;
399 }*/
400 colorSave[(winWidth * y + x) * 3 + 0] =
401 stencilValueToColorMap[stencilValue & 3][0];
402 colorSave[(winWidth * y + x) * 3 + 1] =
403 stencilValueToColorMap[stencilValue & 3][1];
404 colorSave[(winWidth * y + x) * 3 + 2] =
405 stencilValueToColorMap[stencilValue & 3][2];
406 }
407 push_ortho_view(0., 1., 0., 1., 0., 1.);
408 glRasterPos3f(0., 0., -.5);
409 glDisable(GL_DEPTH_TEST);
410 glDisable(GL_STENCIL_TEST);
411 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
412 glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
413 glDrawBuffer(GL_BACK);
414 glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
415 glDrawBuffer(previousColorBuffer);
416 glEnable(GL_STENCIL_TEST);
417 glEnable(GL_DEPTH_TEST);
418 pop_view();
419 }
420
draw_b_box(csg_node * node)421 void draw_b_box(csg_node *node)
422 {
423 b_box b;
424 geom_get_b_box(node, &b);
425 glBegin(GL_LINE_STRIP);
426 glColor3f(.1,1,1);
427 glVertex3f(b.p_min[0], b.p_min[1], b.p_min[2]);
428 glVertex3f(b.p_max[0], b.p_min[1], b.p_min[2]);
429 glVertex3f(b.p_max[0], b.p_max[1], b.p_min[2]);
430 glVertex3f(b.p_min[0], b.p_max[1], b.p_min[2]);
431 glVertex3f(b.p_min[0], b.p_min[1], b.p_min[2]);
432 glVertex3f(b.p_min[0], b.p_min[1], b.p_max[2]);
433 glVertex3f(b.p_max[0], b.p_min[1], b.p_max[2]);
434 glVertex3f(b.p_max[0], b.p_max[1], b.p_max[2]);
435 glVertex3f(b.p_min[0], b.p_max[1], b.p_max[2]);
436 glVertex3f(b.p_min[0], b.p_min[1], b.p_max[2]);
437 glEnd();
438 glBegin(GL_LINE);
439 glVertex3f(b.p_max[0], b.p_min[1], b.p_min[2]);
440 glVertex3f(b.p_max[0], b.p_min[1], b.p_max[2]);
441 glVertex3f(b.p_max[0], b.p_max[1], b.p_min[2]);
442 glVertex3f(b.p_max[0], b.p_max[1], b.p_max[2]);
443 glVertex3f(b.p_min[0], b.p_max[1], b.p_min[2]);
444 glVertex3f(b.p_min[0], b.p_max[1], b.p_max[2]);
445 glEnd();
446 }
447 #endif /* !NDEBUG */
448
draw_union_of_partial_products(csg_union_of_partial_products * uopp)449 void draw_union_of_partial_products(csg_union_of_partial_products *uopp)
450 {
451 /* On ne peut pas tracer les partiels indendament des groupes, car le zbuffer doit etre integre entre deux vraies unions
452 * (les unions entre les partiels sont des fausses unions justement en ce sens : le zbuffer ne contient pas d'info sur ces unions).
453 * Donc entre deux groupes on DOIT sauver/restaurer le zbuffer.
454 * Mais pas entre partiels d'un meme groupe : la, on utilise le stencil autant que possible pour tout tracer a la fin si possible.
455 * Si pas possible (pas assez de bits dans le stencil), on traite le partiel comme un groupe normal : on restaure le zbuffer, on trace et
456 * on resauvegarde le zbuffer pour continuer le groupe.
457 */
458 unsigned g, uu, u = 0, p;
459 int a;
460 char fake_new_group = 0;
461 b_box_2d *region; /* 2d region of a group (to save only this region) */
462 b_box_2d region_full = { 0, 0,0, 0,0 };
463 region_full.xmax=glut_fenLong;
464 region_full.ymax=glut_fenHaut;
465 gltv_log_warning(GLTV_LOG_DEBUG, "------\nDRAW");
466 csg_union_of_partial_products_resize(uopp);
467 glDisable(GL_TEXTURE_2D);
468 while (u<uopp->nb_unions) {
469 // new group
470 g = uopp->unions[u].group_id;
471 // what's its target ?
472 if (!fake_new_group) {
473 region = &uopp->max2d_group[g];
474 }
475 gltv_log_warning(GLTV_LOG_DEBUG, "nouveau groupe");
476 // else keep the last group_target as this "group" is a fake group, considered as a group because of the lack of stencil bits
477 fake_new_group = 0;
478 if (1==uopp->unions[u].nb_products) {
479 glDepthMask(1);
480 glColorMask(1,1,1,1);
481 glEnable(GL_LIGHTING);
482 glDisable(GL_STENCIL_TEST);
483 glEnable(GL_DEPTH_TEST);
484 if (uopp->unions[u].products[0].frontal) {
485 glCullFace(GL_BACK);
486 } else {
487 glCullFace(GL_FRONT);
488 }
489 draw_node(uopp->unions[u].products[0].node);
490 gltv_log_warning(GLTV_LOG_DEBUG, "fast draw target %s colors", uopp->unions[u].products[0].node->u.prim.m->name);
491 u++;
492 continue;
493 }
494 zbuffer_save(region);
495 // classification of the group
496 gltv_log_warning(GLTV_LOG_DEBUG, "save zbuffer");
497 a = 0;
498 glDisable(GL_LIGHTING);
499 while (u<uopp->nb_unions && uopp->unions[u].group_id==g) { // foreach target surface in the group = for each partial in the group
500 // draw depth of the target and clear Spacc and Sp, set the Sa-bit
501 glDepthMask(1);
502 glColorMask(0,0,0,0);
503 glDisable(GL_STENCIL_TEST);
504 glDepthFunc(GL_ALWAYS);
505 glDisable(GL_CULL_FACE);
506 zbuffer_clear(region);
507 glEnable(GL_CULL_FACE);
508 glEnable(GL_STENCIL_TEST);
509 glEnable(GL_DEPTH_TEST);
510 glDepthFunc(GL_LESS);
511 gltv_log_warning(GLTV_LOG_DEBUG, "\tclear zbuffer");
512 if (uopp->unions[u].products[0].frontal) {
513 glCullFace(GL_BACK);
514 } else {
515 glCullFace(GL_FRONT);
516 }
517 glStencilMask(0x3+(1<<(2+a)));
518 glStencilFunc(GL_ALWAYS, 1<<(2+a),0);
519 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
520 draw_node(uopp->unions[u].products[0].node);
521 gltv_log_warning(GLTV_LOG_DEBUG, "\tdraw target %s depth, %s frontal, clearing Sp & Spacc, setting Sa", uopp->unions[u].products[0].node->u.prim.m->name, uopp->unions[u].products[0].frontal?"":"not");
522 // trim the depth values with every trimmers (so that information is stored in Spacc and we use only 2 bits of stencil (Spacc and Sp) -> Spacc=1 when pixels are OUT)
523 glDepthMask(0);
524 glColorMask(0,0,0,0);
525 for (p=1; p<uopp->unions[u].nb_products; p++) {
526 glStencilMask(2); // bit 1 for Sp
527 glStencilFunc(GL_ALWAYS, 0,0);
528 glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
529 glDisable(GL_CULL_FACE);
530 draw_node(uopp->unions[u].products[p].node);
531 gltv_log_warning(GLTV_LOG_DEBUG, "\t\tset Sp to 1 where %s is cut", uopp->unions[u].products[p].node->u.prim.m->name);
532 // set Spacc to 1 if Sp=1 or Sp=0 (depending of negation of target)
533 glEnable(GL_CULL_FACE); // restaure it to the target state
534 glStencilFunc((!uopp->unions[u].products[p].frontal)?GL_LEQUAL:GL_GREATER, 0x1, 0x3); // pourquoi ce NOT ??????
535 glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
536 glStencilMask(0x3); // write Sp and Spacc
537 draw_node(uopp->unions[u].products[0].node);
538 gltv_log_warning(GLTV_LOG_DEBUG, "\t\tset Spacc to trim against %s, %s frontal", uopp->unions[u].products[p].node->u.prim.m->name, uopp->unions[u].products[p].frontal?"":"not");
539 if (p<uopp->unions[u].nb_products-1) {
540 // draw another time to clear Sp
541 glStencilFunc(GL_ALWAYS, 0,0);
542 glStencilMask(2); // clear Sp
543 glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
544 draw_node(uopp->unions[u].products[0].node);
545 gltv_log_warning(GLTV_LOG_DEBUG, "\t\tclear Sp");
546 }
547 }
548 // clear bit 2+a of stencil to 0 where Spacc=1 for the target (pixel is out)
549 glStencilMask(1<<(2+a));
550 glStencilFunc(GL_EQUAL, 1, 1); // Spacc == 1 ?
551 glStencilOp(GL_KEEP, GL_ZERO, GL_ZERO);
552 draw_node(uopp->unions[u].products[0].node);
553 gltv_log_warning(GLTV_LOG_DEBUG, "\tclear Sa-bit %d for target %s where Spacc=1", (2+a), uopp->unions[u].products[0].node->u.prim.m->name);
554 a++;
555 u++;
556 if (a+2==stencil_size) {
557 fake_new_group=1;
558 break;
559 }
560 }
561 // restore the zbuffer
562 zbuffer_restore(region);
563 gltv_log_warning(GLTV_LOG_DEBUG, "restore zbuffer");
564 // render the target primitives of that group, trimmed by their stencil a-bits
565 glDepthMask(1);
566 glColorMask(1,1,1,1);
567 glStencilMask(0);
568 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
569 glEnable(GL_LIGHTING);
570 uu = u-a;
571 for (a--; a>=0; a--) {
572 if (uopp->unions[uu+a].products[0].frontal) {
573 glCullFace(GL_BACK);
574 } else {
575 glCullFace(GL_FRONT);
576 }
577 glStencilFunc(GL_EQUAL, 1<<(a+2), 1<<(a+2));
578 draw_node(uopp->unions[uu+a].products[0].node);
579 gltv_log_warning(GLTV_LOG_DEBUG, "draw target %s colors where Sa-bit is set (%d)", uopp->unions[uu+a].products[0].node->u.prim.m->name, (a+2));
580 }
581 /*debug
582 glDisable(GL_STENCIL_TEST);
583 draw_b_box(group_target);
584 glEnable(GL_STENCIL_TEST);
585 end_debug*/
586 }
587 glDisable(GL_STENCIL_TEST);
588 }
589
draw_union_of_products(csg_union_of_products * uop)590 void draw_union_of_products(csg_union_of_products *uop)
591 {
592 /* this convertion should be done earlyer */
593 csg_union_of_partial_products *uopp = csg_union_of_partial_products_new(uop);
594 if (NULL!=uopp) draw_union_of_partial_products(uopp);
595 csg_union_of_partial_products_del(uopp);
596 }
597
draw_csg_tree(csg_node * node)598 void draw_csg_tree(csg_node *node)
599 {
600 /* this convertion should be done earlyer */
601 csg_union_of_products *uop = csg_union_of_products_new(node);
602 if (NULL!=uop) draw_union_of_products(uop);
603 csg_union_of_products_del(uop);
604 }
605
draw_position(position * pos)606 void draw_position(position *pos)
607 {
608 unsigned s;
609 glPushMatrix();
610 glMultMatrixf(pos->c);
611 for (s=0; s<pos->nb_sons; s++) {
612 draw_position(pos->sons[s]);
613 }
614 for (s=0; s<pos->nb_meshes; s++) {
615 draw_mesh(pos->meshes[s]);
616 }
617 glPopMatrix();
618 }
619
620