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

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * sm_ogl.c
9 */
10 #include "standard.h"
11
12 #include <GL/gl.h>
13
14 #ifdef TEST_DRIVER
15 #include <gl/device.h>
16 #include <GL/glu.h>
17 #include <glut.h>
18 #endif
19 #include "sm_flag.h"
20 #include "sm_list.h"
21 #include "sm_geom.h"
22 #include "sm_qtree.h"
23 #include "sm_stree.h"
24 #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 static int smClean_notify = TRUE;
34 #endif
35
36 typedef struct {
37 float dist; /* average distance */
38 BYTE rgb[3]; /* average color */
39 } QTRAVG; /* average quadtree value */
40
41 typedef struct {
42 QUADTREE qt; /* quadtree node (key & hash value) */
43 QTRAVG av; /* node average */
44 } QT_LUENT; /* lookup table entry */
45
46 static QT_LUENT *qt_htbl = NULL; /* quadtree cache */
47 static int qt_hsiz = 0; /* quadtree cache size */
48
49
50 typedef struct _T_DEPTH {
51 int tri;
52 double depth;
53 }T_DEPTH;
54
55 /*
56 * smClean(tmflag) : display has been wiped clean
57 * int tmflag;
58 * 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 * If tmflag is set, tone-mapping should be performed
61 */
62 smClean(tmflag)
63 int tmflag;
64 {
65 smClean_notify = TRUE;
66 if(tmflag)
67 SM_TONE_MAP(smMesh) = 0;
68 }
69
70 int
71 qtCache_init(nel) /* initialize for at least nel elements */
72 int nel;
73 {
74 static int hsiztab[] = {
75 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0
76 };
77 register int i;
78
79 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 qtCache_find(qt) /* find a quadtree table entry */
103 QUADTREE qt;
104 {
105 int i, n;
106 register int ndx;
107 register QT_LUENT *le;
108
109 if (qt_hsiz == 0 && !qtCache_init(1))
110 return(NULL);
111 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 if (!qtCache_init(ndx+1)) { /* no more memory! */
124 qt_htbl = le;
125 qt_hsiz = ndx;
126 return(NULL);
127 }
128 /* copy old table to new and free */
129 while (ndx--)
130 if (!QT_IS_EMPTY(le[ndx].qt))
131 copystruct(qtCache_find(le[ndx].qt), &le[ndx]);
132 free((char *)le);
133 goto tryagain; /* should happen only once! */
134 }
135
136 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 if(QT_LEAF_IS_FLAG(qt))
152 lcnt[0]++;
153 }
154
155
156 QTRAVG *
157 qtRender_level(qt,v0,v1,v2,sm,lvl)
158 QUADTREE qt;
159 FVECT v0,v1,v2;
160 SM *sm;
161 int lvl;
162 {
163 FVECT a,b,c;
164 register QT_LUENT *le;
165 QTRAVG *rc[4];
166 TRI *tri;
167
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 if(QT_IS_LEAF(qt) && !QT_LEAF_IS_FLAG(qt)) /* not in our frustum */
173 return(NULL);
174 /* else look up node */
175 if ((le = qtCache_find(qt)) == NULL)
176 error(SYSTEM, "out of memory in qtRender_level");
177 if (QT_IS_TREE(qt) && (QT_IS_EMPTY(le->qt) || lvl > 0))
178 { /* compute children */
179 qtSubdivide_tri(v0,v1,v2,a,b,c);
180 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 }
185 if (QT_IS_EMPTY(le->qt))
186 { /* let's make some data! */
187 int rgbs[3];
188 double distsum;
189 register int i, n;
190 /* 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 if (rc[i] != NULL)
197 {
198 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 }
201 }
202 else
203 { /* from triangle set */
204 OBJECT *os;
205 int s0, s1, s2;
206
207 os = qtqueryset(qt);
208 for (i = os[0]; i; i--)
209 {
210 if(SM_IS_NTH_T_BASE(sm,os[i]))
211 continue;
212 tri = SM_NTH_TRI(sm,os[i]);
213 if(!T_IS_VALID(tri))
214 continue;
215 n++;
216 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 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 n *= 3;
236 }
237 if (!n)
238 return(NULL);
239 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 }
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 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 /* draw triangle */
252 glColor3ub(le->av.rgb[0],le->av.rgb[1],le->av.rgb[2]);
253 glVertex3d(a[0],a[1],a[2]);
254 glVertex3d(b[0],b[1],b[2]);
255 glVertex3d(c[0],c[1],c[2]);
256
257 }
258 return(&le->av);
259 }
260
261
262 smRender_stree_level(sm,lvl)
263 SM *sm;
264 int lvl;
265 {
266 QUADTREE qt;
267 int i;
268 FVECT t0,t1,t2;
269 STREE *st;
270
271
272 if (lvl < 0)
273 return;
274 st = SM_LOCATOR(sm);
275 glPushAttrib(GL_LIGHTING_BIT);
276 glShadeModel(GL_FLAT);
277 glBegin(GL_TRIANGLES);
278 for(i=0; i < ST_NUM_ROOT_NODES; i++)
279 {
280 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 sm,lvl);
283 }
284 glEnd();
285 glPopAttrib();
286 }
287
288
289 smRender_stree(sm, qual) /* render some quadtree triangles */
290 SM *sm;
291 int qual;
292 {
293 int i, n,ntarget;
294 int lvlcnt[QT_MAX_LEVELS];
295 STREE *st;
296 int4 *active_flag;
297 if (qual <= 0)
298 return;
299 /* compute rendering target */
300 ntarget = 0;
301
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 if (!ntarget)
311 return;
312 for (i = QT_MAX_LEVELS; i--; )
313 lvlcnt[i] = 0;
314
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 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
328 #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
333 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 {
339 double p[3],d;
340 int j,ids[3],cnt;
341 int rgb[3];
342
343 /* NOTE:Triangles are defined clockwise:historical relative to spherical
344 tris: could change
345 */
346 if(bg0 && bg1 && bg2)
347 return;
348
349 cnt = 0;
350 d = 0.0;
351 rgb[0] = rgb[1] = rgb[2] = 0;
352
353 if(!bg0)
354 {
355 rgb[0] += rgb0[0];
356 rgb[1] += rgb0[1];
357 rgb[2] += rgb0[2];
358 cnt++;
359 d += DIST(vp,v0);
360 }
361 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 if(cnt > 1)
378 {
379 rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
380 d /= (double)cnt;
381 }
382 if(bg0)
383 {
384 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 }
397 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 }
429
430 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 double d;
435 {
436 double p[3];
437
438 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
449 glColor3ub(rgb1[0],rgb1[1],rgb1[2]);
450 VSUB(p,v1,vc);
451 if(dev_zmin >= 0.99)
452 {
453 p[0] *= d;
454 p[1] *= d;
455 p[2] *= d;
456 }
457 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 }
473
474 smRender_mesh(sm,vp)
475 SM *sm;
476 FVECT vp;
477 {
478 int i,n,bg0,bg1,bg2;
479 double d;
480 int v0_id,v1_id,v2_id;
481 TRI *tri;
482 float (*wp)[3];
483 BYTE (*rgb)[3];
484 int4 *active_flag,*bg_flag;
485
486 wp = SM_WP(sm);
487 rgb =SM_RGB(sm);
488 d = (dev_zmin+dev_zmax)/2.0;
489 glPushAttrib(GL_DEPTH_BUFFER_BIT);
490
491 /* First draw background polygons */
492 glDisable(GL_DEPTH_TEST);
493 glBegin(GL_TRIANGLES);
494
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 glEnd();
510
511 glEnable(GL_DEPTH_TEST);
512 glBegin(GL_TRIANGLES);
513 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 glEnd();
533
534 glPopAttrib();
535 }
536
537 int
538 compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
539 {
540 double d;
541
542 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
551 }
552
553 #ifdef DEBUG
554 #define freebuf(b) tempbuf(-1)
555 #endif
556
557
558 char *
559 tempbuf(len) /* get a temporary buffer */
560 unsigned len;
561 {
562 extern char *malloc(), *realloc();
563 static char *tempbuf = NULL;
564 static unsigned tempbuflen = 0;
565
566 #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 }
579 #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 }
592
593 smOrder_new_tris(sm,vp,td)
594 SM *sm;
595 FVECT vp;
596 T_DEPTH *td;
597 {
598 int n,i,j,tcnt,v;
599 TRI *tri;
600 double d,min_d;
601 FVECT diff;
602 int4 *new_flag,*bg_flag;
603
604 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 }
628 td[tcnt].tri = -1;
629 if(tcnt)
630 qsort((void *)td,tcnt,sizeof(T_DEPTH),compare_tri_depths);
631 }
632
633
634 smUpdate_Rendered_mesh(sm,vp,clr)
635 SM *sm;
636 FVECT vp;
637 int clr;
638 {
639 int i,n,v0_id,v1_id,v2_id,bg0,bg1,bg2;
640 GLint depth_test;
641 double d;
642 TRI *tri;
643 float (*wp)[3];
644 BYTE (*rgb)[3];
645 int4 *new_flag,*bg_flag;
646 T_DEPTH *td = NULL;
647 /* 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 if(!EQUAL_VEC3(SM_VIEW_CENTER(sm),vp))
652 {
653 /* 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 }
661 wp = SM_WP(sm);
662 rgb =SM_RGB(sm);
663 /* Turn Depth Test off -- using Painter's algorithm */
664 glPushAttrib(GL_DEPTH_BUFFER_BIT);
665 glDepthFunc(GL_ALWAYS);
666 d = (dev_zmin+dev_zmax)/2.0;
667
668 /* Now render back-to front */
669 /* First render bg triangles */
670 new_flag = SM_NTH_FLAGS(sm,T_NEW_FLAG);
671 bg_flag = SM_NTH_FLAGS(sm,T_BG_FLAG);
672 glBegin(GL_TRIANGLES);
673 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 glEnd();
686
687
688 glBegin(GL_TRIANGLES);
689 if(!td)
690 {
691 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 }
715 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 glEnd();
742
743 /* Restore Depth Test */
744 glPopAttrib();
745 }
746
747 /*
748 * smUpdate(view, qua) : update OpenGL output geometry for view vp
749 * VIEW *view; : desired view
750 * 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 * been output since the last call to smClean(). (The last view drawn will
757 * be view==&odev.v each time.)
758 */
759 smUpdate(view,qual)
760 VIEW *view;
761 int qual;
762 {
763 double d;
764 int last_update,t;
765
766 if(!smMesh)
767 return;
768
769 /* If view has moved beyond epsilon from canonical: must rebuild -
770 epsilon is calculated as running avg of distance of sample points
771 from canonical view: m = 1/(AVG(1/r)): some fraction of this
772 */
773 d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
774 if(qual >= MAXQUALITY && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
775 {
776 /* Re-build the mesh */
777 #ifdef TEST_DRIVER
778 odev.v = *view;
779 #endif
780 mark_tris_in_frustum(view);
781 smRebuild_mesh(smMesh,view);
782 smClean_notify = TRUE;
783 }
784 /* This is our final update iff qual==MAXQUALITY and view==&odev.v */
785 last_update = qual>=MAXQUALITY && view==&(odev.v);
786 /* Check if we should draw ALL triangles in current frustum */
787 if(smClean_notify || smNew_tri_cnt>SM_SAMPLE_TRIS(smMesh)*SM_INC_PERCENT)
788 {
789 #ifdef TEST_DRIVER
790 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
791 #else
792 if (SM_TONE_MAP(smMesh) < SM_NUM_SAMP(smMesh))
793 {
794 tmClearHisto();
795 tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
796 if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
797 return;
798 tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
799 SM_NUM_SAMP(smMesh));
800 }
801 #endif
802 mark_tris_in_frustum(view);
803 if (qual <= (MAXQUALITY*3/4))
804 smRender_stree(smMesh,qual);
805 else
806 smRender_mesh(smMesh,view->vp);
807 #ifdef TEST_DRIVER
808 glFlush();
809 glutSwapBuffers();
810 #endif
811 }
812 /* Do an incremental update instead */
813 else
814 {
815 if(!smNew_tri_cnt)
816 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 tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
829 SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t);
830
831 #endif
832 smUpdate_Rendered_mesh(smMesh,view->vp,last_update);
833
834 #ifdef TEST_DRIVER
835 glDrawBuffer(GL_BACK);
836 #endif
837 }
838
839 SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
840
841 if (last_update)
842 {
843 smClean_notify = FALSE;
844 smNew_tri_cnt = 0;
845 smClear_flags(smMesh,T_NEW_FLAG);
846 qtCache_init(0);
847 }
848
849 }
850
851
852
853
854
855
856
857