#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& 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 BoundingBox::getCorners() { std::vector 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(); }