ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.7
Committed: Wed Sep 16 18:16:29 1998 UTC (25 years, 7 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.6: +68 -16 lines
Log Message:
implemented integer triangle tracing

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