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