extern void ambnotify( /* record new modifier */ OBJECT obj ) { static int hitlimit = 0; OBJREC *o; char **amblp; if (obj == OVOID) { /* starting over */ ambset[0] = 0; hitlimit = 0; return; } o = objptr(obj); if (hitlimit || !ismodifier(o->otype)) return; for (amblp = amblist; *amblp != NULL; amblp++) if (!strcmp(o->oname, *amblp)) { if (ambset[0] >= MAXASET) { error(WARNING, "too many modifiers in ambient list"); hitlimit++; return; /* should this be fatal? */ } insertelem(ambset, obj); return; } }
extern int rayshade( /* shade ray r with material mod */ RAY *r, int mod ) { OBJREC *m; r->rt = r->rot; /* set effective ray length */ for ( ; mod != OVOID; mod = m->omod) { m = objptr(mod); /****** unnecessary test since modifier() is always called if (!ismodifier(m->otype)) { sprintf(errmsg, "illegal modifier \"%s\"", m->oname); error(USER, errmsg); } ******/ /* hack for irradiance calculation */ if (do_irrad && !(r->crtype & ~(PRIMARY|TRANS)) && m->otype != MAT_CLIP && (ofun[m->otype].flags & (T_M|T_X))) { if (irr_ignore(m->otype)) { raytrans(r); return(1); } if (!islight(m->otype)) m = &Lamb; } if ((*ofun[m->otype].funp)(m, r)) return(1); /* materials call raytexture() */ } return(0); /* no material! */ }
static void addface( /* add a face to a cube */ register CUBE *cu, OBJECT obj ) { if (o_face(objptr(obj), cu) == O_MISS) return; if (istree(cu->cutree)) { CUBE cukid; /* do children */ int i, j; 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; } addface(&cukid, obj); octkid(cu->cutree, i) = cukid.cutree; } return; } if (isempty(cu->cutree)) { OBJECT oset[2]; /* singular set */ oset[0] = 1; oset[1] = obj; cu->cutree = fullnode(oset); return; } /* add to full node */ add2full(cu, obj); }
extern void preload_objs(void) /* preload object data structures */ { register OBJECT on; /* note that nobjects may change during loop */ for (on = 0; on < nobjects; on++) load_os(objptr(on)); }
ObjectUidT Service::insertConnection( const SocketDevice &_rsd, frame::aio::openssl::Context *_pctx, bool _secure ){ //create a new connection with the given channel DynamicPointer<Connection> conptr(new Connection(_rsd)); ObjectUidT rv = registerObject(*conptr); DynamicPointer<frame::aio::Object> objptr(conptr); Manager::the().scheduleAioObject(objptr); return rv; }
static int transillum( /* check if material is transparent illum */ OBJECT obj ) { OBJREC *m = findmaterial(objptr(obj)); if (m == NULL) return(1); if (m->otype != MAT_ILLUM) return(0); return(!m->oargs.nsargs || !strcmp(m->oargs.sarg[0], VOIDID)); }
static void addobject( /* add an object to a cube */ register CUBE *cu, OBJECT obj ) { int inc; inc = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu); if (inc == O_MISS) return; /* no intersection */ if (istree(cu->cutree)) { CUBE cukid; /* do children */ int i, j; 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)) { OBJECT oset[2]; /* singular set */ oset[0] = 1; oset[1] = obj; cu->cutree = fullnode(oset); return; } /* add to full node */ add2full(cu, obj, inc); }
void photonPreCompDensity (PhotonMap *pmap, RAY *r, COLOR irrad) /* Returns precomputed photon density estimate at ray -> rop. */ { Photon p; setcolor(irrad, 0, 0, 0); /* Ignore sources */ if (r -> ro && islight(objptr(r -> ro -> omod) -> otype)) return; find1Photon(preCompPmap, r, &p); getPhotonFlux(&p, irrad); }
extern OBJREC * /* find an object's actual material */ findmaterial(register OBJREC *o) { while (!ismaterial(o->otype)) { if (o->otype == MOD_ALIAS && o->oargs.nsargs) { OBJECT aobj; OBJREC *ao; aobj = lastmod(objndx(o), o->oargs.sarg[0]); if (aobj < 0) objerror(o, USER, "bad reference"); ao = objptr(aobj); if (ismaterial(ao->otype)) return(ao); if (ao->otype == MOD_ALIAS) { o = ao; continue; } } if (o->omod == OVOID) return(NULL); o = objptr(o->omod); } return(o); /* mixtures will return NULL */ }
OBJREC * findmaterial(OBJREC *o) /* find an object's actual material */ { while (!ismaterial(o->otype)) { if (o->otype == MOD_ALIAS && o->oargs.nsargs) { OBJECT aobj; OBJREC *ao; aobj = lastmod(objndx(o), o->oargs.sarg[0]); if (aobj < 0) objerror(o, USER, "bad reference"); /* recursive check on alias branch */ if ((ao = findmaterial(objptr(aobj))) != NULL) return(ao); } if (o->omod == OVOID) { /* void mixture de facto material? */ if (ismixture(o->otype)) break; return(NULL); /* else no material found */ } o = objptr(o->omod); } return(o); }
extern void rayhit( /* standard ray hit test */ OBJECT *oset, RAY *r ) { OBJREC *o; int i; for (i = oset[0]; i > 0; i--) { o = objptr(oset[i]); if ((*ofun[o->otype].funp)(o, r)) r->robj = oset[i]; } }
static void add2full( /* add object to full node */ register CUBE *cu, OBJECT obj ) { OCTREE ot; OBJECT oset[MAXSET+1]; CUBE cukid; register int i, j; objset(oset, cu->cutree); cukid.cusize = cu->cusize * 0.5; if (oset[0] < objlim || cukid.cusize < (oset[0] < MAXSET ? mincusize : mincusize/256.0)) { /* 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"); /* 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; } for (j = 1; j <= oset[0]; j++) addface(&cukid, oset[j]); addface(&cukid, obj); /* returned node */ octkid(ot, i) = cukid.cutree; } cu->cutree = ot; }
static int nonsurfintree(OCTREE ot) /* check tree for modifiers */ { OBJECT set[MAXSET+1]; register int i; if (isempty(ot)) return(0); if (istree(ot)) { for (i = 0; i < 8; i++) if (nonsurfintree(octkid(ot, i))) return(1); return(0); } objset(set, ot); for (i = set[0]; i > 0; i-- ) if (ismodifier(objptr(set[i])->otype)) return(1); return(0); }
extern void raytexture( /* get material modifiers */ RAY *r, OBJECT mod ) { OBJREC *m; /* execute textures and patterns */ for ( ; mod != OVOID; mod = m->omod) { m = objptr(mod); /****** unnecessary test since modifier() is always called if (!ismodifier(m->otype)) { sprintf(errmsg, "illegal modifier \"%s\"", m->oname); error(USER, errmsg); } ******/ if ((*ofun[m->otype].funp)(m, r)) { sprintf(errmsg, "conflicting material \"%s\"", m->oname); objerror(r->ro, USER, errmsg); } } }
static OBJECT cvmeshtri( /* add an extended triangle to our mesh */ OBJECT obj ) { OBJREC *o = objptr(obj); TRIDATA *ts; MESHVERT vert[3]; int i, j; if (o->otype != OBJ_FACE) error(CONSISTENCY, "non-face in mesh"); if (o->oargs.nfargs != 9) error(CONSISTENCY, "non-triangle in mesh"); if (o->os == NULL) error(CONSISTENCY, "missing face record in cvmeshtri"); ts = (TRIDATA *)((FACE *)o->os + 1); if (ts->obj != OVOID) /* already added? */ return(ts->obj); vert[0].fl = vert[1].fl = vert[2].fl = ts->fl; for (i = 3; i--; ) for (j = 3; j--; ) vert[i].v[j] = o->oargs.farg[3*i+j]; if (ts->fl & MT_N) for (i = 3; i--; ) for (j = 3; j--; ) vert[i].n[j] = ts->vn[i][j]; if (ts->fl & MT_UV) for (i = 3; i--; ) for (j = 2; j--; ) vert[i].uv[j] = ts->vc[i][j]; ts->obj = addmeshtri(ourmesh, vert, o->omod); if (ts->obj == OVOID) error(INTERNAL, "addmeshtri failed"); return(ts->obj); }
int main( /* convert object files to an octree */ int argc, char *argv[] ) { FVECT bbmin, bbmax; char *infile = NULL; int inpfrozen = 0; int outflags = IO_ALL; OBJECT startobj; int i; progname = argv[0] = fixargv0(argv[0]); ot_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: SET_FILE_BINARY(stdout); 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) inpfrozen++; } else newheader("RADIANCE", stdout); /* new binary file header */ printargs(argc, argv, stdout); 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; if (inpfrozen && outflags & IO_FILES) { error(WARNING, "frozen octree"); outflags &= ~IO_FILES; } /* 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); return 0; /* pro forma return */ }
static void add2full( /* add object to full node */ register CUBE *cu, OBJECT obj, int inc ) { OCTREE ot; OBJECT oset[MAXSET+1]; CUBE cukid; unsigned char inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8]; register int i, j; objset(oset, cu->cutree); cukid.cusize = cu->cusize * 0.5; if (inc==O_IN || oset[0] < objlim || cukid.cusize < (oset[0] < MAXSET ? mincusize : mincusize/256.0)) { /* 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; }
char * checkmesh(MESH *mp) /* validate mesh data */ { static char embuf[128]; int nouvbounds = 1; int i; /* basic checks */ if (mp == NULL) return("NULL mesh pointer"); if (!mp->ldflags) return("unassigned mesh"); if (mp->name == NULL) return("missing mesh name"); if (mp->nref <= 0) return("unreferenced mesh"); /* check boundaries */ if (mp->ldflags & IO_BOUNDS) { if (mp->mcube.cusize <= FTINY) return("illegal octree bounds in mesh"); nouvbounds = (mp->uvlim[1][0] - mp->uvlim[0][0] <= FTINY || mp->uvlim[1][1] - mp->uvlim[0][1] <= FTINY); } /* check octree */ if (mp->ldflags & IO_TREE) { if (isempty(mp->mcube.cutree)) error(WARNING, "empty mesh octree"); } /* check scene data */ if (mp->ldflags & IO_SCENE) { if (!(mp->ldflags & IO_BOUNDS)) return("unbounded scene in mesh"); if (mp->mat0 < 0 || mp->mat0+mp->nmats > nobjects) return("bad mesh modifier range"); for (i = mp->mat0+mp->nmats; i-- > mp->mat0; ) { int otyp = objptr(i)->otype; if (!ismodifier(otyp)) { sprintf(embuf, "non-modifier in mesh (%s \"%s\")", ofun[otyp].funame, objptr(i)->oname); return(embuf); } } if (mp->npatches <= 0) error(WARNING, "no patches in mesh"); for (i = 0; i < mp->npatches; i++) { MESHPATCH *pp = &mp->patch[i]; if (pp->nverts <= 0) error(WARNING, "no vertices in patch"); else { if (pp->xyz == NULL) return("missing patch vertex list"); if (nouvbounds && pp->uv != NULL) return("unreferenced uv coordinates"); } if (pp->ntris > 0 && pp->tri == NULL) return("missing patch triangle list"); if (pp->nj1tris > 0 && pp->j1tri == NULL) return("missing patch joiner triangle list"); if (pp->nj2tris > 0 && pp->j2tri == NULL) return("missing patch double-joiner list"); } } return(NULL); /* seems OK */ }
extern void marksources(void) /* find and mark source objects */ { int foundsource = 0; int i; register OBJREC *o, *m; register int ns; /* initialize dispatch table */ initstypes(); /* find direct sources */ for (i = 0; i < nsceneobjs; i++) { o = objptr(i); if (!issurface(o->otype) || o->omod == OVOID) continue; /* find material */ m = findmaterial(objptr(o->omod)); if (m == NULL) continue; if (m->otype == MAT_CLIP) { markclip(m); /* special case for antimatter */ continue; } if (!islight(m->otype)) continue; /* not source modifier */ if (m->oargs.nfargs != (m->otype == MAT_GLOW ? 4 : m->otype == MAT_SPOT ? 7 : 3)) objerror(m, USER, "bad # arguments"); if (m->oargs.farg[0] <= FTINY && m->oargs.farg[1] <= FTINY && m->oargs.farg[2] <= FTINY) continue; /* don't bother */ if (m->otype == MAT_GLOW && o->otype != OBJ_SOURCE && m->oargs.farg[3] <= FTINY) { foundsource += (ambounce > 0); continue; /* don't track these */ } if (sfun[o->otype].of == NULL || sfun[o->otype].of->setsrc == NULL) objerror(o, USER, "illegal material"); if ((ns = newsource()) < 0) goto memerr; setsource(&source[ns], o); if (m->otype == MAT_GLOW) { source[ns].sflags |= SPROX; source[ns].sl.prox = m->oargs.farg[3]; if (source[ns].sflags & SDISTANT) { source[ns].sflags |= SSKIP; foundsource += (ambounce > 0); } } else if (m->otype == MAT_SPOT) { source[ns].sflags |= SSPOT; if ((source[ns].sl.s = makespot(m)) == NULL) goto memerr; if (source[ns].sflags & SFLAT && !checkspot(source[ns].sl.s,source[ns].snorm)) { objerror(o, WARNING, "invalid spotlight direction"); source[ns].sflags |= SSKIP; } } #if SHADCACHE initobscache(ns); #endif foundsource += !(source[ns].sflags & SSKIP); } if (!foundsource) { error(WARNING, "no light sources found"); return; } markvirtuals(); /* find and add virtual sources */ /* allocate our contribution arrays */ maxcntr = nsources + MAXSPART; /* start with this many */ srccnt = (CONTRIB *)malloc(maxcntr*sizeof(CONTRIB)); cntord = (CNTPTR *)malloc(maxcntr*sizeof(CNTPTR)); if ((srccnt == NULL) | (cntord == NULL)) goto memerr; return; memerr: error(SYSTEM, "out of memory in marksources"); }
void photonDensity (PhotonMap *pmap, RAY *ray, COLOR irrad) /* Photon density estimate. Returns irradiance at ray -> rop. */ { unsigned i; float r2; COLOR flux; Photon *photon; const PhotonSearchQueueNode *sqn; setcolor(irrad, 0, 0, 0); if (!pmap -> maxGather) return; /* Ignore sources */ if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype)) return; findPhotons(pmap, ray); /* Need at least 2 photons */ if (pmap -> squeue.tail < 2) { #ifdef PMAP_NONEFOUND sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)", ray -> ro ? ray -> ro -> oname : "<null>", ray -> rop [0], ray -> rop [1], ray -> rop [2]); error(WARNING, errmsg); #endif return; } if (pmap -> minGather == pmap -> maxGather) { /* No bias compensation. Just do a plain vanilla estimate */ sqn = pmap -> squeue.node + 1; /* Average radius^2 between furthest two photons to improve accuracy */ r2 = max(sqn -> dist2, (sqn + 1) -> dist2); r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2)); /* Skip the extra photon */ for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) { photon = getNearestPhoton(&pmap -> squeue, sqn -> idx); getPhotonFlux(photon, flux); #ifdef PMAP_EPANECHNIKOV /* Apply Epanechnikov kernel to photon flux based on photon dist */ scalecolor(flux, 2 * (1 - sqn -> dist2 / r2)); #endif addcolor(irrad, flux); } /* Divide by search area PI * r^2, 1 / PI required as ambient normalisation factor */ scalecolor(irrad, 1 / (PI * PI * r2)); return; } else /* Apply bias compensation to density estimate */ biasComp(pmap, irrad); }
int newPhoton (PhotonMap* pmap, const RAY* ray) { unsigned i; Photon photon; COLOR photonFlux; /* Account for distribution ratio */ if (!pmap || pmapRandom(pmap -> randState) > pmap -> distribRatio) return -1; /* Don't store on sources */ if (ray -> robj > -1 && islight(objptr(ray -> ro -> omod) -> otype)) return -1; /* if modifier in include/exclude set */ if (ambincl != -1 && ray -> ro && ambincl != inset(ambset, ray -> ro -> omod)) return -1; if (pmapNumROI && pmapROI) { unsigned inROI = 0; /* Store photon if within a region of interest (for ze Ecksperts!) */ for (i = 0; !inROI && i < pmapNumROI; i++) inROI = (ray -> rop [0] >= pmapROI [i].min [0] && ray -> rop [0] <= pmapROI [i].max [0] && ray -> rop [1] >= pmapROI [i].min [1] && ray -> rop [1] <= pmapROI [i].max [1] && ray -> rop [2] >= pmapROI [i].min [2] && ray -> rop [2] <= pmapROI [i].max [2]); if (!inROI) return -1; } /* Adjust flux according to distribution ratio and ray weight */ copycolor(photonFlux, ray -> rcol); scalecolor(photonFlux, ray -> rweight / (pmap -> distribRatio ? pmap -> distribRatio : 1)); setPhotonFlux(&photon, photonFlux); /* Set photon position and flags */ VCOPY(photon.pos, ray -> rop); photon.flags = 0; photon.caustic = PMAP_CAUSTICRAY(ray); /* Set contrib photon's primary ray and subprocess index (the latter * to linearise the primary ray indices after photon distribution is * complete). Also set primary ray's source index, thereby marking it * as used. */ if (isContribPmap(pmap)) { photon.primary = pmap -> numPrimary; photon.proc = PMAP_GETRAYPROC(ray); pmap -> lastPrimary.srcIdx = ray -> rsrc; } else photon.primary = 0; /* Set normal */ for (i = 0; i <= 2; i++) photon.norm [i] = 127.0 * (isVolumePmap(pmap) ? ray -> rdir [i] : ray -> ron [i]); if (!pmap -> heapBuf) { /* Lazily allocate heap buffa */ #if NIX /* Randomise buffa size to temporally decorellate flushes in * multiprocessing mode */ srandom(randSeed + getpid()); pmap -> heapBufSize = PMAP_HEAPBUFSIZE * (0.5 + frandom()); #else /* Randomisation disabled for single processes on WIN; also useful * for reproducability during debugging */ pmap -> heapBufSize = PMAP_HEAPBUFSIZE; #endif if (!(pmap -> heapBuf = calloc(pmap -> heapBufSize, sizeof(Photon)))) error(SYSTEM, "failed heap buffer allocation in newPhoton"); pmap -> heapBufLen = 0; } /* Photon initialised; now append to heap buffa */ memcpy(pmap -> heapBuf + pmap -> heapBufLen, &photon, sizeof(Photon)); if (++pmap -> heapBufLen >= pmap -> heapBufSize) /* Heap buffa full, flush to heap file */ flushPhotonHeap(pmap); pmap -> numPhotons++; return 0; }
int main( /* compile a .OBJ file into a mesh */ int argc, char *argv[] ) { int nmatf = 0; char pathnames[12800]; char *pns = pathnames; char *matinp[128]; char *cp; int i, j; progname = argv[0]; ofun[OBJ_FACE].funp = o_face; for (i = 1; i < argc && argv[i][0] == '-'; i++) switch (argv[i][1]) { case 'n': /* set limit */ objlim = atoi(argv[++i]); break; case 'r': /* resolution limit */ resolu = atoi(argv[++i]); break; case 'a': /* material file */ matinp[nmatf++] = argv[++i]; break; case 'l': /* library material */ cp = getpath(argv[++i], getrlibpath(), R_OK); if (cp == NULL) { sprintf(errmsg, "cannot find library material: '%s'", argv[i]); error(USER, errmsg); } matinp[nmatf++] = strcpy(pns, cp); while (*pns++) ; break; case 'w': /* supress warnings */ nowarn = 1; break; default: sprintf(errmsg, "unknown option: '%s'", argv[i]); error(USER, errmsg); break; } if (i < argc-2) error(USER, "too many file arguments"); /* initialize mesh */ cvinit(i==argc-2 ? argv[i+1] : "<stdout>"); /* load material input */ for (j = 0; j < nmatf; j++) readobj(matinp[j]); /* read .OBJ file into triangles */ if (i == argc) wfreadobj(NULL); else wfreadobj(argv[i]); cvmeshbounds(); /* set octree boundaries */ if (i == argc-2) /* open output file */ if (freopen(argv[i+1], "w", stdout) == NULL) error(SYSTEM, "cannot open output file"); SET_FILE_BINARY(stdout); newheader("RADIANCE", stdout); /* new binary file header */ printargs(i<argc ? i+1 : argc, argv, stdout); fputformat(MESHFMT, stdout); fputc('\n', stdout); mincusize = ourmesh->mcube.cusize / resolu - FTINY; for (i = 0; i < nobjects; i++) /* add triangles to octree */ if (objptr(i)->otype == OBJ_FACE) addface(&ourmesh->mcube, i); /* optimize octree */ ourmesh->mcube.cutree = combine(ourmesh->mcube.cutree); if (ourmesh->mcube.cutree == EMPTY) error(WARNING, "mesh is empty"); cvmesh(); /* convert mesh and leaf nodes */ writemesh(ourmesh, stdout); /* write mesh to output */ /* printmeshstats(ourmesh, stderr); */ quit(0); return 0; /* pro forma return */ }
void traceray( /* trace a single ray */ char *s ) { RAY thisray; char buf[512]; thisray.rmax = 0.0; if (!sscanvec(s, thisray.rorg) || !sscanvec(sskip2(s,3), thisray.rdir)) { int x, y; if (dev->getcur == NULL) return; (*dev->comout)("Pick ray\n"); if ((*dev->getcur)(&x, &y) == ABORT) return; if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir, &ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) { error(COMMAND, "not on image"); return; } } else if (normalize(thisray.rdir) == 0.0) { error(COMMAND, "zero ray direction"); return; } ray_trace(&thisray); if (thisray.ro == NULL) (*dev->comout)("ray hit nothing"); else { OBJREC *mat = NULL; OBJREC *mod = NULL; char matspec[256]; OBJREC *ino; matspec[0] = '\0'; if (thisray.ro->omod != OVOID) { mod = objptr(thisray.ro->omod); mat = findmaterial(mod); } if (thisray.rod < 0.0) strcpy(matspec, "back of "); if (mod != NULL) { strcat(matspec, mod->oname); if (mat != mod && mat != NULL) sprintf(matspec+strlen(matspec), " (%s)", mat->oname); } else strcat(matspec, VOIDID); sprintf(buf, "ray hit %s %s \"%s\"", matspec, ofun[thisray.ro->otype].funame, thisray.ro->oname); if ((ino = objptr(thisray.robj)) != thisray.ro) sprintf(buf+strlen(buf), " in %s \"%s\"", ofun[ino->otype].funame, ino->oname); (*dev->comout)(buf); (*dev->comin)(buf, NULL); if (thisray.rot >= FHUGE) (*dev->comout)("at infinity"); else { sprintf(buf, "at (%.6g %.6g %.6g) (%.6g)", thisray.rop[0], thisray.rop[1], thisray.rop[2], raydistance(&thisray)); (*dev->comout)(buf); } (*dev->comin)(buf, NULL); sprintf(buf, "value (%.5g %.5g %.5g) (%.3gL)", colval(thisray.rcol,RED), colval(thisray.rcol,GRN), colval(thisray.rcol,BLU), luminance(thisray.rcol)); (*dev->comout)(buf); } (*dev->comin)(buf, NULL); }
int /* create an extended triangle */ cvtri( OBJECT mo, FVECT vp1, FVECT vp2, FVECT vp3, FVECT vn1, FVECT vn2, FVECT vn3, RREAL vc1[2], RREAL vc2[2], RREAL vc3[2] ) { static OBJECT fobj = OVOID; char buf[32]; int flags; TRIDATA *ts; FACE *f; OBJREC *fop; int j; flags = MT_V; /* check what we have */ if (vn1 != NULL && vn2 != NULL && vn3 != NULL) { RREAL *rp; switch (flat_tri(vp1, vp2, vp3, vn1, vn2, vn3)) { case ISBENT: flags |= MT_N; /* fall through */ case ISFLAT: break; case RVBENT: flags |= MT_N; rp = vn1; vn1 = vn3; vn3 = rp; /* fall through */ case RVFLAT: rp = vp1; vp1 = vp3; vp3 = rp; rp = vc1; vc1 = vc3; vc3 = rp; break; case DEGEN: error(WARNING, "degenerate triangle"); return(0); default: error(INTERNAL, "bad return from flat_tri()"); } } if (vc1 != NULL && vc2 != NULL && vc3 != NULL) flags |= MT_UV; if (fobj == OVOID) { /* create new triangle object */ fobj = newobject(); if (fobj == OVOID) goto nomem; fop = objptr(fobj); fop->omod = mo; fop->otype = OBJ_FACE; sprintf(buf, "t%ld", (long)fobj); fop->oname = savqstr(buf); fop->oargs.nfargs = 9; fop->oargs.farg = (RREAL *)malloc(9*sizeof(RREAL)); if (fop->oargs.farg == NULL) goto nomem; } else { /* else reuse failed one */ fop = objptr(fobj); if (fop->otype != OBJ_FACE || fop->oargs.nfargs != 9) error(CONSISTENCY, "code error 1 in cvtri"); } for (j = 3; j--; ) { fop->oargs.farg[j] = vp1[j]; fop->oargs.farg[3+j] = vp2[j]; fop->oargs.farg[6+j] = vp3[j]; } /* create face record */ f = getface(fop); if (f->area == 0.) { free_os(fop); return(0); } if (fop->os != (char *)f) error(CONSISTENCY, "code error 2 in cvtri"); /* follow with auxliary data */ f = (FACE *)realloc((void *)f, sizeof(FACE)+tdsize(flags)); if (f == NULL) goto nomem; fop->os = (char *)f; ts = (TRIDATA *)(f+1); ts->fl = flags; ts->obj = OVOID; if (flags & MT_N) for (j = 3; j--; ) { ts->vn[0][j] = vn1[j]; ts->vn[1][j] = vn2[j]; ts->vn[2][j] = vn3[j]; } if (flags & MT_UV) for (j = 2; j--; ) { ts->vc[0][j] = vc1[j]; ts->vc[1][j] = vc2[j]; ts->vc[2][j] = vc3[j]; } else vc1 = vc2 = vc3 = NULL; /* update bounds */ add2bounds(vp1, vc1); add2bounds(vp2, vc2); add2bounds(vp3, vc3); fobj = OVOID; /* we used this one */ return(1); nomem: error(SYSTEM, "out of memory in cvtri"); return(0); }
void getobject( /* read the next object */ char *name, FILE *fp ) { #define OALIAS -2 OBJECT obj; char sbuf[MAXSTR]; int rval; OBJREC *objp; if ((obj = newobject()) == OVOID) error(SYSTEM, "out of object space"); objp = objptr(obj); /* get modifier */ strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if (strchr(sbuf, '\t')) { sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"", name, sbuf); error(USER, errmsg); } if (!strcmp(sbuf, VOIDID)) objp->omod = OVOID; else if (!strcmp(sbuf, ALIASMOD)) objp->omod = OALIAS; else if ((objp->omod = modifier(sbuf)) == OVOID) { sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf); error(USER, errmsg); } /* get type */ strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if ((objp->otype = otype(sbuf)) < 0) { sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf); error(USER, errmsg); } /* get identifier */ sbuf[0] = '\0'; fgetword(sbuf, MAXSTR, fp); if (strchr(sbuf, '\t')) { sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"", name, sbuf); error(USER, errmsg); } objp->oname = savqstr(sbuf); /* get arguments */ if (objp->otype == MOD_ALIAS) { OBJECT alias; strcpy(sbuf, "EOF"); fgetword(sbuf, MAXSTR, fp); if ((alias = modifier(sbuf)) == OVOID) { sprintf(errmsg, "(%s): bad reference \"%s\"", name, sbuf); objerror(objp, USER, errmsg); } if (objp->omod == OALIAS || objp->omod == objptr(alias)->omod) { objp->omod = alias; } else { objp->oargs.sarg = (char **)malloc(sizeof(char *)); if (objp->oargs.sarg == NULL) error(SYSTEM, "out of memory in getobject"); objp->oargs.nsargs = 1; objp->oargs.sarg[0] = savestr(sbuf); } } else if ((rval = readfargs(&objp->oargs, fp)) == 0) { sprintf(errmsg, "(%s): bad arguments", name); objerror(objp, USER, errmsg); } else if (rval < 0) { sprintf(errmsg, "(%s): error reading scene", name); error(SYSTEM, errmsg); } if (objp->omod == OALIAS) { sprintf(errmsg, "(%s): inappropriate use of '%s' modifier", name, ALIASMOD); objerror(objp, USER, errmsg); } /* initialize */ objp->os = NULL; insertobject(obj); /* add to global structure */ #undef OALIAS }