home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1986 Regents of the University of California */
-
- #ifndef lint
- static char SCCSid[] = "@(#)oconv.c 2.3 8/24/92 LBL";
- #endif
-
- /*
- * oconv.c - main program for object to octree conversion.
- *
- * 7/29/85
- */
-
- #include "standard.h"
-
- #include "octree.h"
-
- #include "object.h"
-
- #include "otypes.h"
-
- #include "paths.h"
-
- #define OMARGIN (10*FTINY) /* margin around global cube */
-
- #define MAXOBJFIL 63 /* maximum number of scene files */
-
- char *progname; /* argv[0] */
-
- char *libpath; /* library search path */
-
- int nowarn = 0; /* supress warnings? */
-
- int objlim = 5; /* # of objects before split */
-
- int resolu = 1024; /* octree resolution limit */
-
- CUBE thescene = {EMPTY, {0.0, 0.0, 0.0}, 0.0}; /* our scene */
-
- char *ofname[MAXOBJFIL+1]; /* object file names */
- int nfiles = 0; /* number of object files */
-
- double mincusize; /* minimum cube size from resolu */
-
- int (*addobjnotify[])() = {NULL}; /* new object notifier functions */
-
-
- main(argc, argv) /* convert object files to an octree */
- int argc;
- char **argv;
- {
- extern char *getenv();
- FVECT bbmin, bbmax;
- char *infile = NULL;
- int outflags = IO_ALL;
- OBJECT startobj;
- int i;
-
- progname = argv[0] = fixargv0(argv[0]);
-
- if ((libpath = getenv(ULIBVAR)) == NULL)
- libpath = DEFPATH;
-
- initotypes();
-
- for (i = 1; i < argc && argv[i][0] == '-'; i++)
- switch (argv[i][1]) {
- case '\0': /* scene from stdin */
- goto breakopt;
- case 'i': /* input octree */
- infile = argv[++i];
- break;
- case 'b': /* bounding cube */
- thescene.cuorg[0] = atof(argv[++i]) - OMARGIN;
- thescene.cuorg[1] = atof(argv[++i]) - OMARGIN;
- thescene.cuorg[2] = atof(argv[++i]) - OMARGIN;
- thescene.cusize = atof(argv[++i]) + 2*OMARGIN;
- break;
- case 'n': /* set limit */
- objlim = atoi(argv[++i]);
- break;
- case 'r': /* resolution limit */
- resolu = atoi(argv[++i]);
- break;
- case 'f': /* freeze octree */
- outflags &= ~IO_FILES;
- break;
- case 'w': /* supress warnings */
- nowarn = 1;
- break;
- default:
- sprintf(errmsg, "unknown option: '%s'", argv[i]);
- error(USER, errmsg);
- break;
- }
- breakopt:
- #ifdef MSDOS
- setmode(fileno(stdout), O_BINARY);
- #endif
- if (infile != NULL) { /* get old octree & objects */
- if (thescene.cusize > FTINY)
- error(USER, "only one of '-b' or '-i'");
- nfiles = readoct(infile, IO_ALL, &thescene, ofname);
- if (nfiles == 0 && outflags & IO_FILES) {
- error(WARNING, "frozen octree");
- outflags &= ~IO_FILES;
- }
- }
-
- printargs(argc, argv, stdout); /* info. header */
- fputformat(OCTFMT, stdout);
- printf("\n");
-
- startobj = nobjects; /* previous objects already converted */
-
- for ( ; i < argc; i++) /* read new scene descriptions */
- if (!strcmp(argv[i], "-")) { /* from stdin */
- readobj(NULL);
- outflags &= ~IO_FILES;
- } else { /* from file */
- if (nfiles >= MAXOBJFIL)
- error(INTERNAL, "too many scene files");
- readobj(ofname[nfiles++] = argv[i]);
- }
-
- ofname[nfiles] = NULL;
- /* find bounding box */
- bbmin[0] = bbmin[1] = bbmin[2] = FHUGE;
- bbmax[0] = bbmax[1] = bbmax[2] = -FHUGE;
- for (i = startobj; i < nobjects; i++)
- add2bbox(objptr(i), bbmin, bbmax);
- /* set/check cube */
- if (thescene.cusize == 0.0) {
- if (bbmin[0] <= bbmax[0]) {
- for (i = 0; i < 3; i++) {
- bbmin[i] -= OMARGIN;
- bbmax[i] += OMARGIN;
- }
- for (i = 0; i < 3; i++)
- if (bbmax[i] - bbmin[i] > thescene.cusize)
- thescene.cusize = bbmax[i] - bbmin[i];
- for (i = 0; i < 3; i++)
- thescene.cuorg[i] =
- (bbmax[i]+bbmin[i]-thescene.cusize)*.5;
- }
- } else {
- for (i = 0; i < 3; i++)
- if (bbmin[i] < thescene.cuorg[i] ||
- bbmax[i] > thescene.cuorg[i] + thescene.cusize)
- error(USER, "boundary does not encompass scene");
- }
-
- mincusize = thescene.cusize / resolu - FTINY;
-
- for (i = startobj; i < nobjects; i++) /* add new objects */
- addobject(&thescene, i);
-
- thescene.cutree = combine(thescene.cutree); /* optimize */
-
- writeoct(outflags, &thescene, ofname); /* write structures to stdout */
-
- quit(0);
- }
-
-
- quit(code) /* exit program */
- int code;
- {
- exit(code);
- }
-
-
- cputs() /* interactive error */
- {
- /* referenced, but not used */
- }
-
-
- wputs(s) /* warning message */
- char *s;
- {
- if (!nowarn)
- eputs(s);
- }
-
-
- eputs(s) /* put string to stderr */
- register char *s;
- {
- static int inln = 0;
-
- if (!inln++) {
- fputs(progname, stderr);
- fputs(": ", stderr);
- }
- fputs(s, stderr);
- if (*s && s[strlen(s)-1] == '\n')
- inln = 0;
- }
-
-
- #define bitop(f,i,op) (f[((i)>>3)] op (1<<((i)&7)))
- #define tstbit(f,i) bitop(f,i,&)
- #define setbit(f,i) bitop(f,i,|=)
- #define clrbit(f,i) bitop(f,i,&=~)
- #define tglbit(f,i) bitop(f,i,^=)
-
-
- addobject(cu, obj) /* add an object to a cube */
- register CUBE *cu;
- OBJECT obj;
- {
- CUBE cukid;
- OCTREE ot;
- OBJECT oset[MAXSET+1];
- unsigned char inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8];
- int in;
- register int i, j;
-
- in = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu);
-
- if (in == O_MISS)
- return; /* no intersection */
-
- if (istree(cu->cutree)) {
- /* do children */
- cukid.cusize = cu->cusize * 0.5;
- for (i = 0; i < 8; i++) {
- cukid.cutree = octkid(cu->cutree, i);
- for (j = 0; j < 3; j++) {
- cukid.cuorg[j] = cu->cuorg[j];
- if ((1<<j) & i)
- cukid.cuorg[j] += cukid.cusize;
- }
- addobject(&cukid, obj);
- octkid(cu->cutree, i) = cukid.cutree;
- }
- return;
- }
- if (isempty(cu->cutree)) {
- /* singular set */
- oset[0] = 1; oset[1] = obj;
- cu->cutree = fullnode(oset);
- return;
- }
- /* add to full node */
- objset(oset, cu->cutree);
- cukid.cusize = cu->cusize * 0.5;
-
- if (in==O_IN || oset[0] < objlim || cukid.cusize < mincusize) {
- /* add to set */
- if (oset[0] >= MAXSET) {
- sprintf(errmsg, "set overflow in addobject (%s)",
- objptr(obj)->oname);
- error(INTERNAL, errmsg);
- }
- insertelem(oset, obj);
- cu->cutree = fullnode(oset);
- return;
- }
- /* subdivide cube */
- if ((ot = octalloc()) == EMPTY)
- error(SYSTEM, "out of octree space");
- /* mark volumes */
- j = (oset[0]+7)>>3;
- while (j--)
- volflg[j] = inflg[j] = 0;
- for (j = 1; j <= oset[0]; j++)
- if (isvolume(objptr(oset[j])->otype)) {
- setbit(volflg,j-1);
- if ((*ofun[objptr(oset[j])->otype].funp)
- (objptr(oset[j]), cu) == O_IN)
- setbit(inflg,j-1);
- }
- /* assign subcubes */
- for (i = 0; i < 8; i++) {
- cukid.cutree = EMPTY;
- for (j = 0; j < 3; j++) {
- cukid.cuorg[j] = cu->cuorg[j];
- if ((1<<j) & i)
- cukid.cuorg[j] += cukid.cusize;
- }
- /* surfaces first */
- for (j = 1; j <= oset[0]; j++)
- if (!tstbit(volflg,j-1))
- addobject(&cukid, oset[j]);
- /* then this object */
- addobject(&cukid, obj);
- /* then partial volumes */
- for (j = 1; j <= oset[0]; j++)
- if (tstbit(volflg,j-1) &&
- !tstbit(inflg,j-1))
- addobject(&cukid, oset[j]);
- /* full volumes last */
- for (j = 1; j <= oset[0]; j++)
- if (tstbit(inflg,j-1))
- addobject(&cukid, oset[j]);
- /* returned node */
- octkid(ot, i) = cukid.cutree;
- }
- cu->cutree = ot;
- }
-