ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
(Generate patch)

Comparing ray/src/hd/sm_ogl.c (file contents):
Revision 3.2 by gwlarson, Thu Aug 20 16:47:21 1998 UTC vs.
Revision 3.10 by gwlarson, Mon Dec 28 18:07:35 1998 UTC

# Line 16 | Line 16 | static char SCCSid[] = "$SunId$ SGI";
16   #include <GL/glu.h>
17   #include <glut.h>
18   #endif
19 < #include "object.h"
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
# Line 27 | Line 30 | MAKE STATIC LATER: ui.c using for now;
30   */
31   char smClean_notify = TRUE;
32   #else
33 < static char smClean_notify = TRUE;
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 < mark_active_tris(qtptr,arg)
63 < QUADTREE *qtptr;
36 < char *arg;
62 > qtCache_init(nel)               /* initialize for at least nel elements */
63 > int     nel;
64   {
65 <  OBJECT os[MAXSET+1],*optr;
66 <  int i,t_id;
67 <  SM *sm;
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 <  sm = (SM *)arg;
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 <  /* For each triangle in the set, set the which flag*/
101 <  if(QT_IS_EMPTY(*qtptr))
102 <  {
103 <      return(FALSE);
104 <  }
105 <  else
106 <  {
107 <    qtgetset(os,*qtptr);
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 <    for (i = QT_SET_CNT(os),optr = QT_SET_PTR(os); i > 0; i--)
128 <    {
129 <      t_id = QT_SET_NEXT_ELEM(optr);
130 <      /* Set the render flag */
131 <      if(SM_IS_NTH_T_BASE(sm,t_id))
132 <        continue;
133 <      SM_SET_NTH_T_ACTIVE(sm,t_id);
134 <      /* FOR NOW:Also set the LRU clock bit: MAY WANT TO CHANGE: */      
135 <      SM_SET_NTH_T_LRU(sm,t_id);
136 <    }
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 <  return(TRUE);
141 >  else
142 >    if(QT_LEAF_IS_FLAG(qt))
143 >      lcnt[0]++;
144   }
145  
146  
147 < smMark_tris_in_frustum(sm,vp)
147 > QTRAVG *
148 > qtRender_level(qt,v0,v1,v2,sm,lvl)
149 > QUADTREE qt;
150 > FVECT v0,v1,v2;
151   SM *sm;
152 < VIEW *vp;
152 > int lvl;
153   {
154 <    FVECT nr[4],far[4];
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,a,c,sm,lvl-1);
172 >    rc[1] = qtRender_level(QT_NTH_CHILD(qt,1),a,v1,b,sm,lvl-1);
173 >    rc[2] = qtRender_level(QT_NTH_CHILD(qt,2),c,b,v2,sm,lvl-1);
174 >    rc[3] = qtRender_level(QT_NTH_CHILD(qt,3),b,c,a,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 <    /* Mark triangles in approx. view frustum as being active:set
199 <       LRU counter: for use in discarding samples when out
200 <       of space
201 <       Radiance often has no far clipping plane: but driver will set
202 <       dev_zmin,dev_zmax to satisfy OGL
203 <    */
198 >      os = qtqueryset(qt);
199 >      for (n = os[0]; n; n--)
200 >      {
201 >        if(SM_IS_NTH_T_BASE(sm,os[n]))
202 >           continue;
203 >        tri = SM_NTH_TRI(sm,os[n]);
204 >        if(!T_IS_VALID(tri))
205 >          continue;
206 >        
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*os[0];
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 <    /* First clear all the triangle active flags */
249 <    smClear_flags(sm,T_ACTIVE_FLAG);
248 >  }
249 >  return(&le->av);
250 > }
251  
85    /* calculate the world space coordinates of the view frustum */
86    calculate_view_frustum(vp->vp,vp->hvec,vp->vvec,vp->horiz,vp->vert,
87                           dev_zmin,dev_zmax,nr,far);
252  
253 <    /* Project the view frustum onto the spherical quadtree */
254 <    /* For every cell intersected by the projection of the faces
255 <       of the frustum: mark all triangles in the cell as ACTIVE-
256 <       Also set the triangles LRU clock counter
257 <       */
258 <    /* Need to do tonemap call */
259 <    /* Near face triangles */
260 <    smLocator_apply_func(sm,nr[0],nr[2],nr[3],mark_active_tris,(char *)(sm));
97 <    smLocator_apply_func(sm,nr[2],nr[0],nr[1],mark_active_tris,(char *)(sm));
98 <    /* Right face triangles */
99 <    smLocator_apply_func(sm,nr[0],far[3],far[0],mark_active_tris,(char *)(sm));
100 <    smLocator_apply_func(sm,far[3],nr[0],nr[3],mark_active_tris,(char *)(sm));
101 <    /* Left face triangles */
102 <    smLocator_apply_func(sm,nr[1],far[2],nr[2],mark_active_tris,(char *)(sm));
103 <    smLocator_apply_func(sm,far[2],nr[1],far[1],mark_active_tris,(char *)(sm));
104 <    /* Top face triangles */
105 <    smLocator_apply_func(sm,nr[0],far[0],nr[1],mark_active_tris,(char *)(sm));
106 <    smLocator_apply_func(sm,nr[1],far[0],far[1],mark_active_tris,(char *)(sm));
107 <    /* Bottom face triangles */
108 <    smLocator_apply_func(sm,nr[3],nr[2],far[3],mark_active_tris,(char *)(sm));
109 <    smLocator_apply_func(sm,nr[2],far[2],far[3],mark_active_tris,(char *)(sm));
110 <    /* Far face triangles */
111 <   smLocator_apply_func(sm,far[0],far[2],far[1],mark_active_tris,(char *)(sm));
112 <   smLocator_apply_func(sm,far[2],far[0],far[3],mark_active_tris,(char *)(sm));
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 < #ifdef TEST_DRIVER
263 <    VCOPY(FrustumFar[0],far[0]);
264 <    VCOPY(FrustumFar[1],far[1]);
265 <    VCOPY(FrustumFar[2],far[2]);
266 <    VCOPY(FrustumFar[3],far[3]);
267 <    VCOPY(FrustumNear[0],nr[0]);
268 <    VCOPY(FrustumNear[1],nr[1]);
269 <    VCOPY(FrustumNear[2],nr[2]);
270 <    VCOPY(FrustumNear[3],nr[3]);
271 < #endif
262 >  
263 >  if (lvl < 1)
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-1);
274 >  }
275 >  glEnd();
276 >  glPopAttrib();
277   }
278  
279 < /*
280 < * smClean()            : display has been wiped clean
281 < *
282 < * Called after display has been effectively cleared, meaning that all
130 < * geometry must be resent down the pipeline in the next call to smUpdate().
131 < */
132 < smClean()
279 >
280 > smRender_stree(sm, qual)        /* render some quadtree triangles */
281 > SM *sm;
282 > int qual;
283   {
284 <  /* Mark all triangles in the frustum as active */
285 <    if(!smMesh || SM_NUM_TRIS(smMesh)==0)
286 <       return;
287 <    
288 < #ifdef TEST_DRIVER
289 <    smMark_tris_in_frustum(smMesh,&Current_View);
290 < #else
291 <    smMark_tris_in_frustum(smMesh,&(odev.v));
292 < #endif
293 <    smClean_notify = TRUE;
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 < smRender_tri(sm,i,vp)
312 > smRender_tri(sm,i,vp,clr)
313   SM *sm;
314   int i;
315   FVECT vp;
316 + int clr;
317   {
318    TRI *tri;
319    double ptr[3];
320    int j;
321  
322    tri = SM_NTH_TRI(sm,i);
323 <  SM_CLEAR_NTH_T_NEW(sm,i);
324 <  if(smNew_tri_cnt)
159 <     smNew_tri_cnt--;
160 <  /* NOTE:Triangles are defined clockwise:historical relative to spherical
161 <     tris: could change
162 <     */
163 <  for(j=2; j>= 0; j--)
323 >  if (clr) SM_CLR_NTH_T_NEW(sm,i);
324 >  for(j=0; j <= 2; j++)
325    {
326   #ifdef DEBUG
327      if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
# Line 174 | Line 335 | FVECT vp;
335    }
336   }
337  
338 < /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
178 < ADJACENT TRIANGLES TO BG be BG
179 < */
180 < smRender_bg_tri(sm,i,vp,d)
338 > smRender_mixed_tri(sm,i,vp,clr)
339   SM *sm;
340   int i;
341   FVECT vp;
342 < double d;
342 > int clr;
343   {
344    TRI *tri;
345 <  FVECT p;
345 >  double p[3],d;
346    int j,ids[3],cnt;
347    int rgb[3];
348  
191
349    tri = SM_NTH_TRI(sm,i);
350 <  SM_CLEAR_NTH_T_NEW(sm,i);
351 <  if(smNew_tri_cnt)
195 <     smNew_tri_cnt--;
350 >  if (clr) SM_CLR_NTH_T_NEW(sm,i);
351 >
352    /* NOTE:Triangles are defined clockwise:historical relative to spherical
353       tris: could change
354       */
355    cnt = 0;
356 +  d = 0.0;
357    rgb[0] = rgb[1] = rgb[2] = 0;
358 <  for(j=0;j<3;j++)
358 >  for(j=0;j < 3;j++)
359    {
360 <    ids[j] = T_NTH_V(tri,j);
361 <    if(SM_BG_SAMPLE(sm,ids[j]))
362 <    {
363 <      rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
364 <      rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
365 <      rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
366 <      cnt++;
367 <    }
360 >      ids[j] = T_NTH_V(tri,j);
361 >      if(!SM_BG_SAMPLE(sm,ids[j]))
362 >      {
363 >          rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
364 >          rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
365 >          rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
366 >          cnt++;
367 >          d += DIST(vp,SM_NTH_WV(sm,ids[j]));
368 >      }
369    }
370 <  if(cnt)
370 >  if(cnt > 1)
371    {
372      rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
373 +    d /= (double)cnt;
374    }
375 <  for(j=2; j>= 0; j--)
375 >  for(j=0; j <= 2; j++)
376    {
377      if(SM_BG_SAMPLE(sm,ids[j]))
378 <      glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
379 <                 SM_NTH_RGB(sm,ids[j])[2]);
378 >    {
379 >        glColor3ub(rgb[0],rgb[1],rgb[2]);
380 >        VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
381 >        p[0] *= d;
382 >        p[1] *= d;
383 >        p[2] *= d;
384 >        VADD(p,p,SM_VIEW_CENTER(sm));
385 >    }
386      else
222      glColor3ub(rgb[0],rgb[1],rgb[2]);
223    if(SM_BG_SAMPLE(sm,ids[j]))
224      VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
225    else
226      smDir(sm,p,ids[j]);
227    if(dev_zmin > 1.0)
387      {
388 <      p[0] *= d;
389 <      p[1] *= d;
390 <      p[2] *= d;
388 >        glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
389 >                   SM_NTH_RGB(sm,ids[j])[2]);
390 >        VCOPY(p,SM_NTH_WV(sm,ids[j]));
391      }
233    VADD(p,p,vp);
392      glVertex3d(p[0],p[1],p[2]);
393 +   }
394 + }
395 +
396 + smRender_bg_tri(sm,i,vp,d,clr)
397 + SM *sm;
398 + int i;
399 + FVECT vp;
400 + double d;
401 + int clr;
402 + {
403 +  double p[3];
404 +  int j,id;
405 +  TRI *tri;
406 +  
407 +  tri = SM_NTH_TRI(sm,i);
408 +  if (clr) SM_CLR_NTH_T_NEW(sm,i);
409 +
410 +  /* NOTE:Triangles are defined clockwise:historical relative to spherical
411 +     tris: could change
412 +     */
413 +  for(j=0; j <= 2; j++)
414 +  {
415 +      id = T_NTH_V(tri,j);
416 +      glColor3ub(SM_NTH_RGB(sm,id)[0],SM_NTH_RGB(sm,id)[1],
417 +                 SM_NTH_RGB(sm,id)[2]);
418 +      VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm));
419 +      if(dev_zmin >= 0.99)
420 +       {
421 +           p[0] *= d;
422 +           p[1] *= d;
423 +           p[2] *= d;
424 +       }
425 +      VADD(p,p,vp);
426 +      glVertex3d(p[0],p[1],p[2]);
427    }
428   }
429  
430 < smRender_mesh(sm,vp)
430 > smRender_mesh(sm,vp,clr)
431   SM *sm;
432   FVECT vp;
433 + int clr;
434   {
435    int i;
436    TRI *tri;
# Line 248 | Line 441 | FVECT vp;
441    glPushAttrib(GL_DEPTH_BUFFER_BIT);
442    
443    /* First draw background polygons */
251
444    glDisable(GL_DEPTH_TEST);
445    glBegin(GL_TRIANGLES);
446    SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
447 <    smRender_bg_tri(sm,i,vp,d);
447 >     smRender_bg_tri(sm,i,vp,d,clr);
448    glEnd();
257  
449    glEnable(GL_DEPTH_TEST);
450    glBegin(GL_TRIANGLES);
451    SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
452 <    smRender_tri(sm,i,vp);
452 >  {
453 >      if(!SM_MIXED_TRI(sm,i))
454 >        smRender_tri(sm,i,vp,clr);
455 >   else
456 >        smRender_mixed_tri(sm,i,vp,clr);
457 >  }
458    glEnd();
459  
460    glPopAttrib();
461   }
462 +
463   smRender_tri_edges(sm,i)
464   SM *sm;
465   int i;
# Line 274 | Line 471 | int i;
471  
472    tri = SM_NTH_TRI(sm,i);
473  
474 <  /* Triangles are defined clockwise:historical relative to spherical
278 <     tris: could change
279 <     */
280 <  for(j=2; j >=0; j--)
474 >  for(j=0; j <= 2; j++)
475    {
476      VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,j)));
477      glVertex3d(ptr[0],ptr[1],ptr[2]);
# Line 301 | Line 495 | compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
495    return(0);
496   }
497  
498 < smDepth_sort_tris(sm,vp,td)
498 > LIST
499 > *smDepth_sort_tris(sm,vp,td)
500   SM *sm;
501 < VIEW *vp;
501 > FVECT vp;
502   T_DEPTH *td;
503   {
504 <  int i,j,t_id;
504 >  int i,j,t_id,v;
505    TRI *tri;
506 <  double d[3];
506 >  double d,min_d;
507 >  LIST *tlist=NULL;
508  
509    i = 0;
510    SM_FOR_ALL_NEW_TRIS(sm,t_id)
511    {
512 <    if(i >= smNew_tri_cnt)
512 >    if(SM_BG_TRI(sm,t_id))
513      {
514 < #ifdef DEBUG
515 <        eputs("smDepth_sort_tris(): more new tris then counted\n");
320 < #endif
321 <        break;
514 >        tlist = push_data(tlist,t_id);
515 >        continue;
516      }
517      tri = SM_NTH_TRI(sm,t_id);
518 + #ifdef DEBUG
519 +    if(i >= smNew_tri_cnt)
520 +    {
521 +      eputs("smDepth_sort_tris():More tris than reported by smNew_tri_cnt\n");
522 +      break;
523 +    }
524 + #endif
525      td[i].tri = t_id;
526 +    min_d = -1;
527      for(j=0;j < 3;j++)
528 <      d[j] = DIST(vp->vp,SM_T_NTH_WV(sm,tri,j));
529 <    td[i].depth = MIN_VEC3(d);
528 >    {
529 >        v = T_NTH_V(tri,j);
530 >        if(!SM_BG_SAMPLE(sm,v))
531 >        {
532 >            d = DIST(vp,SM_NTH_WV(sm,v));
533 >            if(min_d == -1 || d < min_d)
534 >               min_d = d;
535 >        }
536 >    }
537 >    td[i].depth = min_d;
538      i++;
539    }
540 <  qsort((void *)td,smNew_tri_cnt,sizeof(T_DEPTH),compare_tri_depths);
540 >  td[i].tri = -1;
541 >  if(i)
542 >     qsort((void *)td,i,sizeof(T_DEPTH),compare_tri_depths);
543 >  return(tlist);
544   }
545  
546  
547 < smUpdate_Rendered_mesh(sm,vp)
547 > smUpdate_Rendered_mesh(sm,vp,clr)
548   SM *sm;
549 < VIEW *vp;
549 > FVECT vp;
550 > int clr;
551   {
552    static T_DEPTH *td= NULL;
553    static int tsize = 0;
554    int i;
555    GLint depth_test;
556    double d;
557 <
557 >  LIST *bglist;
558    /* For all of the NEW triangles (since last update): assume
559       ACTIVE. Go through and sort on depth value (from vp). Turn
560       Depth Buffer test off and render back-front
# Line 349 | Line 563 | VIEW *vp;
563    if(smNew_tri_cnt > tsize)
564    {
565      if(td)
566 <      free(td);
566 >      free((char *)td);
567      td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
568      tsize = smNew_tri_cnt;
569    }
# Line 357 | Line 571 | VIEW *vp;
571    {
572      error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
573    }
574 <  smDepth_sort_tris(sm,vp,td);
574 >  bglist = smDepth_sort_tris(sm,vp,td);
575  
576 <  /* Turn Depth Test off */
576 >  /* Turn Depth Test off -- using Painter's algorithm */
577    glPushAttrib(GL_DEPTH_BUFFER_BIT);
578 <  glDepthFunc(GL_ALWAYS);          /* Turn off Depth-painter's algorithm */
365 <
578 >  glDepthFunc(GL_ALWAYS);
579    d = (dev_zmin+dev_zmax)/2.0;
580    /* Now render back-to front */
581    /* First render bg triangles */
369  glDisable(GL_DEPTH_TEST);
582    glBegin(GL_TRIANGLES);
583 <  for(i=0; i< smNew_tri_cnt; i++)
584 <    if(SM_BG_TRI(sm,td[i].tri))
373 <      smRender_bg_tri(sm,td[i].tri,vp,d);
583 >  while(bglist)
584 >     smRender_bg_tri(sm,pop_list(&bglist),vp,d,clr);
585    glEnd();
586  
587 <  glEnable(GL_DEPTH_TEST);
587 >
588    glBegin(GL_TRIANGLES);
589 <  for(i=0; i< smNew_tri_cnt; i++)
590 <    if(!SM_BG_TRI(sm,td[i].tri))
591 <      smRender_tri(sm,td[i].tri,vp);
589 >  i=0;
590 >  while(td[i].tri != -1)
591 >     if(!SM_MIXED_TRI(sm,td[i].tri))
592 >        smRender_tri(sm,td[i++].tri,vp,clr);
593 >     else
594 >        smRender_mixed_tri(sm,td[i++].tri,vp,clr);
595    glEnd();
596  
597    /* Restore Depth Test */
# Line 385 | Line 599 | VIEW *vp;
599   }
600  
601   /*
602 < * smUpdate(vp, qua)    : update OpenGL output geometry for view vp
603 < * VIEW *vp;            : desired view
602 > * smUpdate(view, qua)  : update OpenGL output geometry for view vp
603 > * VIEW *view;          : desired view
604   * int  qual;           : quality level (percentage on linear time scale)
605   *
606   * Draw new geometric representation using OpenGL calls.  Assume that the
607   * view has already been set up and the correct frame buffer has been
608   * selected for drawing.  The quality level is on a linear scale, where 100%
609   * is full (final) quality.  It is not necessary to redraw geometry that has
610 < * been output since the last call to smClean().
610 > * been output since the last call to smClean().  (The last view drawn will
611 > * be view==&odev.v each time.)
612   */
613 < smUpdate(vp,qual)
614 <   VIEW *vp;
613 > smUpdate(view,qual)
614 >   VIEW *view;
615     int qual;
616   {
617    double d;
618 +  int last_update;
619    int t;
620 < #ifdef TEST_DRIVER  
405 <  Current_View = (*vp);
406 < #endif
620 >
621    /* If view has moved beyond epsilon from canonical: must rebuild -
622       epsilon is calculated as running avg of distance of sample points
623 <     from canonical view: m = 1/(SUM1/r): some fraction of this
623 >     from canonical view: m = 1/(AVG(1/r)): some fraction of this
624     */
625 <  d = DIST(vp->vp,SM_VIEW_CENTER(smMesh));
625 >
626 >  if(!smMesh)
627 >    return;
628 >
629 >
630 >
631 >  d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
632    if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
633    {
414      smNew_tri_cnt = 0;
634        /* Re-build the mesh */
635 <      smRebuild_mesh(smMesh,vp);
635 > #ifdef TEST_DRIVER
636 >    odev.v = *view;
637 > #endif  
638 >      mark_tris_in_frustum(view);
639 >      smRebuild_mesh(smMesh,view);
640    }
641 <  /* Check if should draw ALL triangles in current frustum */
642 <  if(smClean_notify || (smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT))
641 >  /* This is our final update iff qual==100 and view==&odev.v */
642 >  last_update = qual>=100 && view==&(odev.v);
643 >  /* Check if we should draw ALL triangles in current frustum */
644 >  if(smClean_notify || smNew_tri_cnt > SM_SAMPLE_TRIS(smMesh)*SM_INC_PERCENT)
645    {
646   #ifdef TEST_DRIVER
647      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
648   #else
649 <    tmClearHisto();
650 <    tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
651 <    if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
652 <       return;
653 <    if(tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
654 <                   SM_NUM_SAMP(smMesh))!=TM_E_OK)
655 <       return;
649 >    if ( SM_TONE_MAP(smMesh) < SM_NUM_SAMP(smMesh))
650 >    {
651 >       tmClearHisto();
652 >       tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
653 >       tmComputeMapping(0.,0.,0.);
654 >       tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
655 >                   SM_NUM_SAMP(smMesh));
656 >    }
657   #endif
658 <    smRender_mesh(smMesh,vp->vp);
659 <    smClean_notify = FALSE;
658 >    mark_tris_in_frustum(view);
659 >    if (qual <= 75)
660 >        smRender_stree(smMesh,qual);
661 >    else
662 >        smRender_mesh(smMesh,view->vp,last_update);
663   #ifdef TEST_DRIVER
664      glFlush();
665      glutSwapBuffers();
# Line 438 | Line 667 | smUpdate(vp,qual)
667    }
668    /* Do an incremental update instead */
669    else
670 <  {  
671 <    if(!smNew_tri_cnt)
670 >  {
671 >      if(!smNew_tri_cnt)
672        return;
673   #ifdef TEST_DRIVER
674      glDrawBuffer(GL_FRONT);
# Line 452 | Line 681 | smUpdate(vp,qual)
681          if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
682             return;
683      }
684 <    if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
685 <                   SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
686 <          return;
684 >    tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
685 >                   SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t);
686 >        
687   #endif    
688 <    smUpdate_Rendered_mesh(smMesh,vp);
688 >    smUpdate_Rendered_mesh(smMesh,view->vp,last_update);
689      
690   #ifdef TEST_DRIVER
691      glDrawBuffer(GL_BACK);
692   #endif
693    }
694 +
695    SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
466 }
696  
697 <    /* LATER:If quality < 100 should draw approximation because it indicates
698 <       the user is moving
699 <       */
697 >  if (last_update)
698 >  {
699 >    smClean_notify = FALSE;
700 >    smNew_tri_cnt = 0;
701 >    smClear_flags(smMesh,T_NEW_FLAG);
702 >    qtCache_init(0);
703 >  }
704  
705 <
705 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines