Back to index

radiance  4R0+20100331
readoct.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: readoct.c,v 2.28 2004/12/16 19:31:36 greg Exp $";
00003 #endif
00004 /*
00005  *  readoct.c - routines to read octree information.
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include  <stdio.h>
00011 #include  <time.h>
00012 
00013 #include  "platform.h"
00014 #include  "rtprocess.h"
00015 #include  "standard.h"
00016 #include  "octree.h"
00017 #include  "object.h"
00018 #include  "otypes.h"
00019 #include  "resolu.h"
00020 
00021 #ifdef getc_unlocked        /* avoid horrendous overhead of flockfile */
00022 #undef getc
00023 #define getc    getc_unlocked
00024 #endif
00025 
00026 static double  ogetflt(void);
00027 static long  ogetint(int);
00028 static char  *ogetstr(char *);
00029 static int  nonsurfintree(OCTREE ot);
00030 static void  octerror(int  etyp, char  *msg);
00031 static void  skiptree(void);
00032 static OCTREE  getfullnode(void), gettree(void);
00033 
00034 static char  *infn;                /* input file specification */
00035 static FILE  *infp;                /* input file stream */
00036 static int  objsize;               /* size of stored OBJECT's */
00037 static OBJECT  objorig;                   /* zeroeth object */
00038 static OBJECT  fnobjects;          /* number of objects in this file */
00039 
00040 
00041 int
00042 readoct(                           /* read in octree file or stream */
00043        char  *inpspec,
00044        int  load,
00045        CUBE  *scene,
00046        char  *ofn[]
00047 )
00048 {
00049        char  sbuf[512];
00050        int  nf;
00051        int  i;
00052        long  m;
00053        
00054        if (inpspec == NULL) {
00055               infn = "standard input";
00056               infp = stdin;
00057        } else if (inpspec[0] == '!') {
00058               infn = inpspec;
00059               if ((infp = popen(inpspec+1, "r")) == NULL) {
00060                      sprintf(errmsg, "cannot execute \"%s\"", inpspec);
00061                      error(SYSTEM, errmsg);
00062               }
00063        } else {
00064               infn = inpspec;
00065               if ((infp = fopen(inpspec, "r")) == NULL) {
00066                      sprintf(errmsg, "cannot open octree file \"%s\"",
00067                                    inpspec);
00068                      error(SYSTEM, errmsg);
00069               }
00070        }
00071        SET_FILE_BINARY(infp);
00072                                    /* get header */
00073        if (checkheader(infp, OCTFMT, load&IO_INFO ? stdout : (FILE *)NULL) < 0)
00074               octerror(USER, "not an octree");
00075                                    /* check format */
00076        if ((objsize = ogetint(2)-OCTMAGIC) <= 0 ||
00077                      objsize > MAXOBJSIZ || objsize > sizeof(long))
00078               octerror(USER, "incompatible octree format");
00079                                    /* get boundaries */
00080        if (load & IO_BOUNDS) {
00081               for (i = 0; i < 3; i++)
00082                      scene->cuorg[i] = atof(ogetstr(sbuf));
00083               scene->cusize = atof(ogetstr(sbuf));
00084        } else {
00085               for (i = 0; i < 4; i++)
00086                      ogetstr(sbuf);
00087        }
00088        objorig = nobjects;         /* set object offset */
00089        nf = 0;                            /* get object files */
00090        while (*ogetstr(sbuf)) {
00091               if (load & IO_SCENE)
00092                      readobj(sbuf);
00093               if (load & IO_FILES)
00094                      ofn[nf] = savqstr(sbuf);
00095               nf++;
00096        }
00097        if (load & IO_FILES)
00098               ofn[nf] = NULL;
00099                                    /* get number of objects */
00100        fnobjects = m = ogetint(objsize);
00101        if (fnobjects != m)
00102               octerror(USER, "too many objects");
00103 
00104        if (load & IO_TREE)         /* get the octree */
00105               scene->cutree = gettree();
00106        else if (load & IO_SCENE && nf == 0)
00107               skiptree();
00108               
00109        if (load & IO_SCENE) {             /* get the scene */
00110            if (nf == 0) {
00111                                    /* load binary scene data */
00112               readscene(infp, objsize);
00113 
00114            } else {                /* consistency checks */
00115                             /* check object count */
00116               if (nobjects != objorig+fnobjects)
00117                      octerror(USER, "bad object count; octree stale?");
00118                             /* check for non-surfaces */
00119               if (nonsurfintree(scene->cutree))
00120                      octerror(USER, "modifier in tree; octree stale?");
00121            }
00122        }
00123                             /* close the input */
00124        if (infn[0] == '!')
00125               pclose(infp);
00126        else
00127               fclose(infp);
00128        return(nf);
00129 }
00130 
00131 
00132 static char *
00133 ogetstr(char *s)            /* get null-terminated string */
00134 {
00135        extern char  *getstr();
00136 
00137        if (getstr(s, infp) == NULL)
00138               octerror(USER, "truncated octree");
00139        return(s);
00140 }
00141 
00142 
00143 static OCTREE
00144 getfullnode()               /* get a set, return fullnode */
00145 {
00146        OBJECT set[MAXSET+1];
00147        register int  i;
00148        register long  m;
00149 
00150        if ((set[0] = ogetint(objsize)) > MAXSET)
00151               octerror(USER, "bad set in getfullnode");
00152        for (i = 1; i <= set[0]; i++) {
00153               m = ogetint(objsize) + objorig;
00154               if ((set[i] = m) != m)
00155                      octerror(USER, "too many objects");
00156        }
00157        return(fullnode(set));
00158 }      
00159 
00160 
00161 static long
00162 ogetint(int siz)            /* get a siz-byte integer */
00163 {
00164        extern long  getint();
00165        register long  r;
00166 
00167        r = getint(siz, infp);
00168        if (feof(infp))
00169               octerror(USER, "truncated octree");
00170        return(r);
00171 }
00172 
00173 
00174 static double
00175 ogetflt()                   /* get a floating point number */
00176 {
00177        extern double  getflt();
00178        double r;
00179 
00180        r = getflt(infp);
00181        if (feof(infp))
00182               octerror(USER, "truncated octree");
00183        return(r);
00184 }
00185        
00186 
00187 static OCTREE
00188 gettree()                   /* get a pre-ordered octree */
00189 {
00190        register OCTREE       ot;
00191        register int  i;
00192        
00193        switch (getc(infp)) {
00194        case OT_EMPTY:
00195               return(EMPTY);
00196        case OT_FULL:
00197               return(getfullnode());
00198        case OT_TREE:
00199               if ((ot = octalloc()) == EMPTY)
00200                      octerror(SYSTEM, "out of tree space in gettree");
00201               for (i = 0; i < 8; i++)
00202                      octkid(ot, i) = gettree();
00203               return(ot);
00204        case EOF:
00205               octerror(USER, "truncated octree");
00206        default:
00207               octerror(USER, "damaged octree");
00208        }
00209        return EMPTY; /* pro forma return */
00210 }
00211 
00212 
00213 static int
00214 nonsurfintree(OCTREE ot)           /* check tree for modifiers */
00215 {
00216        OBJECT  set[MAXSET+1];
00217        register int  i;
00218 
00219        if (isempty(ot))
00220               return(0);
00221        if (istree(ot)) {
00222               for (i = 0; i < 8; i++)
00223                      if (nonsurfintree(octkid(ot, i)))
00224                             return(1);
00225               return(0);
00226        }
00227        objset(set, ot);
00228        for (i = set[0]; i > 0; i-- )
00229               if (ismodifier(objptr(set[i])->otype))
00230                      return(1);
00231        return(0);
00232 }
00233 
00234 
00235 static void
00236 skiptree(void)                            /* skip octree on input */
00237 {
00238        register int  i;
00239        
00240        switch (getc(infp)) {
00241        case OT_EMPTY:
00242               return;
00243        case OT_FULL:
00244               for (i = ogetint(objsize)*objsize; i-- > 0; )
00245                      if (getc(infp) == EOF)
00246                             octerror(USER, "truncated octree");
00247               return;
00248        case OT_TREE:
00249               for (i = 0; i < 8; i++)
00250                      skiptree();
00251               return;
00252        case EOF:
00253               octerror(USER, "truncated octree");
00254        default:
00255               octerror(USER, "damaged octree");
00256        }
00257 }
00258 
00259 
00260 static void
00261 octerror(int etyp, char *msg)             /* octree error */
00262 {
00263        char  msgbuf[128];
00264 
00265        sprintf(msgbuf, "(%s): %s", infn, msg);
00266        error(etyp, msgbuf);
00267 }