ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.6
Committed: Tue Feb 25 02:47:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 3.5: +1 -56 lines
Log Message:
Replaced inline copyright notice with #include "copyright.h"

File Contents

# User Rev Content
1 gwlarson 3.1 #ifndef lint
2 greg 3.5 static const char RCSid[] = "$Id$";
3 gwlarson 3.1 #endif
4     /*
5     * Routines for reading instances and converting to OpenGL.
6     */
7    
8 greg 3.6 #include "copyright.h"
9 greg 3.5
10 gwlarson 3.1 #include "radogl.h"
11     #include "octree.h"
12    
13 gwlarson 3.2 #define MAXLEVEL 16 /* maximum instance hierarchy level */
14    
15 gwlarson 3.1 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 greg 3.5 static int loadobj();
26     static void skiptree();
27     static void octerror();
28 gwlarson 3.1 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 gwlarson 3.4 static unsigned long imhash(mod) char *mod; {return((unsigned long)mod);}
36 gwlarson 3.1 static LUTAB imtab = {imhash,NULL,NULL,NULL,0,NULL,0};
37    
38     static LUTAB ottab = LU_SINIT(free,free);
39    
40    
41 greg 3.5 int
42 gwlarson 3.1 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 greg 3.5 setmaterial((MATREC *)o->os, ot->cent, 0);
71 gwlarson 3.1 /* call the assigned list */
72     glCallList(ot->listid);
73    
74     if (o->oargs.nsargs > 1) { /* end transform */
75 gwlarson 3.3 glMatrixMode(GL_MODELVIEW);
76 gwlarson 3.1 glPopMatrix();
77     glPopAttrib();
78     }
79     rgl_checkerr("creating instance");
80     }
81    
82    
83     static int
84     buildoctlist(lp) /* build octree list */
85     LUENT *lp;
86     {
87     int old_dolights = dolights, old_domats = domats;
88     register OCTINST *op = (OCTINST *)lp->data;
89    
90     domats = !op->localmatl; /* do materials only if needed */
91     dolights = 0; /* never do light sources */
92     glNewList(op->listid, GL_COMPILE);
93     loadoct(op->octfile); /* load objects into display list */
94     surfclean(); /* clean up */
95     glEndList();
96     dolights = old_dolights; /* restore */
97     domats = old_domats;
98     return(1); /* return success */
99     }
100    
101    
102     int
103     loadoctrees() /* load octrees we've saved up */
104     {
105 gwlarson 3.2 int levelsleft = MAXLEVEL;
106 gwlarson 3.1 int nocts = 0;
107     LUTAB looptab;
108     /* loop through new octree references */
109     while (ottab.tsiz) {
110 gwlarson 3.2 if (!levelsleft--)
111     error(USER, "too many octree levels -- instance loop?");
112 gwlarson 3.1 copystruct(&looptab, &ottab);
113     ottab.tsiz = 0;
114     nocts += lu_doall(&looptab, buildoctlist);
115     lu_done(&looptab);
116     }
117     return(nocts);
118     }
119    
120    
121     static OCTINST *
122     getoct(name) /* get/assign octree list id */
123     char *name;
124     {
125     extern char *getpath(), *getlibpath();
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, getlibpath(), 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 greg 3.5 int
199 gwlarson 3.1 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 greg 3.5 static void
289 gwlarson 3.1 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 greg 3.5 static int
314 gwlarson 3.1 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 greg 3.5 static void
387 gwlarson 3.1 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     }