ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.3
Committed: Thu Sep 3 08:14:29 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.2: +391 -148 lines
Log Message:
added draft-quality rendering and fixed multiple frustum culling

File Contents

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * sm_ogl.c
9 */
10 #include "standard.h"
11
12 #include <GL/gl.h>
13
14 #ifdef TEST_DRIVER
15 #include <gl/device.h>
16 #include <GL/glu.h>
17 #include <glut.h>
18 #endif
19 #include "object.h"
20 #include "sm_list.h"
21 #include "sm_geom.h"
22 #include "sm.h"
23 #include "lookup.h"
24
25 #ifdef TEST_DRIVER
26 #include "sm_draw.h"
27 /*static char smClean_notify = TRUE;
28 MAKE STATIC LATER: ui.c using for now;
29 */
30 char smClean_notify = TRUE;
31 #else
32 static char smClean_notify = TRUE;
33 #endif
34
35 extern unsigned long qthash();
36 extern int qtcmp();
37 extern int free();
38
39 static LUTAB qtr_tab = {qthash,qtcmp,NULL,(void (*)())free,0,NULL,0};
40
41 typedef struct {
42 BYTE rgb[3]; /* average color */
43 float dist; /* average distance */
44 } QTRAVG; /* average quadtree value */
45
46
47 unsigned long
48 qthash(qtc) /* hash a quadtree node value */
49 char *qtc;
50 {
51 register unsigned long qt = qtc;
52
53 return(qt>>10 ^ qt<<5);
54 }
55
56 int
57 qtcmp(qt1, qt2)
58 char *qt1, *qt2;
59 {
60 return(qt1 - qt2);
61 }
62
63
64 int
65 mark_active_tris(qtptr,arg)
66 QUADTREE *qtptr;
67 char *arg;
68 {
69 QUADTREE qt = *qtptr;
70 OBJECT os[QT_MAX_SET+1],*optr;
71 register int i,t_id;
72
73 if (!QT_IS_LEAF(qt))
74 return(TRUE);
75 /* For each triangle in the set, set the which flag*/
76 qtgetset(os,qt);
77
78 for (i = QT_SET_CNT(os), optr = QT_SET_PTR(os); i > 0; i--)
79 {
80 t_id = QT_SET_NEXT_ELEM(optr);
81 /* Set the render flag */
82 if(SM_IS_NTH_T_BASE(smMesh,t_id))
83 continue;
84 SM_SET_NTH_T_ACTIVE(smMesh,t_id);
85 /* FOR NOW:Also set the LRU clock bit: MAY WANT TO CHANGE: */
86 SM_SET_NTH_T_LRU(smMesh,t_id);
87 }
88 return(TRUE);
89 }
90
91 mark_tris_in_frustum(view)
92 VIEW *view;
93 {
94 FVECT nr[4],far[4];
95
96 /* Mark triangles in approx. view frustum as being active:set
97 LRU counter: for use in discarding samples when out
98 of space
99 Radiance often has no far clipping plane: but driver will set
100 dev_zmin,dev_zmax to satisfy OGL
101 */
102
103 /* First clear all the quadtree node and triangle active flags */
104 qtClearAllFlags();
105 smClear_flags(smMesh,T_ACTIVE_FLAG);
106
107 /* calculate the world space coordinates of the view frustum */
108 calculate_view_frustum(view->vp,view->hvec,view->vvec,view->horiz,
109 view->vert, dev_zmin,dev_zmax,nr,far);
110
111 /* Project the view frustum onto the spherical quadtree */
112 /* For every cell intersected by the projection of the faces
113 of the frustum: mark all triangles in the cell as ACTIVE-
114 Also set the triangles LRU clock counter
115 */
116 /* Near face triangles */
117 smLocator_apply_func(smMesh,nr[0],nr[2],nr[3],mark_active_tris,NULL);
118 smLocator_apply_func(smMesh,nr[2],nr[0],nr[1],mark_active_tris,NULL);
119 /* Right face triangles */
120 smLocator_apply_func(smMesh,nr[0],far[3],far[0],mark_active_tris,NULL);
121 smLocator_apply_func(smMesh,far[3],nr[0],nr[3],mark_active_tris,NULL);
122 /* Left face triangles */
123 smLocator_apply_func(smMesh,nr[1],far[2],nr[2],mark_active_tris,NULL);
124 smLocator_apply_func(smMesh,far[2],nr[1],far[1],mark_active_tris,NULL);
125 /* Top face triangles */
126 smLocator_apply_func(smMesh,nr[0],far[0],nr[1],mark_active_tris,NULL);
127 smLocator_apply_func(smMesh,nr[1],far[0],far[1],mark_active_tris,NULL);
128 /* Bottom face triangles */
129 smLocator_apply_func(smMesh,nr[3],nr[2],far[3],mark_active_tris,NULL);
130 smLocator_apply_func(smMesh,nr[2],far[2],far[3],mark_active_tris,NULL);
131 /* Far face triangles */
132 smLocator_apply_func(smMesh,far[0],far[2],far[1],mark_active_tris,NULL);
133 smLocator_apply_func(smMesh,far[2],far[0],far[3],mark_active_tris,NULL);
134
135 #ifdef TEST_DRIVER
136 VCOPY(FrustumFar[0],far[0]);
137 VCOPY(FrustumFar[1],far[1]);
138 VCOPY(FrustumFar[2],far[2]);
139 VCOPY(FrustumFar[3],far[3]);
140 VCOPY(FrustumNear[0],nr[0]);
141 VCOPY(FrustumNear[1],nr[1]);
142 VCOPY(FrustumNear[2],nr[2]);
143 VCOPY(FrustumNear[3],nr[3]);
144 #endif
145 }
146
147 /*
148 * smClean() : display has been wiped clean
149 *
150 * Called after display has been effectively cleared, meaning that all
151 * geometry must be resent down the pipeline in the next call to smUpdate().
152 */
153 smClean()
154 {
155 smClean_notify = TRUE;
156 }
157
158
159 stCount_level_leaves(lcnt, qt) /* count quadtree leaf nodes at each level */
160 int lcnt[];
161 register QUADTREE qt;
162 {
163 if (QT_IS_EMPTY(qt))
164 return;
165 if (QT_IS_TREE(qt)) {
166 if (!QT_IS_FLAG(qt)) /* not in our frustum */
167 return;
168 stCount_level_leaves(lcnt+1, QT_NTH_CHILD(qt,0));
169 stCount_level_leaves(lcnt+1, QT_NTH_CHILD(qt,1));
170 stCount_level_leaves(lcnt+1, QT_NTH_CHILD(qt,2));
171 stCount_level_leaves(lcnt+1, QT_NTH_CHILD(qt,3));
172 }
173 else
174 lcnt[0]++;
175 }
176
177
178 QTRAVG *
179 qtRender_level(qt,v0,v1,v2,sm,lvl)
180 QUADTREE qt;
181 FVECT v0,v1,v2;
182 SM *sm;
183 int lvl;
184 {
185 FVECT a,b,c;
186 LUENT *le;
187 QTRAVG *rc[4];
188 register QTRAVG *ra;
189
190 if (QT_IS_EMPTY(qt)) /* empty leaf node */
191 return(NULL);
192 if (QT_IS_TREE(qt) && !QT_IS_FLAG(qt)) /* not in our frustum */
193 return(NULL);
194 /* else look up node */
195 if ((le = lu_find(&qtr_tab,(char *)qt)) == NULL)
196 goto nomemory;
197 ra = (QTRAVG *)le->data;
198 if (QT_IS_TREE(qt) && (ra == NULL || lvl > 0))
199 { /* compute children */
200 qtSubdivide_tri(v0,v1,v2,a,b,c);
201 rc[0] = qtRender_level(QT_NTH_CHILD(qt,0),v0,a,c,sm,lvl-1);
202 rc[1] = qtRender_level(QT_NTH_CHILD(qt,1),a,v1,b,sm,lvl-1);
203 rc[2] = qtRender_level(QT_NTH_CHILD(qt,2),c,b,v2,sm,lvl-1);
204 rc[3] = qtRender_level(QT_NTH_CHILD(qt,3),b,c,a,sm,lvl-1);
205 }
206 if (ra == NULL)
207 { /* let's make some data! */
208 int rgbs[3];
209 double distsum;
210 int i;
211 register int n;
212 /* average our triangle vertices */
213 rgbs[0] = rgbs[1] = rgbs[2] = 0;
214 distsum = 0.; n = 0;
215 if(QT_IS_TREE(qt))
216 { /* from subtree */
217 for (i = 4; i--; )
218 if ((ra = rc[i]) != NULL)
219 {
220 rgbs[0] += ra->rgb[0]; rgbs[1] += ra->rgb[1]; rgbs[2] += ra->rgb[2];
221 distsum += ra->dist; n++;
222 }
223 }
224 else
225 { /* from triangle set */
226 OBJECT os[QT_MAX_SET+1];
227 int s0, s1, s2;
228
229 qtgetset(os,qt);
230 for (n = os[0]; n; n--)
231 {
232 qtTri_from_id(os[n],a,b,c,NULL,NULL,NULL,&s0,&s1,&s2);
233 distsum += SM_BG_SAMPLE(sm,s0) ? dev_zmax
234 : sqrt(dist2(a,SM_VIEW_CENTER(sm)));
235 distsum += SM_BG_SAMPLE(sm,s1) ? dev_zmax
236 : sqrt(dist2(b,SM_VIEW_CENTER(sm)));
237 distsum += SM_BG_SAMPLE(sm,s2) ? dev_zmax
238 : sqrt(dist2(c,SM_VIEW_CENTER(sm)));
239 rgbs[0] += SM_NTH_RGB(sm,s0)[0] + SM_NTH_RGB(sm,s1)[0]
240 + SM_NTH_RGB(sm,s2)[0];
241 rgbs[1] += SM_NTH_RGB(sm,s0)[1] + SM_NTH_RGB(sm,s1)[1]
242 + SM_NTH_RGB(sm,s2)[1];
243 rgbs[2] += SM_NTH_RGB(sm,s0)[2] + SM_NTH_RGB(sm,s1)[2]
244 + SM_NTH_RGB(sm,s2)[2];
245 }
246 n = 3*os[0];
247 }
248 if (!n)
249 return(NULL);
250 if ((ra = (QTRAVG *)malloc(sizeof(QTRAVG))) == NULL)
251 goto nomemory;
252 ra->rgb[0] = rgbs[0]/n; ra->rgb[1] = rgbs[1]/n; ra->rgb[2] = rgbs[2]/n;
253 ra->dist = distsum/(double)n;
254 le->key = (char *)qt;
255 le->data = (char *)ra;
256 }
257 if (lvl == 0 || (lvl > 0 && QT_IS_LEAF(qt)))
258 { /* render this node */
259 /* compute pseudo vertices */
260 VCOPY(a,v0); VCOPY(b,v1); VCOPY(c,v2);
261 normalize(a); normalize(b); normalize(c);
262 VSUM(a,SM_VIEW_CENTER(sm),a,ra->dist);
263 VSUM(b,SM_VIEW_CENTER(sm),b,ra->dist);
264 VSUM(c,SM_VIEW_CENTER(sm),c,ra->dist);
265 /* draw triangle */
266 glColor3ub(ra->rgb[0],ra->rgb[1],ra->rgb[2]);
267 /* NOTE: Triangle vertex order may change */
268 glVertex3d(c[0],c[1],c[2]);
269 glVertex3d(b[0],b[1],b[2]);
270 glVertex3d(a[0],a[1],a[2]);
271 }
272 return(ra);
273 nomemory:
274 error(SYSTEM, "out of memory in qtRender_level");
275 }
276
277
278 smRender_stree_level(sm,lvl)
279 SM *sm;
280 int lvl;
281 {
282 QUADTREE root;
283 int i;
284 FVECT t0,t1,t2;
285
286 if (lvl < 1)
287 return;
288 glPushAttrib(GL_LIGHTING_BIT);
289 glShadeModel(GL_FLAT);
290 glBegin(GL_TRIANGLES);
291 for(i=0; i < 4; i++)
292 {
293 root = ST_NTH_ROOT(SM_LOCATOR(sm),i);
294 stNth_base_verts(SM_LOCATOR(sm),i,t0,t1,t2);
295 qtRender_level(root,t0,t1,t2,sm,lvl-1);
296 }
297 glEnd();
298 glPopAttrib();
299 }
300
301
302 smRender_stree(sm, qual) /* render some quadtree triangles */
303 SM *sm;
304 int qual;
305 {
306 int i, ntarget;
307 int lvlcnt[QT_MAX_LEVELS];
308
309 if (qual <= 0)
310 return;
311 /* compute rendering target */
312 ntarget = 0;
313 SM_FOR_ALL_ACTIVE_TRIS(sm,i)
314 ntarget++;
315 ntarget = ntarget*qual/100;
316 if (!ntarget)
317 return;
318 for (i = QT_MAX_LEVELS; i--; )
319 lvlcnt[i] = 0;
320 stCount_level_leaves(lvlcnt, SM_LOCATOR(sm)->root);
321 for (ntarget -= lvlcnt[i=0]; i < QT_MAX_LEVELS-1; ntarget -= lvlcnt[++i])
322 if (ntarget < lvlcnt[i+1])
323 break;
324 /* compute and render target level */
325 smRender_stree_level(sm,i);
326 }
327
328
329 smRender_tri(sm,i,vp,clr)
330 SM *sm;
331 int i;
332 FVECT vp;
333 int clr;
334 {
335 TRI *tri;
336 double ptr[3];
337 int j;
338
339 tri = SM_NTH_TRI(sm,i);
340 if (clr) SM_CLEAR_NTH_T_NEW(sm,i);
341
342 /* NOTE:Triangles are defined clockwise:historical relative to spherical
343 tris: could change
344 */
345 for(j=2; j>= 0; j--)
346 {
347 #ifdef DEBUG
348 if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
349 eputs("SmRenderTri(): shouldnt have bg samples\n");
350 #endif
351 glColor3ub(SM_NTH_RGB(sm,T_NTH_V(tri,j))[0],
352 SM_NTH_RGB(sm,T_NTH_V(tri,j))[1],
353 SM_NTH_RGB(sm,T_NTH_V(tri,j))[2]);
354 VCOPY(ptr,SM_T_NTH_WV(sm,tri,j));
355 glVertex3d(ptr[0],ptr[1],ptr[2]);
356 }
357 }
358
359 smRender_mixed_tri(sm,i,vp,clr)
360 SM *sm;
361 int i;
362 FVECT vp;
363 int clr;
364 {
365 TRI *tri;
366 double p[3],d;
367 int j,ids[3],cnt;
368 int rgb[3];
369
370 tri = SM_NTH_TRI(sm,i);
371 if (clr) SM_CLEAR_NTH_T_NEW(sm,i);
372
373 /* NOTE:Triangles are defined clockwise:historical relative to spherical
374 tris: could change
375 */
376 cnt = 0;
377 d = 0.0;
378 rgb[0] = rgb[1] = rgb[2] = 0;
379 for(j=0;j < 3;j++)
380 {
381 ids[j] = T_NTH_V(tri,j);
382 if(!SM_BG_SAMPLE(sm,ids[j]))
383 {
384 rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
385 rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
386 rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
387 cnt++;
388 d += DIST(vp,SM_NTH_WV(sm,ids[j]));
389 }
390 }
391 if(cnt > 1)
392 {
393 rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
394 d /= (double)cnt;
395 }
396 for(j=2; j>= 0; j--)
397 {
398 if(SM_BG_SAMPLE(sm,ids[j]))
399 {
400 glColor3ub(rgb[0],rgb[1],rgb[2]);
401 VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
402 p[0] *= d;
403 p[1] *= d;
404 p[2] *= d;
405 VADD(p,p,SM_VIEW_CENTER(sm));
406 }
407 else
408 {
409 glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
410 SM_NTH_RGB(sm,ids[j])[2]);
411 VCOPY(p,SM_NTH_WV(sm,ids[j]));
412 }
413 glVertex3d(p[0],p[1],p[2]);
414 }
415 }
416
417 smRender_bg_tri(sm,i,vp,d,clr)
418 SM *sm;
419 int i;
420 FVECT vp;
421 double d;
422 int clr;
423 {
424 double p[3];
425 int j,id;
426 TRI *tri;
427
428 tri = SM_NTH_TRI(sm,i);
429 if (clr) SM_CLEAR_NTH_T_NEW(sm,i);
430
431 /* NOTE:Triangles are defined clockwise:historical relative to spherical
432 tris: could change
433 */
434 for(j=2; j>= 0; j--)
435 {
436 id = T_NTH_V(tri,j);
437 glColor3ub(SM_NTH_RGB(sm,id)[0],SM_NTH_RGB(sm,id)[1],
438 SM_NTH_RGB(sm,id)[2]);
439 VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
440 if(dev_zmin >= 0.99)
441 {
442 p[0] *= d;
443 p[1] *= d;
444 p[2] *= d;
445 }
446 VADD(p,p,vp);
447 glVertex3d(p[0],p[1],p[2]);
448 }
449 }
450
451 smRender_mesh(sm,vp,clr)
452 SM *sm;
453 FVECT vp;
454 int clr;
455 {
456 int i;
457 TRI *tri;
458 double ptr[3],d;
459 int j;
460
461 d = (dev_zmin+dev_zmax)/2.0;
462 glPushAttrib(GL_DEPTH_BUFFER_BIT);
463
464 /* First draw background polygons */
465
466 glDisable(GL_DEPTH_TEST);
467 glBegin(GL_TRIANGLES);
468 SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
469 smRender_bg_tri(sm,i,vp,d,clr);
470 glEnd();
471
472 glEnable(GL_DEPTH_TEST);
473 glBegin(GL_TRIANGLES);
474 SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
475 {
476 if(!SM_MIXED_TRI(sm,i))
477 smRender_tri(sm,i,vp,clr);
478 else
479 smRender_mixed_tri(sm,i,vp,clr);
480 }
481 glEnd();
482
483 glPopAttrib();
484 }
485
486 smRender_tri_edges(sm,i)
487 SM *sm;
488 int i;
489 {
490 TRI *tri;
491 int j;
492 double ptr[3];
493
494
495 tri = SM_NTH_TRI(sm,i);
496
497 /* Triangles are defined clockwise:historical relative to spherical
498 tris: could change
499 */
500 for(j=2; j >=0; j--)
501 {
502 VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,j)));
503 glVertex3d(ptr[0],ptr[1],ptr[2]);
504 VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,(j+1)%3)));
505 glVertex3d(ptr[0],ptr[1],ptr[2]);
506 }
507 }
508
509 int
510 compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
511 {
512 double d;
513
514 d = td2->depth-td1->depth;
515
516 if(d > 0.0)
517 return(1);
518 if(d < 0.0)
519 return(-1);
520
521 return(0);
522 }
523
524 LIST
525 *smDepth_sort_tris(sm,vp,td)
526 SM *sm;
527 FVECT vp;
528 T_DEPTH *td;
529 {
530 int i,j,t_id,v;
531 TRI *tri;
532 double d,min_d;
533 LIST *tlist=NULL;
534
535 i = 0;
536 SM_FOR_ALL_NEW_TRIS(sm,t_id)
537 {
538 if(SM_BG_TRI(sm,t_id))
539 {
540 tlist = push_data(tlist,t_id);
541 continue;
542 }
543 tri = SM_NTH_TRI(sm,t_id);
544 td[i].tri = t_id;
545 min_d = -1;
546 for(j=0;j < 3;j++)
547 {
548 v = T_NTH_V(tri,j);
549 if(!SM_BG_SAMPLE(sm,v))
550 {
551 d = DIST(vp,SM_NTH_WV(sm,v));
552 if(min_d == -1 || d < min_d)
553 min_d = d;
554 }
555 }
556 td[i].depth = min_d;
557 i++;
558 }
559 td[i].tri = -1;
560 if(i)
561 qsort((void *)td,i,sizeof(T_DEPTH),compare_tri_depths);
562 return(tlist);
563 }
564
565
566 smUpdate_Rendered_mesh(sm,vp,clr)
567 SM *sm;
568 FVECT vp;
569 int clr;
570 {
571 static T_DEPTH *td= NULL;
572 static int tsize = 0;
573 int i;
574 GLint depth_test;
575 double d;
576 LIST *bglist;
577 /* For all of the NEW triangles (since last update): assume
578 ACTIVE. Go through and sort on depth value (from vp). Turn
579 Depth Buffer test off and render back-front
580 */
581 /* NOTE: could malloc each time or hard code */
582 if(smNew_tri_cnt > tsize)
583 {
584 if(td)
585 free((char *)td);
586 td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
587 tsize = smNew_tri_cnt;
588 }
589 if(!td)
590 {
591 error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
592 }
593 bglist = smDepth_sort_tris(sm,vp,td);
594
595 /* Turn Depth Test off -- using Painter's algorithm */
596 glPushAttrib(GL_DEPTH_BUFFER_BIT);
597 glDisable(GL_DEPTH_TEST);
598 d = (dev_zmin+dev_zmax)/2.0;
599 /* Now render back-to front */
600 /* First render bg triangles */
601 glBegin(GL_TRIANGLES);
602 while(bglist)
603 smRender_bg_tri(sm,pop_list(&bglist),vp,d,clr);
604 glEnd();
605
606 glEnable(GL_DEPTH_TEST);
607 glBegin(GL_TRIANGLES);
608 i=0;
609 while(td[i].tri != -1)
610 if(!SM_MIXED_TRI(sm,td[i].tri))
611 smRender_tri(sm,td[i++].tri,vp,clr);
612 else
613 smRender_mixed_tri(sm,td[i++].tri,vp,clr);
614 glEnd();
615
616 /* Restore Depth Test */
617 glPopAttrib();
618 }
619
620 /*
621 * smUpdate(view, qua) : update OpenGL output geometry for view vp
622 * VIEW *view; : desired view
623 * int qual; : quality level (percentage on linear time scale)
624 *
625 * Draw new geometric representation using OpenGL calls. Assume that the
626 * view has already been set up and the correct frame buffer has been
627 * selected for drawing. The quality level is on a linear scale, where 100%
628 * is full (final) quality. It is not necessary to redraw geometry that has
629 * been output since the last call to smClean(). (The last view drawn will
630 * be view==&odev.v each time.)
631 */
632 smUpdate(view,qual)
633 VIEW *view;
634 int qual;
635 {
636 double d;
637 int last_update;
638 int t;
639
640 /* If view has moved beyond epsilon from canonical: must rebuild -
641 epsilon is calculated as running avg of distance of sample points
642 from canonical view: m = 1/(AVG(1/r)): some fraction of this
643 */
644 d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
645 if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
646 {
647 /* Re-build the mesh */
648 #ifdef TEST_DRIVER
649 odev.v = *view;
650 #endif
651 smRebuild_mesh(smMesh,view->vp);
652 }
653 /* This is our final update iff qual==100 and view==&odev.v */
654 last_update = qual>=100 && view==&(odev.v);
655 /* Check if we should draw ALL triangles in current frustum */
656 if(smClean_notify || smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT)
657 {
658 #ifdef TEST_DRIVER
659 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
660 #else
661 if (SM_TONE_MAP(smMesh) < SM_NUM_SAMP(smMesh))
662 {
663 tmClearHisto();
664 tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
665 if(tmComputeMapping(0.,0.,0.) != TM_E_OK ||
666 tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
667 SM_NUM_SAMP(smMesh)) != TM_E_OK)
668 return;
669 }
670 #endif
671 mark_tris_in_frustum(view);
672 if (qual <= 75)
673 smRender_stree(smMesh,qual);
674 else
675 smRender_mesh(smMesh,view->vp,last_update);
676 #ifdef TEST_DRIVER
677 glFlush();
678 glutSwapBuffers();
679 #endif
680 }
681 /* Do an incremental update instead */
682 else
683 {
684 if(!smNew_tri_cnt)
685 return;
686 #ifdef TEST_DRIVER
687 glDrawBuffer(GL_FRONT);
688 #else
689 t = SM_TONE_MAP(smMesh);
690 if(t == 0)
691 {
692 tmClearHisto();
693 tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
694 if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
695 return;
696 }
697 if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
698 SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
699 return;
700 #endif
701 smUpdate_Rendered_mesh(smMesh,view->vp,last_update);
702
703 #ifdef TEST_DRIVER
704 glDrawBuffer(GL_BACK);
705 #endif
706 }
707 SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
708 if (last_update)
709 {
710 smClean_notify = FALSE;
711 smNew_tri_cnt = 0;
712 lu_done(&qtr_tab);
713 }
714
715 }