home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / OT / OCONV.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  8KB  |  302 lines

  1. /* Copyright (c) 1986 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)oconv.c 2.3 8/24/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  oconv.c - main program for object to octree conversion.
  9.  *
  10.  *     7/29/85
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  "octree.h"
  16.  
  17. #include  "object.h"
  18.  
  19. #include  "otypes.h"
  20.  
  21. #include  "paths.h"
  22.  
  23. #define  OMARGIN        (10*FTINY)      /* margin around global cube */
  24.  
  25. #define  MAXOBJFIL      63              /* maximum number of scene files */
  26.  
  27. char  *progname;                        /* argv[0] */
  28.  
  29. char  *libpath;                         /* library search path */
  30.  
  31. int  nowarn = 0;                        /* supress warnings? */
  32.  
  33. int  objlim = 5;                        /* # of objects before split */
  34.  
  35. int  resolu = 1024;                     /* octree resolution limit */
  36.  
  37. CUBE  thescene = {EMPTY, {0.0, 0.0, 0.0}, 0.0};         /* our scene */
  38.  
  39. char  *ofname[MAXOBJFIL+1];             /* object file names */
  40. int  nfiles = 0;                        /* number of object files */
  41.  
  42. double  mincusize;                      /* minimum cube size from resolu */
  43.  
  44. int  (*addobjnotify[])() = {NULL};      /* new object notifier functions */
  45.  
  46.  
  47. main(argc, argv)                /* convert object files to an octree */
  48. int  argc;
  49. char  **argv;
  50. {
  51.     extern char  *getenv();
  52.     FVECT  bbmin, bbmax;
  53.     char  *infile = NULL;
  54.     int  outflags = IO_ALL;
  55.     OBJECT  startobj;
  56.     int  i;
  57.     
  58.     progname = argv[0] = fixargv0(argv[0]);
  59.  
  60.     if ((libpath = getenv(ULIBVAR)) == NULL)
  61.         libpath = DEFPATH;
  62.  
  63.     initotypes();
  64.  
  65.     for (i = 1; i < argc && argv[i][0] == '-'; i++)
  66.         switch (argv[i][1]) {
  67.         case '\0':                              /* scene from stdin */
  68.             goto breakopt;
  69.         case 'i':                               /* input octree */
  70.             infile = argv[++i];
  71.             break;
  72.         case 'b':                               /* bounding cube */
  73.             thescene.cuorg[0] = atof(argv[++i]) - OMARGIN;
  74.             thescene.cuorg[1] = atof(argv[++i]) - OMARGIN;
  75.             thescene.cuorg[2] = atof(argv[++i]) - OMARGIN;
  76.             thescene.cusize = atof(argv[++i]) + 2*OMARGIN;
  77.             break;
  78.         case 'n':                               /* set limit */
  79.             objlim = atoi(argv[++i]);
  80.             break;
  81.         case 'r':                               /* resolution limit */
  82.             resolu = atoi(argv[++i]);
  83.             break;
  84.         case 'f':                               /* freeze octree */
  85.             outflags &= ~IO_FILES;
  86.             break;
  87.         case 'w':                               /* supress warnings */
  88.             nowarn = 1;
  89.             break;
  90.         default:
  91.             sprintf(errmsg, "unknown option: '%s'", argv[i]);
  92.             error(USER, errmsg);
  93.             break;
  94.         }
  95. breakopt:
  96. #ifdef MSDOS
  97.     setmode(fileno(stdout), O_BINARY);
  98. #endif
  99.     if (infile != NULL) {           /* get old octree & objects */
  100.         if (thescene.cusize > FTINY)
  101.             error(USER, "only one of '-b' or '-i'");
  102.         nfiles = readoct(infile, IO_ALL, &thescene, ofname);
  103.         if (nfiles == 0 && outflags & IO_FILES) {
  104.             error(WARNING, "frozen octree");
  105.             outflags &= ~IO_FILES;
  106.         }
  107.     }
  108.  
  109.     printargs(argc, argv, stdout);  /* info. header */
  110.     fputformat(OCTFMT, stdout);
  111.     printf("\n");
  112.  
  113.     startobj = nobjects;            /* previous objects already converted */
  114.     
  115.     for ( ; i < argc; i++)          /* read new scene descriptions */
  116.         if (!strcmp(argv[i], "-")) {    /* from stdin */
  117.             readobj(NULL);
  118.             outflags &= ~IO_FILES;
  119.         } else {                        /* from file */
  120.             if (nfiles >= MAXOBJFIL)
  121.                 error(INTERNAL, "too many scene files");
  122.             readobj(ofname[nfiles++] = argv[i]);
  123.         }
  124.  
  125.     ofname[nfiles] = NULL;
  126.                         /* find bounding box */
  127.     bbmin[0] = bbmin[1] = bbmin[2] = FHUGE;
  128.     bbmax[0] = bbmax[1] = bbmax[2] = -FHUGE;
  129.     for (i = startobj; i < nobjects; i++)
  130.         add2bbox(objptr(i), bbmin, bbmax);
  131.                         /* set/check cube */
  132.     if (thescene.cusize == 0.0) {
  133.         if (bbmin[0] <= bbmax[0]) {
  134.             for (i = 0; i < 3; i++) {
  135.                 bbmin[i] -= OMARGIN;
  136.                 bbmax[i] += OMARGIN;
  137.             }
  138.             for (i = 0; i < 3; i++)
  139.                 if (bbmax[i] - bbmin[i] > thescene.cusize)
  140.                     thescene.cusize = bbmax[i] - bbmin[i];
  141.             for (i = 0; i < 3; i++)
  142.                 thescene.cuorg[i] =
  143.                     (bbmax[i]+bbmin[i]-thescene.cusize)*.5;
  144.         }
  145.     } else {
  146.         for (i = 0; i < 3; i++)
  147.             if (bbmin[i] < thescene.cuorg[i] ||
  148.                 bbmax[i] > thescene.cuorg[i] + thescene.cusize)
  149.                 error(USER, "boundary does not encompass scene");
  150.     }
  151.  
  152.     mincusize = thescene.cusize / resolu - FTINY;
  153.         
  154.     for (i = startobj; i < nobjects; i++)           /* add new objects */
  155.         addobject(&thescene, i);
  156.     
  157.     thescene.cutree = combine(thescene.cutree);     /* optimize */
  158.  
  159.     writeoct(outflags, &thescene, ofname);  /* write structures to stdout */
  160.  
  161.     quit(0);
  162. }
  163.  
  164.  
  165. quit(code)                              /* exit program */
  166. int  code;
  167. {
  168.     exit(code);
  169. }
  170.  
  171.  
  172. cputs()                                 /* interactive error */
  173. {
  174.     /* referenced, but not used */
  175. }
  176.  
  177.  
  178. wputs(s)                                /* warning message */
  179. char  *s;
  180. {
  181.     if (!nowarn)
  182.         eputs(s);
  183. }
  184.  
  185.  
  186. eputs(s)                                /* put string to stderr */
  187. register char  *s;
  188. {
  189.     static int  inln = 0;
  190.  
  191.     if (!inln++) {
  192.         fputs(progname, stderr);
  193.         fputs(": ", stderr);
  194.     }
  195.     fputs(s, stderr);
  196.     if (*s && s[strlen(s)-1] == '\n')
  197.         inln = 0;
  198. }
  199.  
  200.  
  201. #define  bitop(f,i,op)          (f[((i)>>3)] op (1<<((i)&7)))
  202. #define  tstbit(f,i)            bitop(f,i,&)
  203. #define  setbit(f,i)            bitop(f,i,|=)
  204. #define  clrbit(f,i)            bitop(f,i,&=~)
  205. #define  tglbit(f,i)            bitop(f,i,^=)
  206.  
  207.  
  208. addobject(cu, obj)                      /* add an object to a cube */
  209. register CUBE  *cu;
  210. OBJECT  obj;
  211. {
  212.     CUBE  cukid;
  213.     OCTREE  ot;
  214.     OBJECT  oset[MAXSET+1];
  215.     unsigned char  inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8];
  216.     int  in;
  217.     register int  i, j;
  218.  
  219.     in = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu);
  220.  
  221.     if (in == O_MISS)
  222.         return;                         /* no intersection */
  223.     
  224.     if (istree(cu->cutree)) {
  225.                         /* do children */
  226.         cukid.cusize = cu->cusize * 0.5;
  227.         for (i = 0; i < 8; i++) {
  228.             cukid.cutree = octkid(cu->cutree, i);
  229.             for (j = 0; j < 3; j++) {
  230.                 cukid.cuorg[j] = cu->cuorg[j];
  231.                 if ((1<<j) & i)
  232.                     cukid.cuorg[j] += cukid.cusize;
  233.             }
  234.             addobject(&cukid, obj);
  235.             octkid(cu->cutree, i) = cukid.cutree;
  236.         }
  237.         return;
  238.     }
  239.     if (isempty(cu->cutree)) {
  240.                         /* singular set */
  241.         oset[0] = 1; oset[1] = obj;
  242.         cu->cutree = fullnode(oset);
  243.         return;
  244.     }
  245.                     /* add to full node */
  246.     objset(oset, cu->cutree);
  247.     cukid.cusize = cu->cusize * 0.5;
  248.     
  249.     if (in==O_IN || oset[0] < objlim || cukid.cusize < mincusize) {
  250.                         /* add to set */
  251.         if (oset[0] >= MAXSET) {
  252.             sprintf(errmsg, "set overflow in addobject (%s)",
  253.                     objptr(obj)->oname);
  254.             error(INTERNAL, errmsg);
  255.         }
  256.         insertelem(oset, obj);
  257.         cu->cutree = fullnode(oset);
  258.         return;
  259.     }
  260.                     /* subdivide cube */
  261.     if ((ot = octalloc()) == EMPTY)
  262.         error(SYSTEM, "out of octree space");
  263.                     /* mark volumes */
  264.     j = (oset[0]+7)>>3;
  265.     while (j--)
  266.         volflg[j] = inflg[j] = 0;
  267.     for (j = 1; j <= oset[0]; j++)
  268.         if (isvolume(objptr(oset[j])->otype)) {
  269.             setbit(volflg,j-1);
  270.             if ((*ofun[objptr(oset[j])->otype].funp)
  271.                     (objptr(oset[j]), cu) == O_IN)
  272.                 setbit(inflg,j-1);
  273.         }
  274.                     /* assign subcubes */
  275.     for (i = 0; i < 8; i++) {
  276.         cukid.cutree = EMPTY;
  277.         for (j = 0; j < 3; j++) {
  278.             cukid.cuorg[j] = cu->cuorg[j];
  279.             if ((1<<j) & i)
  280.                 cukid.cuorg[j] += cukid.cusize;
  281.         }
  282.                     /* surfaces first */
  283.         for (j = 1; j <= oset[0]; j++)
  284.             if (!tstbit(volflg,j-1))
  285.                 addobject(&cukid, oset[j]);
  286.                     /* then this object */
  287.         addobject(&cukid, obj);
  288.                     /* then partial volumes */
  289.         for (j = 1; j <= oset[0]; j++)
  290.             if (tstbit(volflg,j-1) &&
  291.                     !tstbit(inflg,j-1))
  292.                 addobject(&cukid, oset[j]);
  293.                     /* full volumes last */
  294.         for (j = 1; j <= oset[0]; j++)
  295.             if (tstbit(inflg,j-1))
  296.                 addobject(&cukid, oset[j]);
  297.                     /* returned node */
  298.         octkid(ot, i) = cukid.cutree;
  299.     }
  300.     cu->cutree = ot;
  301. }
  302.