ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.10
Committed: Mon Dec 28 18:07:35 1998 UTC (25 years, 4 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.9: +28 -202 lines
Log Message:
New insertion routine
New Culling routine based on insertion algorithm
Adapted old insertion code: now used by picking
Point location code returns on-vertex,on-edge, or in-triangle
Added on_edge case for subdivision
Implemented unordered sets
Removed deletion from quadtree- added set compression to replace functionality

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