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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Convert Radiance -> OpenGL surfaces.
6 */
7
8 /* ====================================================================
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 #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 void
87 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 static void
139 glu_error(en) /* report an error as a warning */
140 GLenum en;
141 {
142 sprintf(errmsg, "GLU error %s: %s", glu_rout, gluErrorString(en));
143 error(WARNING, errmsg);
144 }
145
146
147 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 static
165 newtess() /* allocate GLU tessellation object */
166 {
167 if ((gluto = gluNewTess()) == NULL)
168 error(INTERNAL, "gluNewTess failed");
169 gluTessCallback(gluto, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin);
170 gluTessCallback(gluto, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv);
171 gluTessCallback(gluto, GLU_TESS_END, glEnd);
172 gluTessCallback(gluto, GLU_TESS_COMBINE, myCombine);
173 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 int
189 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 doflatsrc((MATREC *)o->os, cent, norm, area);
203 setmaterial((MATREC *)o->os, cent, 1); /* set material */
204 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 void
239 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 int
255 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 dosphsrc((MATREC *)o->os, o->oargs.farg,
268 PI*o->oargs.farg[3]*o->oargs.farg[3]);
269 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
270 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 int
285 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 objerror(o, USER, "bad # real arguments");
295 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 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 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 setmaterial((MATREC *)o->os, cent, 0);
319 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 int
348 o_ring(o) /* convert a ring */
349 register OBJREC *o;
350 {
351 double x1, y1, d;
352
353 if (o->oargs.nfargs != 8)
354 objerror(o, USER, "bad # real arguments");
355 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 doflatsrc((MATREC *)o->os, o->oargs.farg, o->oargs.farg+3,
368 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
369 o->oargs.farg[6]*o->oargs.farg[6]));
370 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
371 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 }