ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglsurf.c
Revision: 3.8
Committed: Sun May 25 06:09:44 2003 UTC (20 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.7: +14 -6 lines
Log Message:
Fixed bug in cylinder rotation, but not the one causing all the problems

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
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 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 static void
84 glu_error(en) /* report an error as a warning */
85 GLenum en;
86 {
87 sprintf(errmsg, "GLU error %s: %s", glu_rout, gluErrorString(en));
88 error(WARNING, errmsg);
89 }
90
91
92 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 static
110 newtess() /* allocate GLU tessellation object */
111 {
112 if ((gluto = gluNewTess()) == NULL)
113 error(INTERNAL, "gluNewTess failed");
114 gluTessCallback(gluto, GLU_TESS_BEGIN, glBegin);
115 gluTessCallback(gluto, GLU_TESS_VERTEX, glVertex3dv);
116 gluTessCallback(gluto, GLU_TESS_END, glEnd);
117 gluTessCallback(gluto, GLU_TESS_COMBINE, myCombine);
118 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 int
134 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 return(0);
146 if (dolights) /* check for source */
147 doflatsrc((MATREC *)o->os, cent, norm, area);
148 setmaterial((MATREC *)o->os, cent, 1); /* set material */
149 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 return(0);
181 }
182
183
184 void
185 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 int
201 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 return(0);
212 if (dolights)
213 dosphsrc((MATREC *)o->os, o->oargs.farg,
214 PI*o->oargs.farg[3]*o->oargs.farg[3]);
215 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
216 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 return(0);
228 }
229
230
231 int
232 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 objerror(o, USER, "bad # real arguments");
242 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 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 cent[0] = .5*(o->oargs.farg[0] + o->oargs.farg[3]);
263 cent[1] = .5*(o->oargs.farg[1] + o->oargs.farg[4]);
264 cent[2] = .5*(o->oargs.farg[2] + o->oargs.farg[5]);
265 setmaterial((MATREC *)o->os, cent, 0);
266 if (gluqo == NULL) newquadric();
267 glu_rout = "making cylinder";
268 gluQuadricOrientation(gluqo, o->otype==OBJ_CUP | o->otype==OBJ_TUBE ?
269 GLU_INSIDE : GLU_OUTSIDE);
270 gluQuadricNormals(gluqo, GLU_SMOOTH);
271 glMatrixMode(GL_MODELVIEW);
272 glPushMatrix();
273 /* do base translation */
274 glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
275 (GLdouble)o->oargs.farg[2]);
276 /* compute height & rotation angle */
277 h = sqrt(dist2(o->oargs.farg,o->oargs.farg+3));
278 if (h <= FTINY)
279 return;
280 x1 = o->oargs.farg[1] - o->oargs.farg[4];
281 y1 = o->oargs.farg[3] - o->oargs.farg[0];
282 /* z1 = 0; */
283 d = x1*x1 + y1*y1;
284 if (d <= FTINY*FTINY)
285 x1 = 1.;
286 else
287 d = 180./PI * asin(sqrt(d) / h);
288 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 return(0);
296 }
297
298
299 int
300 o_ring(o) /* convert a ring */
301 register OBJREC *o;
302 {
303 double x1, y1, d, h;
304
305 if (o->oargs.nfargs != 8)
306 objerror(o, USER, "bad # real arguments");
307 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 if (dolights)
319 doflatsrc((MATREC *)o->os, o->oargs.farg, o->oargs.farg+3,
320 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
321 o->oargs.farg[6]*o->oargs.farg[6]));
322 setmaterial((MATREC *)o->os, o->oargs.farg, 0);
323 if (gluqo == NULL) newquadric();
324 glu_rout = "making disk";
325 gluQuadricOrientation(gluqo, GLU_OUTSIDE);
326 gluQuadricNormals(gluqo, GLU_FLAT);
327 glMatrixMode(GL_MODELVIEW);
328 glPushMatrix();
329 glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
330 (GLdouble)o->oargs.farg[2]);
331 /* compute rotation angle */
332 h = VLEN(o->oargs.farg+3);
333 if (h <= FTINY)
334 return;
335 x1 = -o->oargs.farg[4];
336 y1 = o->oargs.farg[3];
337 /* z1 = 0; */
338 d = x1*x1 + y1*y1;
339 if (d <= FTINY*FTINY)
340 x1 = 1.;
341 else
342 d = 180./PI * asin(sqrt(d) / h);
343 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 return(0);
350 }