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

# User Rev Content
1 gwlarson 3.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 gwlarson 3.3 #include "sm_list.h"
21 gwlarson 3.1 #include "sm_geom.h"
22     #include "sm.h"
23 gwlarson 3.3 #include "lookup.h"
24 gwlarson 3.1
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 gwlarson 3.3 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 gwlarson 3.1 int
57 gwlarson 3.3 qtcmp(qt1, qt2)
58     char *qt1, *qt2;
59     {
60     return(qt1 - qt2);
61     }
62    
63    
64     int
65 gwlarson 3.1 mark_active_tris(qtptr,arg)
66     QUADTREE *qtptr;
67     char *arg;
68     {
69 gwlarson 3.3 QUADTREE qt = *qtptr;
70     OBJECT os[QT_MAX_SET+1],*optr;
71     register int i,t_id;
72 gwlarson 3.1
73 gwlarson 3.3 if (!QT_IS_LEAF(qt))
74     return(TRUE);
75     /* For each triangle in the set, set the which flag*/
76     qtgetset(os,qt);
77 gwlarson 3.1
78 gwlarson 3.3 for (i = QT_SET_CNT(os), optr = QT_SET_PTR(os); i > 0; i--)
79 gwlarson 3.1 {
80 gwlarson 3.3 t_id = QT_SET_NEXT_ELEM(optr);
81     /* Set the render flag */
82     if(SM_IS_NTH_T_BASE(smMesh,t_id))
83 gwlarson 3.1 continue;
84 gwlarson 3.3 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 gwlarson 3.1 }
88     return(TRUE);
89     }
90    
91 gwlarson 3.3 mark_tris_in_frustum(view)
92     VIEW *view;
93 gwlarson 3.1 {
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 gwlarson 3.3 /* First clear all the quadtree node and triangle active flags */
104     qtClearAllFlags();
105     smClear_flags(smMesh,T_ACTIVE_FLAG);
106 gwlarson 3.1
107     /* calculate the world space coordinates of the view frustum */
108 gwlarson 3.3 calculate_view_frustum(view->vp,view->hvec,view->vvec,view->horiz,
109     view->vert, dev_zmin,dev_zmax,nr,far);
110 gwlarson 3.1
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 gwlarson 3.3 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 gwlarson 3.1 /* Right face triangles */
120 gwlarson 3.3 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 gwlarson 3.1 /* Left face triangles */
123 gwlarson 3.3 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 gwlarson 3.1 /* Top face triangles */
126 gwlarson 3.3 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 gwlarson 3.1 /* Bottom face triangles */
129 gwlarson 3.3 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 gwlarson 3.1 /* Far face triangles */
132 gwlarson 3.3 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 gwlarson 3.1
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 gwlarson 3.3 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 gwlarson 3.1 SM *sm;
183 gwlarson 3.3 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 gwlarson 3.1 int i;
332     FVECT vp;
333 gwlarson 3.3 int clr;
334 gwlarson 3.1 {
335     TRI *tri;
336     double ptr[3];
337     int j;
338    
339     tri = SM_NTH_TRI(sm,i);
340 gwlarson 3.3 if (clr) SM_CLEAR_NTH_T_NEW(sm,i);
341    
342 gwlarson 3.1 /* NOTE:Triangles are defined clockwise:historical relative to spherical
343     tris: could change
344     */
345     for(j=2; j>= 0; j--)
346     {
347 gwlarson 3.2 #ifdef DEBUG
348     if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
349     eputs("SmRenderTri(): shouldnt have bg samples\n");
350     #endif
351 gwlarson 3.1 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 gwlarson 3.3 smRender_mixed_tri(sm,i,vp,clr)
360 gwlarson 3.1 SM *sm;
361     int i;
362     FVECT vp;
363 gwlarson 3.3 int clr;
364 gwlarson 3.1 {
365     TRI *tri;
366 gwlarson 3.3 double p[3],d;
367 gwlarson 3.1 int j,ids[3],cnt;
368 gwlarson 3.2 int rgb[3];
369 gwlarson 3.1
370 gwlarson 3.3 tri = SM_NTH_TRI(sm,i);
371     if (clr) SM_CLEAR_NTH_T_NEW(sm,i);
372 gwlarson 3.2
373 gwlarson 3.1 /* NOTE:Triangles are defined clockwise:historical relative to spherical
374     tris: could change
375     */
376     cnt = 0;
377 gwlarson 3.3 d = 0.0;
378 gwlarson 3.1 rgb[0] = rgb[1] = rgb[2] = 0;
379 gwlarson 3.3 for(j=0;j < 3;j++)
380 gwlarson 3.1 {
381 gwlarson 3.3 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 gwlarson 3.1 }
391 gwlarson 3.3 if(cnt > 1)
392 gwlarson 3.1 {
393     rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
394 gwlarson 3.3 d /= (double)cnt;
395 gwlarson 3.1 }
396     for(j=2; j>= 0; j--)
397     {
398     if(SM_BG_SAMPLE(sm,ids[j]))
399 gwlarson 3.3 {
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 gwlarson 3.1 else
408 gwlarson 3.2 {
409 gwlarson 3.3 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 gwlarson 3.2 }
413 gwlarson 3.1 glVertex3d(p[0],p[1],p[2]);
414 gwlarson 3.3 }
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 gwlarson 3.1 }
449     }
450    
451 gwlarson 3.3 smRender_mesh(sm,vp,clr)
452 gwlarson 3.1 SM *sm;
453     FVECT vp;
454 gwlarson 3.3 int clr;
455 gwlarson 3.1 {
456     int i;
457     TRI *tri;
458 gwlarson 3.2 double ptr[3],d;
459 gwlarson 3.1 int j;
460    
461 gwlarson 3.2 d = (dev_zmin+dev_zmax)/2.0;
462 gwlarson 3.1 glPushAttrib(GL_DEPTH_BUFFER_BIT);
463    
464     /* First draw background polygons */
465 gwlarson 3.2
466 gwlarson 3.1 glDisable(GL_DEPTH_TEST);
467     glBegin(GL_TRIANGLES);
468     SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
469 gwlarson 3.3 smRender_bg_tri(sm,i,vp,d,clr);
470 gwlarson 3.1 glEnd();
471    
472     glEnable(GL_DEPTH_TEST);
473     glBegin(GL_TRIANGLES);
474     SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
475 gwlarson 3.3 {
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 gwlarson 3.1 glEnd();
482    
483     glPopAttrib();
484     }
485 gwlarson 3.3
486 gwlarson 3.1 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 gwlarson 3.3 LIST
525     *smDepth_sort_tris(sm,vp,td)
526 gwlarson 3.1 SM *sm;
527 gwlarson 3.3 FVECT vp;
528 gwlarson 3.1 T_DEPTH *td;
529     {
530 gwlarson 3.3 int i,j,t_id,v;
531 gwlarson 3.1 TRI *tri;
532 gwlarson 3.3 double d,min_d;
533     LIST *tlist=NULL;
534 gwlarson 3.1
535     i = 0;
536     SM_FOR_ALL_NEW_TRIS(sm,t_id)
537     {
538 gwlarson 3.3 if(SM_BG_TRI(sm,t_id))
539 gwlarson 3.1 {
540 gwlarson 3.3 tlist = push_data(tlist,t_id);
541     continue;
542 gwlarson 3.1 }
543     tri = SM_NTH_TRI(sm,t_id);
544     td[i].tri = t_id;
545 gwlarson 3.3 min_d = -1;
546 gwlarson 3.1 for(j=0;j < 3;j++)
547 gwlarson 3.3 {
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 gwlarson 3.1 i++;
558     }
559 gwlarson 3.3 td[i].tri = -1;
560     if(i)
561     qsort((void *)td,i,sizeof(T_DEPTH),compare_tri_depths);
562     return(tlist);
563 gwlarson 3.1 }
564    
565    
566 gwlarson 3.3 smUpdate_Rendered_mesh(sm,vp,clr)
567 gwlarson 3.1 SM *sm;
568 gwlarson 3.3 FVECT vp;
569     int clr;
570 gwlarson 3.1 {
571     static T_DEPTH *td= NULL;
572     static int tsize = 0;
573     int i;
574     GLint depth_test;
575 gwlarson 3.2 double d;
576 gwlarson 3.3 LIST *bglist;
577 gwlarson 3.1 /* 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 gwlarson 3.3 free((char *)td);
586 gwlarson 3.1 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 gwlarson 3.3 bglist = smDepth_sort_tris(sm,vp,td);
594 gwlarson 3.1
595 gwlarson 3.3 /* Turn Depth Test off -- using Painter's algorithm */
596 gwlarson 3.1 glPushAttrib(GL_DEPTH_BUFFER_BIT);
597 gwlarson 3.3 glDisable(GL_DEPTH_TEST);
598 gwlarson 3.2 d = (dev_zmin+dev_zmax)/2.0;
599 gwlarson 3.1 /* Now render back-to front */
600     /* First render bg triangles */
601     glBegin(GL_TRIANGLES);
602 gwlarson 3.3 while(bglist)
603     smRender_bg_tri(sm,pop_list(&bglist),vp,d,clr);
604 gwlarson 3.1 glEnd();
605    
606     glEnable(GL_DEPTH_TEST);
607     glBegin(GL_TRIANGLES);
608 gwlarson 3.3 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 gwlarson 3.1 glEnd();
615    
616     /* Restore Depth Test */
617     glPopAttrib();
618     }
619    
620     /*
621 gwlarson 3.3 * smUpdate(view, qua) : update OpenGL output geometry for view vp
622     * VIEW *view; : desired view
623 gwlarson 3.1 * 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 gwlarson 3.3 * been output since the last call to smClean(). (The last view drawn will
630     * be view==&odev.v each time.)
631 gwlarson 3.1 */
632 gwlarson 3.3 smUpdate(view,qual)
633     VIEW *view;
634 gwlarson 3.1 int qual;
635     {
636     double d;
637 gwlarson 3.3 int last_update;
638 gwlarson 3.1 int t;
639 gwlarson 3.3
640 gwlarson 3.1 /* If view has moved beyond epsilon from canonical: must rebuild -
641     epsilon is calculated as running avg of distance of sample points
642 gwlarson 3.3 from canonical view: m = 1/(AVG(1/r)): some fraction of this
643 gwlarson 3.1 */
644 gwlarson 3.3 d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
645 gwlarson 3.1 if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
646     {
647     /* Re-build the mesh */
648 gwlarson 3.3 #ifdef TEST_DRIVER
649     odev.v = *view;
650     #endif
651     smRebuild_mesh(smMesh,view->vp);
652 gwlarson 3.1 }
653 gwlarson 3.3 /* 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 gwlarson 3.1 {
658     #ifdef TEST_DRIVER
659     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
660     #else
661 gwlarson 3.3 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 gwlarson 3.1 #endif
671 gwlarson 3.3 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 gwlarson 3.1 #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 gwlarson 3.3 smUpdate_Rendered_mesh(smMesh,view->vp,last_update);
702 gwlarson 3.1
703     #ifdef TEST_DRIVER
704     glDrawBuffer(GL_BACK);
705     #endif
706     }
707     SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
708 gwlarson 3.3 if (last_update)
709     {
710     smClean_notify = FALSE;
711     smNew_tri_cnt = 0;
712     lu_done(&qtr_tab);
713     }
714    
715 gwlarson 3.1 }