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

File Contents

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