ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.8
Committed: Tue May 13 17:58:32 2003 UTC (20 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.7: +1 -2 lines
Log Message:
Changed (char *) casts for memory copies to (void *) and other fixes

File Contents

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