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 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rglsurf.c,v 3.11 2003/11/14 17:22:06 schorsch Exp $";
3 #endif
4 /*
5 * Convert Radiance -> OpenGL surfaces.
6 */
7
8 #include "copyright.h"
9
10 #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 void
32 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
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 static void
85 glu_error(en) /* report an error as a warning */
86 GLenum en;
87 {
88 sprintf(errmsg, "GLU error %s: %s", glu_rout, gluErrorString(en));
89 error(WARNING, errmsg);
90 }
91
92
93 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 static void
111 newtess() /* allocate GLU tessellation object */
112 {
113 if ((gluto = gluNewTess()) == NULL)
114 error(INTERNAL, "gluNewTess failed");
115 gluTessCallback(gluto, GLU_TESS_BEGIN, glBegin);
116 gluTessCallback(gluto, GLU_TESS_VERTEX, glVertex3dv);
117 gluTessCallback(gluto, GLU_TESS_END, glEnd);
118 gluTessCallback(gluto, GLU_TESS_COMBINE, myCombine);
119 gluTessCallback(gluto, GLU_TESS_ERROR, glu_error);
120 gluTessProperty(gluto, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
121 }
122
123
124 static void
125 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 int
135 o_face(o) /* convert a face */
136 register OBJREC *o;
137 {
138 double area;
139 FVECT norm, cent;
140 register int i;
141
142 if ((o->oargs.nfargs < 9) | (o->oargs.nfargs % 3))
143 objerror(o, USER, "bad # real arguments");
144 area = polyarea(cent, norm, o->oargs.nfargs/3, (FVECT *)o->oargs.farg);
145 if (area <= FTINY)
146 return(0);
147 if (dolights) /* check for source */
148 doflatsrc((MATREC *)o->os, cent, norm, area);
149 setmaterial((MATREC *)o->os, cent, 1); /* set material */
150 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 return(0);
182 }
183
184
185 void
186 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 int
202 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 return(0);
213 if (dolights)
214 dosphsrc((MATREC *)o->os, o->oargs.farg,
215 PI*o->oargs.farg[3]*o->oargs.farg[3]);
216 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
217 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 return(0);
229 }
230
231
232 int
233 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 iscyl = (o->otype==OBJ_CYLINDER) | (o->otype==OBJ_TUBE);
241 if (o->oargs.nfargs != (iscyl ? 7 : 8))
242 objerror(o, USER, "bad # real arguments");
243 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 return(0);
257 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 h = sqrt(dist2(o->oargs.farg,o->oargs.farg+3));
264 if (h <= FTINY)
265 return(0);
266 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 setmaterial((MATREC *)o->os, cent, 0);
270 if (gluqo == NULL) newquadric();
271 glu_rout = "making cylinder";
272 gluQuadricOrientation(gluqo, (o->otype==OBJ_CUP) | (o->otype==OBJ_TUBE) ?
273 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 d = x1*x1 + y1*y1;
285 if (d <= FTINY*FTINY)
286 x1 = 1.;
287 else
288 d = 180./PI * asin(sqrt(d) / h);
289 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 return(0);
297 }
298
299
300 int
301 o_ring(o) /* convert a ring */
302 register OBJREC *o;
303 {
304 double x1, y1, d, h;
305
306 if (o->oargs.nfargs != 8)
307 objerror(o, USER, "bad # real arguments");
308 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 return(0);
319 h = VLEN(o->oargs.farg+3);
320 if (h <= FTINY)
321 return(0);
322 if (dolights)
323 doflatsrc((MATREC *)o->os, o->oargs.farg, o->oargs.farg+3,
324 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
325 o->oargs.farg[6]*o->oargs.farg[6]));
326 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
327 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 d = x1*x1 + y1*y1;
340 if (d <= FTINY*FTINY)
341 x1 = 1.;
342 else
343 d = 180./PI * asin(sqrt(d) / h);
344 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 return(0);
351 }