Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/AABox.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56#include <Jolt/Geometry/Triangle.h>7#include <Jolt/Geometry/IndexedTriangle.h>8#include <Jolt/Geometry/Plane.h>9#include <Jolt/Math/Mat44.h>1011JPH_NAMESPACE_BEGIN1213/// Axis aligned box14class [[nodiscard]] AABox15{16public:17JPH_OVERRIDE_NEW_DELETE1819/// Constructor20AABox() : mMin(Vec3::sReplicate(FLT_MAX)), mMax(Vec3::sReplicate(-FLT_MAX)) { }21AABox(Vec3Arg inMin, Vec3Arg inMax) : mMin(inMin), mMax(inMax) { }22AABox(DVec3Arg inMin, DVec3Arg inMax) : mMin(inMin.ToVec3RoundDown()), mMax(inMax.ToVec3RoundUp()) { }23AABox(Vec3Arg inCenter, float inRadius) : mMin(inCenter - Vec3::sReplicate(inRadius)), mMax(inCenter + Vec3::sReplicate(inRadius)) { }2425/// Create box from 2 points26static AABox sFromTwoPoints(Vec3Arg inP1, Vec3Arg inP2) { return AABox(Vec3::sMin(inP1, inP2), Vec3::sMax(inP1, inP2)); }2728/// Create box from indexed triangle29static AABox sFromTriangle(const VertexList &inVertices, const IndexedTriangle &inTriangle)30{31AABox box = sFromTwoPoints(Vec3(inVertices[inTriangle.mIdx[0]]), Vec3(inVertices[inTriangle.mIdx[1]]));32box.Encapsulate(Vec3(inVertices[inTriangle.mIdx[2]]));33return box;34}3536/// Get bounding box of size FLT_MAX37static AABox sBiggest()38{39/// Max half extent of AABox is 0.5 * FLT_MAX so that GetSize() remains finite40return AABox(Vec3::sReplicate(-0.5f * FLT_MAX), Vec3::sReplicate(0.5f * FLT_MAX));41}4243/// Comparison operators44bool operator == (const AABox &inRHS) const { return mMin == inRHS.mMin && mMax == inRHS.mMax; }45bool operator != (const AABox &inRHS) const { return mMin != inRHS.mMin || mMax != inRHS.mMax; }4647/// Reset the bounding box to an empty bounding box48void SetEmpty()49{50mMin = Vec3::sReplicate(FLT_MAX);51mMax = Vec3::sReplicate(-FLT_MAX);52}5354/// Check if the bounding box is valid (max >= min)55bool IsValid() const56{57return mMin.GetX() <= mMax.GetX() && mMin.GetY() <= mMax.GetY() && mMin.GetZ() <= mMax.GetZ();58}5960/// Encapsulate point in bounding box61void Encapsulate(Vec3Arg inPos)62{63mMin = Vec3::sMin(mMin, inPos);64mMax = Vec3::sMax(mMax, inPos);65}6667/// Encapsulate bounding box in bounding box68void Encapsulate(const AABox &inRHS)69{70mMin = Vec3::sMin(mMin, inRHS.mMin);71mMax = Vec3::sMax(mMax, inRHS.mMax);72}7374/// Encapsulate triangle in bounding box75void Encapsulate(const Triangle &inRHS)76{77Vec3 v = Vec3::sLoadFloat3Unsafe(inRHS.mV[0]);78Encapsulate(v);79v = Vec3::sLoadFloat3Unsafe(inRHS.mV[1]);80Encapsulate(v);81v = Vec3::sLoadFloat3Unsafe(inRHS.mV[2]);82Encapsulate(v);83}8485/// Encapsulate triangle in bounding box86void Encapsulate(const VertexList &inVertices, const IndexedTriangle &inTriangle)87{88for (uint32 idx : inTriangle.mIdx)89Encapsulate(Vec3(inVertices[idx]));90}9192/// Intersect this bounding box with inOther, returns the intersection93AABox Intersect(const AABox &inOther) const94{95return AABox(Vec3::sMax(mMin, inOther.mMin), Vec3::sMin(mMax, inOther.mMax));96}9798/// Make sure that each edge of the bounding box has a minimal length99void EnsureMinimalEdgeLength(float inMinEdgeLength)100{101Vec3 min_length = Vec3::sReplicate(inMinEdgeLength);102mMax = Vec3::sSelect(mMax, mMin + min_length, Vec3::sLess(mMax - mMin, min_length));103}104105/// Widen the box on both sides by inVector106void ExpandBy(Vec3Arg inVector)107{108mMin -= inVector;109mMax += inVector;110}111112/// Get center of bounding box113Vec3 GetCenter() const114{115return 0.5f * (mMin + mMax);116}117118/// Get extent of bounding box (half of the size)119Vec3 GetExtent() const120{121return 0.5f * (mMax - mMin);122}123124/// Get size of bounding box125Vec3 GetSize() const126{127return mMax - mMin;128}129130/// Get surface area of bounding box131float GetSurfaceArea() const132{133Vec3 extent = mMax - mMin;134return 2.0f * (extent.GetX() * extent.GetY() + extent.GetX() * extent.GetZ() + extent.GetY() * extent.GetZ());135}136137/// Get volume of bounding box138float GetVolume() const139{140Vec3 extent = mMax - mMin;141return extent.GetX() * extent.GetY() * extent.GetZ();142}143144/// Check if this box contains another box145bool Contains(const AABox &inOther) const146{147return UVec4::sAnd(Vec3::sLessOrEqual(mMin, inOther.mMin), Vec3::sGreaterOrEqual(mMax, inOther.mMax)).TestAllXYZTrue();148}149150/// Check if this box contains a point151bool Contains(Vec3Arg inOther) const152{153return UVec4::sAnd(Vec3::sLessOrEqual(mMin, inOther), Vec3::sGreaterOrEqual(mMax, inOther)).TestAllXYZTrue();154}155156/// Check if this box contains a point157bool Contains(DVec3Arg inOther) const158{159return Contains(Vec3(inOther));160}161162/// Check if this box overlaps with another box163bool Overlaps(const AABox &inOther) const164{165return !UVec4::sOr(Vec3::sGreater(mMin, inOther.mMax), Vec3::sLess(mMax, inOther.mMin)).TestAnyXYZTrue();166}167168/// Check if this box overlaps with a plane169bool Overlaps(const Plane &inPlane) const170{171Vec3 normal = inPlane.GetNormal();172float dist_normal = inPlane.SignedDistance(GetSupport(normal));173float dist_min_normal = inPlane.SignedDistance(GetSupport(-normal));174return dist_normal * dist_min_normal <= 0.0f; // If both support points are on the same side of the plane we don't overlap175}176177/// Translate bounding box178void Translate(Vec3Arg inTranslation)179{180mMin += inTranslation;181mMax += inTranslation;182}183184/// Translate bounding box185void Translate(DVec3Arg inTranslation)186{187mMin = (DVec3(mMin) + inTranslation).ToVec3RoundDown();188mMax = (DVec3(mMax) + inTranslation).ToVec3RoundUp();189}190191/// Transform bounding box192AABox Transformed(Mat44Arg inMatrix) const193{194// Start with the translation of the matrix195Vec3 new_min, new_max;196new_min = new_max = inMatrix.GetTranslation();197198// Now find the extreme points by considering the product of the min and max with each column of inMatrix199for (int c = 0; c < 3; ++c)200{201Vec3 col = inMatrix.GetColumn3(c);202203Vec3 a = col * mMin[c];204Vec3 b = col * mMax[c];205206new_min += Vec3::sMin(a, b);207new_max += Vec3::sMax(a, b);208}209210// Return the new bounding box211return AABox(new_min, new_max);212}213214/// Transform bounding box215AABox Transformed(DMat44Arg inMatrix) const216{217AABox transformed = Transformed(inMatrix.GetRotation());218transformed.Translate(inMatrix.GetTranslation());219return transformed;220}221222/// Scale this bounding box, can handle non-uniform and negative scaling223AABox Scaled(Vec3Arg inScale) const224{225return AABox::sFromTwoPoints(mMin * inScale, mMax * inScale);226}227228/// Calculate the support vector for this convex shape.229Vec3 GetSupport(Vec3Arg inDirection) const230{231return Vec3::sSelect(mMax, mMin, Vec3::sLess(inDirection, Vec3::sZero()));232}233234/// Get the vertices of the face that faces inDirection the most235template <class VERTEX_ARRAY>236void GetSupportingFace(Vec3Arg inDirection, VERTEX_ARRAY &outVertices) const237{238outVertices.resize(4);239240int axis = inDirection.Abs().GetHighestComponentIndex();241if (inDirection[axis] < 0.0f)242{243switch (axis)244{245case 0:246outVertices[0] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());247outVertices[1] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());248outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());249outVertices[3] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());250break;251252case 1:253outVertices[0] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());254outVertices[1] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());255outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());256outVertices[3] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());257break;258259case 2:260outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());261outVertices[1] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());262outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMax.GetZ());263outVertices[3] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());264break;265}266}267else268{269switch (axis)270{271case 0:272outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());273outVertices[1] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());274outVertices[2] = Vec3(mMin.GetX(), mMax.GetY(), mMax.GetZ());275outVertices[3] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());276break;277278case 1:279outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());280outVertices[1] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());281outVertices[2] = Vec3(mMax.GetX(), mMin.GetY(), mMax.GetZ());282outVertices[3] = Vec3(mMin.GetX(), mMin.GetY(), mMax.GetZ());283break;284285case 2:286outVertices[0] = Vec3(mMin.GetX(), mMin.GetY(), mMin.GetZ());287outVertices[1] = Vec3(mMin.GetX(), mMax.GetY(), mMin.GetZ());288outVertices[2] = Vec3(mMax.GetX(), mMax.GetY(), mMin.GetZ());289outVertices[3] = Vec3(mMax.GetX(), mMin.GetY(), mMin.GetZ());290break;291}292}293}294295/// Get the closest point on or in this box to inPoint296Vec3 GetClosestPoint(Vec3Arg inPoint) const297{298return Vec3::sMin(Vec3::sMax(inPoint, mMin), mMax);299}300301/// Get the squared distance between inPoint and this box (will be 0 if in Point is inside the box)302inline float GetSqDistanceTo(Vec3Arg inPoint) const303{304return (GetClosestPoint(inPoint) - inPoint).LengthSq();305}306307/// Bounding box min and max308Vec3 mMin;309Vec3 mMax;310};311312JPH_NAMESPACE_END313314315