// // C++ Implementation: BoundingBox // // Description: // // // Authors: Dalla Corte Ludovic (C) 2011 // Phan Laurent // Etudiants Infographie Groupe 1 2010-2011 // // Copyright: See COPYING file that comes with this distribution // // #include "BoundingBox.h" #include "BVTree.h" BoundingBox::BoundingBox(Gmodel* newModel) { model = newModel; if(newModel->typeID() == GSPHERE) { sphereBB((Gsphere*) newModel); } else if (newModel->typeID() == GDISC) { discBB((Gdisc*) newModel); } else if (newModel->typeID() == GMESHMODEL) { meshModelBB((Gmeshmodel*) newModel); } } BoundingBox::BoundingBox(BoundingBox* box_1, BoundingBox* box_2) { point_t box1_center = box_1->getBBoxCenter(); point_t box2_center = box_2->getBBoxCenter(); center.X = (box1_center.X + box2_center.X) / 2; center.Y = (box1_center.Y + box2_center.Y) / 2; center.Z = (box1_center.Z + box2_center.Z) / 2; std::vector cornerPoints_1 = box_1->getCornerPoints(); std::vector cornerPoints_2 = box_2->getCornerPoints(); double minX, minY, minZ, maxX, maxY, maxZ; if(getMinCoordinateX(cornerPoints_1) < getMinCoordinateX(cornerPoints_2)) minX = getMinCoordinateX(cornerPoints_1); else minX = getMinCoordinateX(cornerPoints_2); if(getMinCoordinateY(cornerPoints_1) < getMinCoordinateY(cornerPoints_2)) minY = getMinCoordinateY(cornerPoints_1); else minY = getMinCoordinateY(cornerPoints_2); if(getMinCoordinateZ(cornerPoints_1) < getMinCoordinateZ(cornerPoints_2)) minZ = getMinCoordinateZ(cornerPoints_1); else minZ = getMinCoordinateZ(cornerPoints_2); if(getMaxCoordinateX(cornerPoints_1) > getMaxCoordinateX(cornerPoints_2)) maxX = getMaxCoordinateX(cornerPoints_1); else maxX = getMaxCoordinateX(cornerPoints_2); if(getMaxCoordinateY(cornerPoints_1) > getMaxCoordinateY(cornerPoints_2)) maxY = getMaxCoordinateY(cornerPoints_1); else maxY = getMaxCoordinateY(cornerPoints_2); if(getMaxCoordinateZ(cornerPoints_1) > getMaxCoordinateZ(cornerPoints_2)) maxZ = getMaxCoordinateZ(cornerPoints_1); else maxZ = getMaxCoordinateZ(cornerPoints_2); cornerPoints.push_back(point_t(minX, minY, minZ)); cornerPoints.push_back(point_t(maxX, minY, minZ)); cornerPoints.push_back(point_t(maxX, minY, maxZ)); cornerPoints.push_back(point_t(minX, minY, maxZ)); cornerPoints.push_back(point_t(minX, maxY, maxZ)); cornerPoints.push_back(point_t(maxX, maxY, maxZ)); cornerPoints.push_back(point_t(maxX, maxY, minZ)); cornerPoints.push_back(point_t(minX, maxY, minZ)); initFaces(); model = NULL; } void BoundingBox::sphereBB(Gsphere* sphere) { center = sphere->getCenter(); double radius = sphere->getRadius(); cornerPoints.push_back(point_t(center.X-radius, center.Y-radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y-radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y-radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y-radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y+radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y+radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y+radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y+radius, center.Z-radius)); initFaces(); } void BoundingBox::meshModelBB(Gmeshmodel* meshModel) { point_t min = meshModel->getMin(); point_t max = meshModel->getMax(); center.X = (min.X + max.X) / 2; center.Y = (min.Y + max.Y) / 2; center.Z = (min.Z + max.Z) / 2; cornerPoints.push_back(point_t(min.X, min.Y, min.Z)); cornerPoints.push_back(point_t(max.X, min.Y, min.Z)); cornerPoints.push_back(point_t(max.X, min.Y, max.Z)); cornerPoints.push_back(point_t(min.X, min.Y, max.Z)); cornerPoints.push_back(point_t(min.X, max.Y, max.Z)); cornerPoints.push_back(point_t(max.X, max.Y, max.Z)); cornerPoints.push_back(point_t(max.X, max.Y, min.Z)); cornerPoints.push_back(point_t(min.X, max.Y, min.Z)); initFaces(); } void BoundingBox::discBB(Gdisc* disc) { center = disc->getPoint(); double radius = disc->getRadius(); cornerPoints.push_back(point_t(center.X-radius, center.Y-radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y-radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y-radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y-radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y+radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y+radius, center.Z+radius)); cornerPoints.push_back(point_t(center.X+radius, center.Y+radius, center.Z-radius)); cornerPoints.push_back(point_t(center.X-radius, center.Y+radius, center.Z-radius)); initFaces(); } bool BoundingBox::intersect(ray* r) { if(intersectionY(faces[0], r)) return true; if(intersectionY(faces[1], r)) return true; if(intersectionX(faces[2], r)) return true; if(intersectionX(faces[3], r)) return true; if(intersectionZ(faces[4], r)) return true; if(intersectionZ(faces[5], r)) return true; return false; } double BoundingBox::getMinCoordinateX(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double min = (*it).X; for(it++; it != pointsVector.end(); it++) { if((*it).X < min) min = (*it).X; } return min; } double BoundingBox::getMinCoordinateY(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double min = (*it).Y; for(it++; it != pointsVector.end(); it++) { if((*it).Y < min) min = (*it).Y; } return min; } double BoundingBox::getMinCoordinateZ(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double min = (*it).Z; for(it++; it != pointsVector.end(); it++) { if((*it).Z < min) min = (*it).Z; } return min; } double BoundingBox::getMaxCoordinateX(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double max = (*it).X; for(it++; it != pointsVector.end(); it++) { if((*it).X > max) max = (*it).X; } return max; } double BoundingBox::getMaxCoordinateY(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double max = (*it).Y; for(it++; it != pointsVector.end(); it++) { if((*it).Y > max) max = (*it).Y; } return max; } double BoundingBox::getMaxCoordinateZ(std::vector pointsVector) { std::vector::iterator it = pointsVector.begin(); double max = (*it).Z; for(it++; it != pointsVector.end(); it++) { if((*it).Z > max) max = (*it).Z; } return max; } bool BoundingBox::intersectionX(Face face, ray* ray) { double yPlane = ray->p.Y - (((ray->p.X - face.points[0].X) / ray->v.X) * (ray->v.Y)); double zPlane = ray->p.Z - (((ray->p.X - face.points[0].X) / ray->v.X) * (ray->v.Z)); if((face.min.Y <= yPlane) && (yPlane <= face.max.Y) && (face.min.Z <= zPlane) && (zPlane <= face.max.Z)) { return true; } return false; } bool BoundingBox::intersectionY(Face face, ray* ray) { double xPlane = ray->p.X - (((ray->p.Y - face.points[0].Y) / ray->v.Y) * (ray->v.X)); double zPlane = ray->p.Z - (((ray->p.Y - face.points[0].Y) / ray->v.Y) * (ray->v.Z)); if((face.min.X <= xPlane) && (xPlane <= face.max.X) && (face.min.Z <= zPlane) && (zPlane <= face.max.Z)) { return true; } return false; } bool BoundingBox::intersectionZ(Face face, ray* ray) { double yPlane = ray->p.Y - (((ray->p.Z - face.points[0].Z) / ray->v.Z) * (ray->v.Y)); double xPlane = ray->p.X - (((ray->p.Z - face.points[0].Z) / ray->v.Z) * (ray->v.X)); if((face.min.Y <= yPlane) && (yPlane <= face.max.Y) && (face.min.X <= xPlane) && (xPlane <= face.max.X)) { return true; } return false; } void BoundingBox::initFaces() { std::vector facePoints; point_t min; point_t max; // face du bas facePoints.push_back(cornerPoints[0]); facePoints.push_back(cornerPoints[1]); facePoints.push_back(cornerPoints[2]); facePoints.push_back(cornerPoints[3]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); // face du haut facePoints.clear(); facePoints.push_back(cornerPoints[7]); facePoints.push_back(cornerPoints[6]); facePoints.push_back(cornerPoints[5]); facePoints.push_back(cornerPoints[4]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); // face à gauche facePoints.clear(); facePoints.push_back(cornerPoints[3]); facePoints.push_back(cornerPoints[0]); facePoints.push_back(cornerPoints[7]); facePoints.push_back(cornerPoints[4]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); // face à droite facePoints.clear(); facePoints.push_back(cornerPoints[1]); facePoints.push_back(cornerPoints[2]); facePoints.push_back(cornerPoints[5]); facePoints.push_back(cornerPoints[6]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); // face de devant facePoints.clear(); facePoints.push_back(cornerPoints[0]); facePoints.push_back(cornerPoints[1]); facePoints.push_back(cornerPoints[6]); facePoints.push_back(cornerPoints[7]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); // face de derriere facePoints.clear(); facePoints.push_back(cornerPoints[3]); facePoints.push_back(cornerPoints[2]); facePoints.push_back(cornerPoints[5]); facePoints.push_back(cornerPoints[4]); min = point_t(getMinCoordinateX(facePoints),getMinCoordinateY(facePoints),getMinCoordinateZ(facePoints)); max = point_t(getMaxCoordinateX(facePoints),getMaxCoordinateY(facePoints),getMaxCoordinateZ(facePoints)); faces.push_back(Face(facePoints, min, max)); }