Back to index

radiance  4R0+20100331
obj2mesh.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: obj2mesh.c,v 2.13 2008/11/12 03:54:31 greg Exp $";
00003 #endif
00004 /*
00005  *  Main program to compile a Wavefront .OBJ file into a Radiance mesh
00006  */
00007 
00008 #include "copyright.h"
00009 #include "paths.h"
00010 #include "platform.h"
00011 #include "standard.h"
00012 #include "resolu.h"
00013 #include "cvmesh.h"
00014 #include "otypes.h"
00015 
00016 extern int    o_face(); /* XXX should go to a header file */
00017 
00018 int    o_default() { return(O_MISS); }
00019 
00020 FUN  ofun[NUMOTYPE] = INIT_OTYPE;  /* needed for link resolution */
00021 
00022 char  *progname;                   /* argv[0] */
00023 
00024 int  nowarn = 0;                   /* supress warnings? */
00025 
00026 int  objlim = 9;                   /* # of objects before split */
00027 
00028 int  resolu = 16384;               /* octree resolution limit */
00029 
00030 double mincusize;                  /* minimum cube size from resolu */
00031 
00032 static void addface(CUBE  *cu, OBJECT     obj);
00033 static void add2full(CUBE  *cu, OBJECT    obj);
00034 
00035 
00036 int
00037 main(         /* compile a .OBJ file into a mesh */
00038        int  argc,
00039        char  *argv[]
00040 )
00041 {
00042        int  nmatf = 0;
00043        char  pathnames[12800];
00044        char  *pns = pathnames;
00045        char  *matinp[128];
00046        char  *cp;
00047        int  i, j;
00048 
00049        progname = argv[0];
00050        ofun[OBJ_FACE].funp = o_face;
00051 
00052        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00053               switch (argv[i][1]) {
00054               case 'n':                          /* set limit */
00055                      objlim = atoi(argv[++i]);
00056                      break;
00057               case 'r':                          /* resolution limit */
00058                      resolu = atoi(argv[++i]);
00059                      break;
00060               case 'a':                          /* material file */
00061                      matinp[nmatf++] = argv[++i];
00062                      break;
00063               case 'l':                          /* library material */
00064                      cp = getpath(argv[++i], getrlibpath(), R_OK);
00065                      if (cp == NULL) {
00066                             sprintf(errmsg,
00067                                    "cannot find library material: '%s'",
00068                                           argv[i]);
00069                             error(USER, errmsg);
00070                      }
00071                      matinp[nmatf++] = strcpy(pns, cp);
00072                      while (*pns++)
00073                             ;
00074                      break;
00075               case 'w':                          /* supress warnings */
00076                      nowarn = 1;
00077                      break;
00078               default:
00079                      sprintf(errmsg, "unknown option: '%s'", argv[i]);
00080                      error(USER, errmsg);
00081                      break;
00082               }
00083 
00084        if (i < argc-2)
00085               error(USER, "too many file arguments");
00086                                    /* initialize mesh */
00087        cvinit(i==argc-2 ? argv[i+1] : "<stdout>");
00088                                    /* load material input */
00089        for (j = 0; j < nmatf; j++)
00090               readobj(matinp[j]);
00091                                    /* read .OBJ file into triangles */
00092        if (i == argc)
00093               wfreadobj(NULL);
00094        else
00095               wfreadobj(argv[i]);
00096        
00097        cvmeshbounds();                    /* set octree boundaries */
00098 
00099        if (i == argc-2)            /* open output file */
00100               if (freopen(argv[i+1], "w", stdout) == NULL)
00101                      error(SYSTEM, "cannot open output file");
00102        SET_FILE_BINARY(stdout);
00103        newheader("RADIANCE", stdout);     /* new binary file header */
00104        printargs(i<argc ? i+1 : argc, argv, stdout);
00105        fputformat(MESHFMT, stdout);
00106        fputc('\n', stdout);
00107 
00108        mincusize = ourmesh->mcube.cusize / resolu - FTINY;
00109 
00110        for (i = 0; i < nobjects; i++)     /* add triangles to octree */
00111               if (objptr(i)->otype == OBJ_FACE)
00112                      addface(&ourmesh->mcube, i);
00113 
00114                                    /* optimize octree */
00115        ourmesh->mcube.cutree = combine(ourmesh->mcube.cutree);
00116 
00117        if (ourmesh->mcube.cutree == EMPTY)
00118               error(WARNING, "mesh is empty");
00119        
00120        cvmesh();                   /* convert mesh and leaf nodes */
00121 
00122        writemesh(ourmesh, stdout); /* write mesh to output */
00123        
00124        /* printmeshstats(ourmesh, stderr); */
00125 
00126        quit(0);
00127        return 0; /* pro forma return */
00128 }
00129 
00130 
00131 void
00132 quit(                       /* exit program */
00133        int  code
00134 )
00135 {
00136        exit(code);
00137 }
00138 
00139 
00140 void
00141 cputs(void)                               /* interactive error */
00142 {
00143        /* referenced, but not used */
00144 }
00145 
00146 
00147 void
00148 wputs(                      /* warning message */
00149        char  *s
00150 )
00151 {
00152        if (!nowarn)
00153               eputs(s);
00154 }
00155 
00156 
00157 void
00158 eputs(                      /* put string to stderr */
00159        register char  *s
00160 )
00161 {
00162        static int  inln = 0;
00163 
00164        if (!inln++) {
00165               fputs(progname, stderr);
00166               fputs(": ", stderr);
00167        }
00168        fputs(s, stderr);
00169        if (*s && s[strlen(s)-1] == '\n')
00170               inln = 0;
00171 }
00172 
00173 
00174 static void
00175 addface(                    /* add a face to a cube */
00176        register CUBE  *cu,
00177        OBJECT obj
00178 )
00179 {
00180 
00181        if (o_face(objptr(obj), cu) == O_MISS)
00182               return;
00183 
00184        if (istree(cu->cutree)) {
00185               CUBE  cukid;                /* do children */
00186               int  i, j;
00187               cukid.cusize = cu->cusize * 0.5;
00188               for (i = 0; i < 8; i++) {
00189                      cukid.cutree = octkid(cu->cutree, i);
00190                      for (j = 0; j < 3; j++) {
00191                             cukid.cuorg[j] = cu->cuorg[j];
00192                             if ((1<<j) & i)
00193                                    cukid.cuorg[j] += cukid.cusize;
00194                      }
00195                      addface(&cukid, obj);
00196                      octkid(cu->cutree, i) = cukid.cutree;
00197               }
00198               return;
00199        }
00200        if (isempty(cu->cutree)) {
00201               OBJECT oset[2];             /* singular set */
00202               oset[0] = 1; oset[1] = obj;
00203               cu->cutree = fullnode(oset);
00204               return;
00205        }
00206                                    /* add to full node */
00207        add2full(cu, obj);
00208 }
00209 
00210 
00211 static void
00212 add2full(                   /* add object to full node */
00213        register CUBE  *cu,
00214        OBJECT obj
00215 )
00216 {
00217        OCTREE ot;
00218        OBJECT oset[MAXSET+1];
00219        CUBE  cukid;
00220        register int  i, j;
00221 
00222        objset(oset, cu->cutree);
00223        cukid.cusize = cu->cusize * 0.5;
00224 
00225        if (oset[0] < objlim || cukid.cusize <
00226                      (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
00227                                           /* add to set */
00228               if (oset[0] >= MAXSET) {
00229                      sprintf(errmsg, "set overflow in addobject (%s)",
00230                                    objptr(obj)->oname);
00231                      error(INTERNAL, errmsg);
00232               }
00233               insertelem(oset, obj);
00234               cu->cutree = fullnode(oset);
00235               return;
00236        }
00237                                    /* subdivide cube */
00238        if ((ot = octalloc()) == EMPTY)
00239               error(SYSTEM, "out of octree space");
00240                                    /* assign subcubes */
00241        for (i = 0; i < 8; i++) {
00242               cukid.cutree = EMPTY;
00243               for (j = 0; j < 3; j++) {
00244                      cukid.cuorg[j] = cu->cuorg[j];
00245                      if ((1<<j) & i)
00246                             cukid.cuorg[j] += cukid.cusize;
00247               }
00248               for (j = 1; j <= oset[0]; j++)
00249                      addface(&cukid, oset[j]);
00250               addface(&cukid, obj);
00251                                    /* returned node */
00252               octkid(ot, i) = cukid.cutree;
00253        }
00254        cu->cutree = ot;
00255 }