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

# 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 /*
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 smClean()
57 {
58 smClean_notify = TRUE;
59 }
60
61 int
62 qtCache_init(nel) /* initialize for at least nel elements */
63 int nel;
64 {
65 static int hsiztab[] = {
66 8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0
67 };
68 register int i;
69
70 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 qtCache_find(qt) /* find a quadtree table entry */
94 QUADTREE qt;
95 {
96 int i, n;
97 register int ndx;
98 register QT_LUENT *le;
99
100 if (qt_hsiz == 0 && !qtCache_init(1))
101 return(NULL);
102 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 if (!qtCache_init(ndx+1)) { /* no more memory! */
115 qt_htbl = le;
116 qt_hsiz = ndx;
117 return(NULL);
118 }
119 /* copy old table to new and free */
120 while (ndx--)
121 if (!QT_IS_EMPTY(le[ndx].qt))
122 copystruct(qtCache_find(le[ndx].qt), &le[ndx]);
123 free((char *)le);
124 goto tryagain; /* should happen only once! */
125 }
126
127 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 if(QT_LEAF_IS_FLAG(qt))
143 lcnt[0]++;
144 }
145
146
147 QTRAVG *
148 qtRender_level(qt,v0,v1,v2,sm,lvl)
149 QUADTREE qt;
150 FVECT v0,v1,v2;
151 SM *sm;
152 int lvl;
153 {
154 FVECT a,b,c;
155 register QT_LUENT *le;
156 QTRAVG *rc[4];
157 TRI *tri;
158
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 if(QT_IS_LEAF(qt) && !QT_LEAF_IS_FLAG(qt)) /* not in our frustum */
164 return(NULL);
165 /* else look up node */
166 if ((le = qtCache_find(qt)) == NULL)
167 error(SYSTEM, "out of memory in qtRender_level");
168 if (QT_IS_TREE(qt) && (QT_IS_EMPTY(le->qt) || lvl > 0))
169 { /* compute children */
170 qtSubdivide_tri(v0,v1,v2,a,b,c);
171 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 }
176 if (QT_IS_EMPTY(le->qt))
177 { /* let's make some data! */
178 int rgbs[3];
179 double distsum;
180 register int i, n;
181 /* 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 if (rc[i] != NULL)
188 {
189 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 }
192 }
193 else
194 { /* from triangle set */
195 OBJECT *os;
196 int s0, s1, s2;
197
198 os = qtqueryset(qt);
199 for (i = os[0]; i; i--)
200 {
201 if(SM_IS_NTH_T_BASE(sm,os[i]))
202 continue;
203 tri = SM_NTH_TRI(sm,os[i]);
204 if(!T_IS_VALID(tri))
205 continue;
206 n++;
207 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 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 n *= 3;
227 }
228 if (!n)
229 return(NULL);
230 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 }
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 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 /* draw triangle */
243 glColor3ub(le->av.rgb[0],le->av.rgb[1],le->av.rgb[2]);
244 glVertex3d(a[0],a[1],a[2]);
245 glVertex3d(b[0],b[1],b[2]);
246 glVertex3d(c[0],c[1],c[2]);
247
248 }
249 return(&le->av);
250 }
251
252
253 smRender_stree_level(sm,lvl)
254 SM *sm;
255 int lvl;
256 {
257 QUADTREE qt;
258 int i;
259 FVECT t0,t1,t2;
260 STREE *st;
261
262
263 if (lvl < 0)
264 return;
265 st = SM_LOCATOR(sm);
266 glPushAttrib(GL_LIGHTING_BIT);
267 glShadeModel(GL_FLAT);
268 glBegin(GL_TRIANGLES);
269 for(i=0; i < ST_NUM_ROOT_NODES; i++)
270 {
271 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 sm,lvl);
274 }
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 STREE *st;
287
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
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 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
313 #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
318 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 {
324 double p[3],d;
325 int j,ids[3],cnt;
326 int rgb[3];
327
328 /* NOTE:Triangles are defined clockwise:historical relative to spherical
329 tris: could change
330 */
331 cnt = 0;
332 d = 0.0;
333 rgb[0] = rgb[1] = rgb[2] = 0;
334
335 if(bg0 && bg1 && bg2)
336 return;
337
338 if(!bg0)
339 {
340 rgb[0] += rgb0[0];
341 rgb[1] += rgb0[1];
342 rgb[2] += rgb0[2];
343 cnt++;
344 d += DIST(vp,v0);
345 }
346 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 if(cnt > 1)
363 {
364 rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
365 d /= (double)cnt;
366 }
367 if(bg0)
368 {
369 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 }
382 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 }
414
415 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 double d;
420 {
421 double p[3];
422
423 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
434 glColor3ub(rgb1[0],rgb1[1],rgb1[2]);
435 VSUB(p,v1,vc);
436 if(dev_zmin >= 0.99)
437 {
438 p[0] *= d;
439 p[1] *= d;
440 p[2] *= d;
441 }
442 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 }
458
459 smRender_mesh(sm,vp,clr)
460 SM *sm;
461 FVECT vp;
462 int clr;
463 {
464 int i,bg0,bg1,bg2;
465 double d;
466 int v0_id,v1_id,v2_id;
467 TRI *tri;
468 float (*wp)[3];
469 BYTE (*rgb)[3];
470
471 wp = SM_WP(sm);
472 rgb =SM_RGB(sm);
473 d = (dev_zmin+dev_zmax)/2.0;
474 glPushAttrib(GL_DEPTH_BUFFER_BIT);
475
476 /* First draw background polygons */
477 glDisable(GL_DEPTH_TEST);
478 glBegin(GL_TRIANGLES);
479 /* Maintain a list? */
480 SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
481 {
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 glEnd();
492 glEnable(GL_DEPTH_TEST);
493 glBegin(GL_TRIANGLES);
494 SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
495 {
496 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 else
509 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 }
512 glEnd();
513
514 glPopAttrib();
515 }
516
517 int
518 compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
519 {
520 double d;
521
522 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
532 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 }
541
542 int
543 compare_tri_depths_old(T_DEPTH *td1,T_DEPTH *td2)
544 {
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 LIST
558 *smDepth_sort_tris(sm,vp,td)
559 SM *sm;
560 FVECT vp;
561 T_DEPTH *td;
562 {
563 int i,j,t_id,v;
564 TRI *tri;
565 double d,min_d;
566 LIST *tlist=NULL;
567 FVECT diff;
568
569 i = 0;
570 SM_FOR_ALL_NEW_TRIS(sm,t_id)
571 {
572 if(SM_BG_TRI(sm,t_id))
573 {
574 tlist = push_data(tlist,t_id);
575 continue;
576 }
577 tri = SM_NTH_TRI(sm,t_id);
578 td[i].tri = t_id;
579 min_d = -1;
580 for(j=0;j < 3;j++)
581 {
582 v = T_NTH_V(tri,j);
583 if(!SM_BG_SAMPLE(sm,v))
584 {
585 VSUB(diff,SM_NTH_WV(sm,v),vp);
586 d = DOT(diff,diff);
587 if(min_d == -1 || d < min_d)
588 min_d = d;
589 }
590 }
591 td[i].depth = min_d;
592 i++;
593 }
594 td[i].tri = -1;
595 if(i)
596 qsort((void *)td,i,sizeof(T_DEPTH),compare_tri_depths);
597 return(tlist);
598 }
599
600
601
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 smUpdate_Rendered_mesh(sm,vp,clr)
656 SM *sm;
657 FVECT vp;
658 int clr;
659 {
660 static T_DEPTH *td= NULL;
661 static int tsize = 0;
662 int i,v0_id,v1_id,v2_id,bg0,bg1,bg2;
663 GLint depth_test;
664 double d;
665 LIST *bglist;
666 TRI *tri;
667 float (*wp)[3];
668 BYTE (*rgb)[3];
669
670 /* 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 #if 0
676 if(smNew_tri_cnt > tsize)
677 {
678 if(td)
679 free((char *)td);
680 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 bglist = smDepth_sort_tris(sm,vp,td);
688 #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 /* Turn Depth Test off -- using Painter's algorithm */
698 glPushAttrib(GL_DEPTH_BUFFER_BIT);
699 glDepthFunc(GL_ALWAYS);
700 d = (dev_zmin+dev_zmax)/2.0;
701 /* Now render back-to front */
702 /* First render bg triangles */
703 glBegin(GL_TRIANGLES);
704 while(bglist)
705 {
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 glEnd();
717
718
719 glBegin(GL_TRIANGLES);
720 i=0;
721 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 glEnd();
746
747 /* Restore Depth Test */
748 glPopAttrib();
749 }
750
751 /*
752 * smUpdate(view, qua) : update OpenGL output geometry for view vp
753 * VIEW *view; : desired view
754 * 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 * been output since the last call to smClean(). (The last view drawn will
761 * be view==&odev.v each time.)
762 */
763 smUpdate(view,qual)
764 VIEW *view;
765 int qual;
766 {
767 double d;
768 int last_update;
769 int t;
770
771 /* If view has moved beyond epsilon from canonical: must rebuild -
772 epsilon is calculated as running avg of distance of sample points
773 from canonical view: m = 1/(AVG(1/r)): some fraction of this
774 */
775
776 if(!smMesh)
777 return;
778
779 d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
780 if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
781 {
782 /* Re-build the mesh */
783 #ifdef TEST_DRIVER
784 odev.v = *view;
785 #endif
786 mark_tris_in_frustum(view);
787 smRebuild_mesh(smMesh,view);
788 smClean_notify = TRUE;
789 }
790 /* 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 if(smClean_notify || smNew_tri_cnt > SM_SAMPLE_TRIS(smMesh)*SM_INC_PERCENT)
794 {
795 #ifdef TEST_DRIVER
796 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
797 #else
798 if ( SM_TONE_MAP(smMesh) < SM_NUM_SAMP(smMesh))
799 {
800 tmClearHisto();
801 tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
802 tmComputeMapping(0.,0.,0.);
803 tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
804 SM_NUM_SAMP(smMesh));
805 }
806 #endif
807 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 #ifdef TEST_DRIVER
813 glFlush();
814 glutSwapBuffers();
815 #endif
816 }
817 /* Do an incremental update instead */
818 else
819 {
820 if(!smNew_tri_cnt)
821 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 tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
834 SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t);
835
836 #endif
837 smUpdate_Rendered_mesh(smMesh,view->vp,last_update);
838
839 #ifdef TEST_DRIVER
840 glDrawBuffer(GL_BACK);
841 #endif
842 }
843
844 SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
845
846 if (last_update)
847 {
848 smClean_notify = FALSE;
849 smNew_tri_cnt = 0;
850 #if 0
851 smClear_flags(smMesh,T_NEW_FLAG);
852 #endif
853 qtCache_init(0);
854 }
855
856 }