Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
static OCTREE
cvmeshoct(			/* convert triangles in subtree */
	OCTREE	ot
)
{
	int	i;

	if (isempty(ot))
		return(EMPTY);

	if (isfull(ot)) {
		OBJECT	oset1[MAXSET+1];
		OBJECT	oset2[MAXSET+1];
		objset(oset1, ot);
		oset2[0] = 0;
		for (i = oset1[0]; i > 0; i--)
			insertelem(oset2, cvmeshtri(oset1[i]));
		return(fullnode(oset2));
	}

	for (i = 8; i--; )
		octkid(ot, i) = cvmeshoct(octkid(ot, i));
	return(ot);
}
Ejemplo n.º 4
0
static void
puttree(			/* write octree to stdout in pre-order form */
	register OCTREE  ot
)
{
	register int  i;
	
	if (istree(ot)) {
		putc(OT_TREE, stdout);		/* indicate tree */
		for (i = 0; i < 8; i++)		/* write tree */
			puttree(octkid(ot, i));
	} else if (isfull(ot)) {
		putc(OT_FULL, stdout);		/* indicate fullnode */
		putfullnode(ot);		/* write fullnode */
	} else
		putc(OT_EMPTY, stdout);		/* indicate empty */
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
static void
puttree(			/* write octree to fp in pre-order form */
	register OCTREE	ot,
	FILE		*fp
)
{
	
	if (istree(ot)) {
		register int	i;
		putc(OT_TREE, fp);		/* indicate tree */
		for (i = 0; i < 8; i++)		/* write tree */
			puttree(octkid(ot, i), fp);
		return;
	}
	if (isfull(ot)) {
		putc(OT_FULL, fp);		/* indicate fullnode */
		putfullnode(ot, fp);		/* write fullnode */
		return;
	}
	putc(OT_EMPTY, fp);			/* indicate empty */
}
Ejemplo n.º 8
0
static void
tallyoctree(			/* tally octree size */
	OCTREE	ot,
	int	*ecp,
	int	*lcp,
	int	*ocp
)
{
	int	i;

	if (isempty(ot)) {
		(*ecp)++;
		return;
	}
	if (isfull(ot)) {
		OBJECT	oset[MAXSET+1];
		(*lcp)++;
		objset(oset, ot);
		*ocp += oset[0];
		return;
	}
	for (i = 0; i < 8; i++)
		tallyoctree(octkid(ot, i), ecp, lcp, ocp);
}
Ejemplo n.º 9
0
static OCTREE
gettree()			/* get a pre-ordered octree */
{
	register OCTREE	 ot;
	register int  i;
	
	switch (getc(infp)) {
	case OT_EMPTY:
		return(EMPTY);
	case OT_FULL:
		return(getfullnode());
	case OT_TREE:
		if ((ot = octalloc()) == EMPTY)
			octerror(SYSTEM, "out of tree space in gettree");
		for (i = 0; i < 8; i++)
			octkid(ot, i) = gettree();
		return(ot);
	case EOF:
		octerror(USER, "truncated octree");
	default:
		octerror(USER, "damaged octree");
	}
	return EMPTY; /* pro forma return */
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
static int
raymove(		/* check for hit as we move */
	FVECT  pos,			/* current position, modified herein */
	OBJECT  *cxs,			/* checked objects, modified by checkhit */
	int  dirf,			/* direction indicators to speed tests */
	RAY  *r,
	CUBE  *cu
)
{
	int  ax;
	double  dt, t;

	if (istree(cu->cutree)) {		/* recurse on subcubes */
		CUBE  cukid;
		int  br, sgn;

		cukid.cusize = cu->cusize * 0.5;	/* find subcube */
		VCOPY(cukid.cuorg, cu->cuorg);
		br = 0;
		if (pos[0] >= cukid.cuorg[0]+cukid.cusize) {
			cukid.cuorg[0] += cukid.cusize;
			br |= 1;
		}
		if (pos[1] >= cukid.cuorg[1]+cukid.cusize) {
			cukid.cuorg[1] += cukid.cusize;
			br |= 2;
		}
		if (pos[2] >= cukid.cuorg[2]+cukid.cusize) {
			cukid.cuorg[2] += cukid.cusize;
			br |= 4;
		}
		for ( ; ; ) {
			cukid.cutree = octkid(cu->cutree, br);
			if ((ax = raymove(pos,cxs,dirf,r,&cukid)) == RAYHIT)
				return(RAYHIT);
			sgn = 1 << ax;
			if (sgn & dirf)			/* positive axis? */
				if (sgn & br)
					return(ax);	/* overflow */
				else {
					cukid.cuorg[ax] += cukid.cusize;
					br |= sgn;
				}
			else
				if (sgn & br) {
					cukid.cuorg[ax] -= cukid.cusize;
					br &= ~sgn;
				} else
					return(ax);	/* underflow */
		}
		/*NOTREACHED*/
	}
	if (isfull(cu->cutree)) {
		if (checkhit(r, cu, cxs))
			return(RAYHIT);
	} else if (r->ro == &Aftplane && incube(cu, r->rop))
		return(RAYHIT);
					/* advance to next cube */
	if (dirf&0x11) {
		dt = dirf&1 ? cu->cuorg[0] + cu->cusize : cu->cuorg[0];
		t = (dt - pos[0])/r->rdir[0];
		ax = 0;
	} else
		t = FHUGE;
	if (dirf&0x22) {
		dt = dirf&2 ? cu->cuorg[1] + cu->cusize : cu->cuorg[1];
		dt = (dt - pos[1])/r->rdir[1];
		if (dt < t) {
			t = dt;
			ax = 1;
		}
	}
	if (dirf&0x44) {
		dt = dirf&4 ? cu->cuorg[2] + cu->cusize : cu->cuorg[2];
		dt = (dt - pos[2])/r->rdir[2];
		if (dt < t) {
			t = dt;
			ax = 2;
		}
	}
	VSUM(pos, pos, r->rdir, t);
	return(ax);
}