ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/sm_ogl.c
Revision: 3.1
Committed: Wed Aug 19 17:45:24 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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     glColor3ub(SM_NTH_RGB(sm,T_NTH_V(tri,j))[0],
166     SM_NTH_RGB(sm,T_NTH_V(tri,j))[1],
167     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]);
170     }
171     }
172    
173     /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
174     ADJACENT TRIANGLES TO BG be BG
175     */
176     smRender_bg_tri(sm,i,vp)
177     SM *sm;
178     int i;
179     FVECT vp;
180     {
181     TRI *tri;
182     FVECT p;
183     int j,ids[3],cnt;
184     BYTE rgb[3];
185    
186     tri = SM_NTH_TRI(sm,i);
187     SM_CLEAR_NTH_T_NEW(sm,i);
188     if(smNew_tri_cnt)
189     smNew_tri_cnt--;
190     /* NOTE:Triangles are defined clockwise:historical relative to spherical
191     tris: could change
192     */
193     cnt = 0;
194     rgb[0] = rgb[1] = rgb[2] = 0;
195     for(j=0;j<3;j++)
196     {
197     ids[j] = T_NTH_V(tri,j);
198     if(SM_BG_SAMPLE(sm,ids[j]))
199     {
200     rgb[0] += SM_NTH_RGB(sm,ids[j])[0];
201     rgb[1] += SM_NTH_RGB(sm,ids[j])[1];
202     rgb[2] += SM_NTH_RGB(sm,ids[j])[2];
203     cnt++;
204     }
205     }
206     if(cnt)
207     {
208     rgb[0]/=cnt; rgb[1]/=cnt; rgb[2]/=cnt;
209     }
210     for(j=2; j>= 0; j--)
211     {
212     if(SM_BG_SAMPLE(sm,ids[j]))
213     glColor3ub(SM_NTH_RGB(sm,ids[j])[0],SM_NTH_RGB(sm,ids[j])[1],
214     SM_NTH_RGB(sm,ids[j])[2]);
215     else
216     glColor3ub(rgb[0],rgb[1],rgb[2]);
217     VSUB(p,SM_NTH_WV(sm,ids[j]),SM_VIEW_CENTER(sm));
218     VADD(p,p,vp);
219     glVertex3d(p[0],p[1],p[2]);
220     }
221     }
222    
223     smRender_mesh(sm,vp)
224     SM *sm;
225     FVECT vp;
226     {
227     int i;
228     TRI *tri;
229     double ptr[3];
230     int j;
231    
232     glPushAttrib(GL_DEPTH_BUFFER_BIT);
233    
234     /* First draw background polygons */
235     glDisable(GL_DEPTH_TEST);
236     glBegin(GL_TRIANGLES);
237     SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
238     smRender_bg_tri(sm,i,vp);
239     glEnd();
240    
241     glEnable(GL_DEPTH_TEST);
242     glBegin(GL_TRIANGLES);
243     SM_FOR_ALL_ACTIVE_FG_TRIS(sm,i)
244     smRender_tri(sm,i,vp);
245     glEnd();
246    
247     glPopAttrib();
248     }
249     smRender_tri_edges(sm,i)
250     SM *sm;
251     int i;
252     {
253     TRI *tri;
254     int j;
255     double ptr[3];
256    
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    
272     int
273     compare_tri_depths(T_DEPTH *td1,T_DEPTH *td2)
274     {
275     double d;
276    
277     d = td2->depth-td1->depth;
278    
279     if(d > 0.0)
280     return(1);
281     if(d < 0.0)
282     return(-1);
283    
284     return(0);
285     }
286    
287     smDepth_sort_tris(sm,vp,td)
288     SM *sm;
289     VIEW *vp;
290     T_DEPTH *td;
291     {
292     int i,j,t_id;
293     TRI *tri;
294     double d[3];
295    
296     i = 0;
297     SM_FOR_ALL_NEW_TRIS(sm,t_id)
298     {
299     if(i >= smNew_tri_cnt)
300     {
301     #ifdef DEBUG
302     eputs("smDepth_sort_tris(): more new tris then counted\n");
303     #endif
304     break;
305     }
306     tri = SM_NTH_TRI(sm,t_id);
307     td[i].tri = t_id;
308     for(j=0;j < 3;j++)
309     d[j] = DIST(vp->vp,SM_T_NTH_WV(sm,tri,j));
310     td[i].depth = MIN_VEC3(d);
311     i++;
312     }
313     qsort((void *)td,smNew_tri_cnt,sizeof(T_DEPTH),compare_tri_depths);
314     }
315    
316    
317     smUpdate_Rendered_mesh(sm,vp)
318     SM *sm;
319     VIEW *vp;
320     {
321     static T_DEPTH *td= NULL;
322     static int tsize = 0;
323     int i;
324     GLint depth_test;
325    
326     /* For all of the NEW triangles (since last update): assume
327     ACTIVE. Go through and sort on depth value (from vp). Turn
328     Depth Buffer test off and render back-front
329     */
330     /* NOTE: could malloc each time or hard code */
331     if(smNew_tri_cnt > tsize)
332     {
333     if(td)
334     free(td);
335     td = (T_DEPTH *)malloc(smNew_tri_cnt*sizeof(T_DEPTH));
336     tsize = smNew_tri_cnt;
337     }
338     if(!td)
339     {
340     error(SYSTEM,"smUpdate_Rendered_mesh:Cannot allocate memory\n");
341     }
342     smDepth_sort_tris(sm,vp,td);
343    
344     /* Turn Depth Test off */
345     glPushAttrib(GL_DEPTH_BUFFER_BIT);
346     glDepthFunc(GL_ALWAYS); /* Turn off Depth-painter's algorithm */
347    
348     /* Now render back-to front */
349     /* First render bg triangles */
350     glDisable(GL_DEPTH_TEST);
351     glBegin(GL_TRIANGLES);
352     for(i=0; i< smNew_tri_cnt; i++)
353     if(SM_BG_TRI(sm,td[i].tri))
354     smRender_bg_tri(sm,td[i].tri,vp);
355     glEnd();
356    
357     glEnable(GL_DEPTH_TEST);
358     glBegin(GL_TRIANGLES);
359     for(i=0; i< smNew_tri_cnt; i++)
360     if(!SM_BG_TRI(sm,td[i].tri))
361     smRender_tri(sm,td[i].tri,vp);
362     glEnd();
363    
364     /* Restore Depth Test */
365     glPopAttrib();
366     }
367    
368     /*
369     * smUpdate(vp, qua) : update OpenGL output geometry for view vp
370     * VIEW *vp; : desired view
371     * int qual; : quality level (percentage on linear time scale)
372     *
373     * Draw new geometric representation using OpenGL calls. Assume that the
374     * view has already been set up and the correct frame buffer has been
375     * selected for drawing. The quality level is on a linear scale, where 100%
376     * is full (final) quality. It is not necessary to redraw geometry that has
377     * been output since the last call to smClean().
378     */
379     smUpdate(vp,qual)
380     VIEW *vp;
381     int qual;
382     {
383     double d;
384     int t;
385     #ifdef TEST_DRIVER
386     Current_View = (*vp);
387     #endif
388     /* If view has moved beyond epsilon from canonical: must rebuild -
389     epsilon is calculated as running avg of distance of sample points
390     from canonical view: m = 1/(SUM1/r): some fraction of this
391     */
392     d = DIST(vp->vp,SM_VIEW_CENTER(smMesh));
393     if(qual >= 100 && d > SM_ALLOWED_VIEW_CHANGE(smMesh))
394     {
395     smNew_tri_cnt = 0;
396     /* Re-build the mesh */
397     smRebuild_mesh(smMesh,vp);
398     }
399     /* Check if should draw ALL triangles in current frustum */
400     if(smClean_notify || (smNew_tri_cnt > SM_NUM_TRIS(smMesh)*SM_INC_PERCENT))
401     {
402     #ifdef TEST_DRIVER
403     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
404     #else
405     tmClearHisto();
406     tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
407     if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
408     return;
409     if(tmMapPixels(SM_RGB(smMesh),SM_BRT(smMesh),SM_CHR(smMesh),
410     SM_NUM_SAMP(smMesh))!=TM_E_OK)
411     return;
412     #endif
413     smRender_mesh(smMesh,vp->vp);
414     smClean_notify = FALSE;
415     #ifdef TEST_DRIVER
416     glFlush();
417     glutSwapBuffers();
418     #endif
419     }
420     /* Do an incremental update instead */
421     else
422     {
423     if(!smNew_tri_cnt)
424     return;
425     #ifdef TEST_DRIVER
426     glDrawBuffer(GL_FRONT);
427     #else
428     t = SM_TONE_MAP(smMesh);
429     if(t == 0)
430     {
431     tmClearHisto();
432     tmAddHisto(SM_BRT(smMesh),SM_NUM_SAMP(smMesh),1);
433     if(tmComputeMapping(0.,0.,0.) != TM_E_OK)
434     return;
435     }
436     if(tmMapPixels(SM_NTH_RGB(smMesh,t),&SM_NTH_BRT(smMesh,t),
437     SM_NTH_CHR(smMesh,t), SM_NUM_SAMP(smMesh)-t) != TM_E_OK)
438     return;
439     #endif
440     smUpdate_Rendered_mesh(smMesh,vp);
441    
442     #ifdef TEST_DRIVER
443     glDrawBuffer(GL_BACK);
444     #endif
445     }
446     SM_TONE_MAP(smMesh) = SM_NUM_SAMP(smMesh);
447     }
448    
449     /* LATER:If quality < 100 should draw approximation because it indicates
450     the user is moving
451     */
452    
453