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.1 by gwlarson, Wed Aug 19 17:45:24 1998 UTC vs.
Revision 3.13 by gwlarson, Sun Jan 10 10:27:48 1999 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 < int
37 < mark_active_tris(qtptr,arg)
38 < QUADTREE *qtptr;
39 < char *arg;
37 < {
38 <  OBJECT os[MAXSET+1],*optr;
39 <  int i,t_id;
40 <  SM *sm;
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 <  sm = (SM *)arg;
46 > static QT_LUENT *qt_htbl = NULL;        /* quadtree cache */
47 > static int      qt_hsiz = 0;            /* quadtree cache size */
48  
45  /* For each triangle in the set, set the which flag*/
46  if(QT_IS_EMPTY(*qtptr))
47  {
48      return(FALSE);
49  }
50  else
51  {
52    qtgetset(os,*qtptr);
49  
50 <    for (i = QT_SET_CNT(os),optr = QT_SET_PTR(os); i > 0; i--)
51 <    {
52 <      t_id = QT_SET_NEXT_ELEM(optr);
53 <      /* Set the render flag */
54 <      if(SM_IS_NTH_T_BASE(sm,t_id))
55 <        continue;
56 <      SM_SET_NTH_T_ACTIVE(sm,t_id);
57 <      /* FOR NOW:Also set the LRU clock bit: MAY WANT TO CHANGE: */      
58 <      SM_SET_NTH_T_LRU(sm,t_id);
59 <    }
60 <  }
61 <  return(TRUE);
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 <
71 < smMark_tris_in_frustum(sm,vp)
72 < SM *sm;
71 < VIEW *vp;
70 > int
71 > qtCache_init(nel)               /* initialize for at least nel elements */
72 > int     nel;
73   {
74 <    FVECT nr[4],far[4];
74 >        static int  hsiztab[] = {
75 >                8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0
76 >        };
77 >        register int  i;
78  
79 <    /* Mark triangles in approx. view frustum as being active:set
80 <       LRU counter: for use in discarding samples when out
81 <       of space
82 <       Radiance often has no far clipping plane: but driver will set
83 <       dev_zmin,dev_zmax to satisfy OGL
84 <    */
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 <    /* First clear all the triangle active flags */
102 <    smClear_flags(sm,T_ACTIVE_FLAG);
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 <    /* calculate the world space coordinates of the view frustum */
110 <    calculate_view_frustum(vp->vp,vp->hvec,vp->vvec,vp->horiz,vp->vert,
111 <                           dev_zmin,dev_zmax,nr,far);
112 <
113 <    /* Project the view frustum onto the spherical quadtree */
114 <    /* For every cell intersected by the projection of the faces
115 <       of the frustum: mark all triangles in the cell as ACTIVE-
116 <       Also set the triangles LRU clock counter
117 <       */
118 <    /* Need to do tonemap call */
119 <    /* Near face triangles */
120 <    smLocator_apply_func(sm,nr[0],nr[2],nr[3],mark_active_tris,(char *)(sm));
121 <    smLocator_apply_func(sm,nr[2],nr[0],nr[1],mark_active_tris,(char *)(sm));
122 <    /* Right face triangles */
123 <    smLocator_apply_func(sm,nr[0],far[3],far[0],mark_active_tris,(char *)(sm));
124 <    smLocator_apply_func(sm,far[3],nr[0],nr[3],mark_active_tris,(char *)(sm));
125 <    /* Left face triangles */
126 <    smLocator_apply_func(sm,nr[1],far[2],nr[2],mark_active_tris,(char *)(sm));
127 <    smLocator_apply_func(sm,far[2],nr[1],far[1],mark_active_tris,(char *)(sm));
128 <    /* Top face triangles */
129 <    smLocator_apply_func(sm,nr[0],far[0],nr[1],mark_active_tris,(char *)(sm));
130 <    smLocator_apply_func(sm,nr[1],far[0],far[1],mark_active_tris,(char *)(sm));
131 <    /* Bottom face triangles */
132 <    smLocator_apply_func(sm,nr[3],nr[2],far[3],mark_active_tris,(char *)(sm));
133 <    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));
113 <
114 < #ifdef TEST_DRIVER
115 <    VCOPY(FrustumFar[0],far[0]);
116 <    VCOPY(FrustumFar[1],far[1]);
117 <    VCOPY(FrustumFar[2],far[2]);
118 <    VCOPY(FrustumFar[3],far[3]);
119 <    VCOPY(FrustumNear[0],nr[0]);
120 <    VCOPY(FrustumNear[1],nr[1]);
121 <    VCOPY(FrustumNear[2],nr[2]);
122 <    VCOPY(FrustumNear[3],nr[3]);
123 < #endif
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 < /*
137 < * smClean()            : display has been wiped clean
138 < *
129 < * 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()
136 > stCount_level_leaves(lcnt, qt)  /* count quadtree leaf nodes at each level */
137 > int lcnt[];
138 > register QUADTREE qt;
139   {
140 <  /* Mark all triangles in the frustum as active */
141 <    if(!smMesh || SM_NUM_TRIS(smMesh)==0)
142 <       return;
143 <    
144 < #ifdef TEST_DRIVER
145 <    smMark_tris_in_frustum(smMesh,&Current_View);
146 < #else
147 <    smMark_tris_in_frustum(smMesh,&(odev.v));
148 < #endif
149 <    smClean_notify = TRUE;
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 < smRender_tri(sm,i,vp)
156 > QTRAVG *
157 > qtRender_level(qt,v0,v1,v2,sm,lvl)
158 > QUADTREE qt;
159 > FVECT v0,v1,v2;
160   SM *sm;
161 < int i;
150 < FVECT vp;
161 > int lvl;
162   {
163 +  FVECT a,b,c;
164 +  register QT_LUENT *le;
165 +  QTRAVG *rc[4];
166    TRI *tri;
167 <  double ptr[3];
168 <  int j;
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 <  tri = SM_NTH_TRI(sm,i);
258 <  SM_CLEAR_NTH_T_NEW(sm,i);
259 <  if(smNew_tri_cnt)
260 <     smNew_tri_cnt--;
261 <  /* NOTE:Triangles are defined clockwise:historical relative to spherical
262 <     tris: could change
263 <     */
264 <  for(j=2; j>= 0; j--)
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 <    glColor3ub(SM_NTH_RGB(sm,T_NTH_V(tri,j))[0],
281 <               SM_NTH_RGB(sm,T_NTH_V(tri,j))[1],
282 <               SM_NTH_RGB(sm,T_NTH_V(tri,j))[2]);
168 <    VCOPY(ptr,SM_T_NTH_WV(sm,tri,j));
169 <    glVertex3d(ptr[0],ptr[1],ptr[2]);
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 < /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
289 < ADJACENT TRIANGLES TO BG be BG
175 < */
176 < smRender_bg_tri(sm,i,vp)
288 >
289 > smRender_stree(sm, qual)        /* render some quadtree triangles */
290   SM *sm;
291 < int i;
179 < FVECT vp;
291 > int qual;
292   {
293 <  TRI *tri;
294 <  FVECT p;
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 <  BYTE rgb[3];
341 >  int rgb[3];
342  
186  tri = SM_NTH_TRI(sm,i);
187  SM_CLEAR_NTH_T_NEW(sm,i);
188  if(smNew_tri_cnt)
189     smNew_tri_cnt--;
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 <  for(j=0;j<3;j++)
352 >
353 >  if(!bg0)
354    {
355 <    ids[j] = T_NTH_V(tri,j);
356 <    if(SM_BG_SAMPLE(sm,ids[j]))
357 <    {
358 <      rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
359 <      rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
202 <      rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
203 <      cnt++;
204 <    }
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(cnt)
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 <  for(j=2; j>= 0; j--)
382 >  if(bg0)
383    {
384 <    if(SM_BG_SAMPLE(sm,ids[j]))
385 <      glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
386 <                 SM_NTH_RGB(sm,ids[j])[2]);
387 <    else
388 <      glColor3ub(rgb[0],rgb[1],rgb[2]);
389 <    VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
390 <    VADD(p,p,vp);
219 <    glVertex3d(p[0],p[1],p[2]);
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;
478 >  int i,n,bg0,bg1,bg2;
479 >  double d;
480 >  int v0_id,v1_id,v2_id;
481    TRI *tri;
482 <  double ptr[3];
483 <  int j;
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 <  SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
495 <    smRender_bg_tri(sm,i,vp);
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 <  
510 >
511    glEnable(GL_DEPTH_TEST);
512    glBegin(GL_TRIANGLES);
513 <  SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
514 <    smRender_tri(sm,i,vp);
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   }
249 smRender_tri_edges(sm,i)
250 SM *sm;
251 int i;
252 {
253  TRI *tri;
254  int j;
255  double ptr[3];
536  
257
258  tri = SM_NTH_TRI(sm,i);
259
260  /* Triangles are defined clockwise:historical relative to spherical
261     tris: could change
262     */
263  for(j=2; j >=0; j--)
264  {
265    VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,j)));
266    glVertex3d(ptr[0],ptr[1],ptr[2]);
267    VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,(j+1)%3)));
268    glVertex3d(ptr[0],ptr[1],ptr[2]);
269  }
270 }
271
537   int
538   compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
539   {
# Line 282 | Line 547 | compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
547      return(-1);
548    
549    return(0);
550 +
551   }
552  
553 < smDepth_sort_tris(sm,vp,td)
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 < VIEW *vp;
595 > FVECT vp;
596   T_DEPTH *td;
597   {
598 <  int i,j,t_id;
598 >  int n,i,j,tcnt,v;
599    TRI *tri;
600 <  double d[3];
600 >  double d,min_d;
601 >  FVECT diff;
602 >  int4 *new_flag,*bg_flag;
603  
604 <  i = 0;
605 <  SM_FOR_ALL_NEW_TRIS(sm,t_id)
606 <  {
607 <    if(i >= smNew_tri_cnt)
608 <    {
609 < #ifdef DEBUG
610 <        eputs("smDepth_sort_tris(): more new tris then counted\n");
611 < #endif
612 <        break;
613 <    }
614 <    tri = SM_NTH_TRI(sm,t_id);
615 <    td[i].tri = t_id;
616 <    for(j=0;j < 3;j++)
617 <      d[j] = DIST(vp->vp,SM_T_NTH_WV(sm,tri,j));
618 <    td[i].depth = MIN_VEC3(d);
619 <    i++;
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 <  qsort((void *)td,smNew_tri_cnt,sizeof(T_DEPTH),compare_tri_depths);
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)
634 > smUpdate_Rendered_mesh(sm,vp,clr)
635   SM *sm;
636 < VIEW *vp;
636 > FVECT vp;
637 > int clr;
638   {
639 <  static T_DEPTH *td= NULL;
322 <  static int tsize = 0;
323 <  int i;
639 >  int i,n,v0_id,v1_id,v2_id,bg0,bg1,bg2;
640    GLint depth_test;
641 <
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 <  /* NOTE: could malloc each time or hard code */
331 <  if(smNew_tri_cnt > tsize)
651 >  if(!EQUAL_VEC3(SM_VIEW_CENTER(sm),vp))
652    {
653 <    if(td)
654 <      free(td);
655 <    td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
656 <    tsize = smNew_tri_cnt;
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 <  if(!td)
662 <  {
663 <    error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
341 <  }
342 <  smDepth_sort_tris(sm,vp,td);
343 <
344 <  /* Turn Depth Test off */
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);          /* Turn off Depth-painter's algorithm */
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 <  glDisable(GL_DEPTH_TEST);
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(i=0; i< smNew_tri_cnt; i++)
674 <    if(SM_BG_TRI(sm,td[i].tri))
675 <      smRender_bg_tri(sm,td[i].tri,vp);
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 <  glEnable(GL_DEPTH_TEST);
687 >
688    glBegin(GL_TRIANGLES);
689 <  for(i=0; i< smNew_tri_cnt; i++)
690 <    if(!SM_BG_TRI(sm,td[i].tri))
691 <      smRender_tri(sm,td[i].tri,vp);
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 */
# Line 366 | Line 745 | VIEW *vp;
745   }
746  
747   /*
748 < * smUpdate(vp, qua)    : update OpenGL output geometry for view vp
749 < * VIEW *vp;            : desired view
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().
756 > * been output since the last call to smClean().  (The last view drawn will
757 > * be view==&odev.v each time.)
758   */
759 < smUpdate(vp,qual)
760 <   VIEW *vp;
759 > smUpdate(view,qual)
760 >   VIEW *view;
761     int qual;
762   {
763    double d;
764 <  int t;
765 < #ifdef TEST_DRIVER  
766 <  Current_View = (*vp);
767 < #endif
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/(SUM1/r): some fraction of this
771 >     from canonical view: m = 1/(AVG(1/r)): some fraction of this
772     */
773 <  d = DIST(vp->vp,SM_VIEW_CENTER(smMesh));
774 <  if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
773 >  d = DIST(view->vp,SM_VIEW_CENTER(smMesh));
774 >  if(qual >= MAXQUALITY  && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
775    {
395      smNew_tri_cnt = 0;
776        /* Re-build the mesh */
777 <      smRebuild_mesh(smMesh,vp);
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 <  /* Check if should draw ALL triangles in current frustum */
785 <  if(smClean_notify || (smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT))
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 <    tmClearHisto();
793 <    tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
794 <    if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
795 <       return;
796 <    if(tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
797 <                   SM_NUM_SAMP(smMesh))!=TM_E_OK)
798 <       return;
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 <    smRender_mesh(smMesh,vp->vp);
803 <    smClean_notify = FALSE;
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();
# Line 419 | Line 811 | smUpdate(vp,qual)
811    }
812    /* Do an incremental update instead */
813    else
814 <  {  
815 <    if(!smNew_tri_cnt)
814 >  {
815 >      if(!smNew_tri_cnt)
816        return;
817   #ifdef TEST_DRIVER
818      glDrawBuffer(GL_FRONT);
# Line 433 | Line 825 | smUpdate(vp,qual)
825          if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
826             return;
827      }
828 <    if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
829 <                   SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
830 <          return;
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,vp);
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 <    /* LATER:If quality < 100 should draw approximation because it indicates
852 <       the user is moving
853 <       */
851 >
852 >
853 >
854 >
855 >
856  
857  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines