Esempio n. 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);
}
Esempio n. 2
0
void
xf_xfmpoint(FVECT v1, FVECT v2)	/* transform a point by the current matrix */
{
	if (xf_context == NULL) {
		VCOPY(v1, v2);
		return;
	}
	multp3(v1, v2, xf_context->xf.xfm);
}
static int
o_cube(			/* determine if cubes intersect */
	CUBE  *cu1,
	FULLXF  *fxf,
	CUBE  *cu
)
{
	static int  vstart[4] = {0, 3, 5, 6};
	FVECT  cumin, cumax;
	FVECT  vert[8];
	FVECT  v1, v2;
	int  vloc, vout;
	register int  i, j;
					/* check if cube vertex in octree */
	for (j = 0; j < 3; j++)
		cumax[j] = (cumin[j] = cu1->cuorg[j]) + cu1->cusize;
	vloc = ABOVE | BELOW;
	vout = 0;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 3; j++) {
			v1[j] = cu->cuorg[j];
			if (i & 1<<j)
				v1[j] += cu->cusize;
		}
		multp3(v2, v1, fxf->b.xfm);
		if ( (j = plocate(v2, cumin, cumax)) )
			vout++;
		vloc &= j;
	}
	if (vout == 0)			/* all inside */
		return(O_IN);
	if (vout < 8)			/* some inside */
		return(O_HIT);
	if (vloc)			/* all to one side */
		return(O_MISS);
					/* octree vertices in cube? */
	for (j = 0; j < 3; j++)
		cumax[j] = (cumin[j] = cu->cuorg[j]) + cu->cusize;
	vloc = ABOVE | BELOW;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 3; j++) {
			v1[j] = cu1->cuorg[j];
			if (i & 1<<j)
				v1[j] += cu1->cusize;
		}
		multp3(vert[i], v1, fxf->f.xfm);
		if ( (j = plocate(vert[i], cumin, cumax)) )
			vloc &= j;
		else
			return(O_HIT);	/* vertex inside */
	}
	if (vloc)			/* all to one side */
		return(O_MISS);
					/* check edges */
	for (i = 0; i < 4; i++)
		for (j = 0; j < 3; j++) {
						/* clip modifies vertices! */
			VCOPY(v1, vert[vstart[i]]);
			VCOPY(v2, vert[vstart[i] ^ 1<<j]);
			if (clip(v1, v2, cumin, cumax))
				return(O_HIT);		/* edge inside */
		}

	return(O_MISS);			/* no intersection */
}
Esempio n. 4
0
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;
    }
}
Esempio n. 5
0
int
o_cone(			/* intersect ray with cone */
	OBJREC  *o,
	RAY  *r
)
{
	FVECT  rox, rdx;
	double  a, b, c;
	double  root[2];
	int  nroots, rn;
	CONE  *co;
	int  i;

						/* get cone structure */
	co = getcone(o, 1);

	/*
	 *     To intersect a ray with a cone, we transform the
	 *  ray into the cone's normalized space.  This greatly
	 *  simplifies the computation.
	 *     For a cone or cup, normalization results in the
	 *  equation:
	 *
	 *		x*x + y*y - z*z == 0
	 *
	 *     For a cylinder or tube, the normalized equation is:
	 *
	 *		x*x + y*y - r*r == 0
	 *
	 *     A normalized ring obeys the following set of equations:
	 *
	 *		z == 0			&&
	 *		x*x + y*y >= r0*r0	&&
	 *		x*x + y*y <= r1*r1
	 */

					/* transform ray */
	multp3(rox, r->rorg, co->tm);
	multv3(rdx, r->rdir, co->tm);
					/* compute intersection */

	if (o->otype == OBJ_CONE || o->otype == OBJ_CUP) {

		a = rdx[0]*rdx[0] + rdx[1]*rdx[1] - rdx[2]*rdx[2];
		b = 2.0*(rdx[0]*rox[0] + rdx[1]*rox[1] - rdx[2]*rox[2]);
		c = rox[0]*rox[0] + rox[1]*rox[1] - rox[2]*rox[2];

	} else if (o->otype == OBJ_CYLINDER || o->otype == OBJ_TUBE) {

		a = rdx[0]*rdx[0] + rdx[1]*rdx[1];
		b = 2.0*(rdx[0]*rox[0] + rdx[1]*rox[1]);
		c = rox[0]*rox[0] + rox[1]*rox[1] - CO_R0(co)*CO_R0(co);

	} else { /* OBJ_RING */

		if (rdx[2] <= FTINY && rdx[2] >= -FTINY)
			return(0);			/* parallel */
		root[0] = -rox[2]/rdx[2];
		if (root[0] <= FTINY || root[0] >= r->rot)
			return(0);			/* distance check */
		b = root[0]*rdx[0] + rox[0];
		c = root[0]*rdx[1] + rox[1];
		a = b*b + c*c;
		if (a < CO_R0(co)*CO_R0(co) || a > CO_R1(co)*CO_R1(co))
			return(0);			/* outside radii */
		r->ro = o;
		r->rot = root[0];
		VSUM(r->rop, r->rorg, r->rdir, r->rot);
		VCOPY(r->ron, co->ad);
		r->rod = -rdx[2];
		r->rox = NULL;
		return(1);				/* good */
	}
					/* roots for cone, cup, cyl., tube */
	nroots = quadratic(root, a, b, c);

	for (rn = 0; rn < nroots; rn++) {	/* check real roots */
		if (root[rn] <= FTINY)
			continue;		/* too small */
		if (root[rn] >= r->rot)
			break;			/* too big */
						/* check endpoints */
		VSUM(rox, r->rorg, r->rdir, root[rn]);
		VSUB(rdx, rox, CO_P0(co));
		b = DOT(rdx, co->ad); 
		if (b < 0.0)
			continue;		/* before p0 */
		if (b > co->al)
			continue;		/* after p1 */
		r->ro = o;
		r->rot = root[rn];
		VCOPY(r->rop, rox);
						/* get normal */
		if (o->otype == OBJ_CYLINDER)
			a = CO_R0(co);
		else if (o->otype == OBJ_TUBE)
			a = -CO_R0(co);
		else { /* OBJ_CONE || OBJ_CUP */
			c = CO_R1(co) - CO_R0(co);
			a = CO_R0(co) + b*c/co->al;
			if (o->otype == OBJ_CUP) {
				c = -c;
				a = -a;
			}
		}
		for (i = 0; i < 3; i++)
			r->ron[i] = (rdx[i] - b*co->ad[i])/a;
		if (o->otype == OBJ_CONE || o->otype == OBJ_CUP)
			for (i = 0; i < 3; i++)
				r->ron[i] = (co->al*r->ron[i] - c*co->ad[i])
						/ co->sl;
		a = DOT(r->ron, r->ron);
		if (a > 1.+FTINY || a < 1.-FTINY) {
			c = 1./(.5 + .5*a);     /* avoid numerical error */
			r->ron[0] *= c; r->ron[1] *= c; r->ron[2] *= c;
		}
		r->rod = -DOT(r->rdir, r->ron);
		r->pert[0] = r->pert[1] = r->pert[2] = 0.0;
		r->uv[0] = r->uv[1] = 0.0;
		r->rox = NULL;
		return(1);			/* good */
	}
	return(0);
}