ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.13
Committed: Sun Jan 10 10:27:48 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.12: +225 -224 lines
Log Message:
sm.c, sm_del.c sm_ogl.c sm.h
Fixed failure to tone-map on start up
added code for temporary buffer allocation
added bg flag, and fast flag checking routines for drawing
provided graceful backout if deletion triangulation fails

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