ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglsurf.c
Revision: 3.4
Committed: Sat Feb 22 02:07:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.3: +76 -16 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 gwlarson 3.1 #ifndef lint
2 greg 3.4 static const char RCSid[] = "$Id$";
3 gwlarson 3.1 #endif
4     /*
5     * Convert Radiance -> OpenGL surfaces.
6     */
7    
8 greg 3.4 /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65 gwlarson 3.1 #include "radogl.h"
66    
67     #ifndef NSLICES
68     #define NSLICES 18 /* number of quadric slices */
69     #endif
70     #ifndef NSTACKS
71     #define NSTACKS 10 /* number of quadric stacks */
72     #endif
73    
74     MATREC *curmat = NULL; /* current material */
75    
76     static int curpolysize = 0; /* outputting triangles/quads */
77    
78     static GLUquadricObj *gluqo; /* shared quadric object */
79     static GLUtesselator *gluto; /* shared tessallation object */
80    
81     static char *glu_rout = "unk"; /* active GLU routine */
82    
83     #define NOPOLY() if (curpolysize) {glEnd(); curpolysize = 0;} else
84    
85    
86 greg 3.4 void
87 gwlarson 3.1 setmaterial(mp, cent, ispoly) /* prepare for new material */
88     register MATREC *mp;
89     FVECT cent;
90     int ispoly;
91     {
92     if (mp != curmat && domats) {
93     NOPOLY();
94     domatobj(curmat = mp, cent);
95     } else if (!ispoly)
96     NOPOLY();
97     }
98    
99    
100     double
101     polyarea(cent, norm, n, v) /* compute polygon area & normal */
102     FVECT cent, norm; /* returned center and normal */
103     int n; /* number of vertices */
104     register FVECT v[]; /* vertex list */
105     {
106     FVECT v1, v2, v3;
107     double d;
108     register int i;
109    
110     norm[0] = norm[1] = norm[2] = 0.;
111     v1[0] = v[1][0] - v[0][0];
112     v1[1] = v[1][1] - v[0][1];
113     v1[2] = v[1][2] - v[0][2];
114     for (i = 2; i < n; i++) {
115     v2[0] = v[i][0] - v[0][0];
116     v2[1] = v[i][1] - v[0][1];
117     v2[2] = v[i][2] - v[0][2];
118     fcross(v3, v1, v2);
119     norm[0] += v3[0];
120     norm[1] += v3[1];
121     norm[2] += v3[2];
122     VCOPY(v1, v2);
123     }
124     if (cent != NULL) { /* compute center also */
125     cent[0] = cent[1] = cent[2] = 0.;
126     for (i = n; i--; ) {
127     cent[0] += v[i][0];
128     cent[1] += v[i][1];
129     cent[2] += v[i][2];
130     }
131     d = 1./n;
132     cent[0] *= d; cent[1] *= d; cent[2] *= d;
133     }
134     return(normalize(norm)*.5);
135     }
136    
137    
138 greg 3.4 static void
139 gwlarson 3.2 glu_error(en) /* report an error as a warning */
140 gwlarson 3.1 GLenum en;
141     {
142     sprintf(errmsg, "GLU error %s: %s", glu_rout, gluErrorString(en));
143     error(WARNING, errmsg);
144     }
145    
146    
147 gwlarson 3.3 static void
148     myCombine(coords, vertex_data, weight, dataOut)
149     register GLdouble coords[3];
150     GLdouble *vertex_data[4];
151     GLfloat weight[4];
152     GLdouble **dataOut;
153     {
154     register GLdouble *newvert;
155    
156     newvert = (GLdouble *)malloc(3*sizeof(GLdouble));
157     if (newvert == NULL)
158     error(SYSTEM, "out of memory in myCombine");
159     VCOPY(newvert, coords); /* no data, just coordinates */
160     *dataOut = newvert;
161     }
162    
163    
164 gwlarson 3.1 static
165     newtess() /* allocate GLU tessellation object */
166     {
167     if ((gluto = gluNewTess()) == NULL)
168     error(INTERNAL, "gluNewTess failed");
169 greg 3.4 gluTessCallback(gluto, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin);
170     gluTessCallback(gluto, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
171 gwlarson 3.1 gluTessCallback(gluto, GLU_TESS_END, glEnd);
172 gwlarson 3.3 gluTessCallback(gluto, GLU_TESS_COMBINE, myCombine);
173 gwlarson 3.1 gluTessCallback(gluto, GLU_TESS_ERROR, glu_error);
174     gluTessProperty(gluto, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
175     }
176    
177    
178     static
179     newquadric() /* allocate GLU quadric structure */
180     {
181     if ((gluqo = gluNewQuadric()) == NULL)
182     error(INTERNAL, "gluNewQuadric failed");
183     gluQuadricDrawStyle(gluqo, GLU_FILL);
184     gluQuadricCallback(gluqo, GLU_ERROR, glu_error);
185     }
186    
187    
188 greg 3.4 int
189 gwlarson 3.1 o_face(o) /* convert a face */
190     register OBJREC *o;
191     {
192     double area;
193     FVECT norm, cent;
194     register int i;
195    
196     if (o->oargs.nfargs < 9 | o->oargs.nfargs % 3)
197     objerror(o, USER, "bad # real arguments");
198     area = polyarea(cent, norm, o->oargs.nfargs/3, (FVECT *)o->oargs.farg);
199     if (area <= FTINY)
200     return;
201     if (dolights) /* check for source */
202 greg 3.4 doflatsrc((MATREC *)o->os, cent, norm, area);
203     setmaterial((MATREC *)o->os, cent, 1); /* set material */
204 gwlarson 3.1 if (o->oargs.nfargs/3 != curpolysize) {
205     if (curpolysize) glEnd();
206     curpolysize = o->oargs.nfargs/3;
207     if (curpolysize == 3)
208     glBegin(GL_TRIANGLES);
209     else if (curpolysize == 4)
210     glBegin(GL_QUADS);
211     }
212     glNormal3d((GLdouble)norm[0], (GLdouble)norm[1], (GLdouble)norm[2]);
213     if (curpolysize > 4) {
214     if (gluto == NULL) newtess();
215     glu_rout = "tessellating polygon";
216     gluTessNormal(gluto, (GLdouble)norm[0],
217     (GLdouble)norm[1], (GLdouble)norm[2]);
218     gluTessBeginPolygon(gluto, NULL);
219     gluTessBeginContour(gluto);
220     #ifdef SMLFLT
221     error(INTERNAL, "bad code segment in o_face");
222     #endif
223     for (i = 0; i < curpolysize; i++)
224     gluTessVertex(gluto, (GLdouble *)(o->oargs.farg+3*i),
225     (void *)(o->oargs.farg+3*i));
226     gluTessEndContour(gluto);
227     gluTessEndPolygon(gluto);
228     curpolysize = 0;
229     } else {
230     for (i = 0; i < curpolysize; i++)
231     glVertex3d((GLdouble)o->oargs.farg[3*i],
232     (GLdouble)o->oargs.farg[3*i+1],
233     (GLdouble)o->oargs.farg[3*i+2]);
234     }
235     }
236    
237    
238 greg 3.4 void
239 gwlarson 3.1 surfclean() /* clean up surface routines */
240     {
241     setmaterial(NULL, NULL, 0);
242     if (gluqo != NULL) {
243     gluDeleteQuadric(gluqo);
244     gluqo = NULL;
245     }
246     if (gluto != NULL) {
247     gluDeleteTess(gluto);
248     gluto = NULL;
249     }
250     rgl_checkerr("in surfclean");
251     }
252    
253    
254 greg 3.4 int
255 gwlarson 3.1 o_sphere(o) /* convert a sphere */
256     register OBJREC *o;
257     {
258     /* check arguments */
259     if (o->oargs.nfargs != 4)
260     objerror(o, USER, "bad # real arguments");
261     if (o->oargs.farg[3] < -FTINY) {
262     o->otype = o->otype==OBJ_SPHERE ? OBJ_BUBBLE : OBJ_SPHERE;
263     o->oargs.farg[3] = -o->oargs.farg[3];
264     } else if (o->oargs.farg[3] <= FTINY)
265     return;
266     if (dolights)
267 greg 3.4 dosphsrc((MATREC *)o->os, o->oargs.farg,
268 gwlarson 3.1 PI*o->oargs.farg[3]*o->oargs.farg[3]);
269 greg 3.4 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
270 gwlarson 3.1 if (gluqo == NULL) newquadric();
271     glu_rout = "making sphere";
272     gluQuadricOrientation(gluqo,
273     o->otype==OBJ_BUBBLE ? GLU_INSIDE : GLU_OUTSIDE);
274     gluQuadricNormals(gluqo, GLU_SMOOTH);
275     glMatrixMode(GL_MODELVIEW);
276     glPushMatrix();
277     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
278     (GLdouble)o->oargs.farg[2]);
279     gluSphere(gluqo, (GLdouble)o->oargs.farg[3], NSLICES, NSTACKS);
280     glPopMatrix();
281     }
282    
283    
284 greg 3.4 int
285 gwlarson 3.1 o_cone(o) /* convert a cone or cylinder */
286     register OBJREC *o;
287     {
288     double x1, y1, h, d;
289     FVECT cent;
290     register int iscyl;
291    
292     iscyl = o->otype==OBJ_CYLINDER | o->otype==OBJ_TUBE;
293     if (o->oargs.nfargs != (iscyl ? 7 : 8))
294 greg 3.4 objerror(o, USER, "bad # real arguments");
295 gwlarson 3.1 if (o->oargs.farg[6] < -FTINY) {
296     o->oargs.farg[6] = -o->oargs.farg[6];
297     if (iscyl)
298     o->otype = o->otype==OBJ_CYLINDER ?
299     OBJ_TUBE : OBJ_CYLINDER;
300     else {
301     if ((o->oargs.farg[7] = -o->oargs.farg[7]) < -FTINY)
302     objerror(o, USER, "illegal radii");
303     o->otype = o->otype==OBJ_CONE ? OBJ_CUP : OBJ_CONE;
304     }
305     } else if (!iscyl && o->oargs.farg[7] < -FTINY)
306     objerror(o, USER, "illegal radii");
307     if (o->oargs.farg[6] <= FTINY && (iscyl || o->oargs.farg[7] <= FTINY))
308     return;
309 gwlarson 3.3 if (!iscyl) {
310     if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
311     o->oargs.farg[6] = 0.;
312     if (o->oargs.farg[7] < 0.)
313     o->oargs.farg[7] = 0.;
314     }
315 gwlarson 3.1 cent[0] = .5*(o->oargs.farg[0] + o->oargs.farg[3]);
316     cent[1] = .5*(o->oargs.farg[1] + o->oargs.farg[4]);
317     cent[2] = .5*(o->oargs.farg[2] + o->oargs.farg[5]);
318 greg 3.4 setmaterial((MATREC *)o->os, cent, 0);
319 gwlarson 3.1 if (gluqo == NULL) newquadric();
320     glu_rout = "making cylinder";
321     gluQuadricOrientation(gluqo, o->otype==OBJ_CUP | o->otype==OBJ_TUBE ?
322     GLU_INSIDE : GLU_OUTSIDE);
323     gluQuadricNormals(gluqo, GLU_SMOOTH);
324     glMatrixMode(GL_MODELVIEW);
325     glPushMatrix();
326     /* do base translation */
327     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
328     (GLdouble)o->oargs.farg[2]);
329     /* compute height & rotation angle */
330     h = sqrt(dist2(o->oargs.farg,o->oargs.farg+3));
331     if (h <= FTINY)
332     return;
333     x1 = o->oargs.farg[1] - o->oargs.farg[4];
334     y1 = o->oargs.farg[3] - o->oargs.farg[0];
335     /* z1 = 0; */
336     d = 180./PI * asin(sqrt(x1*x1 + y1*y1) / h);
337     if (o->oargs.farg[5] < o->oargs.farg[2])
338     d = 180. - d;
339     if (d > FTINY)
340     glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
341     gluCylinder(gluqo, o->oargs.farg[6], o->oargs.farg[iscyl ? 6 : 7],
342     h, NSLICES, 1);
343     glPopMatrix();
344     }
345    
346    
347 greg 3.4 int
348 gwlarson 3.1 o_ring(o) /* convert a ring */
349     register OBJREC *o;
350     {
351     double x1, y1, d;
352    
353     if (o->oargs.nfargs != 8)
354 greg 3.4 objerror(o, USER, "bad # real arguments");
355 gwlarson 3.1 if (o->oargs.farg[7] < o->oargs.farg[6]) {
356     register double d = o->oargs.farg[7];
357     o->oargs.farg[7] = o->oargs.farg[6];
358     o->oargs.farg[6] = d;
359     }
360     if (o->oargs.farg[6] < -FTINY)
361     objerror(o, USER, "negative radius");
362     if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
363     o->oargs.farg[6] = 0.;
364     if (o->oargs.farg[7] - o->oargs.farg[6] <= FTINY)
365     return;
366     if (dolights)
367 greg 3.4 doflatsrc((MATREC *)o->os, o->oargs.farg, o->oargs.farg+3,
368 gwlarson 3.1 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
369     o->oargs.farg[6]*o->oargs.farg[6]));
370 greg 3.4 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
371 gwlarson 3.1 if (gluqo == NULL) newquadric();
372     glu_rout = "making disk";
373     gluQuadricOrientation(gluqo, GLU_OUTSIDE);
374     gluQuadricNormals(gluqo, GLU_FLAT);
375     glMatrixMode(GL_MODELVIEW);
376     glPushMatrix();
377     glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
378     (GLdouble)o->oargs.farg[2]);
379     /* compute rotation angle */
380     d = VLEN(o->oargs.farg+3);
381     if (d <= FTINY)
382     return;
383     x1 = -o->oargs.farg[4];
384     y1 = o->oargs.farg[3];
385     /* z1 = 0; */
386     d = 180./PI * asin(sqrt(x1*x1 + y1*y1) / d);
387     if (o->oargs.farg[5] < 0.)
388     d = 180. - d;
389     if (d > FTINY)
390     glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
391     gluDisk(gluqo, o->oargs.farg[6], o->oargs.farg[7], NSLICES, 1);
392     glPopMatrix();
393     }