ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.6
Committed: Mon Sep 14 10:33:47 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.5: +10 -2 lines
Log Message:
optimized normalizing calls and bug fix in triangle counting

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