ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.5
Committed: Sat Feb 22 02:07:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.4: +67 -13 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

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.5 /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65 gwlarson 3.1 #include "radogl.h"
66     #include "octree.h"
67    
68 gwlarson 3.2 #define MAXLEVEL 16 /* maximum instance hierarchy level */
69    
70 gwlarson 3.1 typedef struct {
71     int listid; /* our list id */
72     short localmatl; /* uses local material only */
73     FVECT cent; /* center of octree cube */
74     char octfile[256]; /* octree file path */
75     } OCTINST; /* octree to instantiate */
76    
77     static double ogetflt();
78     static long ogetint();
79     static char *ogetstr();
80 greg 3.5 static int loadobj();
81     static void skiptree();
82     static void octerror();
83 gwlarson 3.1 static OCTINST *getoct();
84    
85     static char *infn; /* input file name */
86     static FILE *infp; /* input file stream */
87     static int objsize; /* size of stored OBJECT's */
88     static short otypmap[NUMOTYPE+8]; /* object type map */
89    
90 gwlarson 3.4 static unsigned long imhash(mod) char *mod; {return((unsigned long)mod);}
91 gwlarson 3.1 static LUTAB imtab = {imhash,NULL,NULL,NULL,0,NULL,0};
92    
93     static LUTAB ottab = LU_SINIT(free,free);
94    
95    
96 greg 3.5 int
97 gwlarson 3.1 o_instance(o) /* convert instance to list call */
98     register OBJREC *o;
99     {
100     XF xfs;
101     register OCTINST *ot;
102     /* set up */
103     if (o->oargs.nsargs < 1)
104     objerror(o, USER, "missing octree");
105     setmaterial(NULL, NULL, 0);
106     /* put out transform (if any) */
107     if (o->oargs.nsargs > 1) {
108     if (xf(&xfs, o->oargs.nsargs-1, o->oargs.sarg+1) !=
109     o->oargs.nsargs-1)
110     objerror(o, USER, "bad transform");
111     glPushAttrib(GL_TRANSFORM_BIT);
112     if (xfs.sca < 1.-FTINY | xfs.sca > 1.+FTINY)
113     glEnable(GL_NORMALIZE);
114     glMatrixMode(GL_MODELVIEW);
115     glPushMatrix();
116     /* matrix order works out to same */
117     #ifdef SMLFLT
118     glMultMatrixf((GLfloat *)xfs.xfm);
119     #else
120     glMultMatrixd((GLdouble *)xfs.xfm);
121     #endif
122     }
123     ot = getoct(o->oargs.sarg[0]); /* get octree reference */
124     if (ot->localmatl &= o->os != NULL) /* set material */
125 greg 3.5 setmaterial((MATREC *)o->os, ot->cent, 0);
126 gwlarson 3.1 /* call the assigned list */
127     glCallList(ot->listid);
128    
129     if (o->oargs.nsargs > 1) { /* end transform */
130 gwlarson 3.3 glMatrixMode(GL_MODELVIEW);
131 gwlarson 3.1 glPopMatrix();
132     glPopAttrib();
133     }
134     rgl_checkerr("creating instance");
135     }
136    
137    
138     static int
139     buildoctlist(lp) /* build octree list */
140     LUENT *lp;
141     {
142     int old_dolights = dolights, old_domats = domats;
143     register OCTINST *op = (OCTINST *)lp->data;
144    
145     domats = !op->localmatl; /* do materials only if needed */
146     dolights = 0; /* never do light sources */
147     glNewList(op->listid, GL_COMPILE);
148     loadoct(op->octfile); /* load objects into display list */
149     surfclean(); /* clean up */
150     glEndList();
151     dolights = old_dolights; /* restore */
152     domats = old_domats;
153     return(1); /* return success */
154     }
155    
156    
157     int
158     loadoctrees() /* load octrees we've saved up */
159     {
160 gwlarson 3.2 int levelsleft = MAXLEVEL;
161 gwlarson 3.1 int nocts = 0;
162     LUTAB looptab;
163     /* loop through new octree references */
164     while (ottab.tsiz) {
165 gwlarson 3.2 if (!levelsleft--)
166     error(USER, "too many octree levels -- instance loop?");
167 gwlarson 3.1 copystruct(&looptab, &ottab);
168     ottab.tsiz = 0;
169     nocts += lu_doall(&looptab, buildoctlist);
170     lu_done(&looptab);
171     }
172     return(nocts);
173     }
174    
175    
176     static OCTINST *
177     getoct(name) /* get/assign octree list id */
178     char *name;
179     {
180     extern char *getpath(), *getlibpath();
181     char *path;
182     register LUENT *lp;
183     register OCTINST *op;
184    
185     if ((lp = lu_find(&ottab, name)) == NULL)
186     goto memerr;
187     if (lp->key == NULL) {
188     lp->key = (char *)malloc(strlen(name)+1);
189     if (lp->key == NULL)
190     goto memerr;
191     strcpy(lp->key, name);
192     }
193     if ((op = (OCTINST *)lp->data) == NULL) {
194     path = getpath(name, getlibpath(), R_OK);
195     if (path == NULL) {
196     sprintf(errmsg, "cannot find octree \"%s\"", name);
197     error(USER, errmsg);
198     }
199     op = (OCTINST *)(lp->data = (char *)malloc(sizeof(OCTINST)));
200     strcpy(op->octfile, path);
201     checkoct(op->octfile, op->cent);
202     op->listid = newglist();
203     op->localmatl = ~0;
204     }
205     return(op);
206     memerr:
207     error(SYSTEM, "out of memory in getoct");
208     }
209    
210    
211     double
212     checkoct(fname, cent) /* check octree file for validity */
213     char *fname;
214     FVECT cent;
215     {
216     char sbuf[64];
217     FILE *fp = infp;
218     char *fn = infn;
219     double siz = 0.;
220     register int i;
221    
222     if ((infp = fopen(infn=fname, "r")) == NULL) {
223     sprintf(errmsg, "cannot open octree file \"%s\"", fname);
224     error(SYSTEM, errmsg);
225     }
226     #ifdef MSDOS
227     setmode(fileno(infp), O_BINARY);
228     #endif
229     /* get header */
230     if (checkheader(infp, OCTFMT, NULL) < 0)
231     octerror(USER, "not an octree");
232     /* check format */
233     if ((objsize = ogetint(2)-OCTMAGIC) <= 0 ||
234     objsize > MAXOBJSIZ || objsize > sizeof(long))
235     octerror("incompatible octree format");
236     if (cent != NULL) { /* get boundaries (compute center) */
237     for (i = 0; i < 3; i++)
238     cent[i] = atof(ogetstr(sbuf));
239     siz = atof(ogetstr(sbuf))*.5;
240     cent[0] += siz; cent[1] += siz; cent[2] += siz;
241     } else { /* get size (radius) only */
242     for (i = 0; i < 3; i++)
243     ogetstr(sbuf);
244     siz = atof(ogetstr(sbuf))*.5;
245     }
246     fclose(infp);
247     infp = fp;
248     infn = fn;
249     return(siz);
250     }
251    
252    
253 greg 3.5 int
254 gwlarson 3.1 loadoct(fname) /* read in objects from octree */
255     char *fname;
256     {
257     OBJECT fnobjects;
258     char sbuf[256];
259     int nf;
260     register int i;
261     long m;
262    
263     infn = fname;
264     infp = fopen(fname, "r"); /* assume already checked */
265     #ifdef MSDOS
266     setmode(fileno(infp), O_BINARY);
267     #endif
268     /* skip header */
269     getheader(infp, NULL, NULL);
270     /* get format */
271     objsize = ogetint(2)-OCTMAGIC;
272     /* skip boundaries */
273     for (i = 0; i < 4; i++)
274     ogetstr(sbuf);
275     nf = 0; /* load object files */
276     while (*ogetstr(sbuf)) {
277     rgl_load(sbuf);
278     nf++;
279     }
280     /* get number of objects */
281     fnobjects = m = ogetint(objsize);
282     if (fnobjects != m)
283     octerror(USER, "too many objects");
284    
285     if (nf == 0) {
286     skiptree();
287     for (i = 0; *ogetstr(sbuf); i++)
288     if ((otypmap[i] = otype(sbuf)) < 0) {
289     sprintf(errmsg, "unknown type \"%s\"", sbuf);
290     octerror(WARNING, errmsg);
291     }
292     lu_init(&imtab, 1000); nobjects = 0;
293     while (loadobj() != OVOID)
294     ;
295     lu_done(&imtab);
296     if (nobjects != fnobjects)
297     octerror(USER, "inconsistent object count");
298     }
299     fclose(infp);
300     return(nf);
301     }
302    
303    
304     static char *
305     ogetstr(s) /* get null-terminated string */
306     char *s;
307     {
308     extern char *getstr();
309    
310     if (getstr(s, infp) == NULL)
311     octerror(USER, "truncated octree");
312     return(s);
313     }
314    
315    
316     static long
317     ogetint(siz) /* get a siz-byte integer */
318     int siz;
319     {
320     extern long getint();
321     register long r;
322    
323     r = getint(siz, infp);
324     if (feof(infp))
325     octerror(USER, "truncated octree");
326     return(r);
327     }
328    
329    
330     static double
331     ogetflt() /* get a floating point number */
332     {
333     extern double getflt();
334     double r;
335    
336     r = getflt(infp);
337     if (feof(infp))
338     octerror(USER, "truncated octree");
339     return(r);
340     }
341    
342    
343 greg 3.5 static void
344 gwlarson 3.1 skiptree() /* skip octree on input */
345     {
346     register int i;
347    
348     switch (getc(infp)) {
349     case OT_EMPTY:
350     return;
351     case OT_FULL:
352     for (i = ogetint(objsize)*objsize; i-- > 0; )
353     if (getc(infp) == EOF)
354     octerror(USER, "truncated octree");
355     return;
356     case OT_TREE:
357     for (i = 0; i < 8; i++)
358     skiptree();
359     return;
360     case EOF:
361     octerror(USER, "truncated octree");
362     default:
363     octerror(USER, "damaged octree");
364     }
365     }
366    
367    
368 greg 3.5 static int
369 gwlarson 3.1 loadobj() /* get next object */
370     {
371     static OBJREC ob;
372     char idbuf[MAXSTR], sbuf[MAXSTR];
373     register LUENT *lep;
374     register int i;
375     register long m;
376     /* get type */
377     i = ogetint(1);
378     if (i == -1)
379     return(OVOID); /* terminator */
380     if ((ob.otype = otypmap[i]) < 0)
381     octerror(USER, "reference to unknown type");
382     /* get modifier */
383     if ((m = ogetint(objsize)) != OVOID && (OBJECT)m != m)
384     octerror(USER, "too many objects");
385     if ((ob.omod = m) != OVOID && domats) {
386     if ((lep = lu_find(&imtab, (char *)m)) == NULL)
387     goto memerr;
388     ob.os = lep->data;
389     } else
390     ob.os = NULL;
391     /* get name id */
392     ob.oname = ogetstr(idbuf);
393     /* get string arguments */
394     if (ob.oargs.nsargs = ogetint(2)) {
395     ob.oargs.sarg = (char **)malloc
396     (ob.oargs.nsargs*sizeof(char *));
397     if (ob.oargs.sarg == NULL)
398     goto memerr;
399     for (i = 0; i < ob.oargs.nsargs; i++)
400     ob.oargs.sarg[i] = savestr(ogetstr(sbuf));
401     } else
402     ob.oargs.sarg = NULL;
403     /* get integer arguments */
404     #ifdef IARGS
405     if (ob.oargs.niargs = ogetint(2)) {
406     ob.oargs.iarg = (long *)malloc
407     (ob.oargs.niargs*sizeof(long));
408     if (ob.oargs.iarg == NULL)
409     goto memerr;
410     for (i = 0; i < ob.oargs.niargs; i++)
411     ob.oargs.iarg[i] = ogetint(4);
412     } else
413     ob.oargs.iarg = NULL;
414     #endif
415     /* get real arguments */
416     if (ob.oargs.nfargs = ogetint(2)) {
417     ob.oargs.farg = (FLOAT *)malloc
418     (ob.oargs.nfargs*sizeof(FLOAT));
419     if (ob.oargs.farg == NULL)
420     goto memerr;
421     for (i = 0; i < ob.oargs.nfargs; i++)
422     ob.oargs.farg[i] = ogetflt();
423     } else
424     ob.oargs.farg = NULL;
425     /* process object */
426     (*ofun[ob.otype].funp)(&ob);
427     /* record material if modifier */
428     if (ismodifier(ob.otype)) {
429     if ((lep = lu_find(&imtab, (char *)nobjects)) == NULL)
430     goto memerr;
431     lep->key = (char *)nobjects;
432     lep->data = (char *)getmatp(ob.oname);
433     }
434     freefargs(&ob.oargs); /* free arguments */
435     return(nobjects++); /* return object id */
436     memerr:
437     error(SYSTEM, "out of memory in loadobj");
438     }
439    
440    
441 greg 3.5 static void
442 gwlarson 3.1 octerror(etyp, msg) /* octree error */
443     int etyp;
444     char *msg;
445     {
446     char msgbuf[128];
447    
448     sprintf(msgbuf, "(%s): %s", infn, msg);
449     error(etyp, msgbuf);
450     }