ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.12
Committed: Tue Jan 5 16:52:38 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.11: +277 -126 lines
Log Message:
fixed logic in smTest to handle nearby and coincident points, added base tris to rendering, made list of new triangles to speed up rendering

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