ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglsurf.c
Revision: 3.9
Committed: Sun May 25 15:41:31 2003 UTC (20 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.8: +6 -6 lines
Log Message:
Fixed another bug pointed out by Thoms Bleicher, but this isn't it, either

File Contents

# User Rev Content
1 gwlarson 3.1 #ifndef lint
2 greg 3.8 static const char RCSid[] = "$Id$";
3 gwlarson 3.1 #endif
4     /*
5     * Convert Radiance -> OpenGL surfaces.
6     */
7    
8 greg 3.5 #include "copyright.h"
9 greg 3.4
10 gwlarson 3.1 #include "radogl.h"
11    
12     #ifndef NSLICES
13     #define NSLICES 18 /* number of quadric slices */
14     #endif
15     #ifndef NSTACKS
16     #define NSTACKS 10 /* number of quadric stacks */
17     #endif
18    
19     MATREC *curmat = NULL; /* current material */
20    
21     static int curpolysize = 0; /* outputting triangles/quads */
22    
23     static GLUquadricObj *gluqo; /* shared quadric object */
24     static GLUtesselator *gluto; /* shared tessallation object */
25    
26     static char *glu_rout = "unk"; /* active GLU routine */
27    
28     #define NOPOLY() if (curpolysize) {glEnd(); curpolysize = 0;} else
29    
30    
31 greg 3.4 void
32 gwlarson 3.1 setmaterial(mp, cent, ispoly) /* prepare for new material */
33     register MATREC *mp;
34     FVECT cent;
35     int ispoly;
36     {
37     if (mp != curmat && domats) {
38     NOPOLY();
39     domatobj(curmat = mp, cent);
40     } else if (!ispoly)
41     NOPOLY();
42     }
43    
44    
45     double
46     polyarea(cent, norm, n, v) /* compute polygon area & normal */
47     FVECT cent, norm; /* returned center and normal */
48     int n; /* number of vertices */
49     register FVECT v[]; /* vertex list */
50     {
51     FVECT v1, v2, v3;
52     double d;
53     register int i;
54    
55     norm[0] = norm[1] = norm[2] = 0.;
56     v1[0] = v[1][0] - v[0][0];
57     v1[1] = v[1][1] - v[0][1];
58     v1[2] = v[1][2] - v[0][2];
59     for (i = 2; i < n; i++) {
60     v2[0] = v[i][0] - v[0][0];
61     v2[1] = v[i][1] - v[0][1];
62     v2[2] = v[i][2] - v[0][2];
63     fcross(v3, v1, v2);
64     norm[0] += v3[0];
65     norm[1] += v3[1];
66     norm[2] += v3[2];
67     VCOPY(v1, v2);
68     }
69     if (cent != NULL) { /* compute center also */
70     cent[0] = cent[1] = cent[2] = 0.;
71     for (i = n; i--; ) {
72     cent[0] += v[i][0];
73     cent[1] += v[i][1];
74     cent[2] += v[i][2];
75     }
76     d = 1./n;
77     cent[0] *= d; cent[1] *= d; cent[2] *= d;
78     }
79     return(normalize(norm)*.5);
80     }
81    
82    
83 greg 3.4 static void
84 gwlarson 3.2 glu_error(en) /* report an error as a warning */
85 gwlarson 3.1 GLenum en;
86     {
87     sprintf(errmsg, "GLU error %s: %s", glu_rout, gluErrorString(en));
88     error(WARNING, errmsg);
89     }
90    
91    
92 gwlarson 3.3 static void
93     myCombine(coords, vertex_data, weight, dataOut)
94     register GLdouble coords[3];
95     GLdouble *vertex_data[4];
96     GLfloat weight[4];
97     GLdouble **dataOut;
98     {
99     register GLdouble *newvert;
100    
101     newvert = (GLdouble *)malloc(3*sizeof(GLdouble));
102     if (newvert == NULL)
103     error(SYSTEM, "out of memory in myCombine");
104     VCOPY(newvert, coords); /* no data, just coordinates */
105     *dataOut = newvert;
106     }
107    
108    
109 gwlarson 3.1 static
110     newtess() /* allocate GLU tessellation object */
111     {
112     if ((gluto = gluNewTess()) == NULL)
113     error(INTERNAL, "gluNewTess failed");
114 greg 3.6 gluTessCallback(gluto, GLU_TESS_BEGIN, glBegin);
115     gluTessCallback(gluto, GLU_TESS_VERTEX, glVertex3dv);
116 gwlarson 3.1 gluTessCallback(gluto, GLU_TESS_END, glEnd);
117 gwlarson 3.3 gluTessCallback(gluto, GLU_TESS_COMBINE, myCombine);
118 gwlarson 3.1 gluTessCallback(gluto, GLU_TESS_ERROR, glu_error);
119     gluTessProperty(gluto, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
120     }
121    
122    
123     static
124     newquadric() /* allocate GLU quadric structure */
125     {
126     if ((gluqo = gluNewQuadric()) == NULL)
127     error(INTERNAL, "gluNewQuadric failed");
128     gluQuadricDrawStyle(gluqo, GLU_FILL);
129     gluQuadricCallback(gluqo, GLU_ERROR, glu_error);
130     }
131    
132    
133 greg 3.4 int
134 gwlarson 3.1 o_face(o) /* convert a face */
135     register OBJREC *o;
136     {
137     double area;
138     FVECT norm, cent;
139     register int i;
140    
141     if (o->oargs.nfargs < 9 | o->oargs.nfargs % 3)
142     objerror(o, USER, "bad # real arguments");
143     area = polyarea(cent, norm, o->oargs.nfargs/3, (FVECT *)o->oargs.farg);
144     if (area <= FTINY)
145 greg 3.7 return(0);
146 gwlarson 3.1 if (dolights) /* check for source */
147 greg 3.4 doflatsrc((MATREC *)o->os, cent, norm, area);
148     setmaterial((MATREC *)o->os, cent, 1); /* set material */
149 gwlarson 3.1 if (o->oargs.nfargs/3 != curpolysize) {
150     if (curpolysize) glEnd();
151     curpolysize = o->oargs.nfargs/3;
152     if (curpolysize == 3)
153     glBegin(GL_TRIANGLES);
154     else if (curpolysize == 4)
155     glBegin(GL_QUADS);
156     }
157     glNormal3d((GLdouble)norm[0], (GLdouble)norm[1], (GLdouble)norm[2]);
158     if (curpolysize > 4) {
159     if (gluto == NULL) newtess();
160     glu_rout = "tessellating polygon";
161     gluTessNormal(gluto, (GLdouble)norm[0],
162     (GLdouble)norm[1], (GLdouble)norm[2]);
163     gluTessBeginPolygon(gluto, NULL);
164     gluTessBeginContour(gluto);
165     #ifdef SMLFLT
166     error(INTERNAL, "bad code segment in o_face");
167     #endif
168     for (i = 0; i < curpolysize; i++)
169     gluTessVertex(gluto, (GLdouble *)(o->oargs.farg+3*i),
170     (void *)(o->oargs.farg+3*i));
171     gluTessEndContour(gluto);
172     gluTessEndPolygon(gluto);
173     curpolysize = 0;
174     } else {
175     for (i = 0; i < curpolysize; i++)
176     glVertex3d((GLdouble)o->oargs.farg[3*i],
177     (GLdouble)o->oargs.farg[3*i+1],
178     (GLdouble)o->oargs.farg[3*i+2]);
179     }
180 greg 3.7 return(0);
181 gwlarson 3.1 }
182    
183    
184 greg 3.4 void
185 gwlarson 3.1 surfclean() /* clean up surface routines */
186     {
187     setmaterial(NULL, NULL, 0);
188     if (gluqo != NULL) {
189     gluDeleteQuadric(gluqo);
190     gluqo = NULL;
191     }
192     if (gluto != NULL) {
193     gluDeleteTess(gluto);
194     gluto = NULL;
195     }
196     rgl_checkerr("in surfclean");
197     }
198    
199    
200 greg 3.4 int
201 gwlarson 3.1 o_sphere(o) /* convert a sphere */
202     register OBJREC *o;
203     {
204     /* check arguments */
205     if (o->oargs.nfargs != 4)
206     objerror(o, USER, "bad # real arguments");
207     if (o->oargs.farg[3] < -FTINY) {
208     o->otype = o->otype==OBJ_SPHERE ? OBJ_BUBBLE : OBJ_SPHERE;
209     o->oargs.farg[3] = -o->oargs.farg[3];
210     } else if (o->oargs.farg[3] <= FTINY)
211 greg 3.7 return(0);
212 gwlarson 3.1 if (dolights)
213 greg 3.4 dosphsrc((MATREC *)o->os, o->oargs.farg,
214 gwlarson 3.1 PI*o->oargs.farg[3]*o->oargs.farg[3]);
215 greg 3.4 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
216 gwlarson 3.1 if (gluqo == NULL) newquadric();
217     glu_rout = "making sphere";
218     gluQuadricOrientation(gluqo,
219     o->otype==OBJ_BUBBLE ? GLU_INSIDE : GLU_OUTSIDE);
220     gluQuadricNormals(gluqo, GLU_SMOOTH);
221     glMatrixMode(GL_MODELVIEW);
222     glPushMatrix();
223     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
224     (GLdouble)o->oargs.farg[2]);
225     gluSphere(gluqo, (GLdouble)o->oargs.farg[3], NSLICES, NSTACKS);
226     glPopMatrix();
227 greg 3.7 return(0);
228 gwlarson 3.1 }
229    
230    
231 greg 3.4 int
232 gwlarson 3.1 o_cone(o) /* convert a cone or cylinder */
233     register OBJREC *o;
234     {
235     double x1, y1, h, d;
236     FVECT cent;
237     register int iscyl;
238    
239     iscyl = o->otype==OBJ_CYLINDER | o->otype==OBJ_TUBE;
240     if (o->oargs.nfargs != (iscyl ? 7 : 8))
241 greg 3.4 objerror(o, USER, "bad # real arguments");
242 gwlarson 3.1 if (o->oargs.farg[6] < -FTINY) {
243     o->oargs.farg[6] = -o->oargs.farg[6];
244     if (iscyl)
245     o->otype = o->otype==OBJ_CYLINDER ?
246     OBJ_TUBE : OBJ_CYLINDER;
247     else {
248     if ((o->oargs.farg[7] = -o->oargs.farg[7]) < -FTINY)
249     objerror(o, USER, "illegal radii");
250     o->otype = o->otype==OBJ_CONE ? OBJ_CUP : OBJ_CONE;
251     }
252     } else if (!iscyl && o->oargs.farg[7] < -FTINY)
253     objerror(o, USER, "illegal radii");
254     if (o->oargs.farg[6] <= FTINY && (iscyl || o->oargs.farg[7] <= FTINY))
255     return;
256 gwlarson 3.3 if (!iscyl) {
257     if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
258     o->oargs.farg[6] = 0.;
259     if (o->oargs.farg[7] < 0.)
260     o->oargs.farg[7] = 0.;
261     }
262 greg 3.9 h = sqrt(dist2(o->oargs.farg,o->oargs.farg+3));
263     if (h <= FTINY)
264     return;
265 gwlarson 3.1 cent[0] = .5*(o->oargs.farg[0] + o->oargs.farg[3]);
266     cent[1] = .5*(o->oargs.farg[1] + o->oargs.farg[4]);
267     cent[2] = .5*(o->oargs.farg[2] + o->oargs.farg[5]);
268 greg 3.4 setmaterial((MATREC *)o->os, cent, 0);
269 gwlarson 3.1 if (gluqo == NULL) newquadric();
270     glu_rout = "making cylinder";
271     gluQuadricOrientation(gluqo, o->otype==OBJ_CUP | o->otype==OBJ_TUBE ?
272     GLU_INSIDE : GLU_OUTSIDE);
273     gluQuadricNormals(gluqo, GLU_SMOOTH);
274     glMatrixMode(GL_MODELVIEW);
275     glPushMatrix();
276     /* do base translation */
277     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
278     (GLdouble)o->oargs.farg[2]);
279     /* compute height & rotation angle */
280     x1 = o->oargs.farg[1] - o->oargs.farg[4];
281     y1 = o->oargs.farg[3] - o->oargs.farg[0];
282     /* z1 = 0; */
283 greg 3.8 d = x1*x1 + y1*y1;
284     if (d <= FTINY*FTINY)
285     x1 = 1.;
286     else
287     d = 180./PI * asin(sqrt(d) / h);
288 gwlarson 3.1 if (o->oargs.farg[5] < o->oargs.farg[2])
289     d = 180. - d;
290     if (d > FTINY)
291     glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
292     gluCylinder(gluqo, o->oargs.farg[6], o->oargs.farg[iscyl ? 6 : 7],
293     h, NSLICES, 1);
294     glPopMatrix();
295 greg 3.7 return(0);
296 gwlarson 3.1 }
297    
298    
299 greg 3.4 int
300 gwlarson 3.1 o_ring(o) /* convert a ring */
301     register OBJREC *o;
302     {
303 greg 3.8 double x1, y1, d, h;
304 gwlarson 3.1
305     if (o->oargs.nfargs != 8)
306 greg 3.4 objerror(o, USER, "bad # real arguments");
307 gwlarson 3.1 if (o->oargs.farg[7] < o->oargs.farg[6]) {
308     register double d = o->oargs.farg[7];
309     o->oargs.farg[7] = o->oargs.farg[6];
310     o->oargs.farg[6] = d;
311     }
312     if (o->oargs.farg[6] < -FTINY)
313     objerror(o, USER, "negative radius");
314     if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
315     o->oargs.farg[6] = 0.;
316     if (o->oargs.farg[7] - o->oargs.farg[6] <= FTINY)
317     return;
318 greg 3.9 h = VLEN(o->oargs.farg+3);
319     if (h <= FTINY)
320     return;
321 gwlarson 3.1 if (dolights)
322 greg 3.4 doflatsrc((MATREC *)o->os, o->oargs.farg, o->oargs.farg+3,
323 gwlarson 3.1 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
324     o->oargs.farg[6]*o->oargs.farg[6]));
325 greg 3.4 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
326 gwlarson 3.1 if (gluqo == NULL) newquadric();
327     glu_rout = "making disk";
328     gluQuadricOrientation(gluqo, GLU_OUTSIDE);
329     gluQuadricNormals(gluqo, GLU_FLAT);
330     glMatrixMode(GL_MODELVIEW);
331     glPushMatrix();
332     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
333     (GLdouble)o->oargs.farg[2]);
334     /* compute rotation angle */
335     x1 = -o->oargs.farg[4];
336     y1 = o->oargs.farg[3];
337     /* z1 = 0; */
338 greg 3.8 d = x1*x1 + y1*y1;
339     if (d <= FTINY*FTINY)
340     x1 = 1.;
341     else
342     d = 180./PI * asin(sqrt(d) / h);
343 gwlarson 3.1 if (o->oargs.farg[5] < 0.)
344     d = 180. - d;
345     if (d > FTINY)
346     glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
347     gluDisk(gluqo, o->oargs.farg[6], o->oargs.farg[7], NSLICES, 1);
348     glPopMatrix();
349 greg 3.7 return(0);
350 gwlarson 3.1 }