ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.10
Committed: Thu Jun 26 00:58:09 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.9: +3 -3 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rglinst.c,v 3.9 2003/06/05 19:29:34 schorsch Exp $";
3 #endif
4 /*
5 * Routines for reading instances and converting to OpenGL.
6 */
7
8 #include "copyright.h"
9
10 #include "radogl.h"
11 #include "octree.h"
12 #include "platform.h"
13
14 #define MAXLEVEL 16 /* maximum instance hierarchy level */
15
16 typedef struct {
17 int listid; /* our list id */
18 short localmatl; /* uses local material only */
19 FVECT cent; /* center of octree cube */
20 char octfile[256]; /* octree file path */
21 } OCTINST; /* octree to instantiate */
22
23 static double ogetflt();
24 static long ogetint();
25 static char *ogetstr();
26 static int loadobj();
27 static void skiptree();
28 static void octerror();
29 static OCTINST *getoct();
30
31 static char *infn; /* input file name */
32 static FILE *infp; /* input file stream */
33 static int objsize; /* size of stored OBJECT's */
34 static short otypmap[NUMOTYPE+8]; /* object type map */
35
36 static unsigned long imhash(mod) char *mod; {return((unsigned long)mod);}
37 static LUTAB imtab = {imhash,NULL,NULL,NULL,0,NULL,0};
38
39 static LUTAB ottab = LU_SINIT(free,free);
40
41
42 int
43 o_instance(o) /* convert instance to list call */
44 register OBJREC *o;
45 {
46 XF xfs;
47 register OCTINST *ot;
48 /* set up */
49 if (o->oargs.nsargs < 1)
50 objerror(o, USER, "missing octree");
51 setmaterial(NULL, NULL, 0);
52 /* put out transform (if any) */
53 if (o->oargs.nsargs > 1) {
54 if (xf(&xfs, o->oargs.nsargs-1, o->oargs.sarg+1) !=
55 o->oargs.nsargs-1)
56 objerror(o, USER, "bad transform");
57 glPushAttrib(GL_TRANSFORM_BIT);
58 if (xfs.sca < 1.-FTINY | xfs.sca > 1.+FTINY)
59 glEnable(GL_NORMALIZE);
60 glMatrixMode(GL_MODELVIEW);
61 glPushMatrix();
62 /* matrix order works out to same */
63 #ifdef SMLFLT
64 glMultMatrixf((GLfloat *)xfs.xfm);
65 #else
66 glMultMatrixd((GLdouble *)xfs.xfm);
67 #endif
68 }
69 ot = getoct(o->oargs.sarg[0]); /* get octree reference */
70 if (ot->localmatl &= o->os != NULL) /* set material */
71 setmaterial((MATREC *)o->os, ot->cent, 0);
72 /* call the assigned list */
73 glCallList(ot->listid);
74
75 if (o->oargs.nsargs > 1) { /* end transform */
76 glMatrixMode(GL_MODELVIEW);
77 glPopMatrix();
78 glPopAttrib();
79 }
80 rgl_checkerr("creating instance");
81 return(0);
82 }
83
84
85 static int
86 buildoctlist(lp) /* build octree list */
87 LUENT *lp;
88 {
89 int old_dolights = dolights, old_domats = domats;
90 register OCTINST *op = (OCTINST *)lp->data;
91
92 domats = !op->localmatl; /* do materials only if needed */
93 dolights = 0; /* never do light sources */
94 glNewList(op->listid, GL_COMPILE);
95 loadoct(op->octfile); /* load objects into display list */
96 surfclean(); /* clean up */
97 glEndList();
98 dolights = old_dolights; /* restore */
99 domats = old_domats;
100 return(1); /* return success */
101 }
102
103
104 int
105 loadoctrees() /* load octrees we've saved up */
106 {
107 int levelsleft = MAXLEVEL;
108 int nocts = 0;
109 LUTAB looptab;
110 /* loop through new octree references */
111 while (ottab.tsiz) {
112 if (!levelsleft--)
113 error(USER, "too many octree levels -- instance loop?");
114 copystruct(&looptab, &ottab);
115 ottab.tsiz = 0;
116 nocts += lu_doall(&looptab, buildoctlist);
117 lu_done(&looptab);
118 }
119 return(nocts);
120 }
121
122
123 static OCTINST *
124 getoct(name) /* get/assign octree list id */
125 char *name;
126 {
127 char *path;
128 register LUENT *lp;
129 register OCTINST *op;
130
131 if ((lp = lu_find(&ottab, name)) == NULL)
132 goto memerr;
133 if (lp->key == NULL) {
134 lp->key = (char *)malloc(strlen(name)+1);
135 if (lp->key == NULL)
136 goto memerr;
137 strcpy(lp->key, name);
138 }
139 if ((op = (OCTINST *)lp->data) == NULL) {
140 path = getpath(name, getrlibpath(), R_OK);
141 if (path == NULL) {
142 sprintf(errmsg, "cannot find octree \"%s\"", name);
143 error(USER, errmsg);
144 }
145 op = (OCTINST *)(lp->data = (char *)malloc(sizeof(OCTINST)));
146 strcpy(op->octfile, path);
147 checkoct(op->octfile, op->cent);
148 op->listid = newglist();
149 op->localmatl = ~0;
150 }
151 return(op);
152 memerr:
153 error(SYSTEM, "out of memory in getoct");
154 }
155
156
157 double
158 checkoct(fname, cent) /* check octree file for validity */
159 char *fname;
160 FVECT cent;
161 {
162 char sbuf[64];
163 FILE *fp = infp;
164 char *fn = infn;
165 double siz = 0.;
166 register int i;
167
168 if ((infp = fopen(infn=fname, "r")) == NULL) {
169 sprintf(errmsg, "cannot open octree file \"%s\"", fname);
170 error(SYSTEM, errmsg);
171 }
172 SET_FILE_BINARY(infp);
173 /* get header */
174 if (checkheader(infp, OCTFMT, NULL) < 0)
175 octerror(USER, "not an octree");
176 /* check format */
177 if ((objsize = ogetint(2)-OCTMAGIC) <= 0 ||
178 objsize > MAXOBJSIZ || objsize > sizeof(long))
179 octerror("incompatible octree format");
180 if (cent != NULL) { /* get boundaries (compute center) */
181 for (i = 0; i < 3; i++)
182 cent[i] = atof(ogetstr(sbuf));
183 siz = atof(ogetstr(sbuf))*.5;
184 cent[0] += siz; cent[1] += siz; cent[2] += siz;
185 } else { /* get size (radius) only */
186 for (i = 0; i < 3; i++)
187 ogetstr(sbuf);
188 siz = atof(ogetstr(sbuf))*.5;
189 }
190 fclose(infp);
191 infp = fp;
192 infn = fn;
193 return(siz);
194 }
195
196
197 int
198 loadoct(fname) /* read in objects from octree */
199 char *fname;
200 {
201 OBJECT fnobjects;
202 char sbuf[256];
203 int nf;
204 register int i;
205 long m;
206
207 infn = fname;
208 infp = fopen(fname, "r"); /* assume already checked */
209 SET_FILE_BINARY(infp);
210 /* skip header */
211 getheader(infp, NULL, NULL);
212 /* get format */
213 objsize = ogetint(2)-OCTMAGIC;
214 /* skip boundaries */
215 for (i = 0; i < 4; i++)
216 ogetstr(sbuf);
217 nf = 0; /* load object files */
218 while (*ogetstr(sbuf)) {
219 rgl_load(sbuf);
220 nf++;
221 }
222 /* get number of objects */
223 fnobjects = m = ogetint(objsize);
224 if (fnobjects != m)
225 octerror(USER, "too many objects");
226
227 if (nf == 0) {
228 skiptree();
229 for (i = 0; *ogetstr(sbuf); i++)
230 if ((otypmap[i] = otype(sbuf)) < 0) {
231 sprintf(errmsg, "unknown type \"%s\"", sbuf);
232 octerror(WARNING, errmsg);
233 }
234 lu_init(&imtab, 1000); nobjects = 0;
235 while (loadobj() != OVOID)
236 ;
237 lu_done(&imtab);
238 if (nobjects != fnobjects)
239 octerror(USER, "inconsistent object count");
240 }
241 fclose(infp);
242 return(nf);
243 }
244
245
246 static char *
247 ogetstr(s) /* get null-terminated string */
248 char *s;
249 {
250 extern char *getstr();
251
252 if (getstr(s, infp) == NULL)
253 octerror(USER, "truncated octree");
254 return(s);
255 }
256
257
258 static long
259 ogetint(siz) /* get a siz-byte integer */
260 int siz;
261 {
262 extern long getint();
263 register long r;
264
265 r = getint(siz, infp);
266 if (feof(infp))
267 octerror(USER, "truncated octree");
268 return(r);
269 }
270
271
272 static double
273 ogetflt() /* get a floating point number */
274 {
275 extern double getflt();
276 double r;
277
278 r = getflt(infp);
279 if (feof(infp))
280 octerror(USER, "truncated octree");
281 return(r);
282 }
283
284
285 static void
286 skiptree() /* skip octree on input */
287 {
288 register int i;
289
290 switch (getc(infp)) {
291 case OT_EMPTY:
292 return;
293 case OT_FULL:
294 for (i = ogetint(objsize)*objsize; i-- > 0; )
295 if (getc(infp) == EOF)
296 octerror(USER, "truncated octree");
297 return;
298 case OT_TREE:
299 for (i = 0; i < 8; i++)
300 skiptree();
301 return;
302 case EOF:
303 octerror(USER, "truncated octree");
304 default:
305 octerror(USER, "damaged octree");
306 }
307 }
308
309
310 static int
311 loadobj() /* get next object */
312 {
313 static OBJREC ob;
314 char idbuf[MAXSTR], sbuf[MAXSTR];
315 register LUENT *lep;
316 register int i;
317 register long m;
318 /* get type */
319 i = ogetint(1);
320 if (i == -1)
321 return(OVOID); /* terminator */
322 if ((ob.otype = otypmap[i]) < 0)
323 octerror(USER, "reference to unknown type");
324 /* get modifier */
325 if ((m = ogetint(objsize)) != OVOID && (OBJECT)m != m)
326 octerror(USER, "too many objects");
327 if ((ob.omod = m) != OVOID && domats) {
328 if ((lep = lu_find(&imtab, (char *)m)) == NULL)
329 goto memerr;
330 ob.os = lep->data;
331 } else
332 ob.os = NULL;
333 /* get name id */
334 ob.oname = ogetstr(idbuf);
335 /* get string arguments */
336 if (ob.oargs.nsargs = ogetint(2)) {
337 ob.oargs.sarg = (char **)malloc
338 (ob.oargs.nsargs*sizeof(char *));
339 if (ob.oargs.sarg == NULL)
340 goto memerr;
341 for (i = 0; i < ob.oargs.nsargs; i++)
342 ob.oargs.sarg[i] = savestr(ogetstr(sbuf));
343 } else
344 ob.oargs.sarg = NULL;
345 /* get integer arguments */
346 #ifdef IARGS
347 if (ob.oargs.niargs = ogetint(2)) {
348 ob.oargs.iarg = (long *)malloc
349 (ob.oargs.niargs*sizeof(long));
350 if (ob.oargs.iarg == NULL)
351 goto memerr;
352 for (i = 0; i < ob.oargs.niargs; i++)
353 ob.oargs.iarg[i] = ogetint(4);
354 } else
355 ob.oargs.iarg = NULL;
356 #endif
357 /* get real arguments */
358 if (ob.oargs.nfargs = ogetint(2)) {
359 ob.oargs.farg = (RREAL *)malloc
360 (ob.oargs.nfargs*sizeof(RREAL));
361 if (ob.oargs.farg == NULL)
362 goto memerr;
363 for (i = 0; i < ob.oargs.nfargs; i++)
364 ob.oargs.farg[i] = ogetflt();
365 } else
366 ob.oargs.farg = NULL;
367 /* process object */
368 (*ofun[ob.otype].funp)(&ob);
369 /* record material if modifier */
370 if (ismodifier(ob.otype)) {
371 if ((lep = lu_find(&imtab, (char *)nobjects)) == NULL)
372 goto memerr;
373 lep->key = (char *)nobjects;
374 lep->data = (char *)getmatp(ob.oname);
375 }
376 freefargs(&ob.oargs); /* free arguments */
377 return(nobjects++); /* return object id */
378 memerr:
379 error(SYSTEM, "out of memory in loadobj");
380 }
381
382
383 static void
384 octerror(etyp, msg) /* octree error */
385 int etyp;
386 char *msg;
387 {
388 char msgbuf[128];
389
390 sprintf(msgbuf, "(%s): %s", infn, msg);
391 error(etyp, msgbuf);
392 }