ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglsurf.c
Revision: 3.1
Committed: Tue Jun 9 11:18:36 1998 UTC (25 years, 10 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Convert Radiance -> OpenGL surfaces.
9 */
10
11 #include "radogl.h"
12
13 #ifndef NSLICES
14 #define NSLICES 18 /* number of quadric slices */
15 #endif
16 #ifndef NSTACKS
17 #define NSTACKS 10 /* number of quadric stacks */
18 #endif
19
20 MATREC *curmat = NULL; /* current material */
21
22 static int curpolysize = 0; /* outputting triangles/quads */
23
24 static GLUquadricObj *gluqo; /* shared quadric object */
25 static GLUtesselator *gluto; /* shared tessallation object */
26
27 static char *glu_rout = "unk"; /* active GLU routine */
28
29 #define NOPOLY() if (curpolysize) {glEnd(); curpolysize = 0;} else
30
31
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
84 glu_error(en) /* report a tessellation 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
93 newtess() /* allocate GLU tessellation object */
94 {
95 if ((gluto = gluNewTess()) == NULL)
96 error(INTERNAL, "gluNewTess failed");
97 gluTessCallback(gluto, GLU_TESS_BEGIN, glBegin);
98 gluTessCallback(gluto, GLU_TESS_VERTEX, glVertex3dv);
99 gluTessCallback(gluto, GLU_TESS_END, glEnd);
100 gluTessCallback(gluto, GLU_TESS_ERROR, glu_error);
101 gluTessProperty(gluto, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
102 }
103
104
105 static
106 newquadric() /* allocate GLU quadric structure */
107 {
108 if ((gluqo = gluNewQuadric()) == NULL)
109 error(INTERNAL, "gluNewQuadric failed");
110 gluQuadricDrawStyle(gluqo, GLU_FILL);
111 gluQuadricCallback(gluqo, GLU_ERROR, glu_error);
112 }
113
114
115 o_face(o) /* convert a face */
116 register OBJREC *o;
117 {
118 double area;
119 FVECT norm, cent;
120 register int i;
121
122 if (o->oargs.nfargs < 9 | o->oargs.nfargs % 3)
123 objerror(o, USER, "bad # real arguments");
124 area = polyarea(cent, norm, o->oargs.nfargs/3, (FVECT *)o->oargs.farg);
125 if (area <= FTINY)
126 return;
127 if (dolights) /* check for source */
128 doflatsrc(o->os, cent, norm, area);
129 setmaterial(o->os, cent, 1); /* set material */
130 if (o->oargs.nfargs/3 != curpolysize) {
131 if (curpolysize) glEnd();
132 curpolysize = o->oargs.nfargs/3;
133 if (curpolysize == 3)
134 glBegin(GL_TRIANGLES);
135 else if (curpolysize == 4)
136 glBegin(GL_QUADS);
137 }
138 glNormal3d((GLdouble)norm[0], (GLdouble)norm[1], (GLdouble)norm[2]);
139 if (curpolysize > 4) {
140 if (gluto == NULL) newtess();
141 glu_rout = "tessellating polygon";
142 gluTessNormal(gluto, (GLdouble)norm[0],
143 (GLdouble)norm[1], (GLdouble)norm[2]);
144 gluTessBeginPolygon(gluto, NULL);
145 gluTessBeginContour(gluto);
146 #ifdef SMLFLT
147 error(INTERNAL, "bad code segment in o_face");
148 #endif
149 for (i = 0; i < curpolysize; i++)
150 gluTessVertex(gluto, (GLdouble *)(o->oargs.farg+3*i),
151 (void *)(o->oargs.farg+3*i));
152 gluTessEndContour(gluto);
153 gluTessEndPolygon(gluto);
154 curpolysize = 0;
155 } else {
156 for (i = 0; i < curpolysize; i++)
157 glVertex3d((GLdouble)o->oargs.farg[3*i],
158 (GLdouble)o->oargs.farg[3*i+1],
159 (GLdouble)o->oargs.farg[3*i+2]);
160 }
161 }
162
163
164 surfclean() /* clean up surface routines */
165 {
166 setmaterial(NULL, NULL, 0);
167 if (gluqo != NULL) {
168 gluDeleteQuadric(gluqo);
169 gluqo = NULL;
170 }
171 if (gluto != NULL) {
172 gluDeleteTess(gluto);
173 gluto = NULL;
174 }
175 rgl_checkerr("in surfclean");
176 }
177
178
179 o_sphere(o) /* convert a sphere */
180 register OBJREC *o;
181 {
182 /* check arguments */
183 if (o->oargs.nfargs != 4)
184 objerror(o, USER, "bad # real arguments");
185 if (o->oargs.farg[3] < -FTINY) {
186 o->otype = o->otype==OBJ_SPHERE ? OBJ_BUBBLE : OBJ_SPHERE;
187 o->oargs.farg[3] = -o->oargs.farg[3];
188 } else if (o->oargs.farg[3] <= FTINY)
189 return;
190 if (dolights)
191 dosphsrc(o->os, o->oargs.farg,
192 PI*o->oargs.farg[3]*o->oargs.farg[3]);
193 setmaterial(o->os, o->oargs.farg, 0);
194 if (gluqo == NULL) newquadric();
195 glu_rout = "making sphere";
196 gluQuadricOrientation(gluqo,
197 o->otype==OBJ_BUBBLE ? GLU_INSIDE : GLU_OUTSIDE);
198 gluQuadricNormals(gluqo, GLU_SMOOTH);
199 glMatrixMode(GL_MODELVIEW);
200 glPushMatrix();
201 glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
202 (GLdouble)o->oargs.farg[2]);
203 gluSphere(gluqo, (GLdouble)o->oargs.farg[3], NSLICES, NSTACKS);
204 glPopMatrix();
205 rgl_checkerr("creating sphere");
206 }
207
208
209 o_cone(o) /* convert a cone or cylinder */
210 register OBJREC *o;
211 {
212 double x1, y1, h, d;
213 FVECT cent;
214 register int iscyl;
215
216 iscyl = o->otype==OBJ_CYLINDER | o->otype==OBJ_TUBE;
217 if (o->oargs.nfargs != (iscyl ? 7 : 8))
218 objerror(o, "bad # real arguments");
219 if (o->oargs.farg[6] < -FTINY) {
220 o->oargs.farg[6] = -o->oargs.farg[6];
221 if (iscyl)
222 o->otype = o->otype==OBJ_CYLINDER ?
223 OBJ_TUBE : OBJ_CYLINDER;
224 else {
225 if ((o->oargs.farg[7] = -o->oargs.farg[7]) < -FTINY)
226 objerror(o, USER, "illegal radii");
227 o->otype = o->otype==OBJ_CONE ? OBJ_CUP : OBJ_CONE;
228 }
229 } else if (!iscyl && o->oargs.farg[7] < -FTINY)
230 objerror(o, USER, "illegal radii");
231 if (o->oargs.farg[6] <= FTINY && (iscyl || o->oargs.farg[7] <= FTINY))
232 return;
233 if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
234 o->oargs.farg[6] = 0.;
235 if (!iscyl && o->oargs.farg[7] < 0.)
236 o->oargs.farg[7] = 0.;
237 cent[0] = .5*(o->oargs.farg[0] + o->oargs.farg[3]);
238 cent[1] = .5*(o->oargs.farg[1] + o->oargs.farg[4]);
239 cent[2] = .5*(o->oargs.farg[2] + o->oargs.farg[5]);
240 setmaterial(o->os, cent, 0);
241 if (gluqo == NULL) newquadric();
242 glu_rout = "making cylinder";
243 gluQuadricOrientation(gluqo, o->otype==OBJ_CUP | o->otype==OBJ_TUBE ?
244 GLU_INSIDE : GLU_OUTSIDE);
245 gluQuadricNormals(gluqo, GLU_SMOOTH);
246 glMatrixMode(GL_MODELVIEW);
247 glPushMatrix();
248 /* do base translation */
249 glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
250 (GLdouble)o->oargs.farg[2]);
251 /* compute height & rotation angle */
252 h = sqrt(dist2(o->oargs.farg,o->oargs.farg+3));
253 if (h <= FTINY)
254 return;
255 x1 = o->oargs.farg[1] - o->oargs.farg[4];
256 y1 = o->oargs.farg[3] - o->oargs.farg[0];
257 /* z1 = 0; */
258 d = 180./PI * asin(sqrt(x1*x1 + y1*y1) / h);
259 if (o->oargs.farg[5] < o->oargs.farg[2])
260 d = 180. - d;
261 if (d > FTINY)
262 glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
263 gluCylinder(gluqo, o->oargs.farg[6], o->oargs.farg[iscyl ? 6 : 7],
264 h, NSLICES, 1);
265 glPopMatrix();
266 rgl_checkerr("creating cone");
267 }
268
269
270 o_ring(o) /* convert a ring */
271 register OBJREC *o;
272 {
273 double x1, y1, d;
274
275 if (o->oargs.nfargs != 8)
276 objerror(o, "bad # real arguments");
277 if (o->oargs.farg[7] < o->oargs.farg[6]) {
278 register double d = o->oargs.farg[7];
279 o->oargs.farg[7] = o->oargs.farg[6];
280 o->oargs.farg[6] = d;
281 }
282 if (o->oargs.farg[6] < -FTINY)
283 objerror(o, USER, "negative radius");
284 if (o->oargs.farg[6] < 0.) /* complains for tiny neg's */
285 o->oargs.farg[6] = 0.;
286 if (o->oargs.farg[7] - o->oargs.farg[6] <= FTINY)
287 return;
288 if (dolights)
289 doflatsrc(o->os, o->oargs.farg, o->oargs.farg+3,
290 PI*(o->oargs.farg[7]*o->oargs.farg[7] -
291 o->oargs.farg[6]*o->oargs.farg[6]));
292 setmaterial(o->os, o->oargs.farg, 0);
293 if (gluqo == NULL) newquadric();
294 glu_rout = "making disk";
295 gluQuadricOrientation(gluqo, GLU_OUTSIDE);
296 gluQuadricNormals(gluqo, GLU_FLAT);
297 glMatrixMode(GL_MODELVIEW);
298 glPushMatrix();
299 glTranslated((GLdouble)o->oargs.farg[0], (GLdouble)o->oargs.farg[1],
300 (GLdouble)o->oargs.farg[2]);
301 /* compute rotation angle */
302 d = VLEN(o->oargs.farg+3);
303 if (d <= FTINY)
304 return;
305 x1 = -o->oargs.farg[4];
306 y1 = o->oargs.farg[3];
307 /* z1 = 0; */
308 d = 180./PI * asin(sqrt(x1*x1 + y1*y1) / d);
309 if (o->oargs.farg[5] < 0.)
310 d = 180. - d;
311 if (d > FTINY)
312 glRotated(d, (GLdouble)x1, (GLdouble)y1, 0.);
313 gluDisk(gluqo, o->oargs.farg[6], o->oargs.farg[7], NSLICES, 1);
314 glPopMatrix();
315 rgl_checkerr("creating ring");
316 }