1 |
– |
/* Copyright (c) 1998 Silicon Graphics, Inc. */ |
2 |
– |
|
1 |
|
#ifndef lint |
2 |
< |
static char SCCSid[] = "$SunId$ SGI"; |
2 |
> |
static const char RCSid[] = "$Id$"; |
3 |
|
#endif |
6 |
– |
|
4 |
|
/* |
5 |
|
* sm_ogl.c |
6 |
|
* |
7 |
|
* Rendering routines for triangle mesh representation utilizing OpenGL |
8 |
< |
*/ |
8 |
> |
* |
9 |
> |
* smClean(tmflag) : display has been wiped clean |
10 |
> |
* int tmflag; |
11 |
> |
* Called after display has been effectively cleared, meaning that all |
12 |
> |
* geometry must be resent down the pipeline in the next call to smUpdate(). |
13 |
> |
* If tmflag is set, tone-mapping should be performed |
14 |
> |
* |
15 |
> |
* smUpdate(vp, qua) : update OpenGL output geometry for view vp |
16 |
> |
* VIEW *vp; : desired view |
17 |
> |
* int qua; : quality level (percentage on linear time scale) |
18 |
> |
* |
19 |
> |
* Draw new geometric representation using OpenGL calls. Assume that the |
20 |
> |
* view has already been set up and the correct frame buffer has been |
21 |
> |
* selected for drawing. The quality level is on a linear scale, where 100% |
22 |
> |
* is full (final) quality. It is not necessary to redraw geometry that has |
23 |
> |
* been output since the last call to smClean(). (The last view drawn will |
24 |
> |
* be vp==&odev.v each time.) |
25 |
> |
*/ |
26 |
|
#include "standard.h" |
27 |
|
|
28 |
|
#include <GL/gl.h> |
32 |
|
#include "sm_geom.h" |
33 |
|
#include "sm.h" |
34 |
|
|
35 |
< |
int smClean_notify = TRUE; /*If true:Do full redraw on next update*/ |
36 |
< |
static int smCompute_mapping = TRUE;/*If true:re-tonemap on next update */ |
37 |
< |
static int smIncremental = FALSE; /*If true: there has been incremental |
38 |
< |
rendering since last full draw */ |
39 |
< |
#define MAX_NEW_TRIS 1000 |
35 |
> |
int smClean_notify = TRUE; /*If TRUE:Do full redraw on next update*/ |
36 |
> |
static int smCompute_mapping = TRUE; /*If TRUE:re-tonemap on next update */ |
37 |
> |
static int smIncremental = FALSE; /*If TRUE: there has been incremental |
38 |
> |
rendering since last full draw */ |
39 |
> |
#define NEW_TRI_CNT 1000 /* Default number of tris to allocate |
40 |
> |
space to sort for incremental update*/ |
41 |
|
#define SM_RENDER_FG 0 /* Render foreground tris only*/ |
42 |
|
#define SM_RENDER_BG 1 /* Render background tris only */ |
43 |
|
#define SM_RENDER_CULL 8 /* Perform view frustum culling */ |
44 |
|
#define BASE 1 /* Indicates base triangle */ |
45 |
|
#define DIR 2 /* Indicates triangle w/directional pts*/ |
46 |
|
/* FOR DISPLAY LIST RENDERING: **********************************************/ |
47 |
< |
#define SM_DL_LEVELS 2 /* # of levels down to create display lists */ |
48 |
< |
#define SM_DL_LISTS 42 /* # of qtree nodes in tree at above level: |
49 |
< |
should be 2*(4^(SM_DL_LEVELS+1)-1)/(4-1) */ |
47 |
> |
#define SM_DL_LEVELS 2 /* # of levels down to create display lists */ |
48 |
> |
#define SM_DL_LISTS 42 /* # of qtree nodes in tree at above level: |
49 |
> |
should be 2*(4^(SM_DL_LEVELS+1)-1)/(4-1) */ |
50 |
|
static GLuint Display_lists[SM_DL_LISTS][2] = {0}; |
51 |
|
/****************************************************************************/ |
52 |
|
|
83 |
|
int tmflag; |
84 |
|
{ |
85 |
|
smClean_notify = TRUE; |
86 |
< |
if(tmflag) |
72 |
< |
smCompute_mapping = TRUE; |
86 |
> |
smCompute_mapping = tmflag; |
87 |
|
} |
88 |
|
|
89 |
|
int |
90 |
|
qtCache_init(nel) /* initialize for at least nel elements */ |
91 |
|
int nel; |
92 |
|
{ |
93 |
< |
static int hsiztab[] = { |
94 |
< |
8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0 |
95 |
< |
}; |
96 |
< |
register int i; |
93 |
> |
static int hsiztab[] = { |
94 |
> |
8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 0 |
95 |
> |
}; |
96 |
> |
register int i; |
97 |
|
|
98 |
< |
if (nel <= 0) { /* call to free table */ |
99 |
< |
if (qt_hsiz) { |
100 |
< |
free((char *)qt_htbl); |
101 |
< |
qt_htbl = NULL; |
102 |
< |
qt_hsiz = 0; |
89 |
< |
} |
90 |
< |
return(0); |
98 |
> |
if (nel <= 0) { /* call to free table */ |
99 |
> |
if (qt_hsiz) { |
100 |
> |
free((void *)qt_htbl); |
101 |
> |
qt_htbl = NULL; |
102 |
> |
qt_hsiz = 0; |
103 |
|
} |
104 |
< |
nel += nel>>1; /* 66% occupancy */ |
105 |
< |
for (i = 0; hsiztab[i]; i++) |
106 |
< |
if (hsiztab[i] > nel) |
107 |
< |
break; |
108 |
< |
if (!(qt_hsiz = hsiztab[i])) |
109 |
< |
qt_hsiz = nel*2 + 1; /* not always prime */ |
110 |
< |
qt_htbl = (QT_LUENT *)calloc(qt_hsiz, sizeof(QT_LUENT)); |
111 |
< |
if (qt_htbl == NULL) |
112 |
< |
qt_hsiz = 0; |
113 |
< |
for (i = qt_hsiz; i--; ) |
114 |
< |
qt_htbl[i].qt = EMPTY; |
115 |
< |
return(qt_hsiz); |
104 |
> |
return(0); |
105 |
> |
} |
106 |
> |
nel += nel>>1; /* 66% occupancy */ |
107 |
> |
for (i = 0; hsiztab[i]; i++) |
108 |
> |
if (hsiztab[i] > nel) |
109 |
> |
break; |
110 |
> |
if (!(qt_hsiz = hsiztab[i])) |
111 |
> |
qt_hsiz = nel*2 + 1; /* not always prime */ |
112 |
> |
qt_htbl = (QT_LUENT *)calloc(qt_hsiz, sizeof(QT_LUENT)); |
113 |
> |
if (qt_htbl == NULL) |
114 |
> |
qt_hsiz = 0; |
115 |
> |
for (i = qt_hsiz; i--; ) |
116 |
> |
qt_htbl[i].qt = EMPTY; |
117 |
> |
return(qt_hsiz); |
118 |
|
} |
119 |
|
|
120 |
|
QT_LUENT * |
121 |
|
qtCache_find(qt) /* find a quadtree table entry */ |
122 |
|
QUADTREE qt; |
123 |
|
{ |
124 |
< |
int i, n; |
125 |
< |
register int ndx; |
126 |
< |
register QT_LUENT *le; |
124 |
> |
int i, n; |
125 |
> |
register int ndx; |
126 |
> |
register QT_LUENT *le; |
127 |
|
|
128 |
< |
if (qt_hsiz == 0 && !qtCache_init(1)) |
129 |
< |
return(NULL); |
128 |
> |
if (qt_hsiz == 0 && !qtCache_init(1)) |
129 |
> |
return(NULL); |
130 |
|
tryagain: /* hash table lookup */ |
131 |
< |
ndx = (unsigned long)qt % qt_hsiz; |
132 |
< |
for (i = 0, n = 1; i < qt_hsiz; i++, n += 2) { |
133 |
< |
le = &qt_htbl[ndx]; |
134 |
< |
if (QT_IS_EMPTY(le->qt) || le->qt == qt) |
135 |
< |
return(le); |
136 |
< |
if ((ndx += n) >= qt_hsiz) /* this happens rarely */ |
137 |
< |
ndx = ndx % qt_hsiz; |
138 |
< |
} |
139 |
< |
/* table is full, reallocate */ |
140 |
< |
le = qt_htbl; |
141 |
< |
ndx = qt_hsiz; |
142 |
< |
if (!qtCache_init(ndx+1)) { /* no more memory! */ |
143 |
< |
qt_htbl = le; |
144 |
< |
qt_hsiz = ndx; |
145 |
< |
return(NULL); |
146 |
< |
} |
131 |
> |
ndx = (unsigned long)qt % qt_hsiz; |
132 |
> |
for (i = 0, n = 1; i < qt_hsiz; i++, n += 2) { |
133 |
> |
le = &qt_htbl[ndx]; |
134 |
> |
if (QT_IS_EMPTY(le->qt) || le->qt == qt) |
135 |
> |
return(le); |
136 |
> |
if ((ndx += n) >= qt_hsiz) /* this happens rarely */ |
137 |
> |
ndx = ndx % qt_hsiz; |
138 |
> |
} |
139 |
> |
/* table is full, reallocate */ |
140 |
> |
le = qt_htbl; |
141 |
> |
ndx = qt_hsiz; |
142 |
> |
if (!qtCache_init(ndx+1)) { /* no more memory! */ |
143 |
> |
qt_htbl = le; |
144 |
> |
qt_hsiz = ndx; |
145 |
> |
return(NULL); |
146 |
> |
} |
147 |
|
/* copy old table to new and free */ |
148 |
< |
while (ndx--) |
149 |
< |
if (!QT_IS_EMPTY(le[ndx].qt)) |
150 |
< |
copystruct(qtCache_find(le[ndx].qt), &le[ndx]); |
151 |
< |
free((char *)le); |
152 |
< |
goto tryagain; /* should happen only once! */ |
148 |
> |
while (ndx--) |
149 |
> |
if (!QT_IS_EMPTY(le[ndx].qt)) |
150 |
> |
copystruct(qtCache_find(le[ndx].qt), &le[ndx]); |
151 |
> |
free((void *)le); |
152 |
> |
goto tryagain; /* should happen only once! */ |
153 |
|
} |
154 |
|
|
155 |
|
stCount_level_leaves(lcnt, qt) /* count quadtree leaf nodes at each level */ |
219 |
|
} |
220 |
|
else |
221 |
|
{ /* from triangle set */ |
222 |
< |
OBJECT *os; |
223 |
< |
int s0, s1, s2,s_id,t_id; |
222 |
> |
S_ID *os; |
223 |
> |
S_ID s0, s1, s2,s_id; |
224 |
> |
int t_id; |
225 |
|
TRI *tri,*t; |
226 |
|
|
227 |
|
os = qtqueryset(qt); |
287 |
|
} |
288 |
|
|
289 |
|
|
275 |
– |
|
276 |
– |
|
290 |
|
smRender_approx_stree_level(sm,lvl) |
291 |
|
SM *sm; |
292 |
|
int lvl; |
295 |
|
int i; |
296 |
|
FVECT t0,t1,t2; |
297 |
|
STREE *st; |
285 |
– |
|
298 |
|
|
299 |
|
if (lvl < 0) |
300 |
|
return; |
365 |
|
smRender_approx_stree_level(sm,i); |
366 |
|
} |
367 |
|
|
368 |
< |
#ifndef LORES |
357 |
< |
#define GLVERTEX3V(v) glVertex3dv(v) |
358 |
< |
#else |
368 |
> |
|
369 |
|
#define GLVERTEX3V(v) glVertex3fv(v) |
360 |
– |
#endif |
370 |
|
|
371 |
+ |
|
372 |
|
#define render_tri(v0,v1,v2,rgb0,rgb1,rgb2) \ |
373 |
|
{glColor3ub(rgb0[0],rgb0[1],rgb0[2]); GLVERTEX3V(v0); \ |
374 |
|
glColor3ub(rgb1[0],rgb1[1],rgb1[2]); GLVERTEX3V(v1); \ |
529 |
|
|
530 |
|
} |
531 |
|
/* |
532 |
< |
* smRender_new_bg_tris(sm,vp,t_flag,bg_flag,wp,rgb) |
532 |
> |
* smRender_new_bg_tris(sm,vp,new_flag,active_flag,bg_flag,wp,rgb) |
533 |
|
* SM *sm; : mesh |
534 |
|
* FVECT vp; : current viewpoint |
535 |
< |
* int4 *t_flag,*bg_flag; : triangle flags: t_flag is generic, |
536 |
< |
* and bg_flag indicates if background tri; |
535 |
> |
* int4 *new_flag,*active,*bg_flag; : triangle flags: idicates if tri is, |
536 |
> |
* new,active,bg_flag |
537 |
|
* SFLOAT (*wp)[3];BYTE (*rgb)[3]; : arrays of sample points and RGB colors |
538 |
|
* |
539 |
|
* Sequentially traverses triangle list and renders all valid tris who |
540 |
< |
* have t_flag set, and bg_flag set. |
540 |
> |
* have new_flag set and active_flag and bg_flag set. |
541 |
|
*/ |
532 |
– |
|
542 |
|
smRender_new_bg_tris(sm,vp,new_flag,active_flag,bg_flag,wp,rgb) |
543 |
|
SM *sm; |
544 |
|
FVECT vp; |
618 |
|
cnt = 0; |
619 |
|
rgb[0] = rgb[1] = rgb[2] = 0; |
620 |
|
d = 0.0; |
621 |
< |
|
621 |
> |
/* If all vertices are base: don't render */ |
622 |
|
if(b0&&b1&&b2) |
623 |
|
return; |
624 |
|
/* First calculate color and coordinates |
705 |
|
{ |
706 |
|
TRI *tri; |
707 |
|
int i,n,b0,b1,b2; |
708 |
< |
int v0_id,v1_id,v2_id; |
708 |
> |
S_ID v0_id,v1_id,v2_id; |
709 |
|
|
710 |
|
glBegin(GL_TRIANGLES); |
711 |
|
for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) |
733 |
|
} |
734 |
|
|
735 |
|
/* |
736 |
< |
* smRender_fg_tris(sm,vp,t_flag,bg_flag,wp,rgb) |
736 |
> |
* smRender_new_fg_tris(sm,vp,new_flag,active_flag,bg_flag,wp,rgb) |
737 |
|
* SM *sm; : mesh |
738 |
|
* FVECT vp; : current viewpoint |
739 |
< |
* int4 *t_flag,*bg_flag; : triangle flags: t_flag is generic,bg_flag |
740 |
< |
* indicates if background tri; |
739 |
> |
* int4 *new_flag,*active_flag,*bg_flag; : triangle flags: indicate if |
740 |
> |
* tri is new,active,background |
741 |
|
* SFLOAT (*wp)[3];BYTE (*rgb)[3]; : arrays of sample points and RGB colors |
742 |
|
* |
743 |
|
* Sequentially gos through triangle list and renders all valid tris who |
744 |
< |
* have t_flag set, and NOT bg_flag set. |
744 |
> |
* have new_flag and active_flag set, and NOT bg_flag set. |
745 |
|
*/ |
746 |
|
smRender_new_fg_tris(sm,vp,new_flag,active_flag,bg_flag,wp,rgb) |
747 |
|
SM *sm; |
752 |
|
{ |
753 |
|
TRI *tri; |
754 |
|
int i,n,b0,b1,b2; |
755 |
< |
int v0_id,v1_id,v2_id; |
755 |
> |
S_ID v0_id,v1_id,v2_id; |
756 |
|
|
757 |
|
glBegin(GL_TRIANGLES); |
758 |
|
for(n=((SM_NUM_TRI(sm)+31)>>5) +1; --n;) |
773 |
|
else |
774 |
|
render_tri(wp[v0_id],wp[v1_id],wp[v2_id],rgb[v0_id],rgb[v1_id], |
775 |
|
rgb[v2_id]) |
767 |
– |
|
776 |
|
} |
777 |
|
glEnd(); |
778 |
|
|
779 |
|
} |
780 |
|
|
781 |
< |
|
781 |
> |
/* Test for qsort to depth sort triangles */ |
782 |
|
int |
783 |
|
compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2) |
784 |
|
{ |
814 |
|
FVECT diff; |
815 |
|
int4 *new_flag,*bg_flag,*active_flag; |
816 |
|
|
817 |
< |
td = (T_DEPTH *)tempbuf(MAX_NEW_TRIS*sizeof(T_DEPTH),FALSE); |
818 |
< |
size = MAX_NEW_TRIS; |
817 |
> |
td = (T_DEPTH *)tempbuf(NEW_TRI_CNT*sizeof(T_DEPTH),FALSE); |
818 |
> |
size = NEW_TRI_CNT; |
819 |
|
|
820 |
|
tcnt=0; |
821 |
|
new_flag = SM_NTH_FLAGS(sm,T_NEW_FLAG); |
889 |
|
SM *sm; |
890 |
|
FVECT vp; |
891 |
|
{ |
892 |
< |
int i,n,v0_id,v1_id,v2_id,b0,b1,b2; |
892 |
> |
S_ID v0_id,v1_id,v2_id; |
893 |
> |
int i,n,b0,b1,b2; |
894 |
|
TRI *tri; |
895 |
|
SFLOAT (*wp)[3]; |
896 |
|
BYTE (*rgb)[3]; |
898 |
|
T_DEPTH *td = NULL; |
899 |
|
|
900 |
|
|
901 |
< |
/* For all of the NEW triangles (since last update): assume |
902 |
< |
ACTIVE. Go through and sort on depth value (from vp). Turn |
901 |
> |
/* For all of the NEW and ACTIVE triangles (since last update): |
902 |
> |
Go through and sort on depth value (from vp). Turn |
903 |
|
Depth Buffer test off and render back-front |
904 |
< |
*/ |
904 |
> |
*/ |
905 |
|
|
906 |
< |
/* Must depth sort if view points do not coincide */ |
906 |
> |
/* Must depth sort if current view point is not same as canonical */ |
907 |
|
if(!EQUAL_VEC3(SM_VIEW_CENTER(sm),vp)) |
908 |
|
td = smOrder_new_tris(sm,vp); |
909 |
|
wp = SM_WP(sm); |
955 |
|
* SFLOAT (*wp)[3]; : array of sample points |
956 |
|
* BYTE (*rgb)[3]; : array of RGB values for samples |
957 |
|
* int i,level_i,level,max_level,leaf_cnt; |
958 |
< |
* : variables to keep track of where |
958 |
> |
* : variables to keep track of where |
959 |
|
* we are in the quadtree traversal in order to map nodes to |
960 |
|
* corresponding array locations, where nodes are stored in breadth- |
961 |
|
* first order. i is the index of the current node,level_i is the |
1050 |
|
if(QT_IS_LEAF(qt)) |
1051 |
|
{ |
1052 |
|
TRI *t,*tri; |
1053 |
< |
OBJECT *optr; |
1054 |
< |
int v0_id,v1_id,v2_id,bg0,bg1,bg2; |
1046 |
< |
int t_id,s_id; |
1053 |
> |
S_ID *optr,s_id,v0_id,v1_id,v2_id; |
1054 |
> |
int bg0,bg1,bg2,t_id; |
1055 |
|
|
1056 |
|
if(cull && !QT_LEAF_IS_FLAG(qt)) |
1057 |
|
return; |
1133 |
|
int i; |
1134 |
|
STREE *st= SM_LOCATOR(sm); |
1135 |
|
|
1128 |
– |
|
1136 |
|
wp = SM_WP(sm); |
1137 |
|
rgb =SM_RGB(sm); |
1138 |
|
|
1139 |
|
smClear_flags(sm,T_NEW_FLAG); |
1140 |
|
|
1134 |
– |
|
1141 |
|
if(cull) |
1142 |
|
smCull(sm,view,SM_ALL_LEVELS); |
1143 |
|
|
1138 |
– |
|
1144 |
|
glPushAttrib(GL_DEPTH_BUFFER_BIT); |
1145 |
|
glDisable(GL_DEPTH_TEST); |
1146 |
|
|
1149 |
|
/* move relative to the new view */ |
1150 |
|
glTranslated(view->vp[0],view->vp[1],view->vp[2]); |
1151 |
|
|
1147 |
– |
|
1152 |
|
/* The points are a distance of 1 away from the origin: if necessary |
1153 |
|
scale so that they fit in frustum and are therefore not clipped away |
1154 |
|
*/ |
1464 |
|
VIEW *view; |
1465 |
|
int qual; |
1466 |
|
{ |
1467 |
+ |
|
1468 |
|
/* Is there anything to render? */ |
1469 |
|
if(!smMesh || SM_NUM_TRI(smMesh)<=0) |
1470 |
|
return; |
1471 |
< |
|
1471 |
> |
|
1472 |
|
/* Is viewer MOVING?*/ |
1473 |
|
if(qual < MAXQUALITY) |
1474 |
|
{ |
1475 |
|
if(smIncremental) |
1476 |
|
smUpdate_tm(smMesh); |
1477 |
< |
smIncremental = FALSE; |
1477 |
> |
|
1478 |
|
/* Render mesh using display lists */ |
1479 |
|
smRender(smMesh,view,qual); |
1480 |
|
return; |
1526 |
|
} |
1527 |
|
|
1528 |
|
} |
1529 |
+ |
|
1530 |
|
|
1531 |
|
|
1532 |
|
|