ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglsurf.c
Revision: 3.12
Committed: Tue Mar 30 20:40:03 2004 UTC (20 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 3.11: +5 -5 lines
Log Message:
ANSI-discovered fixes thanks to Schorsh

File Contents

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