From cb5e6b4f99a814c62fdbcffbfced46a5f2ec5fc2 Mon Sep 17 00:00:00 2001 From: josh Date: Fri, 2 Feb 2024 15:59:05 -0500 Subject: [PATCH] Implement AABB::CornerPoint/ExtremePoint/PointOnEdge/FaceCenterPoint/FacePoint --- include/J3ML/Geometry/AABB.h | 77 +++++-------------- src/J3ML/Geometry/AABB.cpp | 142 ++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 60 deletions(-) diff --git a/include/J3ML/Geometry/AABB.h b/include/J3ML/Geometry/AABB.h index ced9fd0..ee773f7 100644 --- a/include/J3ML/Geometry/AABB.h +++ b/include/J3ML/Geometry/AABB.h @@ -44,71 +44,32 @@ namespace J3ML::Geometry static int NumFaces() { return 6; } static int NumEdges() { return 12;} static int NumVertices() { return 8;} - - static AABB FromCenterAndSize(const Vector3& center, const Vector3& size) - { - Vector3 halfSize = size * 0.5f; - return {center - halfSize, center + halfSize}; - } - float MinX() const { return minPoint.x; } - float MinY() const { return minPoint.y; } - float MinZ() const { return minPoint.z; } - - float MaxX() const { return maxPoint.x; } - float MaxY() const { return maxPoint.y; } - float MaxZ() const { return maxPoint.z; } - - + static AABB FromCenterAndSize(const Vector3& center, const Vector3& size); + float MinX() const; + float MinY() const; + float MinZ() const; + float MaxX() const; + float MaxY() const; + float MaxZ() const; /// Returns the smallest sphere that contains this AABB. /// This function computes the minimal volume sphere that contains all the points inside this AABB - Sphere MinimalEnclosingSphere() const - { - return Sphere(Centroid(), Size().Length()*0.5f); - } - - Vector3 HalfSize() const { - return this->Size()/2.f; - } - -// Returns the largest sphere that can fit inside this AABB - // This function computes the largest sphere that can fit inside this AABB. - Sphere MaximalContainedSphere() const - { - Vector3 halfSize = HalfSize(); - return Sphere(Centroid(), std::min(halfSize.x, std::min(halfSize.y, halfSize.z))); - } - bool IsFinite() const - { - return minPoint.IsFinite() && maxPoint.IsFinite(); - } - Vector3 Centroid() const - { - return (minPoint+maxPoint) * 0.5f; - } - Vector3 Size() const - { - return this->maxPoint - this->minPoint; - } + Sphere MinimalEnclosingSphere() const; + Vector3 HalfSize() const; + /// Returns the largest sphere that can fit inside this AABB + /// This function computes the largest sphere that can fit inside this AABB. + Sphere MaximalContainedSphere() const; + bool IsFinite() const; + Vector3 Centroid() const; + Vector3 Size() const; // Quickly returns an arbitrary point inside this AABB Vector3 AnyPointFast() const; - Vector3 PointInside(float x, float y, float z) const - { - Vector3 d = maxPoint - minPoint; - return minPoint + d.Mul({x, y, z}); - } + Vector3 PointInside(float x, float y, float z) const; // Returns an edge of this AABB - LineSegment Edge(int edgeIndex) const - { - switch(edgeIndex) - { - default: - case 0: return LineSegment(minPoint, {minPoint.x, minPoint.y, maxPoint.z}); - } - } - Vector3 CornerPoint(int cornerIndex); + LineSegment Edge(int edgeIndex) const; + Vector3 CornerPoint(int cornerIndex) const; Vector3 ExtremePoint(const Vector3& direction) const; - Vector3 ExtremePoint(const Vector3& direction, float projectionDistance); + Vector3 ExtremePoint(const Vector3& direction, float &projectionDistance); Vector3 PointOnEdge(int edgeIndex, float u) const; Vector3 FaceCenterPoint(int faceIndex) const; Vector3 FacePoint(int faceIndex, float u, float v) const; diff --git a/src/J3ML/Geometry/AABB.cpp b/src/J3ML/Geometry/AABB.cpp index dd28311..400be19 100644 --- a/src/J3ML/Geometry/AABB.cpp +++ b/src/J3ML/Geometry/AABB.cpp @@ -1,5 +1,143 @@ #include -namespace Geometry { +namespace J3ML::Geometry { -} \ No newline at end of file + AABB AABB::FromCenterAndSize(const J3ML::Geometry::Vector3 ¢er, const J3ML::Geometry::Vector3 &size) { + Vector3 halfSize = size * 0.5f; + return {center - halfSize, center + halfSize}; + } + + float AABB::MinX() const { return minPoint.x; } + + float AABB::MinY() const { return minPoint.y; } + + float AABB::MinZ() const { return minPoint.z; } + + float AABB::MaxX() const { return maxPoint.x; } + + float AABB::MaxY() const { return maxPoint.y; } + + float AABB::MaxZ() const { return maxPoint.z; } + + Sphere AABB::MinimalEnclosingSphere() const { + return Sphere(Centroid(), Size().Length()*0.5f); + } + + Vector3 AABB::HalfSize() const { + return this->Size()/2.f; + } + + Sphere AABB::MaximalContainedSphere() const { + Vector3 halfSize = HalfSize(); + return Sphere(Centroid(), std::min(halfSize.x, std::min(halfSize.y, halfSize.z))); + } + + bool AABB::IsFinite() const { + return minPoint.IsFinite() && maxPoint.IsFinite(); + } + + Vector3 AABB::Centroid() const { + return (minPoint+maxPoint) * 0.5f; + } + + Vector3 AABB::Size() const { + return this->maxPoint - this->minPoint; + } + + Vector3 AABB::PointInside(float x, float y, float z) const { + Vector3 d = maxPoint - minPoint; + return minPoint + d.Mul({x, y, z}); + } + + LineSegment AABB::Edge(int edgeIndex) const { + switch(edgeIndex) + { + default: + case 0: return LineSegment(minPoint, {minPoint.x, minPoint.y, maxPoint.z}); + } + } + + Vector3 AABB::CornerPoint(int cornerIndex) const { + // TODO: assert(0 <= cornerIndex && cornerIndex <= 7) + switch(cornerIndex) + { + default: + case 0: return minPoint; + case 1: return {minPoint.x, minPoint.y, maxPoint.z}; + case 2: return {minPoint.x, maxPoint.y, minPoint.z}; + case 3: return {minPoint.x, maxPoint.y, maxPoint.z}; + case 4: return {maxPoint.x, minPoint.y, minPoint.z}; + case 5: return {maxPoint.x, minPoint.y, maxPoint.z}; + case 6: return {maxPoint.x, maxPoint.y, minPoint.z}; + case 7: return maxPoint; + } + } + + Vector3 AABB::ExtremePoint(const Vector3 &direction) const { + return {direction.x >= 0.f ? maxPoint.x : minPoint.x, + direction.y >= 0.f ? maxPoint.y : minPoint.y, + direction.z >= 0.f ? maxPoint.z : minPoint.z}; + } + + Vector3 AABB::ExtremePoint(const Vector3 &direction, float &projectionDistance) { + auto extremePt = ExtremePoint(direction); + projectionDistance = extremePt.Dot(direction); + return extremePt; + } + + Vector3 AABB::PointOnEdge(int edgeIndex, float u) const { + // TODO: assert(0 <= edgeIndex && edgeIndex <= 11); + // TODO: assert(0 <= u && u < 1.f); + + auto d = maxPoint - minPoint; + switch(edgeIndex) { + default: + case 0: return {minPoint.x, minPoint.y, minPoint.z + u * d.z}; + case 1: return {minPoint.x, maxPoint.y, minPoint.z + u * d.z}; + case 2: return {maxPoint.x, minPoint.y, minPoint.z + u * d.z}; + case 3: return {maxPoint.x, maxPoint.y, minPoint.z + u * d.z}; + + case 4: return {minPoint.x, minPoint.y + u * d.y, minPoint.z}; + case 5: return {maxPoint.x, minPoint.y + u * d.y, minPoint.z}; + case 6: return {minPoint.x, minPoint.y + u * d.y, maxPoint.z}; + case 7: return {maxPoint.x, minPoint.y + u * d.y, maxPoint.z}; + + case 8: return {minPoint.x + u * d.x, minPoint.y, minPoint.z}; + case 9: return {minPoint.x + u * d.x, minPoint.y, maxPoint.z}; + case 10:return {minPoint.x + u * d.x, maxPoint.y, minPoint.z}; + case 11:return {minPoint.x + u * d.x, maxPoint.y, maxPoint.z}; + } + } + + Vector3 AABB::FaceCenterPoint(int faceIndex) const { + // TODO: assert(0 <= faceIndex && faceIndex <= 5) + auto center = (minPoint + maxPoint) * 0.5f; + switch (faceIndex) { + default: + case 0: return {minPoint.x, center.y, center.z}; + case 1: return {maxPoint.x, center.y, center.z}; + case 2: return {center.x, minPoint.y, center.z}; + case 3: return {center.x, maxPoint.y, center.z}; + case 4: return {center.x, center.y, minPoint.z}; + case 5: return {center.x, center.y, maxPoint.z}; + } + } + + Vector3 AABB::FacePoint(int faceIndex, float u, float v) const { + // TODO: assert(0 <= faceIndex && faceIndex <= 5); + // TODO: assert(0 <= u && u <= 1.f); + // TODO: assert(0 <= v && v <= 1.f); + + auto d = maxPoint - minPoint; + switch(faceIndex) + { + default: // For release builds where assume() is disabled, return always the first option if out-of-bounds. + case 0: return {minPoint.x, minPoint.y + u * d.y, minPoint.z + v * d.z}; + case 1: return {maxPoint.x, minPoint.y + u * d.y, minPoint.z + v * d.z}; + case 2: return {minPoint.x + u * d.x, minPoint.y, minPoint.z + v * d.z}; + case 3: return {minPoint.x + u * d.x, maxPoint.y, minPoint.z + v * d.z}; + case 4: return {minPoint.x + u * d.x, minPoint.y + v * d.y, minPoint.z}; + case 5: return {minPoint.x + u * d.x, minPoint.y + v * d.y, maxPoint.z}; + } + } +}