Пример #1
0
extern int
o_cone(		/* determine if cone intersects cube */
	OBJREC  *o,
	register CUBE  *cu
)
{
	CONE  *co;
	FVECT  ep0, ep1;
#ifdef STRICT
	FVECT  cumin, cumax;
	CUBE  cukid;
	register int  j;
#endif
	double  r;
	FVECT  p;
	register int  i;
					/* get cone arguments */
	co = getcone(o, 0);
					/* get cube center */
	r = cu->cusize * 0.5;
	for (i = 0; i < 3; i++)
		p[i] = cu->cuorg[i] + r;
	r *= ROOT3;			/* bounding radius for cube */

	if (findcseg(ep0, ep1, co, p)) {
					/* check min. distance to cone */
		if (dist2lseg(p, ep0, ep1) > (r+FTINY)*(r+FTINY))
			return(O_MISS);
#ifdef  STRICT
					/* get cube boundaries */
		for (i = 0; i < 3; i++)
			cumax[i] = (cumin[i] = cu->cuorg[i]) + cu->cusize;
					/* closest segment intersects? */
		if (clip(ep0, ep1, cumin, cumax))
			return(O_HIT);
	}
					/* check sub-cubes */
	cukid.cusize = cu->cusize * 0.5;
	if (cukid.cusize < mincusize)
		return(O_HIT);		/* cube too small */
	cukid.cutree = EMPTY;

	for (j = 0; j < 8; j++) {
		for (i = 0; i < 3; i++) {
			cukid.cuorg[i] = cu->cuorg[i];
			if (1<<i & j)
				cukid.cuorg[i] += cukid.cusize;
		}
		if (o_cone(o, &cukid))
			return(O_HIT);	/* sub-cube intersects */
	}
	return(O_MISS);			/* no intersection */
#else
	}
Пример #2
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);
}
Пример #3
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;
    }
}
Пример #4
0
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 */
}