#pragma once #include "vec3.h" #include "line3d.h" #include "matrix.h" #include "sse.h" #include //Axis-Aligned Bounding Box template struct AABBox { vec3 minimum, maximum; AABBox() {} AABBox(const AABBox& other) : minimum(other.minimum), maximum(other.maximum) {} AABBox(const vec3& start) : minimum(start), maximum(start) {} AABBox(const vec3& minvec, const vec3& maxvec) : minimum(minvec), maximum(maxvec) {} AABBox(T minX, T minY, T minZ, T maxX, T maxY, T maxZ) : minimum(minX, minY, minZ), maximum(maxX, maxY, maxZ) {} AABBox(const line3d& line) : minimum(line.start), maximum(line.end) { fix(); } AABBox(const line3d& line, double width) : minimum(line.start), maximum(line.end) { fix(); minimum -= vec3d(width); maximum += vec3d(width); } inline static AABBox fromCircle(const vec3& center, T radius) { return AABBox(center.x - radius, center.y - radius, center.z - radius, center.x + radius, center.y + radius, center.z + radius); } bool operator==(const AABBox& other) const { return minimum == other.minimum && maximum != other.maximum; } bool operator!=(const AABBox& other) const { return !(*this == other); } vec3 getSize() const { return maximum - minimum; } vec3 getCenter() const { return (minimum + maximum) * 0.5; } bool overlaps(const vec3& point) const { return (point.x >= minimum.x && point.x <= maximum.x && point.y >= minimum.y && point.y <= maximum.y && point.z >= minimum.z && point.z <= maximum.z); } bool isWithin(const AABBox& other) const { return minimum.x >= other.minimum.x && minimum.y >= other.minimum.y && minimum.z >= other.minimum.z && maximum.x <= other.maximum.x && maximum.y <= other.maximum.y && maximum.z <= other.maximum.z; } bool overlaps(const vec3& center, double radius) const { if(overlaps(center)) return true; vec3 axisDist; if(center.x < minimum.x) axisDist.x = minimum.x - center.x; else if(center.x > maximum.x) axisDist.x = maximum.x - center.x; if(axisDist.x > radius) return false; if(center.y < minimum.y) axisDist.y = minimum.y - center.y; else if(center.y > maximum.y) axisDist.y = maximum.y - center.y; if(axisDist.y > radius) return false; if(center.z < minimum.z) axisDist.z = minimum.z - center.z; else if(center.z > maximum.z) axisDist.z = maximum.z - center.z; if(axisDist.z > radius) return false; return axisDist.getLengthSQ() <= radius * radius; } bool overlaps(const AABBox& other) const { if( minimum.x > other.maximum.x || minimum.z > other.maximum.z || maximum.x < other.minimum.x || maximum.z < other.minimum.z || minimum.y > other.maximum.y || maximum.y < other.minimum.y ) return false; return true; } //Resets the bounding box to bound around a single point (0,0,0 by default) void reset(vec3 initialize = vec3(0,0,0)) { minimum = initialize; maximum = initialize; } void reset(const AABBox& initialize) { minimum = initialize.minimum; maximum = initialize.maximum; } void reset(const line3d& initialize) { minimum = initialize.start; maximum = initialize.end; fix(); } //Expands the bounding box to contain a point void addPoint(const vec3& point) { #define BBOX_POINTDIM(dim) if(point.dim < minimum.dim) minimum.dim = point.dim;\ else if(point.dim > maximum.dim) maximum.dim = point.dim; BBOX_POINTDIM(x); BBOX_POINTDIM(y); BBOX_POINTDIM(z); } void addBox(const AABBox& box) { #define BBOX_BOXDIM(dim) if(box.minimum.dim < minimum.dim) minimum.dim = box.minimum.dim;\ if(box.maximum.dim > maximum.dim) maximum.dim = box.maximum.dim; BBOX_BOXDIM(x); BBOX_BOXDIM(y); BBOX_BOXDIM(z); } void addLine(const line3d& line) { addPoint(line.start); addPoint(line.end); } //Flips any bounds where Minimum > Maximum void fix() { if(minimum.x > maximum.x) { T temp = maximum.x; maximum.x = minimum.x; minimum.x = temp; } if(minimum.y > maximum.y) { T temp = maximum.y; maximum.y = minimum.y; minimum.y = temp; } if(minimum.z > maximum.z) { T temp = maximum.z; maximum.z = minimum.z; minimum.z = temp; } } //Get a rectangle size after a projection vec3d getProjectedSize(const Matrix& transform) const { AABBox result; for(int i = 0; i < 8; ++i) { vec3d point; point.x = (i & 1) ? minimum.x : maximum.x; point.y = (i & 2) ? minimum.y : maximum.y; point.z = (i & 4) ? minimum.z : maximum.z; point = transform * point; if(i == 0) result.reset(point); else result.addPoint(point); } return result.getSize(); } }; typedef AABBox AABBoxd; typedef AABBox AABBoxf;