static void getacoords_as( /* set up coordinate system */ ASHIKDAT *np ) { MFUNC *mf; int i; mf = getfunc(np->mp, 3, 0x7, 1); setfunc(np->mp, np->rp); errno = 0; for (i = 0; i < 3; i++) np->u[i] = evalue(mf->ep[i]); if ((errno == EDOM) | (errno == ERANGE)) { objerror(np->mp, WARNING, "compute error"); np->specfl |= SPA_BADU; return; } if (mf->fxp != &unitxf) multv3(np->u, np->u, mf->fxp->xfm); fcross(np->v, np->pnorm, np->u); if (normalize(np->v) == 0.0) { objerror(np->mp, WARNING, "illegal orientation vector"); np->specfl |= SPA_BADU; return; } fcross(np->u, np->v, np->pnorm); }
MESHINST * getmeshinst( /* create mesh instance */ OBJREC *o, int flags ) { MESHINST *ins; flags &= IO_LEGAL; if ((ins = (MESHINST *)o->os) == NULL) { if ((ins = (MESHINST *)malloc(sizeof(MESHINST))) == NULL) error(SYSTEM, "out of memory in getmeshinst"); if (o->oargs.nsargs < 1) objerror(o, USER, "bad # of arguments"); if (fullxf(&ins->x, o->oargs.nsargs-1, o->oargs.sarg+1) != o->oargs.nsargs-1) objerror(o, USER, "bad transform"); if (ins->x.f.sca < 0.0) { ins->x.f.sca = -ins->x.f.sca; ins->x.b.sca = -ins->x.b.sca; } ins->msh = NULL; o->os = (char *)ins; } if (ins->msh == NULL) ins->msh = getmesh(o->oargs.sarg[0], flags); else if ((flags &= ~ins->msh->ldflags)) readmesh(ins->msh, getpath(o->oargs.sarg[0], getrlibpath(), R_OK), flags); return(ins); }
int t_func( /* compute texture for ray */ OBJREC *m, RAY *r ) { FVECT disp; double d; MFUNC *mf; int i; if (m->oargs.nsargs < 4) objerror(m, USER, "bad # arguments"); mf = getfunc(m, 3, 0x7, 1); setfunc(m, r); errno = 0; for (i = 0; i < 3; i++) { disp[i] = evalue(mf->ep[i]); if (errno == EDOM || errno == ERANGE) { objerror(m, WARNING, "compute error"); return(0); } } if (mf->fxp != &unitxf) multv3(disp, disp, mf->fxp->xfm); if (r->rox != NULL) { multv3(disp, disp, r->rox->f.xfm); d = 1.0 / (mf->fxp->sca * r->rox->f.sca); } else d = 1.0 / mf->fxp->sca; VSUM(r->pert, r->pert, disp, d); return(0); }
int m_aniso( /* anisotropic material */ register OBJREC *o ) { register MATREC *m; /* check arguments */ if (o->oargs.nfargs < (o->otype == MAT_TRANS2 ? 8 : 6)) objerror(o, USER, "bad # of real arguments"); /* allocate/insert material */ m = newmaterial(o->oname); /* assign parameters */ setcolor(m->u.m.ambdiff, o->oargs.farg[0], o->oargs.farg[1], o->oargs.farg[2]); if ((m->type = o->otype) == MAT_METAL2) copycolor(m->u.m.specular, m->u.m.ambdiff); else setcolor(m->u.m.specular, 1., 1., 1.); scalecolor(m->u.m.specular, o->oargs.farg[3]); scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]); if (m->type == MAT_TRANS2) { scalecolor(m->u.m.specular, 1.-o->oargs.farg[6]); scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[6]); } if (o->oargs.farg[4]*o->oargs.farg[5] <= FTINY*FTINY) m->u.m.specexp = MAXSPECEXP; else m->u.m.specexp = 2./(o->oargs.farg[4]*o->oargs.farg[5]); if (m->u.m.specexp > MAXSPECEXP) m->u.m.specexp = MAXSPECEXP; return(0); }
static int fsck_cache_tree(struct cache_tree *it) { int i; int err = 0; if (verbose) fprintf(stderr, "Checking cache tree\n"); if (0 <= it->entry_count) { struct object *obj = parse_object(&it->oid); if (!obj) { error("%s: invalid sha1 pointer in cache-tree", oid_to_hex(&it->oid)); errors_found |= ERROR_REFS; return 1; } obj->flags |= USED; if (name_objects) add_decoration(fsck_walk_options.object_names, obj, xstrdup(":")); mark_object_reachable(obj); if (obj->type != OBJ_TREE) err |= objerror(obj, "non-tree in cache-tree"); } for (i = 0; i < it->subtree_nr; i++) err |= fsck_cache_tree(it->down[i]->cache_tree); return err; }
static void getacoords( /* set up coordinate system */ ANISODAT *np ) { MFUNC *mf; int i; mf = getfunc(np->mp, 3, 0x7, 1); setfunc(np->mp, np->rp); errno = 0; for (i = 0; i < 3; i++) np->u[i] = evalue(mf->ep[i]); if ((errno == EDOM) | (errno == ERANGE)) np->u[0] = np->u[1] = np->u[2] = 0.0; if (mf->fxp != &unitxf) multv3(np->u, np->u, mf->fxp->xfm); fcross(np->v, np->pnorm, np->u); if (normalize(np->v) == 0.0) { if (fabs(np->u_alpha - np->v_alpha) > 0.001) objerror(np->mp, WARNING, "illegal orientation vector"); getperpendicular(np->u, np->pnorm); /* punting */ fcross(np->v, np->pnorm, np->u); np->u_alpha = np->v_alpha = sqrt( 0.5 * (np->u_alpha*np->u_alpha + np->v_alpha*np->v_alpha) ); } else fcross(np->u, np->v, np->pnorm); }
extern double raynormal( /* compute perturbed normal for ray */ FVECT norm, RAY *r ) { double newdot; int i; /* The perturbation is added to the surface normal to obtain * the new normal. If the new normal would affect the surface * orientation wrt. the ray, a correction is made. The method is * still fraught with problems since reflected rays and similar * directions calculated from the surface normal may spawn rays behind * the surface. The only solution is to curb textures at high * incidence (namely, keep DOT(rdir,pert) < Rdot). */ for (i = 0; i < 3; i++) norm[i] = r->ron[i] + r->pert[i]; if (normalize(norm) == 0.0) { objerror(r->ro, WARNING, "illegal normal perturbation"); VCOPY(norm, r->ron); return(r->rod); } newdot = -DOT(norm, r->rdir); if ((newdot > 0.0) != (r->rod > 0.0)) { /* fix orientation */ for (i = 0; i < 3; i++) norm[i] += 2.0*newdot*r->rdir[i]; newdot = -newdot; } return(newdot); }
extern int o_default(OBJREC *o, RAY *r) /* default action is error */ { objerror(o, CONSISTENCY, "unexpected object call"); /* unused call to load freeobjmem.o */ free_objs(0, 0); return(0); }
int o_unsupported( /* unsupported object primitive */ OBJREC *o ) { objerror(o, WARNING, "unsupported type"); return(0); }
extern int p_bfunc( /* compute brightness pattern */ OBJREC *m, RAY *r ) { double bval; register MFUNC *mf; if (m->oargs.nsargs < 2) objerror(m, USER, "bad # arguments"); mf = getfunc(m, 1, 0x1, 0); setfunc(m, r); errno = 0; bval = evalue(mf->ep[0]); if (errno == EDOM || errno == ERANGE) { objerror(m, WARNING, "compute error"); return(0); } scalecolor(r->pcol, bval); return(0); }
static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options) { struct object *parent = data; /* * The only case data is NULL or type is OBJ_ANY is when * mark_object_reachable() calls us. All the callers of * that function has non-NULL obj hence ... */ if (!obj) { /* ... these references to parent->fld are safe here */ printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf("broken link from %7s %s\n", (type == OBJ_ANY ? "unknown" : type_name(type)), "unknown"); errors_found |= ERROR_REACHABLE; return 1; } if (type != OBJ_ANY && obj->type != type) /* ... and the reference to parent is safe here */ objerror(parent, "wrong object type in link"); if (obj->flags & REACHABLE) return 0; obj->flags |= REACHABLE; if (is_promisor_object(&obj->oid)) /* * Further recursion does not need to be performed on this * object since it is a promisor object (so it does not need to * be added to "pending"). */ return 0; if (!(obj->flags & HAS_OBJ)) { if (parent && !has_object_file(&obj->oid)) { printf("broken link from %7s %s\n", printable_type(parent), describe_object(parent)); printf(" to %7s %s\n", printable_type(obj), describe_object(obj)); errors_found |= ERROR_REACHABLE; } return 1; } add_object_array(obj, NULL, &pending); return 0; }
extern int p_cfunc( /* compute color pattern */ OBJREC *m, RAY *r ) { COLOR cval; register MFUNC *mf; if (m->oargs.nsargs < 4) objerror(m, USER, "bad # arguments"); mf = getfunc(m, 3, 0x7, 0); setfunc(m, r); errno = 0; setcolor(cval, evalue(mf->ep[0]), evalue(mf->ep[1]), evalue(mf->ep[2])); if (errno == EDOM || errno == ERANGE) { objerror(m, WARNING, "compute error"); return(0); } multcolor(r->pcol, cval); return(0); }
static int fsck_obj(struct object *obj) { int err; if (obj->flags & SEEN) return 0; obj->flags |= SEEN; if (verbose) fprintf(stderr, "Checking %s %s\n", printable_type(obj), describe_object(obj)); if (fsck_walk(obj, NULL, &fsck_obj_options)) objerror(obj, "broken links"); err = fsck_object(obj, NULL, 0, &fsck_obj_options); if (err) goto out; if (obj->type == OBJ_COMMIT) { struct commit *commit = (struct commit *) obj; if (!commit->parents && show_root) printf("root %s\n", describe_object(&commit->object)); } if (obj->type == OBJ_TAG) { struct tag *tag = (struct tag *) obj; if (show_tags && tag->tagged) { printf("tagged %s %s", printable_type(tag->tagged), describe_object(tag->tagged)); printf(" (%s) in %s\n", tag->tag, describe_object(&tag->object)); } } out: if (obj->type == OBJ_TREE) free_tree_buffer((struct tree *)obj); if (obj->type == OBJ_COMMIT) free_commit_buffer((struct commit *)obj); return err; }
extern void srcvalue( /* punch ray to source and compute value */ register RAY *r ) { register SRCREC *sp; sp = &source[r->rsrc]; if (sp->sflags & SVIRTUAL) { /* virtual source */ /* check intersection */ if (!(*ofun[sp->so->otype].funp)(sp->so, r)) return; if (!rayshade(r, r->ro->omod)) /* compute contribution */ goto nomat; rayparticipate(r); return; } /* compute intersection */ if (sp->sflags & SDISTANT ? sourcehit(r) : (*ofun[sp->so->otype].funp)(sp->so, r)) { if (sp->sa.success >= 0) sp->sa.success++; if (!rayshade(r, r->ro->omod)) /* compute contribution */ goto nomat; rayparticipate(r); return; } /* we missed our mark! */ if (sp->sa.success < 0) return; /* bitched already */ sp->sa.success -= AIMREQT; if (sp->sa.success >= 0) return; /* leniency */ sprintf(errmsg, "aiming failure for light source \"%s\"", sp->so->oname); error(WARNING, errmsg); /* issue warning */ return; nomat: objerror(r->ro, USER, "material not found"); }
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); } } }
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); }
int m_mist( /* process a ray entering or leaving some mist */ OBJREC *m, RAY *r ) { RAY p; int *myslist = NULL; int newslist[MAXSLIST+1]; COLOR mext; double re, ge, be; int i, j; /* check arguments */ if (m->oargs.nfargs > 7) objerror(m, USER, "bad arguments"); /* get source indices */ if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) { if (m->oargs.nsargs > MAXSLIST) objerror(m, INTERNAL, "too many sources in list"); myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int)); if (myslist == NULL) goto memerr; myslist[0] = 0; /* size is first in list */ for (j = 0; j < m->oargs.nsargs; j++) { i = nsources; /* look up each source id */ while (i--) if (srcmatch(source+i, m->oargs.sarg[j])) break; if (i < 0) { sprintf(errmsg, "unknown source \"%s\"", m->oargs.sarg[j]); objerror(m, WARNING, errmsg); } else if (inslist(myslist, i)) { sprintf(errmsg, "duplicate source \"%s\"", m->oargs.sarg[j]); objerror(m, WARNING, errmsg); } else myslist[++myslist[0]] = i; } m->os = (char *)myslist; } if (m->oargs.nfargs > 2) { /* compute extinction */ setcolor(mext, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); raytexture(r, m->omod); /* get modifiers */ multcolor(mext, r->pcol); } else setcolor(mext, 0., 0., 0.); /* start transmitted ray */ if (rayorigin(&p, TRANS, r, NULL) < 0) return(1); VCOPY(p.rdir, r->rdir); p.slights = newslist; if (r->slights != NULL) /* copy old list if one */ for (j = r->slights[0]; j >= 0; j--) p.slights[j] = r->slights[j]; else p.slights[0] = 0; if (r->rod > 0.) { /* entering ray */ addcolor(p.cext, mext); if (m->oargs.nfargs > 5) setcolor(p.albedo, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); if (m->oargs.nfargs > 6) p.gecc = m->oargs.farg[6]; add2slist(&p, myslist); /* add to list */ } else { /* leaving ray */ if (myslist != NULL) { /* delete from list */ for (j = myslist[0]; j > 0; j--) if ( (i = inslist(p.slights, myslist[j])) ) p.slights[i] = -1; for (i = 0, j = 1; j <= p.slights[0]; j++) if (p.slights[j] != -1) p.slights[++i] = p.slights[j]; if (p.slights[0] - i < myslist[0]) { /* fix old */ addcolor(r->cext, mext); if (m->oargs.nfargs > 5) setcolor(r->albedo, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); if (m->oargs.nfargs > 6) r->gecc = m->oargs.farg[6]; add2slist(r, myslist); } p.slights[0] = i; } if ((re = colval(r->cext,RED) - colval(mext,RED)) < colval(cextinction,RED)) re = colval(cextinction,RED); if ((ge = colval(r->cext,GRN) - colval(mext,GRN)) < colval(cextinction,GRN)) ge = colval(cextinction,GRN); if ((be = colval(r->cext,BLU) - colval(mext,BLU)) < colval(cextinction,BLU)) be = colval(cextinction,BLU); setcolor(p.cext, re, ge, be); if (m->oargs.nfargs > 5) copycolor(p.albedo, salbedo); if (m->oargs.nfargs > 6) p.gecc = seccg; } rayvalue(&p); /* calls rayparticipate() */ copycolor(r->rcol, p.rcol); /* return value */ r->rt = r->rot + p.rt; return(1); memerr: error(SYSTEM, "out of memory in m_mist"); return 0; /* pro forma return */ }
extern int load_os( /* load associated data for object */ register OBJREC *op ) { DATARRAY *dp; switch (op->otype) { case OBJ_FACE: /* polygon */ getface(op); return(1); case OBJ_CONE: /* cone */ case OBJ_RING: /* disk */ case OBJ_CYLINDER: /* cylinder */ case OBJ_CUP: /* inverted cone */ case OBJ_TUBE: /* inverted cylinder */ getcone(op, 1); return(1); case OBJ_INSTANCE: /* octree instance */ getinstance(op, IO_ALL); return(1); case OBJ_MESH: /* mesh instance */ getmeshinst(op, IO_ALL); return(1); case PAT_CPICT: /* color picture */ if (op->oargs.nsargs < 4) goto sargerr; getpict(op->oargs.sarg[3]); getfunc(op, 4, 0x3<<5, 0); return(1); case PAT_CDATA: /* color data */ dp = getdata(op->oargs.sarg[3]); getdata(op->oargs.sarg[4]); getdata(op->oargs.sarg[5]); getfunc(op, 6, ((1<<dp->nd)-1)<<7, 0); return(1); case PAT_BDATA: /* brightness data */ if (op->oargs.nsargs < 2) goto sargerr; dp = getdata(op->oargs.sarg[1]); getfunc(op, 2, ((1<<dp->nd)-1)<<3, 0); return(1); case PAT_BFUNC: /* brightness function */ getfunc(op, 1, 0x1, 0); return(1); case PAT_CFUNC: /* color function */ getfunc(op, 3, 0x7, 0); return(1); case TEX_DATA: /* texture data */ if (op->oargs.nsargs < 6) goto sargerr; dp = getdata(op->oargs.sarg[3]); getdata(op->oargs.sarg[4]); getdata(op->oargs.sarg[5]); getfunc(op, 6, ((1<<dp->nd)-1)<<7, 1); return(1); case TEX_FUNC: /* texture function */ getfunc(op, 3, 0x7, 1); return(1); case MIX_DATA: /* mixture data */ dp = getdata(op->oargs.sarg[3]); getfunc(op, 4, ((1<<dp->nd)-1)<<5, 0); return(1); case MIX_PICT: /* mixture picture */ getpict(op->oargs.sarg[3]); getfunc(op, 4, 0x3<<5, 0); return(1); case MIX_FUNC: /* mixture function */ getfunc(op, 3, 0x4, 0); return(1); case MAT_PLASTIC2: /* anisotropic plastic */ case MAT_METAL2: /* anisotropic metal */ getfunc(op, 3, 0x7, 1); return(1); case MAT_BRTDF: /* BRDTfunc material */ getfunc(op, 9, 0x3f, 0); return(1); case MAT_BSDF: /* BSDF material */ if (op->oargs.nsargs < 6) goto sargerr; getfunc(op, 5, 0x1d, 1); loadBSDF(op->oargs.sarg[1]); return(1); case MAT_PDATA: /* plastic BRDF data */ case MAT_MDATA: /* metal BRDF data */ case MAT_TDATA: /* trans BRDF data */ if (op->oargs.nsargs < 2) goto sargerr; getdata(op->oargs.sarg[1]); getfunc(op, 2, 0, 0); return(1); case MAT_PFUNC: /* plastic BRDF func */ case MAT_MFUNC: /* metal BRDF func */ case MAT_TFUNC: /* trans BRDF func */ getfunc(op, 1, 0, 0); return(1); case MAT_DIRECT1: /* prism1 material */ getfunc(op, 4, 0xf, 1); return(1); case MAT_DIRECT2: /* prism2 material */ getfunc(op, 8, 0xff, 1); return(1); } /* nothing to load for the remaining types */ return(0); sargerr: objerror(op, USER, "too few string arguments"); return 0; /* pro forma return */ }
int m_dielectric( /* color a ray which hit a dielectric interface */ OBJREC *m, RAY *r ) { double cos1, cos2, nratio; COLOR ctrans; COLOR talb; int hastexture; int flatsurface; double refl, trans; FVECT dnorm; double d1, d2; RAY p; int i; /* PMAP: skip refracted shadow or ambient ray if accounted for in photon map */ if (shadowRayInPmap(r) || ambRayInPmap(r)) return(1); if (m->oargs.nfargs != (m->otype==MAT_DIELECTRIC ? 5 : 8)) objerror(m, USER, "bad arguments"); raytexture(r, m->omod); /* get modifiers */ if ( (hastexture = DOT(r->pert,r->pert) > FTINY*FTINY) ) cos1 = raynormal(dnorm, r); /* perturb normal */ else { VCOPY(dnorm, r->ron); cos1 = r->rod; } flatsurface = r->ro != NULL && isflat(r->ro->otype) && !hastexture | (r->crtype & AMBIENT); /* index of refraction */ if (m->otype == MAT_DIELECTRIC) nratio = m->oargs.farg[3] + m->oargs.farg[4]/MLAMBDA; else nratio = m->oargs.farg[3] / m->oargs.farg[7]; if (cos1 < 0.0) { /* inside */ hastexture = -hastexture; cos1 = -cos1; dnorm[0] = -dnorm[0]; dnorm[1] = -dnorm[1]; dnorm[2] = -dnorm[2]; setcolor(r->cext, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)), -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[2]*colval(r->pcol,BLU))); setcolor(r->albedo, 0., 0., 0.); r->gecc = 0.; if (m->otype == MAT_INTERFACE) { setcolor(ctrans, -mylog(m->oargs.farg[4]*colval(r->pcol,RED)), -mylog(m->oargs.farg[5]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[6]*colval(r->pcol,BLU))); setcolor(talb, 0., 0., 0.); } else { copycolor(ctrans, cextinction); copycolor(talb, salbedo); } } else { /* outside */ nratio = 1.0 / nratio; setcolor(ctrans, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)), -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[2]*colval(r->pcol,BLU))); setcolor(talb, 0., 0., 0.); if (m->otype == MAT_INTERFACE) { setcolor(r->cext, -mylog(m->oargs.farg[4]*colval(r->pcol,RED)), -mylog(m->oargs.farg[5]*colval(r->pcol,GRN)), -mylog(m->oargs.farg[6]*colval(r->pcol,BLU))); setcolor(r->albedo, 0., 0., 0.); r->gecc = 0.; } } d2 = 1.0 - nratio*nratio*(1.0 - cos1*cos1); /* compute cos theta2 */ if (d2 < FTINY) /* total reflection */ refl = 1.0; else { /* refraction occurs */ /* compute Fresnel's equations */ cos2 = sqrt(d2); d1 = cos1; d2 = nratio*cos2; d1 = (d1 - d2) / (d1 + d2); refl = d1 * d1; d1 = 1.0 / cos1; d2 = nratio / cos2; d1 = (d1 - d2) / (d1 + d2); refl += d1 * d1; refl *= 0.5; trans = 1.0 - refl; trans *= nratio*nratio; /* solid angle ratio */ setcolor(p.rcoef, trans, trans, trans); if (rayorigin(&p, REFRACTED, r, p.rcoef) == 0) { /* compute refracted ray */ d1 = nratio*cos1 - cos2; for (i = 0; i < 3; i++) p.rdir[i] = nratio*r->rdir[i] + d1*dnorm[i]; /* accidental reflection? */ if (hastexture && DOT(p.rdir,r->ron)*hastexture >= -FTINY) { d1 *= (double)hastexture; for (i = 0; i < 3; i++) /* ignore texture */ p.rdir[i] = nratio*r->rdir[i] + d1*r->ron[i]; normalize(p.rdir); /* not exact */ } else checknorm(p.rdir); #ifdef DISPERSE if (m->otype != MAT_DIELECTRIC || r->rod > 0.0 || r->crtype & SHADOW || !directvis || m->oargs.farg[4] == 0.0 || !disperse(m, r, p.rdir, trans, ctrans, talb)) #endif { copycolor(p.cext, ctrans); copycolor(p.albedo, talb); rayvalue(&p); multcolor(p.rcol, p.rcoef); addcolor(r->rcol, p.rcol); /* virtual distance */ if (flatsurface || (1.-FTINY <= nratio) & (nratio <= 1.+FTINY)) r->rxt = r->rot + raydistance(&p); } } } setcolor(p.rcoef, refl, refl, refl); if (!(r->crtype & SHADOW) && rayorigin(&p, REFLECTED, r, p.rcoef) == 0) { /* compute reflected ray */ VSUM(p.rdir, r->rdir, dnorm, 2.*cos1); /* accidental penetration? */ if (hastexture && DOT(p.rdir,r->ron)*hastexture <= FTINY) VSUM(p.rdir, r->rdir, r->ron, 2.*r->rod); checknorm(p.rdir); rayvalue(&p); /* reflected ray value */ multcolor(p.rcol, p.rcoef); /* color contribution */ copycolor(r->mcol, p.rcol); addcolor(r->rcol, p.rcol); /* virtual distance */ r->rmt = r->rot; if (flatsurface) r->rmt += raydistance(&p); } /* rayvalue() computes absorption */ return(1); }
static void dirbrdf( /* compute source contribution */ COLOR cval, /* returned coefficient */ void *nnp, /* material data */ FVECT ldir, /* light source direction */ double omega /* light source size */ ) { BRDFDAT *np = nnp; double ldot; double dtmp; COLOR ctmp; FVECT ldx; static double vldx[5], pt[MAXDIM]; char **sa; int i; #define lddx (vldx+1) setcolor(cval, 0.0, 0.0, 0.0); ldot = DOT(np->pnorm, ldir); if (ldot <= FTINY && ldot >= -FTINY) return; /* too close to grazing */ if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY) return; /* wrong side */ if (ldot > 0.0) { /* * Compute and add diffuse reflected component to returned * color. The diffuse reflected component will always be * modified by the color of the material. */ copycolor(ctmp, np->rdiff); dtmp = ldot * omega / PI; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } else { /* * Diffuse transmitted component. */ copycolor(ctmp, np->tdiff); dtmp = -ldot * omega / PI; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY) return; /* diffuse only */ /* set up function */ setbrdfunc(np); sa = np->mp->oargs.sarg; errno = 0; /* transform light vector */ multv3(ldx, ldir, funcxf.xfm); for (i = 0; i < 3; i++) lddx[i] = ldx[i]/funcxf.sca; lddx[3] = omega; /* compute BRTDF */ if (np->mp->otype == MAT_BRTDF) { if (sa[6][0] == '0') /* special case */ colval(ctmp,RED) = 0.0; else colval(ctmp,RED) = funvalue(sa[6], 4, lddx); if (sa[7][0] == '0') colval(ctmp,GRN) = 0.0; else if (!strcmp(sa[7],sa[6])) colval(ctmp,GRN) = colval(ctmp,RED); else colval(ctmp,GRN) = funvalue(sa[7], 4, lddx); if (!strcmp(sa[8],sa[6])) colval(ctmp,BLU) = colval(ctmp,RED); else if (!strcmp(sa[8],sa[7])) colval(ctmp,BLU) = colval(ctmp,GRN); else colval(ctmp,BLU) = funvalue(sa[8], 4, lddx); dtmp = bright(ctmp); } else if (np->dp == NULL) { dtmp = funvalue(sa[0], 4, lddx); setcolor(ctmp, dtmp, dtmp, dtmp); } else { for (i = 0; i < np->dp->nd; i++) pt[i] = funvalue(sa[3+i], 4, lddx); vldx[0] = datavalue(np->dp, pt); dtmp = funvalue(sa[0], 5, vldx); setcolor(ctmp, dtmp, dtmp, dtmp); } if ((errno == EDOM) | (errno == ERANGE)) { objerror(np->mp, WARNING, "compute error"); return; } if (dtmp <= FTINY) return; if (ldot > 0.0) { /* * Compute reflected non-diffuse component. */ if ((np->mp->otype == MAT_MFUNC) | (np->mp->otype == MAT_MDATA)) multcolor(ctmp, np->mcolor); dtmp = ldot * omega * np->rspec; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } else { /* * Compute transmitted non-diffuse component. */ if ((np->mp->otype == MAT_TFUNC) | (np->mp->otype == MAT_TDATA)) multcolor(ctmp, np->mcolor); dtmp = -ldot * omega * np->tspec; scalecolor(ctmp, dtmp); addcolor(cval, ctmp); } #undef lddx }
int m_brdf2( /* color a ray that hit a BRDF material */ OBJREC *m, RAY *r ) { BRDFDAT nd; COLOR ctmp; FVECT vtmp; double dtmp; /* always a shadow */ if (r->crtype & SHADOW) return(1); /* check arguments */ if ((m->oargs.nsargs < (hasdata(m->otype)?4:2)) | (m->oargs.nfargs < ((m->otype==MAT_TFUNC)|(m->otype==MAT_TDATA)?6:4))) objerror(m, USER, "bad # arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); nd.mp = m; nd.pr = r; /* get material color */ setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); /* get specular component */ nd.rspec = m->oargs.farg[3]; /* compute transmittance */ if ((m->otype == MAT_TFUNC) | (m->otype == MAT_TDATA)) { nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec); nd.tspec = nd.trans * m->oargs.farg[5]; dtmp = nd.trans - nd.tspec; setcolor(nd.tdiff, dtmp, dtmp, dtmp); } else { nd.tspec = nd.trans = 0.0; setcolor(nd.tdiff, 0.0, 0.0, 0.0); } /* compute reflectance */ dtmp = 1.0 - nd.trans - nd.rspec; setcolor(nd.rdiff, dtmp, dtmp, dtmp); nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ multcolor(nd.mcolor, r->pcol); /* modify material color */ multcolor(nd.rdiff, nd.mcolor); multcolor(nd.tdiff, nd.mcolor); /* load auxiliary files */ if (hasdata(m->otype)) { nd.dp = getdata(m->oargs.sarg[1]); getfunc(m, 2, 0, 0); } else { nd.dp = NULL; getfunc(m, 1, 0, 0); } /* compute ambient */ if (nd.trans < 1.0-FTINY) { copycolor(ctmp, nd.mcolor); /* modified by material color */ scalecolor(ctmp, 1.0-nd.trans); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } if (nd.trans > FTINY) { /* from other side */ flipsurface(r); vtmp[0] = -nd.pnorm[0]; vtmp[1] = -nd.pnorm[1]; vtmp[2] = -nd.pnorm[2]; copycolor(ctmp, nd.mcolor); scalecolor(ctmp, nd.trans); multambient(ctmp, r, vtmp); addcolor(r->rcol, ctmp); flipsurface(r); } /* add direct component */ direct(r, dirbrdf, &nd); return(1); }
int m_brdf( /* color a ray that hit a BRDTfunc material */ OBJREC *m, RAY *r ) { int hitfront = 1; BRDFDAT nd; RAY sr; double mirtest=0, mirdist=0; double transtest=0, transdist=0; int hasrefl, hastrans; int hastexture; COLOR ctmp; FVECT vtmp; double d; MFUNC *mf; int i; /* check arguments */ if ((m->oargs.nsargs < 10) | (m->oargs.nfargs < 9)) objerror(m, USER, "bad # arguments"); nd.mp = m; nd.pr = r; /* dummy values */ nd.rspec = nd.tspec = 1.0; nd.trans = 0.5; /* diffuse reflectance */ if (r->rod > 0.0) setcolor(nd.rdiff, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); else setcolor(nd.rdiff, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); /* diffuse transmittance */ setcolor(nd.tdiff, m->oargs.farg[6], m->oargs.farg[7], m->oargs.farg[8]); /* get modifiers */ raytexture(r, m->omod); hastexture = DOT(r->pert,r->pert) > FTINY*FTINY; if (hastexture) { /* perturb normal */ nd.pdot = raynormal(nd.pnorm, r); } else { VCOPY(nd.pnorm, r->ron); nd.pdot = r->rod; } if (r->rod < 0.0) { /* orient perturbed values */ nd.pdot = -nd.pdot; for (i = 0; i < 3; i++) { nd.pnorm[i] = -nd.pnorm[i]; r->pert[i] = -r->pert[i]; } hitfront = 0; } copycolor(nd.mcolor, r->pcol); /* get pattern color */ multcolor(nd.rdiff, nd.mcolor); /* modify diffuse values */ multcolor(nd.tdiff, nd.mcolor); hasrefl = bright(nd.rdiff) > FTINY; hastrans = bright(nd.tdiff) > FTINY; /* load cal file */ nd.dp = NULL; mf = getfunc(m, 9, 0x3f, 0); /* compute transmitted ray */ setbrdfunc(&nd); errno = 0; setcolor(ctmp, evalue(mf->ep[3]), evalue(mf->ep[4]), evalue(mf->ep[5])); if ((errno == EDOM) | (errno == ERANGE)) objerror(m, WARNING, "compute error"); else if (rayorigin(&sr, TRANS, r, ctmp) == 0) { if (!(r->crtype & SHADOW) && hastexture) { /* perturb direction */ VSUM(sr.rdir, r->rdir, r->pert, -.75); if (normalize(sr.rdir) == 0.0) { objerror(m, WARNING, "illegal perturbation"); VCOPY(sr.rdir, r->rdir); } } else { VCOPY(sr.rdir, r->rdir); } rayvalue(&sr); multcolor(sr.rcol, sr.rcoef); addcolor(r->rcol, sr.rcol); if (!hastexture) { transtest = 2.0*bright(sr.rcol); transdist = r->rot + sr.rt; } } if (r->crtype & SHADOW) /* the rest is shadow */ return(1); /* compute reflected ray */ setbrdfunc(&nd); errno = 0; setcolor(ctmp, evalue(mf->ep[0]), evalue(mf->ep[1]), evalue(mf->ep[2])); if ((errno == EDOM) | (errno == ERANGE)) objerror(m, WARNING, "compute error"); else if (rayorigin(&sr, REFLECTED, r, ctmp) == 0) { VSUM(sr.rdir, r->rdir, nd.pnorm, 2.*nd.pdot); checknorm(sr.rdir); rayvalue(&sr); multcolor(sr.rcol, sr.rcoef); addcolor(r->rcol, sr.rcol); if (!hastexture && r->ro != NULL && isflat(r->ro->otype)) { mirtest = 2.0*bright(sr.rcol); mirdist = r->rot + sr.rt; } } /* compute ambient */ if (hasrefl) { if (!hitfront) flipsurface(r); copycolor(ctmp, nd.rdiff); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ if (!hitfront) flipsurface(r); } if (hastrans) { /* from other side */ if (hitfront) flipsurface(r); vtmp[0] = -nd.pnorm[0]; vtmp[1] = -nd.pnorm[1]; vtmp[2] = -nd.pnorm[2]; copycolor(ctmp, nd.tdiff); multambient(ctmp, r, vtmp); addcolor(r->rcol, ctmp); if (hitfront) flipsurface(r); } if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0') direct(r, dirbrdf, &nd); /* add direct component */ d = bright(r->rcol); /* set effective distance */ if (transtest > d) r->rt = transdist; else if (mirtest > d) r->rt = mirdist; return(1); }
void add2bbox( /* expand bounding box to fit object */ register OBJREC *o, FVECT bbmin, FVECT bbmax ) { CONE *co; FACE *fo; INSTANCE *io; MESHINST *mi; FVECT v; register int i, j; switch (o->otype) { case OBJ_SPHERE: case OBJ_BUBBLE: if (o->oargs.nfargs != 4) objerror(o, USER, "bad arguments"); for (i = 0; i < 3; i++) { VCOPY(v, o->oargs.farg); v[i] -= o->oargs.farg[3]; point2bbox(v, bbmin, bbmax); v[i] += 2.0 * o->oargs.farg[3]; point2bbox(v, bbmin, bbmax); } break; case OBJ_FACE: fo = getface(o); j = fo->nv; while (j--) point2bbox(VERTEX(fo,j), bbmin, bbmax); break; case OBJ_CONE: case OBJ_CUP: case OBJ_CYLINDER: case OBJ_TUBE: case OBJ_RING: co = getcone(o, 0); if (o->otype != OBJ_RING) circle2bbox(CO_P0(co), co->ad, CO_R0(co), bbmin, bbmax); circle2bbox(CO_P1(co), co->ad, CO_R1(co), bbmin, bbmax); break; case OBJ_INSTANCE: io = getinstance(o, IO_BOUNDS); for (j = 0; j < 8; j++) { for (i = 0; i < 3; i++) { v[i] = io->obj->scube.cuorg[i]; if (j & 1<<i) v[i] += io->obj->scube.cusize; } multp3(v, v, io->x.f.xfm); point2bbox(v, bbmin, bbmax); } break; case OBJ_MESH: mi = getmeshinst(o, IO_BOUNDS); for (j = 0; j < 8; j++) { for (i = 0; i < 3; i++) { v[i] = mi->msh->mcube.cuorg[i]; if (j & 1<<i) v[i] += mi->msh->mcube.cusize; } multp3(v, v, mi->x.f.xfm); point2bbox(v, bbmin, bbmax); } break; } }
int m_ashikhmin( /* shade ray that hit something anisotropic */ OBJREC *m, RAY *r ) { ASHIKDAT nd; COLOR ctmp; double fres; int i; /* easy shadow test */ if (r->crtype & SHADOW) return(1); if (m->oargs.nfargs != 8) objerror(m, USER, "bad number of real arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); /* get material color */ nd.mp = m; nd.rp = r; setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); setcolor(nd.scolor, m->oargs.farg[3], m->oargs.farg[4], m->oargs.farg[5]); /* get specular power */ nd.specfl = 0; nd.u_power = m->oargs.farg[6]; nd.v_power = m->oargs.farg[7]; nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ if (nd.pdot < .001) nd.pdot = .001; /* non-zero for dirashik() */ multcolor(nd.mcolor, r->pcol); /* modify diffuse color */ if (bright(nd.scolor) > FTINY) { /* adjust specular color */ nd.specfl |= SPA_REFL; /* check threshold */ if (specthresh >= bright(nd.scolor)-FTINY) nd.specfl |= SPA_RBLT; fres = schlick_fres(nd.pdot); /* Schick's Fresnel approx */ for (i = 0; i < 3; i++) colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres; } if (r->ro != NULL && isflat(r->ro->otype)) nd.specfl |= SPA_FLAT; /* set up coordinates */ getacoords_as(&nd); /* specular sampling? */ if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL) ashiksamp(&nd); /* diffuse interreflection */ if (bright(nd.mcolor) > FTINY) { copycolor(ctmp, nd.mcolor); /* modified by material color */ if (nd.specfl & SPA_RBLT) /* add in specular as well? */ addcolor(ctmp, nd.scolor); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } direct(r, dirashik, &nd); /* add direct component */ return(1); }
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"); }
int m_aniso( /* shade ray that hit something anisotropic */ OBJREC *m, RAY *r ) { ANISODAT nd; COLOR ctmp; int i; /* easy shadow test */ if (r->crtype & SHADOW) return(1); if (m->oargs.nfargs != (m->otype == MAT_TRANS2 ? 8 : 6)) objerror(m, USER, "bad number of real arguments"); /* check for back side */ if (r->rod < 0.0) { if (!backvis) { raytrans(r); return(1); } raytexture(r, m->omod); flipsurface(r); /* reorient if backvis */ } else raytexture(r, m->omod); /* get material color */ nd.mp = m; nd.rp = r; setcolor(nd.mcolor, m->oargs.farg[0], m->oargs.farg[1], m->oargs.farg[2]); /* get roughness */ nd.specfl = 0; nd.u_alpha = m->oargs.farg[4]; nd.v_alpha = m->oargs.farg[5]; if ((nd.u_alpha <= FTINY) | (nd.v_alpha <= FTINY)) objerror(m, USER, "roughness too small"); nd.pdot = raynormal(nd.pnorm, r); /* perturb normal */ if (nd.pdot < .001) nd.pdot = .001; /* non-zero for diraniso() */ multcolor(nd.mcolor, r->pcol); /* modify material color */ /* get specular component */ if ((nd.rspec = m->oargs.farg[3]) > FTINY) { nd.specfl |= SP_REFL; /* compute specular color */ if (m->otype == MAT_METAL2) copycolor(nd.scolor, nd.mcolor); else setcolor(nd.scolor, 1.0, 1.0, 1.0); scalecolor(nd.scolor, nd.rspec); /* check threshold */ if (specthresh >= nd.rspec-FTINY) nd.specfl |= SP_RBLT; /* compute refl. direction */ VSUM(nd.vrefl, r->rdir, nd.pnorm, 2.0*nd.pdot); if (DOT(nd.vrefl, r->ron) <= FTINY) /* penetration? */ VSUM(nd.vrefl, r->rdir, r->ron, 2.0*r->rod); } /* compute transmission */ if (m->otype == MAT_TRANS2) { nd.trans = m->oargs.farg[6]*(1.0 - nd.rspec); nd.tspec = nd.trans * m->oargs.farg[7]; nd.tdiff = nd.trans - nd.tspec; if (nd.tspec > FTINY) { nd.specfl |= SP_TRAN; /* check threshold */ if (specthresh >= nd.tspec-FTINY) nd.specfl |= SP_TBLT; if (DOT(r->pert,r->pert) <= FTINY*FTINY) { VCOPY(nd.prdir, r->rdir); } else { for (i = 0; i < 3; i++) /* perturb */ nd.prdir[i] = r->rdir[i] - r->pert[i]; if (DOT(nd.prdir, r->ron) < -FTINY) normalize(nd.prdir); /* OK */ else VCOPY(nd.prdir, r->rdir); } } } else nd.tdiff = nd.tspec = nd.trans = 0.0; /* diffuse reflection */ nd.rdiff = 1.0 - nd.trans - nd.rspec; if (r->ro != NULL && isflat(r->ro->otype)) nd.specfl |= SP_FLAT; getacoords(&nd); /* set up coordinates */ if (nd.specfl & (SP_REFL|SP_TRAN)) agaussamp(&nd); if (nd.rdiff > FTINY) { /* ambient from this side */ copycolor(ctmp, nd.mcolor); /* modified by material color */ scalecolor(ctmp, nd.rdiff); if (nd.specfl & SP_RBLT) /* add in specular as well? */ addcolor(ctmp, nd.scolor); multambient(ctmp, r, nd.pnorm); addcolor(r->rcol, ctmp); /* add to returned color */ } if (nd.tdiff > FTINY) { /* ambient from other side */ FVECT bnorm; flipsurface(r); bnorm[0] = -nd.pnorm[0]; bnorm[1] = -nd.pnorm[1]; bnorm[2] = -nd.pnorm[2]; copycolor(ctmp, nd.mcolor); /* modified by color */ if (nd.specfl & SP_TBLT) scalecolor(ctmp, nd.trans); else scalecolor(ctmp, nd.tdiff); multambient(ctmp, r, bnorm); addcolor(r->rcol, ctmp); flipsurface(r); } /* add direct component */ direct(r, diraniso, &nd); return(1); }
static int redirect( /* compute n'th ray redirection */ OBJREC *m, RAY *r, int n ) { MFUNC *mf; EPNODE **va; FVECT nsdir; RAY nr; double coef; int j; /* set up function */ mf = getdfunc(m); setfunc(m, r); /* assign direction variable */ if (r->rsrc >= 0) { SRCREC *sp = source + source[r->rsrc].sa.sv.sn; if (sp->sflags & SDISTANT) VCOPY(nsdir, sp->sloc); else { for (j = 0; j < 3; j++) nsdir[j] = sp->sloc[j] - r->rop[j]; normalize(nsdir); } multv3(nsdir, nsdir, funcxf.xfm); varset("DxA", '=', nsdir[0]/funcxf.sca); varset("DyA", '=', nsdir[1]/funcxf.sca); varset("DzA", '=', nsdir[2]/funcxf.sca); } else { varset("DxA", '=', 0.0); varset("DyA", '=', 0.0); varset("DzA", '=', 0.0); } /* compute coefficient */ errno = 0; va = mf->ep + 4*n; coef = evalue(va[0]); if ((errno == EDOM) | (errno == ERANGE)) goto computerr; setcolor(nr.rcoef, coef, coef, coef); if (rayorigin(&nr, TRANS, r, nr.rcoef) < 0) return(0); va++; /* compute direction */ for (j = 0; j < 3; j++) { nr.rdir[j] = evalue(va[j]); if (errno == EDOM || errno == ERANGE) goto computerr; } if (mf->fxp != &unitxf) multv3(nr.rdir, nr.rdir, mf->fxp->xfm); if (r->rox != NULL) multv3(nr.rdir, nr.rdir, r->rox->f.xfm); if (normalize(nr.rdir) == 0.0) goto computerr; /* compute value */ if (r->rsrc >= 0) nr.rsrc = source[r->rsrc].sa.sv.sn; rayvalue(&nr); multcolor(nr.rcol, nr.rcoef); addcolor(r->rcol, nr.rcol); if (r->ro != NULL && isflat(r->ro->otype)) r->rt = r->rot + nr.rt; return(1); computerr: objerror(m, WARNING, "compute error"); return(-1); }
static int dir_proj( /* compute a director's projection */ MAT4 pm, OBJREC *o, SRCREC *s, int n ) { RAY tr; OBJREC *m; MFUNC *mf; EPNODE **va; FVECT cent, newdir, nv, h; double coef, olddot, newdot, od; int i, j; /* initialize test ray */ getmaxdisk(cent, o); if (s->sflags & SDISTANT) for (i = 0; i < 3; i++) { tr.rdir[i] = -s->sloc[i]; tr.rorg[i] = cent[i] - tr.rdir[i]; } else { for (i = 0; i < 3; i++) { tr.rdir[i] = cent[i] - s->sloc[i]; tr.rorg[i] = s->sloc[i]; } if (normalize(tr.rdir) == 0.0) return(0); /* at source! */ } od = getplaneq(nv, o); olddot = DOT(tr.rdir, nv); if (olddot <= FTINY && olddot >= -FTINY) return(0); /* old dir parallels plane */ tr.rmax = 0.0; rayorigin(&tr, PRIMARY, NULL, NULL); if (!(*ofun[o->otype].funp)(o, &tr)) return(0); /* no intersection! */ /* compute redirection */ m = vsmaterial(o); mf = getdfunc(m); setfunc(m, &tr); varset("DxA", '=', 0.0); varset("DyA", '=', 0.0); varset("DzA", '=', 0.0); errno = 0; va = mf->ep + 4*n; coef = evalue(va[0]); if (errno == EDOM || errno == ERANGE) goto computerr; if (coef <= FTINY) return(0); /* insignificant */ va++; for (i = 0; i < 3; i++) { newdir[i] = evalue(va[i]); if (errno == EDOM || errno == ERANGE) goto computerr; } if (mf->fxp != &unitxf) multv3(newdir, newdir, mf->fxp->xfm); /* normalization unnecessary */ newdot = DOT(newdir, nv); if (newdot <= FTINY && newdot >= -FTINY) return(0); /* new dir parallels plane */ /* everything OK -- compute shear */ for (i = 0; i < 3; i++) h[i] = newdir[i]/newdot - tr.rdir[i]/olddot; setident4(pm); for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) pm[i][j] += nv[i]*h[j]; pm[3][j] = -od*h[j]; } if ((newdot > 0.0) ^ (olddot > 0.0)) /* add mirroring */ for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) pm[i][j] -= 2.*nv[i]*nv[j]; pm[3][j] += 2.*od*nv[j]; } return(1); computerr: objerror(m, WARNING, "projection compute error"); 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 }