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

# Content
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 #ifdef DEBUG
166 if(SM_BG_SAMPLE(sm,T_NTH_V(tri,j)))
167 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]);
174 }
175 }
176
177 /* NOTE SEEMS BAD TO PENALIZE POLYGONS INFRONT BY LETTING
178 ADJACENT TRIANGLES TO BG be BG
179 */
180 smRender_bg_tri(sm,i,vp,d)
181 SM *sm;
182 int i;
183 FVECT vp;
184 double d;
185 {
186 TRI *tri;
187 FVECT p;
188 int j,ids[3],cnt;
189 int rgb[3];
190
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--;
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 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 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 double ptr[3],d;
245 int j;
246
247 d = (dev_zmin+dev_zmax)/2.0;
248 glPushAttrib(GL_DEPTH_BUFFER_BIT);
249
250 /* First draw background polygons */
251
252 glDisable(GL_DEPTH_TEST);
253 glBegin(GL_TRIANGLES);
254 SM_FOR_ALL_ACTIVE_BG_TRIS(sm,i)
255 smRender_bg_tri(sm,i,vp,d);
256 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 double d;
343
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 d = (dev_zmin+dev_zmax)/2.0;
367 /* 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 smRender_bg_tri(sm,td[i].tri,vp,d);
374 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