Back to index

radiance  4R0+20100331
oconv.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: oconv.c,v 2.21 2005/09/23 19:04:52 greg Exp $";
00003 #endif
00004 /*
00005  *  oconv.c - main program for object to octree conversion.
00006  *
00007  *     7/29/85
00008  */
00009 
00010 #include  "platform.h"
00011 #include  "standard.h"
00012 #include  "octree.h"
00013 #include  "object.h"
00014 #include  "otypes.h"
00015 #include  "paths.h"
00016 #include  "resolu.h"
00017 #include  "oconv.h"
00018 
00019 #define        OMARGIN      (10*FTINY)    /* margin around global cube */
00020 
00021 #define        MAXOBJFIL    127           /* maximum number of scene files */
00022 
00023 char  *progname;                   /* argv[0] */
00024 
00025 int  nowarn = 0;                   /* supress warnings? */
00026 
00027 int  objlim = 6;                   /* # of objects before split */
00028 
00029 int  resolu = 16384;               /* octree resolution limit */
00030 
00031 CUBE  thescene = {{0.0, 0.0, 0.0}, 0.0, EMPTY};         /* our scene */
00032 
00033 char  *ofname[MAXOBJFIL+1];        /* object file names */
00034 int  nfiles = 0;                   /* number of object files */
00035 
00036 double mincusize;                  /* minimum cube size from resolu */
00037 
00038 void  (*addobjnotify[])() = {NULL};       /* new object notifier functions */
00039 
00040 static void addobject(CUBE  *cu, OBJECT   obj);
00041 static void add2full(CUBE  *cu, OBJECT    obj, int  inc);
00042 
00043 
00044 int
00045 main(         /* convert object files to an octree */
00046        int  argc,
00047        char  *argv[]
00048 )
00049 {
00050        FVECT  bbmin, bbmax;
00051        char  *infile = NULL;
00052        int  inpfrozen = 0;
00053        int  outflags = IO_ALL;
00054        OBJECT startobj;
00055        int  i;
00056 
00057        progname = argv[0] = fixargv0(argv[0]);
00058 
00059        ot_initotypes();
00060 
00061        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00062               switch (argv[i][1]) {
00063               case '\0':                         /* scene from stdin */
00064                      goto breakopt;
00065               case 'i':                          /* input octree */
00066                      infile = argv[++i];
00067                      break;
00068               case 'b':                          /* bounding cube */
00069                      thescene.cuorg[0] = atof(argv[++i]) - OMARGIN;
00070                      thescene.cuorg[1] = atof(argv[++i]) - OMARGIN;
00071                      thescene.cuorg[2] = atof(argv[++i]) - OMARGIN;
00072                      thescene.cusize = atof(argv[++i]) + 2*OMARGIN;
00073                      break;
00074               case 'n':                          /* set limit */
00075                      objlim = atoi(argv[++i]);
00076                      break;
00077               case 'r':                          /* resolution limit */
00078                      resolu = atoi(argv[++i]);
00079                      break;
00080               case 'f':                          /* freeze octree */
00081                      outflags &= ~IO_FILES;
00082                      break;
00083               case 'w':                          /* supress warnings */
00084                      nowarn = 1;
00085                      break;
00086               default:
00087                      sprintf(errmsg, "unknown option: '%s'", argv[i]);
00088                      error(USER, errmsg);
00089                      break;
00090               }
00091 breakopt:
00092        SET_FILE_BINARY(stdout);
00093        if (infile != NULL) {              /* get old octree & objects */
00094               if (thescene.cusize > FTINY)
00095                      error(USER, "only one of '-b' or '-i'");
00096               nfiles = readoct(infile, IO_ALL, &thescene, ofname);
00097               if (nfiles == 0)
00098                      inpfrozen++;
00099        } else
00100               newheader("RADIANCE", stdout);     /* new binary file header */
00101        printargs(argc, argv, stdout);
00102        fputformat(OCTFMT, stdout);
00103        printf("\n");
00104 
00105        startobj = nobjects;        /* previous objects already converted */
00106 
00107        for ( ; i < argc; i++)             /* read new scene descriptions */
00108               if (!strcmp(argv[i], "-")) {       /* from stdin */
00109                      readobj(NULL);
00110                      outflags &= ~IO_FILES;
00111               } else {                    /* from file */
00112                      if (nfiles >= MAXOBJFIL)
00113                             error(INTERNAL, "too many scene files");
00114                      readobj(ofname[nfiles++] = argv[i]);
00115               }
00116 
00117        ofname[nfiles] = NULL;
00118 
00119        if (inpfrozen && outflags & IO_FILES) {
00120               error(WARNING, "frozen octree");
00121               outflags &= ~IO_FILES;
00122        }
00123                                           /* find bounding box */
00124        bbmin[0] = bbmin[1] = bbmin[2] = FHUGE;
00125        bbmax[0] = bbmax[1] = bbmax[2] = -FHUGE;
00126        for (i = startobj; i < nobjects; i++)
00127               add2bbox(objptr(i), bbmin, bbmax);
00128                                           /* set/check cube */
00129        if (thescene.cusize == 0.0) {
00130               if (bbmin[0] <= bbmax[0]) {
00131                      for (i = 0; i < 3; i++) {
00132                             bbmin[i] -= OMARGIN;
00133                             bbmax[i] += OMARGIN;
00134                      }
00135                      for (i = 0; i < 3; i++)
00136                             if (bbmax[i] - bbmin[i] > thescene.cusize)
00137                                    thescene.cusize = bbmax[i] - bbmin[i];
00138                      for (i = 0; i < 3; i++)
00139                             thescene.cuorg[i] =
00140                                    (bbmax[i]+bbmin[i]-thescene.cusize)*.5;
00141               }
00142        } else {
00143               for (i = 0; i < 3; i++)
00144                      if (bbmin[i] < thescene.cuorg[i] ||
00145                             bbmax[i] > thescene.cuorg[i] + thescene.cusize)
00146                             error(USER, "boundary does not encompass scene");
00147        }
00148 
00149        mincusize = thescene.cusize / resolu - FTINY;
00150 
00151        for (i = startobj; i < nobjects; i++)            /* add new objects */
00152               addobject(&thescene, i);
00153 
00154        thescene.cutree = combine(thescene.cutree);      /* optimize */
00155 
00156        writeoct(outflags, &thescene, ofname);    /* write structures to stdout */
00157 
00158        quit(0);
00159        return 0; /* pro forma return */
00160 }
00161 
00162 
00163 void
00164 quit(                       /* exit program */
00165        int  code
00166 )
00167 {
00168        exit(code);
00169 }
00170 
00171 
00172 void
00173 cputs(void)                               /* interactive error */
00174 {
00175        /* referenced, but not used */
00176 }
00177 
00178 
00179 void
00180 wputs(                      /* warning message */
00181        char  *s
00182 )
00183 {
00184        if (!nowarn)
00185               eputs(s);
00186 }
00187 
00188 
00189 void
00190 eputs(                      /* put string to stderr */
00191        register char  *s
00192 )
00193 {
00194        static int  inln = 0;
00195 
00196        if (!inln++) {
00197               fputs(progname, stderr);
00198               fputs(": ", stderr);
00199        }
00200        fputs(s, stderr);
00201        if (*s && s[strlen(s)-1] == '\n')
00202               inln = 0;
00203 }
00204 
00205                             /* conflicting def's in param.h */
00206 #undef  tstbit
00207 #undef  setbit
00208 #undef  clrbit
00209 #undef  tglbit
00210 
00211 #define        bitop(f,i,op)              (f[((i)>>3)] op (1<<((i)&7)))
00212 #define        tstbit(f,i)         bitop(f,i,&)
00213 #define        setbit(f,i)         bitop(f,i,|=)
00214 #define        clrbit(f,i)         bitop(f,i,&=~)
00215 #define        tglbit(f,i)         bitop(f,i,^=)
00216 
00217 
00218 static void
00219 addobject(                  /* add an object to a cube */
00220        register CUBE  *cu,
00221        OBJECT obj
00222 )
00223 {
00224        int  inc;
00225 
00226        inc = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu);
00227 
00228        if (inc == O_MISS)
00229               return;                            /* no intersection */
00230 
00231        if (istree(cu->cutree)) {
00232               CUBE  cukid;                /* do children */
00233               int  i, j;
00234               cukid.cusize = cu->cusize * 0.5;
00235               for (i = 0; i < 8; i++) {
00236                      cukid.cutree = octkid(cu->cutree, i);
00237                      for (j = 0; j < 3; j++) {
00238                             cukid.cuorg[j] = cu->cuorg[j];
00239                             if ((1<<j) & i)
00240                                    cukid.cuorg[j] += cukid.cusize;
00241                      }
00242                      addobject(&cukid, obj);
00243                      octkid(cu->cutree, i) = cukid.cutree;
00244               }
00245               return;
00246        }
00247        if (isempty(cu->cutree)) {
00248               OBJECT  oset[2];            /* singular set */
00249               oset[0] = 1; oset[1] = obj;
00250               cu->cutree = fullnode(oset);
00251               return;
00252        }
00253                                    /* add to full node */
00254        add2full(cu, obj, inc);
00255 }
00256 
00257 
00258 static void
00259 add2full(                   /* add object to full node */
00260        register CUBE  *cu,
00261        OBJECT obj,
00262        int  inc
00263 )
00264 {
00265        OCTREE ot;
00266        OBJECT oset[MAXSET+1];
00267        CUBE  cukid;
00268        unsigned char  inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8];
00269        register int  i, j;
00270 
00271        objset(oset, cu->cutree);
00272        cukid.cusize = cu->cusize * 0.5;
00273 
00274        if (inc==O_IN || oset[0] < objlim || cukid.cusize <
00275                      (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
00276                                           /* add to set */
00277               if (oset[0] >= MAXSET) {
00278                      sprintf(errmsg, "set overflow in addobject (%s)",
00279                                    objptr(obj)->oname);
00280                      error(INTERNAL, errmsg);
00281               }
00282               insertelem(oset, obj);
00283               cu->cutree = fullnode(oset);
00284               return;
00285        }
00286                                    /* subdivide cube */
00287        if ((ot = octalloc()) == EMPTY)
00288               error(SYSTEM, "out of octree space");
00289                                    /* mark volumes */
00290        j = (oset[0]+7)>>3;
00291        while (j--)
00292               volflg[j] = inflg[j] = 0;
00293        for (j = 1; j <= oset[0]; j++)
00294               if (isvolume(objptr(oset[j])->otype)) {
00295                      setbit(volflg,j-1);
00296                      if ((*ofun[objptr(oset[j])->otype].funp)
00297                                    (objptr(oset[j]), cu) == O_IN)
00298                             setbit(inflg,j-1);
00299               }
00300                                    /* assign subcubes */
00301        for (i = 0; i < 8; i++) {
00302               cukid.cutree = EMPTY;
00303               for (j = 0; j < 3; j++) {
00304                      cukid.cuorg[j] = cu->cuorg[j];
00305                      if ((1<<j) & i)
00306                             cukid.cuorg[j] += cukid.cusize;
00307               }
00308                                    /* surfaces first */
00309               for (j = 1; j <= oset[0]; j++)
00310                      if (!tstbit(volflg,j-1))
00311                             addobject(&cukid, oset[j]);
00312                                    /* then this object */
00313               addobject(&cukid, obj);
00314                                    /* then partial volumes */
00315               for (j = 1; j <= oset[0]; j++)
00316                      if (tstbit(volflg,j-1) &&
00317                                    !tstbit(inflg,j-1))
00318                             addobject(&cukid, oset[j]);
00319                                    /* full volumes last */
00320               for (j = 1; j <= oset[0]; j++)
00321                      if (tstbit(inflg,j-1))
00322                             addobject(&cukid, oset[j]);
00323                                    /* returned node */
00324               octkid(ot, i) = cukid.cutree;
00325        }
00326        cu->cutree = ot;
00327 }