Beispiel #1
0
extern int
o_instance(		/* compute ray intersection with octree */
	OBJREC  *o,
	register RAY  *r
)
{
	RAY  rcont;
	double  d;
	register INSTANCE  *ins;
	register int  i;
					/* get the octree */
	ins = getinstance(o, IO_ALL);
					/* copy and transform ray */
	rcont = *r;
	multp3(rcont.rorg, r->rorg, ins->x.b.xfm);
	multv3(rcont.rdir, r->rdir, ins->x.b.xfm);
	for (i = 0; i < 3; i++)
		rcont.rdir[i] /= ins->x.b.sca;
	rcont.rmax *= ins->x.b.sca;
					/* clear and trace it */
	rayclear(&rcont);
	if (!localhit(&rcont, &ins->obj->scube))
		return(0);			/* missed */
	if (rcont.rot * ins->x.f.sca >= r->rot)
		return(0);			/* not close enough */

	if (o->omod != OVOID) {		/* if we have modifier, use it */
		r->ro = o;
		r->rox = NULL;
	} else {			/* else use theirs */
		r->ro = rcont.ro;
		if (rcont.rox != NULL) {
			newrayxf(r);		/* allocate transformation */
					/* NOTE: r->rox may equal rcont.rox! */
			multmat4(r->rox->f.xfm, rcont.rox->f.xfm, ins->x.f.xfm);
			r->rox->f.sca = rcont.rox->f.sca * ins->x.f.sca;
			multmat4(r->rox->b.xfm, ins->x.b.xfm, rcont.rox->b.xfm);
			r->rox->b.sca = ins->x.b.sca * rcont.rox->b.sca;
		} else
			r->rox = &ins->x;
	}
					/* transform it back */
	r->rot = rcont.rot * ins->x.f.sca;
	multp3(r->rop, rcont.rop, ins->x.f.xfm);
	multv3(r->ron, rcont.ron, ins->x.f.xfm);
	multv3(r->pert, rcont.pert, ins->x.f.xfm);
	d = 1./ins->x.f.sca;
	for (i = 0; i < 3; i++) {
		r->ron[i] *= d;
		r->pert[i] *= d;
	}
	r->rod = rcont.rod;
	r->uv[0] = rcont.uv[0];
	r->uv[1] = rcont.uv[1];
					/* return hit */
	return(1);
}
int
xf_handler(int ac, char **av)		/* handle xf entity */
{
	register XF_SPEC	*spec;
	register int	n;
	int	rv;

	if (ac == 1) {			/* something with existing transform */
		if ((spec = xf_context) == NULL)
			return(MG_ECNTXT);
		n = -1;
		if (spec->xarr != NULL) {	/* check for iteration */
			register struct xf_array	*ap = spec->xarr;

			(void)xf_aname((struct xf_array *)NULL);
			n = ap->ndim;
			while (n--) {
				if (++ap->aarg[n].i < ap->aarg[n].n)
					break;
				(void)strcpy(ap->aarg[n].arg, "0");
				ap->aarg[n].i = 0;
			}
			if (n >= 0) {
				if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
					return(rv);
				sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
				(void)xf_aname(ap);
			}
		}
		if (n < 0) {			/* pop transform */
			xf_context = spec->prev;
			free_xf(spec);
			return(MG_OK);
		}
	} else {			/* else allocate transform */
		if ((spec = new_xf(ac-1, av+1)) == NULL)
			return(MG_EMEM);
		if (spec->xarr != NULL)
			(void)xf_aname(spec->xarr);
		spec->prev = xf_context;	/* push onto stack */
		xf_context = spec;
	}
					/* translate new specification */
	n = xf_ac(spec);
	n -= xf_ac(spec->prev);		/* incremental comp. is more eff. */
	if (xf(&spec->xf, n, xf_av(spec)) != n)
		return(MG_ETYPE);
					/* check for vertex reversal */
	if ((spec->rev = (spec->xf.sca < 0.)))
		spec->xf.sca = -spec->xf.sca;
					/* compute total transformation */
	if (spec->prev != NULL) {
		multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
		spec->xf.sca *= spec->prev->xf.sca;
		spec->rev ^= spec->prev->rev;
	}
	spec->xid = comp_xfid(spec->xf.xfm);	/* compute unique ID */
	return(MG_OK);
}