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.12 by gwlarson, Tue Jan 5 16:52:38 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);
63 <    }
64 <  }
65 <  return(TRUE);
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 <
62 < smMark_tris_in_frustum(sm,vp)
63 < SM *sm;
71 < VIEW *vp;
61 > int
62 > qtCache_init(nel)               /* initialize for at least nel elements */
63 > int     nel;
64   {
65 <    FVECT nr[4],far[4];
65 >        static int  hsiztab[] = {
66 >                8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0
67 >        };
68 >        register int  i;
69  
70 <    /* Mark triangles in approx. view frustum as being active:set
71 <       LRU counter: for use in discarding samples when out
72 <       of space
73 <       Radiance often has no far clipping plane: but driver will set
74 <       dev_zmin,dev_zmax to satisfy OGL
75 <    */
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 <    /* First clear all the triangle active flags */
93 <    smClear_flags(sm,T_ACTIVE_FLAG);
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 <    /* calculate the world space coordinates of the view frustum */
101 <    calculate_view_frustum(vp->vp,vp->hvec,vp->vvec,vp->horiz,vp->vert,
102 <                           dev_zmin,dev_zmax,nr,far);
103 <
104 <    /* Project the view frustum onto the spherical quadtree */
105 <    /* For every cell intersected by the projection of the faces
106 <       of the frustum: mark all triangles in the cell as ACTIVE-
107 <       Also set the triangles LRU clock counter
108 <       */
109 <    /* Need to do tonemap call */
110 <    /* Near face triangles */
111 <    smLocator_apply_func(sm,nr[0],nr[2],nr[3],mark_active_tris,(char *)(sm));
112 <    smLocator_apply_func(sm,nr[2],nr[0],nr[1],mark_active_tris,(char *)(sm));
113 <    /* Right face triangles */
114 <    smLocator_apply_func(sm,nr[0],far[3],far[0],mark_active_tris,(char *)(sm));
115 <    smLocator_apply_func(sm,far[3],nr[0],nr[3],mark_active_tris,(char *)(sm));
116 <    /* Left face triangles */
117 <    smLocator_apply_func(sm,nr[1],far[2],nr[2],mark_active_tris,(char *)(sm));
118 <    smLocator_apply_func(sm,far[2],nr[1],far[1],mark_active_tris,(char *)(sm));
119 <    /* Top face triangles */
120 <    smLocator_apply_func(sm,nr[0],far[0],nr[1],mark_active_tris,(char *)(sm));
121 <    smLocator_apply_func(sm,nr[1],far[0],far[1],mark_active_tris,(char *)(sm));
122 <    /* Bottom face triangles */
123 <    smLocator_apply_func(sm,nr[3],nr[2],far[3],mark_active_tris,(char *)(sm));
124 <    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
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 < /*
128 < * smClean()            : display has been wiped clean
129 < *
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()
127 > stCount_level_leaves(lcnt, qt)  /* count quadtree leaf nodes at each level */
128 > int lcnt[];
129 > register QUADTREE qt;
130   {
131 <  /* Mark all triangles in the frustum as active */
132 <    if(!smMesh || SM_NUM_TRIS(smMesh)==0)
133 <       return;
134 <    
135 < #ifdef TEST_DRIVER
136 <    smMark_tris_in_frustum(smMesh,&Current_View);
137 < #else
138 <    smMark_tris_in_frustum(smMesh,&(odev.v));
139 < #endif
140 <    smClean_notify = TRUE;
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 < smRender_tri(sm,i,vp)
147 > QTRAVG *
148 > qtRender_level(qt,v0,v1,v2,sm,lvl)
149 > QUADTREE qt;
150 > FVECT v0,v1,v2;
151   SM *sm;
152 < int i;
150 < FVECT vp;
152 > int lvl;
153   {
154 +  FVECT a,b,c;
155 +  register QT_LUENT *le;
156 +  QTRAVG *rc[4];
157    TRI *tri;
158 <  double ptr[3];
159 <  int j;
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 <  tri = SM_NTH_TRI(sm,i);
249 <  SM_CLEAR_NTH_T_NEW(sm,i);
250 <  if(smNew_tri_cnt)
251 <     smNew_tri_cnt--;
252 <  /* NOTE:Triangles are defined clockwise:historical relative to spherical
253 <     tris: could change
254 <     */
255 <  for(j=2; j>= 0; j--)
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 < #ifdef DEBUG
272 <    if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
273 <      eputs("SmRenderTri(): shouldnt have bg samples\n");
168 < #endif
169 <    glColor3ub(SM_NTH_RGB(sm,T_NTH_V(tri,j))[0],
170 <               SM_NTH_RGB(sm,T_NTH_V(tri,j))[1],
171 <               SM_NTH_RGB(sm,T_NTH_V(tri,j))[2]);
172 <    VCOPY(ptr,SM_T_NTH_WV(sm,tri,j));
173 <    glVertex3d(ptr[0],ptr[1],ptr[2]);
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 < /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
280 < ADJACENT TRIANGLES TO BG be BG
179 < */
180 < smRender_bg_tri(sm,i,vp,d)
279 >
280 > smRender_stree(sm, qual)        /* render some quadtree triangles */
281   SM *sm;
282 < int i;
183 < FVECT vp;
184 < double d;
282 > int qual;
283   {
284 <  TRI *tri;
285 <  FVECT p;
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  
191
192  tri = SM_NTH_TRI(sm,i);
193  SM_CLEAR_NTH_T_NEW(sm,i);
194  if(smNew_tri_cnt)
195     smNew_tri_cnt--;
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 <  for(j=0;j<3;j++)
334 >
335 >  if(bg0 && bg1 && bg2)
336 >    return;
337 >
338 >  if(!bg0)
339    {
340 <    ids[j] = T_NTH_V(tri,j);
341 <    if(SM_BG_SAMPLE(sm,ids[j]))
342 <    {
343 <      rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
344 <      rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
208 <      rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
209 <      cnt++;
210 <    }
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(cnt)
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 <  for(j=2; j>= 0; j--)
367 >  if(bg0)
368    {
369 <    if(SM_BG_SAMPLE(sm,ids[j]))
370 <      glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
371 <                 SM_NTH_RGB(sm,ids[j])[2]);
372 <    else
373 <      glColor3ub(rgb[0],rgb[1],rgb[2]);
374 <    if(SM_BG_SAMPLE(sm,ids[j]))
375 <      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)
228 <    {
229 <      p[0] *= d;
230 <      p[1] *= d;
231 <      p[2] *= d;
232 <    }
233 <    VADD(p,p,vp);
234 <    glVertex3d(p[0],p[1],p[2]);
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 < smRender_mesh(sm,vp)
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;
464 >  int i,bg0,bg1,bg2;
465 >  double d;
466 >  int v0_id,v1_id,v2_id;
467    TRI *tri;
468 <  double ptr[3],d;
469 <  int j;
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 */
251
477    glDisable(GL_DEPTH_TEST);
478    glBegin(GL_TRIANGLES);
479 +  /* Maintain a list? */
480    SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
481 <    smRender_bg_tri(sm,i,vp,d);
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();
257  
492    glEnable(GL_DEPTH_TEST);
493    glBegin(GL_TRIANGLES);
494    SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
495 <    smRender_tri(sm,i,vp);
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 < smRender_tri_edges(sm,i)
517 < SM *sm;
518 < int i;
516 >
517 > int
518 > compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
519   {
520 <  TRI *tri;
271 <  int j;
272 <  double ptr[3];
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 <  tri = SM_NTH_TRI(sm,i);
533 <
534 <  /* Triangles are defined clockwise:historical relative to spherical
535 <     tris: could change
536 <     */
537 <  for(j=2; j >=0; j--)
538 <  {
539 <    VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,j)));
283 <    glVertex3d(ptr[0],ptr[1],ptr[2]);
284 <    VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,(j+1)%3)));
285 <    glVertex3d(ptr[0],ptr[1],ptr[2]);
286 <  }
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(T_DEPTH *td1,T_DEPTH *td2)
543 > compare_tri_depths_old(T_DEPTH *td1,T_DEPTH *td2)
544   {
545    double d;
546  
# Line 301 | Line 554 | compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
554    return(0);
555   }
556  
557 < smDepth_sort_tris(sm,vp,td)
557 > LIST
558 > *smDepth_sort_tris(sm,vp,td)
559   SM *sm;
560 < VIEW *vp;
560 > FVECT vp;
561   T_DEPTH *td;
562   {
563 <  int i,j,t_id;
563 >  int i,j,t_id,v;
564    TRI *tri;
565 <  double d[3];
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(i >= smNew_tri_cnt)
572 >    if(SM_BG_TRI(sm,t_id))
573      {
574 < #ifdef DEBUG
575 <        eputs("smDepth_sort_tris(): more new tris then counted\n");
320 < #endif
321 <        break;
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 <      d[j] = DIST(vp->vp,SM_T_NTH_WV(sm,tri,j));
582 <    td[i].depth = MIN_VEC3(d);
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)
655 > smUpdate_Rendered_mesh(sm,vp,clr)
656   SM *sm;
657 < VIEW *vp;
657 > FVECT vp;
658 > int clr;
659   {
660    static T_DEPTH *td= NULL;
661    static int tsize = 0;
662 <  int i;
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(td);
679 >      free((char *)td);
680      td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
681      tsize = smNew_tri_cnt;
682    }
# Line 357 | Line 684 | VIEW *vp;
684    {
685      error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
686    }
687 <  smDepth_sort_tris(sm,vp,td);
688 <
689 <  /* Turn Depth Test off */
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);          /* Turn off Depth-painter's algorithm */
365 <
699 >  glDepthFunc(GL_ALWAYS);
700    d = (dev_zmin+dev_zmax)/2.0;
701    /* Now render back-to front */
702    /* First render bg triangles */
369  glDisable(GL_DEPTH_TEST);
703    glBegin(GL_TRIANGLES);
704 <  for(i=0; i< smNew_tri_cnt; i++)
705 <    if(SM_BG_TRI(sm,td[i].tri))
706 <      smRender_bg_tri(sm,td[i].tri,vp,d);
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 <  glEnable(GL_DEPTH_TEST);
718 >
719    glBegin(GL_TRIANGLES);
720 <  for(i=0; i< smNew_tri_cnt; i++)
721 <    if(!SM_BG_TRI(sm,td[i].tri))
722 <      smRender_tri(sm,td[i].tri,vp);
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 */
# Line 385 | Line 749 | VIEW *vp;
749   }
750  
751   /*
752 < * smUpdate(vp, qua)    : update OpenGL output geometry for view vp
753 < * VIEW *vp;            : desired view
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().
760 > * been output since the last call to smClean().  (The last view drawn will
761 > * be view==&odev.v each time.)
762   */
763 < smUpdate(vp,qual)
764 <   VIEW *vp;
763 > smUpdate(view,qual)
764 >   VIEW *view;
765     int qual;
766   {
767    double d;
768 +  int last_update;
769    int t;
770 < #ifdef TEST_DRIVER  
405 <  Current_View = (*vp);
406 < #endif
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/(SUM1/r): some fraction of this
773 >     from canonical view: m = 1/(AVG(1/r)): some fraction of this
774     */
775 <  d = DIST(vp->vp,SM_VIEW_CENTER(smMesh));
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    {
414      smNew_tri_cnt = 0;
782        /* Re-build the mesh */
783 <      smRebuild_mesh(smMesh,vp);
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 <  /* Check if should draw ALL triangles in current frustum */
791 <  if(smClean_notify || (smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT))
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 <    tmClearHisto();
799 <    tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
800 <    if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
801 <       return;
802 <    if(tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
803 <                   SM_NUM_SAMP(smMesh))!=TM_E_OK)
804 <       return;
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 <    smRender_mesh(smMesh,vp->vp);
808 <    smClean_notify = FALSE;
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();
# Line 438 | Line 816 | smUpdate(vp,qual)
816    }
817    /* Do an incremental update instead */
818    else
819 <  {  
820 <    if(!smNew_tri_cnt)
819 >  {
820 >      if(!smNew_tri_cnt)
821        return;
822   #ifdef TEST_DRIVER
823      glDrawBuffer(GL_FRONT);
# Line 452 | Line 830 | smUpdate(vp,qual)
830          if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
831             return;
832      }
833 <    if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
834 <                   SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
835 <          return;
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,vp);
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);
466 }
845  
846 <    /* LATER:If quality < 100 should draw approximation because it indicates
847 <       the user is moving
848 <       */
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 <
856 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines