ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.2
Committed: Thu Aug 20 16:47:21 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.1: +25 -6 lines
Log Message:
switched to barycentric coordinates
fixed background poly rendering

File Contents

# User Rev Content
1 gwlarson 3.1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * sm_ogl.c
9     */
10     #include "standard.h"
11    
12     #include <GL/gl.h>
13    
14     #ifdef TEST_DRIVER
15     #include <gl/device.h>
16     #include <GL/glu.h>
17     #include <glut.h>
18     #endif
19     #include "object.h"
20     #include "sm_geom.h"
21     #include "sm.h"
22    
23     #ifdef TEST_DRIVER
24     #include "sm_draw.h"
25     /*static char smClean_notify = TRUE;
26     MAKE STATIC LATER: ui.c using for now;
27     */
28     char smClean_notify = TRUE;
29     #else
30     static char smClean_notify = TRUE;
31     #endif
32    
33     int
34     mark_active_tris(qtptr,arg)
35     QUADTREE *qtptr;
36     char *arg;
37     {
38     OBJECT os[MAXSET+1],*optr;
39     int i,t_id;
40     SM *sm;
41    
42    
43     sm = (SM *)arg;
44    
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);
53    
54     for (i = QT_SET_CNT(os),optr = QT_SET_PTR(os); i > 0; i--)
55     {
56     t_id = QT_SET_NEXT_ELEM(optr);
57     /* Set the render flag */
58     if(SM_IS_NTH_T_BASE(sm,t_id))
59     continue;
60     SM_SET_NTH_T_ACTIVE(sm,t_id);
61     /* FOR NOW:Also set the LRU clock bit: MAY WANT TO CHANGE: */
62     SM_SET_NTH_T_LRU(sm,t_id);
63     }
64     }
65     return(TRUE);
66     }
67    
68    
69     smMark_tris_in_frustum(sm,vp)
70     SM *sm;
71     VIEW *vp;
72     {
73     FVECT nr[4],far[4];
74    
75     /* Mark triangles in approx. view frustum as being active:set
76     LRU counter: for use in discarding samples when out
77     of space
78     Radiance often has no far clipping plane: but driver will set
79     dev_zmin,dev_zmax to satisfy OGL
80     */
81    
82     /* First clear all the triangle active flags */
83     smClear_flags(sm,T_ACTIVE_FLAG);
84    
85     /* calculate the world space coordinates of the view frustum */
86     calculate_view_frustum(vp->vp,vp->hvec,vp->vvec,vp->horiz,vp->vert,
87     dev_zmin,dev_zmax,nr,far);
88    
89     /* Project the view frustum onto the spherical quadtree */
90     /* For every cell intersected by the projection of the faces
91     of the frustum: mark all triangles in the cell as ACTIVE-
92     Also set the triangles LRU clock counter
93     */
94     /* Need to do tonemap call */
95     /* Near face triangles */
96     smLocator_apply_func(sm,nr[0],nr[2],nr[3],mark_active_tris,(char *)(sm));
97     smLocator_apply_func(sm,nr[2],nr[0],nr[1],mark_active_tris,(char *)(sm));
98     /* Right face triangles */
99     smLocator_apply_func(sm,nr[0],far[3],far[0],mark_active_tris,(char *)(sm));
100     smLocator_apply_func(sm,far[3],nr[0],nr[3],mark_active_tris,(char *)(sm));
101     /* Left face triangles */
102     smLocator_apply_func(sm,nr[1],far[2],nr[2],mark_active_tris,(char *)(sm));
103     smLocator_apply_func(sm,far[2],nr[1],far[1],mark_active_tris,(char *)(sm));
104     /* Top face triangles */
105     smLocator_apply_func(sm,nr[0],far[0],nr[1],mark_active_tris,(char *)(sm));
106     smLocator_apply_func(sm,nr[1],far[0],far[1],mark_active_tris,(char *)(sm));
107     /* Bottom face triangles */
108     smLocator_apply_func(sm,nr[3],nr[2],far[3],mark_active_tris,(char *)(sm));
109     smLocator_apply_func(sm,nr[2],far[2],far[3],mark_active_tris,(char *)(sm));
110     /* Far face triangles */
111     smLocator_apply_func(sm,far[0],far[2],far[1],mark_active_tris,(char *)(sm));
112     smLocator_apply_func(sm,far[2],far[0],far[3],mark_active_tris,(char *)(sm));
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
124     }
125    
126     /*
127     * smClean() : display has been wiped clean
128     *
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()
133     {
134     /* Mark all triangles in the frustum as active */
135     if(!smMesh || SM_NUM_TRIS(smMesh)==0)
136     return;
137    
138     #ifdef TEST_DRIVER
139     smMark_tris_in_frustum(smMesh,&Current_View);
140     #else
141     smMark_tris_in_frustum(smMesh,&(odev.v));
142     #endif
143     smClean_notify = TRUE;
144     }
145    
146    
147     smRender_tri(sm,i,vp)
148     SM *sm;
149     int i;
150     FVECT vp;
151     {
152     TRI *tri;
153     double ptr[3];
154     int j;
155    
156     tri = SM_NTH_TRI(sm,i);
157     SM_CLEAR_NTH_T_NEW(sm,i);
158     if(smNew_tri_cnt)
159     smNew_tri_cnt--;
160     /* NOTE:Triangles are defined clockwise:historical relative to spherical
161     tris: could change
162     */
163     for(j=2; j>= 0; j--)
164     {
165 gwlarson 3.2 #ifdef DEBUG
166     if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
167     eputs("SmRenderTri(): shouldnt have bg samples\n");
168     #endif
169 gwlarson 3.1 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]);
174     }
175     }
176    
177     /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
178     ADJACENT TRIANGLES TO BG be BG
179     */
180 gwlarson 3.2 smRender_bg_tri(sm,i,vp,d)
181 gwlarson 3.1 SM *sm;
182     int i;
183     FVECT vp;
184 gwlarson 3.2 double d;
185 gwlarson 3.1 {
186     TRI *tri;
187     FVECT p;
188     int j,ids[3],cnt;
189 gwlarson 3.2 int rgb[3];
190 gwlarson 3.1
191 gwlarson 3.2
192 gwlarson 3.1 tri = SM_NTH_TRI(sm,i);
193     SM_CLEAR_NTH_T_NEW(sm,i);
194     if(smNew_tri_cnt)
195     smNew_tri_cnt--;
196     /* NOTE:Triangles are defined clockwise:historical relative to spherical
197     tris: could change
198     */
199     cnt = 0;
200     rgb[0] = rgb[1] = rgb[2] = 0;
201     for(j=0;j<3;j++)
202     {
203     ids[j] = T_NTH_V(tri,j);
204     if(SM_BG_SAMPLE(sm,ids[j]))
205     {
206     rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
207     rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
208     rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
209     cnt++;
210     }
211     }
212     if(cnt)
213     {
214     rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
215     }
216     for(j=2; j>= 0; j--)
217     {
218     if(SM_BG_SAMPLE(sm,ids[j]))
219     glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
220     SM_NTH_RGB(sm,ids[j])[2]);
221     else
222     glColor3ub(rgb[0],rgb[1],rgb[2]);
223 gwlarson 3.2 if(SM_BG_SAMPLE(sm,ids[j]))
224     VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
225     else
226     smDir(sm,p,ids[j]);
227     if(dev_zmin > 1.0)
228     {
229     p[0] *= d;
230     p[1] *= d;
231     p[2] *= d;
232     }
233 gwlarson 3.1 VADD(p,p,vp);
234     glVertex3d(p[0],p[1],p[2]);
235     }
236     }
237    
238     smRender_mesh(sm,vp)
239     SM *sm;
240     FVECT vp;
241     {
242     int i;
243     TRI *tri;
244 gwlarson 3.2 double ptr[3],d;
245 gwlarson 3.1 int j;
246    
247 gwlarson 3.2 d = (dev_zmin+dev_zmax)/2.0;
248 gwlarson 3.1 glPushAttrib(GL_DEPTH_BUFFER_BIT);
249    
250     /* First draw background polygons */
251 gwlarson 3.2
252 gwlarson 3.1 glDisable(GL_DEPTH_TEST);
253     glBegin(GL_TRIANGLES);
254     SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
255 gwlarson 3.2 smRender_bg_tri(sm,i,vp,d);
256 gwlarson 3.1 glEnd();
257    
258     glEnable(GL_DEPTH_TEST);
259     glBegin(GL_TRIANGLES);
260     SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
261     smRender_tri(sm,i,vp);
262     glEnd();
263    
264     glPopAttrib();
265     }
266     smRender_tri_edges(sm,i)
267     SM *sm;
268     int i;
269     {
270     TRI *tri;
271     int j;
272     double ptr[3];
273    
274    
275     tri = SM_NTH_TRI(sm,i);
276    
277     /* Triangles are defined clockwise:historical relative to spherical
278     tris: could change
279     */
280     for(j=2; j >=0; j--)
281     {
282     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     }
287     }
288    
289     int
290     compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
291     {
292     double d;
293    
294     d = td2->depth-td1->depth;
295    
296     if(d > 0.0)
297     return(1);
298     if(d < 0.0)
299     return(-1);
300    
301     return(0);
302     }
303    
304     smDepth_sort_tris(sm,vp,td)
305     SM *sm;
306     VIEW *vp;
307     T_DEPTH *td;
308     {
309     int i,j,t_id;
310     TRI *tri;
311     double d[3];
312    
313     i = 0;
314     SM_FOR_ALL_NEW_TRIS(sm,t_id)
315     {
316     if(i >= smNew_tri_cnt)
317     {
318     #ifdef DEBUG
319     eputs("smDepth_sort_tris(): more new tris then counted\n");
320     #endif
321     break;
322     }
323     tri = SM_NTH_TRI(sm,t_id);
324     td[i].tri = t_id;
325     for(j=0;j < 3;j++)
326     d[j] = DIST(vp->vp,SM_T_NTH_WV(sm,tri,j));
327     td[i].depth = MIN_VEC3(d);
328     i++;
329     }
330     qsort((void *)td,smNew_tri_cnt,sizeof(T_DEPTH),compare_tri_depths);
331     }
332    
333    
334     smUpdate_Rendered_mesh(sm,vp)
335     SM *sm;
336     VIEW *vp;
337     {
338     static T_DEPTH *td= NULL;
339     static int tsize = 0;
340     int i;
341     GLint depth_test;
342 gwlarson 3.2 double d;
343 gwlarson 3.1
344     /* For all of the NEW triangles (since last update): assume
345     ACTIVE. Go through and sort on depth value (from vp). Turn
346     Depth Buffer test off and render back-front
347     */
348     /* NOTE: could malloc each time or hard code */
349     if(smNew_tri_cnt > tsize)
350     {
351     if(td)
352     free(td);
353     td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
354     tsize = smNew_tri_cnt;
355     }
356     if(!td)
357     {
358     error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
359     }
360     smDepth_sort_tris(sm,vp,td);
361    
362     /* Turn Depth Test off */
363     glPushAttrib(GL_DEPTH_BUFFER_BIT);
364     glDepthFunc(GL_ALWAYS); /* Turn off Depth-painter's algorithm */
365    
366 gwlarson 3.2 d = (dev_zmin+dev_zmax)/2.0;
367 gwlarson 3.1 /* Now render back-to front */
368     /* First render bg triangles */
369     glDisable(GL_DEPTH_TEST);
370     glBegin(GL_TRIANGLES);
371     for(i=0; i< smNew_tri_cnt; i++)
372     if(SM_BG_TRI(sm,td[i].tri))
373 gwlarson 3.2 smRender_bg_tri(sm,td[i].tri,vp,d);
374 gwlarson 3.1 glEnd();
375    
376     glEnable(GL_DEPTH_TEST);
377     glBegin(GL_TRIANGLES);
378     for(i=0; i< smNew_tri_cnt; i++)
379     if(!SM_BG_TRI(sm,td[i].tri))
380     smRender_tri(sm,td[i].tri,vp);
381     glEnd();
382    
383     /* Restore Depth Test */
384     glPopAttrib();
385     }
386    
387     /*
388     * smUpdate(vp, qua) : update OpenGL output geometry for view vp
389     * VIEW *vp; : desired view
390     * int qual; : quality level (percentage on linear time scale)
391     *
392     * Draw new geometric representation using OpenGL calls. Assume that the
393     * view has already been set up and the correct frame buffer has been
394     * selected for drawing. The quality level is on a linear scale, where 100%
395     * is full (final) quality. It is not necessary to redraw geometry that has
396     * been output since the last call to smClean().
397     */
398     smUpdate(vp,qual)
399     VIEW *vp;
400     int qual;
401     {
402     double d;
403     int t;
404     #ifdef TEST_DRIVER
405     Current_View = (*vp);
406     #endif
407     /* If view has moved beyond epsilon from canonical: must rebuild -
408     epsilon is calculated as running avg of distance of sample points
409     from canonical view: m = 1/(SUM1/r): some fraction of this
410     */
411     d = DIST(vp->vp,SM_VIEW_CENTER(smMesh));
412     if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
413     {
414     smNew_tri_cnt = 0;
415     /* Re-build the mesh */
416     smRebuild_mesh(smMesh,vp);
417     }
418     /* Check if should draw ALL triangles in current frustum */
419     if(smClean_notify || (smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT))
420     {
421     #ifdef TEST_DRIVER
422     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
423     #else
424     tmClearHisto();
425     tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
426     if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
427     return;
428     if(tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
429     SM_NUM_SAMP(smMesh))!=TM_E_OK)
430     return;
431     #endif
432     smRender_mesh(smMesh,vp->vp);
433     smClean_notify = FALSE;
434     #ifdef TEST_DRIVER
435     glFlush();
436     glutSwapBuffers();
437     #endif
438     }
439     /* Do an incremental update instead */
440     else
441     {
442     if(!smNew_tri_cnt)
443     return;
444     #ifdef TEST_DRIVER
445     glDrawBuffer(GL_FRONT);
446     #else
447     t = SM_TONE_MAP(smMesh);
448     if(t == 0)
449     {
450     tmClearHisto();
451     tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
452     if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
453     return;
454     }
455     if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
456     SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
457     return;
458     #endif
459     smUpdate_Rendered_mesh(smMesh,vp);
460    
461     #ifdef TEST_DRIVER
462     glDrawBuffer(GL_BACK);
463     #endif
464     }
465     SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
466     }
467    
468     /* LATER:If quality < 100 should draw approximation because it indicates
469     the user is moving
470     */
471    
472