ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rglinst.c
Revision: 3.1
Committed: Tue Jun 9 11:18:35 1998 UTC (25 years, 10 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

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