ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.4
Committed: Thu Sep 3 11:29:00 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.3: +93 -50 lines
Log Message:
switched to custom replacement for lookup.c routines

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