--- ray/src/hd/sm_ogl.c 1998/09/16 18:16:29 3.7 +++ ray/src/hd/sm_ogl.c 1999/01/10 10:27:48 3.13 @@ -16,8 +16,11 @@ static char SCCSid[] = "$SunId$ SGI"; #include #include #endif +#include "sm_flag.h" #include "sm_list.h" #include "sm_geom.h" +#include "sm_qtree.h" +#include "sm_stree.h" #include "sm.h" #ifdef TEST_DRIVER @@ -44,143 +47,24 @@ static QT_LUENT *qt_htbl = NULL; /* quadtree cache */ static int qt_hsiz = 0; /* quadtree cache size */ -int -mark_active_tris(qtptr,fptr,arg1,arg2) -QUADTREE *qtptr; -int *fptr,arg1,*arg2; -{ - QUADTREE qt = *qtptr; - OBJECT *os,*optr; - register int i,t_id; +typedef struct _T_DEPTH { + int tri; + double depth; +}T_DEPTH; - if (!QT_IS_LEAF(qt)) - return(TRUE); - - if(!QT_FLAG_FILL_TRI(*fptr)) - (*fptr)++; - /* For each triangle in the set, set the which flag*/ - os = qtqueryset(qt); - - for (i = QT_SET_CNT(os), optr = QT_SET_PTR(os); i > 0; i--) - { - t_id = QT_SET_NEXT_ELEM(optr); - /* Set the render flag */ - if(SM_IS_NTH_T_BASE(smMesh,t_id)) - continue; - SM_SET_NTH_T_ACTIVE(smMesh,t_id); - /* NOTE:Also set the LRU clock bit: MAY WANT TO CHANGE: */ - SM_SET_NTH_T_LRU(smMesh,t_id); - } - return(TRUE); -} - -int -mark_active_interior(qtptr,q0,q1,q2,t0,t1,t2,n,arg1,arg2,arg3) -QUADTREE *qtptr; -FVECT q0,q1,q2; -FVECT t0,t1,t2; -int n; -int *arg1,arg2,*arg3; + /* + * smClean(tmflag) : display has been wiped clean + * int tmflag; + * Called after display has been effectively cleared, meaning that all + * geometry must be resent down the pipeline in the next call to smUpdate(). + * If tmflag is set, tone-mapping should be performed + */ +smClean(tmflag) + int tmflag; { - QUADTREE qt = *qtptr; - OBJECT *os,*optr; - register int i,t_id; - - if (!QT_IS_LEAF(qt)) - return(TRUE); - /* For each triangle in the set, set the which flag*/ - os = qtqueryset(qt); - - for (i = QT_SET_CNT(os), optr = QT_SET_PTR(os); i > 0; i--) - { - t_id = QT_SET_NEXT_ELEM(optr); - /* Set the render flag */ - if(SM_IS_NTH_T_BASE(smMesh,t_id)) - continue; - SM_SET_NTH_T_ACTIVE(smMesh,t_id); - /* NOTE:Also set the LRU clock bit: MAY WANT TO CHANGE: */ - SM_SET_NTH_T_LRU(smMesh,t_id); - } - return(TRUE); -} - -mark_tris_in_frustum(view) -VIEW *view; -{ - FVECT nr[4],far[4]; - - /* Mark triangles in approx. view frustum as being active:set - LRU counter: for use in discarding samples when out - of space - Radiance often has no far clipping plane: but driver will set - dev_zmin,dev_zmax to satisfy OGL - */ - - /* First clear all the quadtree node and triangle active flags */ - qtClearAllFlags(); - smClear_flags(smMesh,T_ACTIVE_FLAG); - - /* calculate the world space coordinates of the view frustum */ - calculate_view_frustum(view->vp,view->hvec,view->vvec,view->horiz, - view->vert, dev_zmin,dev_zmax,nr,far); - - /* Project the view frustum onto the spherical quadtree */ - /* For every cell intersected by the projection of the faces - of the frustum: mark all triangles in the cell as ACTIVE- - Also set the triangles LRU clock counter - */ - /* Near face triangles */ - smLocator_apply_func(smMesh,nr[0],nr[2],nr[3],mark_active_tris, - mark_active_interior,NULL,NULL); - smLocator_apply_func(smMesh,nr[2],nr[0],nr[1],mark_active_tris, - mark_active_interior,NULL,NULL); - /* Right face triangles */ - smLocator_apply_func(smMesh,nr[0],far[3],far[0],mark_active_tris, - mark_active_interior,NULL,NULL); - smLocator_apply_func(smMesh,far[3],nr[0],nr[3],mark_active_tris, - mark_active_interior,NULL,NULL); - /* Left face triangles */ - smLocator_apply_func(smMesh,nr[1],far[2],nr[2],mark_active_tris, - mark_active_interior,NULL,NULL); - smLocator_apply_func(smMesh,far[2],nr[1],far[1],mark_active_tris, - mark_active_interior,NULL,NULL); - /* Top face triangles */ - smLocator_apply_func(smMesh,nr[0],far[0],nr[1],mark_active_tris, - mark_active_interior,NULL,NULL); - smLocator_apply_func(smMesh,nr[1],far[0],far[1],mark_active_tris, - mark_active_interior,NULL,NULL); - /* Bottom face triangles */ - smLocator_apply_func(smMesh,nr[3],nr[2],far[3],mark_active_tris, - mark_active_interior,NULL,NULL); - smLocator_apply_func(smMesh,nr[2],far[2],far[3],mark_active_tris, - mark_active_interior,NULL,NULL); - /* Far face triangles */ - smLocator_apply_func(smMesh,far[0],far[2],far[1],mark_active_tris, - mark_active_interior,NULL,NULL); - - smLocator_apply_func(smMesh,far[2],far[0],far[3],mark_active_tris, - mark_active_interior,NULL,NULL); -#ifdef TEST_DRIVER - VCOPY(FrustumFar[0],far[0]); - VCOPY(FrustumFar[1],far[1]); - VCOPY(FrustumFar[2],far[2]); - VCOPY(FrustumFar[3],far[3]); - VCOPY(FrustumNear[0],nr[0]); - VCOPY(FrustumNear[1],nr[1]); - VCOPY(FrustumNear[2],nr[2]); - VCOPY(FrustumNear[3],nr[3]); -#endif -} - -/* - * smClean() : display has been wiped clean - * - * Called after display has been effectively cleared, meaning that all - * geometry must be resent down the pipeline in the next call to smUpdate(). - */ -smClean() -{ smClean_notify = TRUE; + if(tmflag) + SM_TONE_MAP(smMesh) = 0; } int @@ -264,7 +148,8 @@ register QUADTREE qt; stCount_level_leaves(lcnt+1, QT_NTH_CHILD(qt,3)); } else - lcnt[0]++; + if(QT_LEAF_IS_FLAG(qt)) + lcnt[0]++; } @@ -284,16 +169,18 @@ int lvl; return(NULL); if (QT_IS_TREE(qt) && !QT_IS_FLAG(qt)) /* not in our frustum */ return(NULL); + if(QT_IS_LEAF(qt) && !QT_LEAF_IS_FLAG(qt)) /* not in our frustum */ + return(NULL); /* else look up node */ if ((le = qtCache_find(qt)) == NULL) error(SYSTEM, "out of memory in qtRender_level"); if (QT_IS_TREE(qt) && (QT_IS_EMPTY(le->qt) || lvl > 0)) { /* compute children */ qtSubdivide_tri(v0,v1,v2,a,b,c); - rc[0] = qtRender_level(QT_NTH_CHILD(qt,0),v0,a,c,sm,lvl-1); - rc[1] = qtRender_level(QT_NTH_CHILD(qt,1),a,v1,b,sm,lvl-1); - rc[2] = qtRender_level(QT_NTH_CHILD(qt,2),c,b,v2,sm,lvl-1); - rc[3] = qtRender_level(QT_NTH_CHILD(qt,3),b,c,a,sm,lvl-1); + rc[0] = qtRender_level(QT_NTH_CHILD(qt,0),v0,c,b,sm,lvl-1); + rc[1] = qtRender_level(QT_NTH_CHILD(qt,1),c,v1,a,sm,lvl-1); + rc[2] = qtRender_level(QT_NTH_CHILD(qt,2),b,a,v2,sm,lvl-1); + rc[3] = qtRender_level(QT_NTH_CHILD(qt,3),a,b,c,sm,lvl-1); } if (QT_IS_EMPTY(le->qt)) { /* let's make some data! */ @@ -316,11 +203,16 @@ int lvl; { /* from triangle set */ OBJECT *os; int s0, s1, s2; - + os = qtqueryset(qt); - for (n = os[0]; n; n--) + for (i = os[0]; i; i--) { - tri = SM_NTH_TRI(sm,os[n]); + if(SM_IS_NTH_T_BASE(sm,os[i])) + continue; + tri = SM_NTH_TRI(sm,os[i]); + if(!T_IS_VALID(tri)) + continue; + n++; s0 = T_NTH_V(tri,0); s1 = T_NTH_V(tri,1); s2 = T_NTH_V(tri,2); @@ -340,7 +232,7 @@ int lvl; rgbs[2] += SM_NTH_RGB(sm,s0)[2] + SM_NTH_RGB(sm,s1)[2] + SM_NTH_RGB(sm,s2)[2]; } - n = 3*os[0]; + n *= 3; } if (!n) return(NULL); @@ -358,10 +250,10 @@ int lvl; VSUM(c,SM_VIEW_CENTER(sm),c,le->av.dist); /* draw triangle */ glColor3ub(le->av.rgb[0],le->av.rgb[1],le->av.rgb[2]); - /* NOTE: Triangle vertex order may change */ - glVertex3d(c[0],c[1],c[2]); - glVertex3d(b[0],b[1],b[2]); glVertex3d(a[0],a[1],a[2]); + glVertex3d(b[0],b[1],b[2]); + glVertex3d(c[0],c[1],c[2]); + } return(&le->av); } @@ -371,20 +263,23 @@ smRender_stree_level(sm,lvl) SM *sm; int lvl; { - QUADTREE root; + QUADTREE qt; int i; FVECT t0,t1,t2; + STREE *st; - if (lvl < 1) + + if (lvl < 0) return; + st = SM_LOCATOR(sm); glPushAttrib(GL_LIGHTING_BIT); glShadeModel(GL_FLAT); glBegin(GL_TRIANGLES); - for(i=0; i < 4; i++) + for(i=0; i < ST_NUM_ROOT_NODES; i++) { - root = ST_NTH_ROOT(SM_LOCATOR(sm),i); - stNth_base_verts(SM_LOCATOR(sm),i,t0,t1,t2); - qtRender_level(root,t0,t1,t2,sm,lvl-1); + qt = ST_ROOT_QT(st,i); + qtRender_level(qt,ST_NTH_V(st,i,0),ST_NTH_V(st,i,1),ST_NTH_V(st,i,2), + sm,lvl); } glEnd(); glPopAttrib(); @@ -395,21 +290,32 @@ smRender_stree(sm, qual) /* render some quadtree trian SM *sm; int qual; { - int i, ntarget; + int i, n,ntarget; int lvlcnt[QT_MAX_LEVELS]; - + STREE *st; + int4 *active_flag; if (qual <= 0) return; /* compute rendering target */ ntarget = 0; - SM_FOR_ALL_ACTIVE_TRIS(sm,i) - ntarget++; - ntarget = ntarget*qual/100; + + active_flag = SM_NTH_FLAGS(sm,T_ACTIVE_FLAG); + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(active_flag[n]) + for(i=0; i < 32; i++) + if(active_flag[n] & (1L << i)) + ntarget++; + + ntarget = ntarget*qual/MAXQUALITY; if (!ntarget) return; for (i = QT_MAX_LEVELS; i--; ) lvlcnt[i] = 0; - stCount_level_leaves(lvlcnt, SM_LOCATOR(sm)->root); + + st = SM_LOCATOR(sm); + for(i=0; i < ST_NUM_ROOT_NODES;i++) + stCount_level_leaves(lvlcnt, ST_ROOT_QT(st,i)); + for (ntarget -= lvlcnt[i=0]; i < QT_MAX_LEVELS-1; ntarget -= lvlcnt[++i]) if (ntarget < lvlcnt[i+1]) break; @@ -418,186 +324,216 @@ int qual; } -smRender_tri(sm,i,vp,clr) -SM *sm; -int i; -FVECT vp; -int clr; -{ - TRI *tri; - double ptr[3]; - int j; - tri = SM_NTH_TRI(sm,i); - if (clr) SM_CLEAR_NTH_T_NEW(sm,i); +#define render_tri(v0,v1,v2,rgb0,rgb1,rgb2) \ + {glColor3ub(rgb0[0],rgb0[1],rgb0[2]); glVertex3fv(v0); \ + glColor3ub(rgb1[0],rgb1[1],rgb1[2]); glVertex3fv(v1); \ + glColor3ub(rgb2[0],rgb2[1],rgb2[2]); glVertex3fv(v2);} \ - /* NOTE:Triangles are defined clockwise:historical relative to spherical - tris: could change - */ - for(j=2; j>= 0; j--) - { -#ifdef DEBUG - if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j))) - eputs("SmRenderTri(): shouldnt have bg samples\n"); -#endif - glColor3ub(SM_NTH_RGB(sm,T_NTH_V(tri,j))[0], - SM_NTH_RGB(sm,T_NTH_V(tri,j))[1], - SM_NTH_RGB(sm,T_NTH_V(tri,j))[2]); - VCOPY(ptr,SM_T_NTH_WV(sm,tri,j)); - glVertex3d(ptr[0],ptr[1],ptr[2]); - } -} - -smRender_mixed_tri(sm,i,vp,clr) -SM *sm; -int i; -FVECT vp; -int clr; +render_mixed_tri(v0,v1,v2,rgb0,rgb1,rgb2,bg0,bg1,bg2,vp,vc) +float v0[3],v1[3],v2[3]; +BYTE rgb0[3],rgb1[3],rgb2[3]; +int bg0,bg1,bg2; +FVECT vp,vc; { - TRI *tri; double p[3],d; int j,ids[3],cnt; int rgb[3]; - tri = SM_NTH_TRI(sm,i); - if (clr) SM_CLEAR_NTH_T_NEW(sm,i); - /* NOTE:Triangles are defined clockwise:historical relative to spherical tris: could change */ + if(bg0 && bg1 && bg2) + return; + cnt = 0; d = 0.0; rgb[0] = rgb[1] = rgb[2] = 0; - for(j=0;j < 3;j++) + + if(!bg0) { - ids[j] = T_NTH_V(tri,j); - if(!SM_BG_SAMPLE(sm,ids[j])) - { - rgb[0] += SM_NTH_RGB(sm,ids[j])[0]; - rgb[1] += SM_NTH_RGB(sm,ids[j])[1]; - rgb[2] += SM_NTH_RGB(sm,ids[j])[2]; - cnt++; - d += DIST(vp,SM_NTH_WV(sm,ids[j])); - } + rgb[0] += rgb0[0]; + rgb[1] += rgb0[1]; + rgb[2] += rgb0[2]; + cnt++; + d += DIST(vp,v0); } + if(!bg1) + { + rgb[0] += rgb1[0]; + rgb[1] += rgb1[1]; + rgb[2] += rgb1[2]; + cnt++; + d += DIST(vp,v1); + } + if(!bg2) + { + rgb[0] += rgb2[0]; + rgb[1] += rgb2[1]; + rgb[2] += rgb2[2]; + cnt++; + d += DIST(vp,v2); + } if(cnt > 1) { rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt; d /= (double)cnt; } - for(j=2; j>= 0; j--) + if(bg0) { - if(SM_BG_SAMPLE(sm,ids[j])) - { - glColor3ub(rgb[0],rgb[1],rgb[2]); - VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm)); - p[0] *= d; - p[1] *= d; - p[2] *= d; - VADD(p,p,SM_VIEW_CENTER(sm)); - } - else - { - glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1], - SM_NTH_RGB(sm,ids[j])[2]); - VCOPY(p,SM_NTH_WV(sm,ids[j])); - } - glVertex3d(p[0],p[1],p[2]); + glColor3ub(rgb[0],rgb[1],rgb[2]); + VSUB(p,v0,vc); + p[0] *= d; + p[1] *= d; + p[2] *= d; + VADD(p,p,vc); + glVertex3dv(p); + } + else + { + glColor3ub(rgb0[0],rgb0[1],rgb0[2]); + glVertex3fv(v0); } + if(bg1) + { + glColor3ub(rgb[0],rgb[1],rgb[2]); + VSUB(p,v1,vc); + p[0] *= d; + p[1] *= d; + p[2] *= d; + VADD(p,p,vc); + glVertex3dv(p); + } + else + { + glColor3ub(rgb1[0],rgb1[1],rgb1[2]); + glVertex3fv(v1); + } + if(bg2) + { + glColor3ub(rgb[0],rgb[1],rgb[2]); + VSUB(p,v2,vc); + p[0] *= d; + p[1] *= d; + p[2] *= d; + VADD(p,p,vc); + glVertex3dv(p); + } + else + { + glColor3ub(rgb2[0],rgb2[1],rgb2[2]); + glVertex3fv(v2); + } + } -smRender_bg_tri(sm,i,vp,d,clr) -SM *sm; -int i; -FVECT vp; +render_bg_tri(v0,v1,v2,rgb0,rgb1,rgb2,vp,vc,d) +float v0[3],v1[3],v2[3]; +BYTE rgb0[3],rgb1[3],rgb2[3]; +FVECT vp,vc; double d; -int clr; { double p[3]; - int j,id; - TRI *tri; - tri = SM_NTH_TRI(sm,i); - if (clr) SM_CLEAR_NTH_T_NEW(sm,i); + glColor3ub(rgb0[0],rgb0[1],rgb0[2]); + VSUB(p,v0,vc); + if(dev_zmin >= 0.99) + { + p[0] *= d; + p[1] *= d; + p[2] *= d; + } + VADD(p,p,vp); + glVertex3dv(p); - /* NOTE:Triangles are defined clockwise:historical relative to spherical - tris: could change - */ - for(j=2; j>= 0; j--) + glColor3ub(rgb1[0],rgb1[1],rgb1[2]); + VSUB(p,v1,vc); + if(dev_zmin >= 0.99) { - id = T_NTH_V(tri,j); - glColor3ub(SM_NTH_RGB(sm,id)[0],SM_NTH_RGB(sm,id)[1], - SM_NTH_RGB(sm,id)[2]); - VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm)); - if(dev_zmin >= 0.99) - { - p[0] *= d; - p[1] *= d; - p[2] *= d; - } - VADD(p,p,vp); - glVertex3d(p[0],p[1],p[2]); + p[0] *= d; + p[1] *= d; + p[2] *= d; } + VADD(p,p,vp); + glVertex3dv(p); + + + glColor3ub(rgb2[0],rgb2[1],rgb2[2]); + VSUB(p,v2,vc); + if(dev_zmin >= 0.99) + { + p[0] *= d; + p[1] *= d; + p[2] *= d; + } + VADD(p,p,vp); + glVertex3dv(p); + } -smRender_mesh(sm,vp,clr) +smRender_mesh(sm,vp) SM *sm; FVECT vp; -int clr; { - int i; + int i,n,bg0,bg1,bg2; + double d; + int v0_id,v1_id,v2_id; TRI *tri; - double ptr[3],d; - int j; + float (*wp)[3]; + BYTE (*rgb)[3]; + int4 *active_flag,*bg_flag; + wp = SM_WP(sm); + rgb =SM_RGB(sm); d = (dev_zmin+dev_zmax)/2.0; glPushAttrib(GL_DEPTH_BUFFER_BIT); /* First draw background polygons */ - glDisable(GL_DEPTH_TEST); glBegin(GL_TRIANGLES); - SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i) - smRender_bg_tri(sm,i,vp,d,clr); + + active_flag = SM_NTH_FLAGS(sm,T_ACTIVE_FLAG); + bg_flag = SM_NTH_FLAGS(sm,T_BG_FLAG); + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(active_flag[n] & bg_flag[n]) + for(i=0; i < 32; i++) + if(active_flag[n] & bg_flag[n] & (1L << i)) + { + tri = SM_NTH_TRI(sm,(n<<5)+i); + v0_id = T_NTH_V(tri,0); + v1_id = T_NTH_V(tri,1); + v2_id = T_NTH_V(tri,2); + render_bg_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], + rgb[v2_id],vp,SM_VIEW_CENTER(sm),d); + } glEnd(); - + glEnable(GL_DEPTH_TEST); glBegin(GL_TRIANGLES); - SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i) - { - if(!SM_MIXED_TRI(sm,i)) - smRender_tri(sm,i,vp,clr); - else - smRender_mixed_tri(sm,i,vp,clr); - } + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(active_flag[n]) + for(i=0; i < 32; i++) + if((active_flag[n] & (1L << i)) && !(bg_flag[n] & (1L << i))) + { + tri = SM_NTH_TRI(sm,(n<<5)+i); + v0_id = T_NTH_V(tri,0); + v1_id = T_NTH_V(tri,1); + v2_id = T_NTH_V(tri,2); + bg0 = SM_DIR_ID(sm,v0_id) || SM_BASE_ID(sm,v0_id); + bg1 = SM_DIR_ID(sm,v1_id) || SM_BASE_ID(sm,v1_id); + bg2 = SM_DIR_ID(sm,v2_id) || SM_BASE_ID(sm,v2_id); + if(!(bg0 || bg1 || bg2)) + render_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], + rgb[v2_id]) + else + render_mixed_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id], + rgb[v1_id],rgb[v2_id],bg0,bg1,bg2,vp,SM_VIEW_CENTER(sm)); + } glEnd(); glPopAttrib(); } -smRender_tri_edges(sm,i) -SM *sm; -int i; -{ - TRI *tri; - int j; - double ptr[3]; - - - tri = SM_NTH_TRI(sm,i); - - /* Triangles are defined clockwise:historical relative to spherical - tris: could change - */ - for(j=2; j >=0; j--) - { - VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,j))); - glVertex3d(ptr[0],ptr[1],ptr[2]); - VCOPY(ptr,SM_NTH_WV(sm,T_NTH_V(tri,(j+1)%3))); - glVertex3d(ptr[0],ptr[1],ptr[2]); - } -} - int compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2) { @@ -611,54 +547,87 @@ compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2) return(-1); return(0); + } -LIST -*smDepth_sort_tris(sm,vp,td) +#ifdef DEBUG +#define freebuf(b) tempbuf(-1) +#endif + + +char * +tempbuf(len) /* get a temporary buffer */ +unsigned len; +{ + extern char *malloc(), *realloc(); + static char *tempbuf = NULL; + static unsigned tempbuflen = 0; + +#ifdef DEBUG + static int in_use=FALSE; + + if(len == -1) + { + in_use = FALSE; + return(NULL); + } + if(in_use) + { + eputs("Buffer in use:cannot allocate:tempbuf()\n"); + return(NULL); + } +#endif + if (len > tempbuflen) { + if (tempbuflen > 0) + tempbuf = realloc(tempbuf, len); + else + tempbuf = malloc(len); + tempbuflen = tempbuf==NULL ? 0 : len; + } +#ifdef DEBUG + in_use = TRUE; +#endif + return(tempbuf); +} + +smOrder_new_tris(sm,vp,td) SM *sm; FVECT vp; T_DEPTH *td; { - int i,j,t_id,v; + int n,i,j,tcnt,v; TRI *tri; double d,min_d; - LIST *tlist=NULL; + FVECT diff; + int4 *new_flag,*bg_flag; - i = 0; - SM_FOR_ALL_NEW_TRIS(sm,t_id) - { - if(SM_BG_TRI(sm,t_id)) - { - tlist = push_data(tlist,t_id); - continue; - } - tri = SM_NTH_TRI(sm,t_id); -#ifdef DEBUG - if(i >= smNew_tri_cnt) - { - eputs("smDepth_sort_tris():More tris than reported by smNew_tri_cnt\n"); - break; - } -#endif - td[i].tri = t_id; - min_d = -1; - for(j=0;j < 3;j++) - { - v = T_NTH_V(tri,j); - if(!SM_BG_SAMPLE(sm,v)) - { - d = DIST(vp,SM_NTH_WV(sm,v)); - if(min_d == -1 || d < min_d) - min_d = d; - } - } - td[i].depth = min_d; - i++; + tcnt=0; + new_flag = SM_NTH_FLAGS(sm,T_NEW_FLAG); + bg_flag = SM_NTH_FLAGS(sm,T_BG_FLAG); + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(new_flag[n] & ~bg_flag[n]) + for(i=0; i < 32; i++) + if(new_flag[n] & (1L << i) & ~bg_flag[n]) + { + tri = SM_NTH_TRI(sm,(n<<5)+i); + td[tcnt].tri = (n << 5)+i; + min_d = -1; + for(j=0;j < 3;j++) + { + v = T_NTH_V(tri,j); + if(!SM_BG_SAMPLE(sm,v)) + { + VSUB(diff,SM_NTH_WV(sm,v),vp); + d = DOT(diff,diff); + if(min_d == -1 || d < min_d) + min_d = d; + } + } + td[tcnt++].depth = min_d; } - td[i].tri = -1; - if(i) - qsort((void *)td,i,sizeof(T_DEPTH),compare_tri_depths); - return(tlist); + td[tcnt].tri = -1; + if(tcnt) + qsort((void *)td,tcnt,sizeof(T_DEPTH),compare_tri_depths); } @@ -667,49 +636,108 @@ SM *sm; FVECT vp; int clr; { - static T_DEPTH *td= NULL; - static int tsize = 0; - int i; + int i,n,v0_id,v1_id,v2_id,bg0,bg1,bg2; GLint depth_test; double d; - LIST *bglist; + TRI *tri; + float (*wp)[3]; + BYTE (*rgb)[3]; + int4 *new_flag,*bg_flag; + T_DEPTH *td = NULL; /* For all of the NEW triangles (since last update): assume ACTIVE. Go through and sort on depth value (from vp). Turn Depth Buffer test off and render back-front */ - /* NOTE: could malloc each time or hard code */ - if(smNew_tri_cnt > tsize) + if(!EQUAL_VEC3(SM_VIEW_CENTER(sm),vp)) { - if(td) - free((char *)td); - td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH)); - tsize = smNew_tri_cnt; + /* Must depth sort if view points do not coincide */ + td = (T_DEPTH *)tempbuf(smNew_tri_cnt*sizeof(T_DEPTH)); +#ifdef DEBUG + if(!td) + eputs("Cant create list:wont depth sort:smUpdate_rendered_mesh\n"); +#endif + smOrder_new_tris(sm,vp,td); } - if(!td) - { - error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n"); - } - bglist = smDepth_sort_tris(sm,vp,td); - + wp = SM_WP(sm); + rgb =SM_RGB(sm); /* Turn Depth Test off -- using Painter's algorithm */ glPushAttrib(GL_DEPTH_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); d = (dev_zmin+dev_zmax)/2.0; + /* Now render back-to front */ /* First render bg triangles */ + new_flag = SM_NTH_FLAGS(sm,T_NEW_FLAG); + bg_flag = SM_NTH_FLAGS(sm,T_BG_FLAG); glBegin(GL_TRIANGLES); - while(bglist) - smRender_bg_tri(sm,pop_list(&bglist),vp,d,clr); + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(new_flag[n] & bg_flag[n]) + for(i=0; i < 32; i++) + if(new_flag[n] & (1L << i) & bg_flag[n] ) + { + tri = SM_NTH_TRI(sm,(n<<5)+i); + v0_id = T_NTH_V(tri,0); + v1_id = T_NTH_V(tri,1); + v2_id = T_NTH_V(tri,2); + render_bg_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], + rgb[v2_id],vp,SM_VIEW_CENTER(sm),d); + } glEnd(); glBegin(GL_TRIANGLES); - i=0; - while(td[i].tri != -1) - if(!SM_MIXED_TRI(sm,td[i].tri)) - smRender_tri(sm,td[i++].tri,vp,clr); - else - smRender_mixed_tri(sm,td[i++].tri,vp,clr); + if(!td) + { + for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) + if(new_flag[n] & ~bg_flag[n]) + for(i=0; i < 32; i++) + if(new_flag[n] & (1L << i) & ~bg_flag[n]) + { + tri = SM_NTH_TRI(sm,(n<<5)+i); + /* Dont need to check for valid tri because flags are + cleared on delete + */ + v0_id = T_NTH_V(tri,0); + v1_id = T_NTH_V(tri,1); + v2_id = T_NTH_V(tri,2); + bg0 = SM_DIR_ID(sm,v0_id) || SM_BASE_ID(sm,v0_id); + bg1 = SM_DIR_ID(sm,v1_id) || SM_BASE_ID(sm,v1_id); + bg2 = SM_DIR_ID(sm,v2_id) || SM_BASE_ID(sm,v2_id); + if(!(bg0 || bg1 || bg2)) + render_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], + rgb[v2_id]) + else + render_mixed_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id], + rgb[v1_id],rgb[v2_id],bg0,bg1,bg2,vp, + SM_VIEW_CENTER(sm)); + } + } + else + { + for(i=0; td[i].tri != -1;i++) + { + tri = SM_NTH_TRI(sm,td[i].tri); + /* Dont need to check for valid tri because flags are + cleared on delete + */ + v0_id = T_NTH_V(tri,0); + v1_id = T_NTH_V(tri,1); + v2_id = T_NTH_V(tri,2); + bg0 = SM_DIR_ID(sm,v0_id) || SM_BASE_ID(sm,v0_id); + bg1 = SM_DIR_ID(sm,v1_id) || SM_BASE_ID(sm,v1_id); + bg2 = SM_DIR_ID(sm,v2_id) || SM_BASE_ID(sm,v2_id); + if(!(bg0 || bg1 || bg2)) + render_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], + rgb[v2_id]) + else + render_mixed_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id], + rgb[v1_id],rgb[v2_id],bg0,bg1,bg2,vp, + SM_VIEW_CENTER(sm)); + } +#ifdef DEBUG + freebuf(td); +#endif + } glEnd(); /* Restore Depth Test */ @@ -733,26 +761,30 @@ smUpdate(view,qual) int qual; { double d; - int last_update; - int t; + int last_update,t; + if(!smMesh) + return; + /* If view has moved beyond epsilon from canonical: must rebuild - epsilon is calculated as running avg of distance of sample points from canonical view: m = 1/(AVG(1/r)): some fraction of this */ d = DIST(view->vp,SM_VIEW_CENTER(smMesh)); - if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh)) + if(qual >= MAXQUALITY && d > SM_ALLOWED_VIEW_CHANGE(smMesh)) { /* Re-build the mesh */ #ifdef TEST_DRIVER odev.v = *view; -#endif - smRebuild_mesh(smMesh,view->vp); +#endif + mark_tris_in_frustum(view); + smRebuild_mesh(smMesh,view); + smClean_notify = TRUE; } - /* This is our final update iff qual==100 and view==&odev.v */ - last_update = qual>=100 && view==&(odev.v); + /* This is our final update iff qual==MAXQUALITY and view==&odev.v */ + last_update = qual>=MAXQUALITY && view==&(odev.v); /* Check if we should draw ALL triangles in current frustum */ - if(smClean_notify || smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT) + if(smClean_notify || smNew_tri_cnt>SM_SAMPLE_TRIS(smMesh)*SM_INC_PERCENT) { #ifdef TEST_DRIVER glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -761,17 +793,17 @@ smUpdate(view,qual) { tmClearHisto(); tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1); - if(tmComputeMapping(0.,0.,0.) != TM_E_OK || - tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh), - SM_NUM_SAMP(smMesh)) != TM_E_OK) - return; + if(tmComputeMapping(0.,0.,0.) != TM_E_OK) + return; + tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh), + SM_NUM_SAMP(smMesh)); } #endif mark_tris_in_frustum(view); - if (qual <= 75) + if (qual <= (MAXQUALITY*3/4)) smRender_stree(smMesh,qual); else - smRender_mesh(smMesh,view->vp,last_update); + smRender_mesh(smMesh,view->vp); #ifdef TEST_DRIVER glFlush(); glutSwapBuffers(); @@ -779,8 +811,8 @@ smUpdate(view,qual) } /* Do an incremental update instead */ else - { - if(!smNew_tri_cnt) + { + if(!smNew_tri_cnt) return; #ifdef TEST_DRIVER glDrawBuffer(GL_FRONT); @@ -793,9 +825,9 @@ smUpdate(view,qual) if(tmComputeMapping(0.,0.,0.) != TM_E_OK) return; } - if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t), - SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK) - return; + tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t), + SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t); + #endif smUpdate_Rendered_mesh(smMesh,view->vp,last_update); @@ -803,7 +835,9 @@ smUpdate(view,qual) glDrawBuffer(GL_BACK); #endif } + SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh); + if (last_update) { smClean_notify = FALSE; @@ -813,3 +847,11 @@ smUpdate(view,qual) } } + + + + + + + +