Revision 39b13612ebd645a65eda854771b517371f2f858a authored by ennetws on 13 March 2015, 18:17:18 UTC, committed by ennetws on 13 March 2015, 18:17:18 UTC
1 parent c702819
Raw File
BoundingBox.cpp
#include "BoundingBox.h"

BoundingBox::BoundingBox()
{
	this->center = Vector3d(0,0,0);

	this->xExtent = 0;
	this->yExtent = 0;
	this->zExtent = 0;
}

BoundingBox::BoundingBox( const Vector3d& c, double x, double y, double z )
{
	this->center = c;

	this->xExtent = x;
	this->yExtent = y;
	this->zExtent = z;

	Vector3d corner(x/2, y/2, z/2);

	vmin = center - corner;
	vmax = center + corner;
}

BoundingBox& BoundingBox::operator=( const BoundingBox& other )
{
	this->center = other.center;

	this->xExtent = other.xExtent;
	this->yExtent = other.yExtent;
	this->zExtent = other.zExtent;

	this->vmax = other.vmax;
	this->vmin = other.vmin;

	return *this;
}

/*void BoundingBox::computeFromTris( const StdVector<BaseTriangle*>& tris )
{
	vmin = Vector3d(DBL_MAX, DBL_MAX, DBL_MAX);
	vmax = Vector3d(-DBL_MAX, -DBL_MAX, -DBL_MAX);

	double minx = 0, miny = 0, minz = 0;
	double maxx = 0, maxy = 0, maxz = 0;

	minx = maxx = tris[0]->vec(0).x();
	miny = maxy = tris[0]->vec(0).y();
	minz = maxz = tris[0]->vec(0).z();

	for (int i = 0; i < (int)tris.size(); i++)
	{
		for(int v = 0; v < 3; v++)
		{
			Vector3d vec = tris[i]->vec(v);

			if (vec.x() < minx) minx = vec.x();
			if (vec.x() > maxx) maxx = vec.x();
			if (vec.y() < miny) miny = vec.y();
			if (vec.y() > maxy) maxy = vec.y();
			if (vec.z() < minz) minz = vec.z();
			if (vec.z() > maxz) maxz = vec.z();
		}
	}

	vmax = Vector3d(maxx, maxy, maxz);
	vmin = Vector3d(minx, miny, minz);

	this->center = (vmin + vmax) / 2.0;

	this->xExtent = abs(vmax.x() - center.x());
	this->yExtent = abs(vmax.y() - center.y());
	this->zExtent = abs(vmax.z() - center.z());
}*/

/*bool BoundingBox::intersects( const Ray& ray ) const
{
    double rhs;
    double fWdU[3];
    double fAWdU[3];
    double fDdU[3];
    double fADdU[3];
    double fAWxDdU[3];

    Vector3d UNIT_X(1.0, 0.0, 0.0);
    Vector3d UNIT_Y(0.0, 1.0, 0.0);
    Vector3d UNIT_Z(0.0, 0.0, 1.0);

    Vector3d diff = ray.origin - center;
    Vector3d wCrossD = cross(ray.direction , diff);

    fWdU[0] = dot(ray.direction , UNIT_X);
    fAWdU[0] = abs(fWdU[0]);
    fDdU[0] = dot(diff , UNIT_X);
    fADdU[0] = abs(fDdU[0]);
    if (fADdU[0] > xExtent && fDdU[0] * fWdU[0] >= 0.0)		return false;

    fWdU[1] = dot(ray.direction , UNIT_Y);
    fAWdU[1] = abs(fWdU[1]);
    fDdU[1] = dot(diff , UNIT_Y);
    fADdU[1] = abs(fDdU[1]);
    if (fADdU[1] > yExtent && fDdU[1] * fWdU[1] >= 0.0)		return false;

    fWdU[2] = dot(ray.direction , UNIT_Z);
    fAWdU[2] = abs(fWdU[2]);
    fDdU[2] = dot(diff , UNIT_Z);
    fADdU[2] = abs(fDdU[2]);
    if (fADdU[2] > zExtent && fDdU[2] * fWdU[2] >= 0.0)		return false;

    fAWxDdU[0] = abs(dot(wCrossD , UNIT_X));
    rhs = yExtent , fAWdU[2] + zExtent * fAWdU[1];
    if (fAWxDdU[0] > rhs)		return false;

    fAWxDdU[1] = abs(dot(wCrossD , UNIT_Y));
    rhs = xExtent * fAWdU[2] + zExtent * fAWdU[0];
    if (fAWxDdU[1] > rhs)		return false;

    fAWxDdU[2] = abs(dot(wCrossD , UNIT_Z));
    rhs = xExtent * fAWdU[1] + yExtent * fAWdU[0];
    if (fAWxDdU[2] > rhs)		return false;

    return true;
}*/

BoundingBox::BoundingBox( const Vector3d& fromMin, const Vector3d& toMax )
{
	vmin = fromMin;
	vmax = toMax;

	this->center = (vmin + vmax) / 2.0;

	this->xExtent = abs(vmax.x() - center.x());
	this->yExtent = abs(vmax.y() - center.y());
	this->zExtent = abs(vmax.z() - center.z());
}

std::vector<Vector3d> BoundingBox::getCorners()
{
    std::vector<Vector3d> corners;

	Vector3d x = (Vector3d(1,0,0) * xExtent);
	Vector3d y = (Vector3d(0,1,0) * yExtent);
	Vector3d z = (Vector3d(0,0,1) * zExtent);

	Vector3d c = center + x + y + z;

	corners.push_back(c);
	corners.push_back(c - (x*2));
	corners.push_back(c - (y*2));
	corners.push_back(c - (x*2) - (y*2));

	corners.push_back(corners[0] - (z*2));
	corners.push_back(corners[1] - (z*2));
	corners.push_back(corners[2] - (z*2));
	corners.push_back(corners[3] - (z*2));

	return corners;
}

/* AABB-triangle overlap test code                      */
/* by Tomas Akenine-Möller                              */
bool BoundingBox::containsTriangle( const Vector3d& tv0, const Vector3d& tv1, const Vector3d& tv2 ) const
{
	Vector3d boxcenter(center);
	Vector3d boxhalfsize(xExtent, yExtent, zExtent);

	int X = 0, Y = 1, Z = 2;

	/*    use separating axis theorem to test overlap between triangle and box */
	/*    need to test for overlap in these directions: */
	/*    1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
	/*       we do not even need to test these) */
	/*    2) normal of the triangle */
	/*    3) crossproduct(edge from tri, {x,y,z}-directin) */
	/*       this gives 3x3=9 more tests */
	Vector3d v0,v1,v2;
	double min,max,p0,p1,p2,rad,fex,fey,fez;
	Vector3d normal,e0,e1,e2;

	/* This is the fastest branch on Sun */
	/* move everything so that the box center is in (0,0,0) */
	v0=tv0-boxcenter;
	v1=tv1-boxcenter;
	v2=tv2-boxcenter;
	
	/* compute triangle edges */
	e0=v1-v0;      /* tri edge 0 */
	e1=v2-v1;      /* tri edge 1 */
	e2=v0-v2;      /* tri edge 2 */
	
	/* Bullet 3:  */
	/*  test the 9 tests first (this was faster) */
	fex = fabsf(e0[X]);
	fey = fabsf(e0[Y]);
	fez = fabsf(e0[Z]);
	AXISTEST_X01(e0[Z], e0[Y], fez, fey);
	AXISTEST_Y02(e0[Z], e0[X], fez, fex);
	AXISTEST_Z12(e0[Y], e0[X], fey, fex);
	fex = fabsf(e1[X]);
	fey = fabsf(e1[Y]);
	fez = fabsf(e1[Z]);
	AXISTEST_X01(e1[Z], e1[Y], fez, fey);
	AXISTEST_Y02(e1[Z], e1[X], fez, fex);
	AXISTEST_Z0(e1[Y], e1[X], fey, fex);
	fex = fabsf(e2[X]);
	fey = fabsf(e2[Y]);
	fez = fabsf(e2[Z]);
	AXISTEST_X2(e2[Z], e2[Y], fez, fey);
	AXISTEST_Y1(e2[Z], e2[X], fez, fex);
	AXISTEST_Z12(e2[Y], e2[X], fey, fex);
	
	/* Bullet 1: */
	/*  first test overlap in the {x,y,z}-directions */
	/*  find min, max of the triangle each direction, and test for overlap in */
	/*  that direction -- this is equivalent to testing a minimal AABB around */
	/*  the triangle against the AABB */
	/* test in X-direction */
	FINDMINMAX(v0[X],v1[X],v2[X],min,max);
	if(min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;
	/* test in Y-direction */
	FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
	if(min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0;
	/* test in Z-direction */
	FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
	if(min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;
	
	/* Bullet 2: */
	/*  test if the box intersects the plane of the triangle */
	/*  compute plane equation of triangle: normal*x+d=0 */
	normal = cross(e0, e1);

	if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0;
	return 1;   /* box and triangle overlaps */
}

bool BoundingBox::intersectsBoundingBox( const BoundingBox& bb ) const
{
	if (center.x() + xExtent < bb.center.x() - bb.xExtent || center.x() - xExtent > bb.center.x() + bb.xExtent)
		return false;
	else if (center.y() + yExtent < bb.center.y() - bb.yExtent || center.y() - yExtent > bb.center.y() + bb.yExtent)
		return false;
	else if (center.z() + zExtent < bb.center.z() - bb.zExtent || center.z() - zExtent > bb.center.z() + bb.zExtent)
		return false;
	else
		return true;
}

bool BoundingBox::intersectsSphere( const Vector3d& sphere_center, double radius )
{
	if (abs(center.x() - sphere_center.x()) < radius + xExtent
		&& abs(center.y() - sphere_center.y()) < radius + yExtent
		&& abs(center.z() - sphere_center.z()) < radius + zExtent)
		return true;

	return false;
}

bool BoundingBox::contains( const Vector3d& point ) const
{
	return abs(center.x() - point.x()) < xExtent
		&& abs(center.y() - point.y()) < yExtent
		&& abs(center.z() - point.z()) < zExtent;
}

Vector3d BoundingBox::Center()
{
	return center;
}

void BoundingBox::Offset( double s )
{
	Offset( Vector3d(s,s,s));
}

void BoundingBox::Offset( Vector3d delta )
{
	*this = BoundingBox(vmin - delta, vmax + delta);
}

double BoundingBox::Diag()
{
	return (vmin - vmax).norm();
}
back to top