// Gray - A simple ray tracing program // Copyright (C) 2008-2018 Eric Bechet // // See the COPYING file for contributions and license information. // Please report all bugs and problems to . // #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 box1_center = box_1->getBBoxCenter(); Point 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 ( minX, minY, minZ ) ); cornerPoints.push_back ( Point ( maxX, minY, minZ ) ); cornerPoints.push_back ( Point ( maxX, minY, maxZ ) ); cornerPoints.push_back ( Point ( minX, minY, maxZ ) ); cornerPoints.push_back ( Point ( minX, maxY, maxZ ) ); cornerPoints.push_back ( Point ( maxX, maxY, maxZ ) ); cornerPoints.push_back ( Point ( maxX, maxY, minZ ) ); cornerPoints.push_back ( Point ( minX, maxY, minZ ) ); initFaces(); model = NULL; } void BoundingBox::sphereBB ( Gsphere* sphere ) { center = sphere->getCenter(); double radius = sphere->getRadius(); cornerPoints.push_back ( Point ( center.X-radius, center.Y-radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y-radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y-radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X-radius, center.Y-radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X-radius, center.Y+radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y+radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y+radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( center.X-radius, center.Y+radius, center.Z-radius ) ); initFaces(); } void BoundingBox::meshModelBB ( Gmeshmodel* meshModel ) { Point min = meshModel->getMin(); Point 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 ( min.X, min.Y, min.Z ) ); cornerPoints.push_back ( Point ( max.X, min.Y, min.Z ) ); cornerPoints.push_back ( Point ( max.X, min.Y, max.Z ) ); cornerPoints.push_back ( Point ( min.X, min.Y, max.Z ) ); cornerPoints.push_back ( Point ( min.X, max.Y, max.Z ) ); cornerPoints.push_back ( Point ( max.X, max.Y, max.Z ) ); cornerPoints.push_back ( Point ( max.X, max.Y, min.Z ) ); cornerPoints.push_back ( Point ( min.X, max.Y, min.Z ) ); initFaces(); } void BoundingBox::discBB ( Gdisc* disc ) { center = disc->getPoint(); double radius = disc->getRadius(); cornerPoints.push_back ( Point ( center.X-radius, center.Y-radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y-radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y-radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X-radius, center.Y-radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X-radius, center.Y+radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y+radius, center.Z+radius ) ); cornerPoints.push_back ( Point ( center.X+radius, center.Y+radius, center.Z-radius ) ); cornerPoints.push_back ( Point ( 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 min; Point 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( 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 ( getMinCoordinateX ( facePoints ),getMinCoordinateY ( facePoints ),getMinCoordinateZ ( facePoints ) ); max = Point ( getMaxCoordinateX ( facePoints ),getMaxCoordinateY ( facePoints ),getMaxCoordinateZ ( facePoints ) ); faces.push_back ( Face ( facePoints, min, max ) ); } // kate: indent-mode cstyle; indent-width 2; replace-tabs on;