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

# 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 /* ====================================================================
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 #include "radogl.h"
66 #include "octree.h"
67
68 #define MAXLEVEL 16 /* maximum instance hierarchy level */
69
70 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 static int loadobj();
81 static void skiptree();
82 static void octerror();
83 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 static unsigned long imhash(mod) char *mod; {return((unsigned long)mod);}
91 static LUTAB imtab = {imhash,NULL,NULL,NULL,0,NULL,0};
92
93 static LUTAB ottab = LU_SINIT(free,free);
94
95
96 int
97 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 setmaterial((MATREC *)o->os, ot->cent, 0);
126 /* call the assigned list */
127 glCallList(ot->listid);
128
129 if (o->oargs.nsargs > 1) { /* end transform */
130 glMatrixMode(GL_MODELVIEW);
131 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 int levelsleft = MAXLEVEL;
161 int nocts = 0;
162 LUTAB looptab;
163 /* loop through new octree references */
164 while (ottab.tsiz) {
165 if (!levelsleft--)
166 error(USER, "too many octree levels -- instance loop?");
167 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 int
254 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 static void
344 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 static int
369 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 static void
442 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 }