ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.15
Committed: Tue May 25 22:04:13 2004 UTC (19 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 3.14: +2 -2 lines
Log Message:
Added const modifier to key and other parameters in lookup.h

File Contents

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