1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

Implementa BoundingBox

This commit is contained in:
Danilo 2024-05-17 16:15:48 -03:00
parent 887dbe7b49
commit 9cdd69562d
2 changed files with 253 additions and 6 deletions

View File

@ -196,4 +196,87 @@ namespace xna {
}
return containmentType;
}
std::optional<float> BoundingBox::Intersects(Ray const& ray) const {
float num1 = 0.0f;
float num2 = FloatMaxValue;
if (std::abs(ray.Direction.X) < 9.9999999747524271E-07)
{
if (ray.Position.X < Min.X || ray.Position.X > Max.X)
return {};
}
else
{
const auto num3 = 1.0f / ray.Direction.X;
auto num4 = (Min.X - ray.Position.X) * num3;
auto num5 = (Max.X - ray.Position.X) * num3;
if (num4 > num5)
{
float num6 = num4;
num4 = num5;
num5 = num6;
}
num1 = MathHelper::Max(num4, num1);
num2 = MathHelper::Min(num5, num2);
if (num1 > num2)
return {};
}
if (std::abs(ray.Direction.Y) < 9.9999999747524271E-07)
{
if (ray.Position.Y < Min.Y || ray.Position.Y > Max.Y)
return {};
}
else
{
const auto num7 = 1.0f / ray.Direction.Y;
auto num8 = (Min.Y - ray.Position.Y) * num7;
auto num9 = (Max.Y - ray.Position.Y) * num7;
if (num8 > num9)
{
float num10 = num8;
num8 = num9;
num9 = num10;
}
num1 = MathHelper::Max(num8, num1);
num2 = MathHelper::Min(num9, num2);
if (num1 > num2)
return {};
}
if (std::abs(ray.Direction.Z) < 9.9999999747524271E-07)
{
if (ray.Position.Z < Min.Z || ray.Position.Z > Max.Z)
return {};
}
else
{
const auto num11 = 1.0f / ray.Direction.Z;
auto num12 = (Min.Z - ray.Position.Z) * num11;
auto num13 = (Max.Z - ray.Position.Z) * num11;
if (num12 > num13)
{
float num14 = num12;
num12 = num13;
num13 = num14;
}
num1 = MathHelper::Max(num12, num1);
const auto num15 = MathHelper::Min(num13, num2);
if (num1 > num15)
return {};
}
return num1;
}
ContainmentType BoundingBox::Contains(BoundingFrustum& frustum) const {
if (!frustum.Intersects(*this))
return ContainmentType::Disjoint;
for (size_t i = 0; i < frustum.CornerCount; ++i) {
const auto corner = frustum[i];
if (Contains(corner) == ContainmentType::Disjoint)
return ContainmentType::Intersects;
}
return ContainmentType::Contains;
}
}

View File

@ -17,6 +17,11 @@ namespace xna {
inline static constexpr int CornerCount = 8;
inline static constexpr int PlaneCount = 6;
constexpr BoundingFrustum() = default;
constexpr BoundingFrustum(Matrix const& matrix) {
SetMatrix(matrix);
}
Plane Near() { return planes[0]; }
Plane Far() { return planes[1]; }
Plane Left() { return planes[2]; }
@ -28,6 +33,13 @@ namespace xna {
return matrix == other.matrix;
}
constexpr Vector3 operator[](size_t index) const {
if (index >= CornerCount)
index = CornerCount - 1;
return corners[index];
}
constexpr void GetCorners(std::vector<Vector3>& destination) const;
constexpr Matrix GetMatrix() const { return matrix; }
constexpr void SetMatrix(Matrix const& value);
@ -40,11 +52,11 @@ namespace xna {
ContainmentType Contains(BoundingFrustum const& box);
constexpr ContainmentType Contains(Vector3 const& point) const;
constexpr ContainmentType Contains(BoundingSphere const& box) const;
constexpr void SupportMapping(Vector3 const& v, Vector3& result) const;
constexpr void SupportMapping(Vector3 const& v, Vector3& result) const;
private:
std::vector<Plane> planes{ 6 };
std::vector<Vector3> corners{ 8 };
std::vector<Plane> planes{ 6 };
Matrix matrix{ Matrix::Identity() };
Gjk gjk{};
@ -54,16 +66,37 @@ namespace xna {
};
struct BoundingBox {
inline static constexpr int CornerCount = 8;
Vector3 Min{};
Vector3 Max{};
constexpr PlaneIntersectionType Intersects(Plane const& plane) const {
return PlaneIntersectionType::Intersecting;
constexpr BoundingBox() = default;
constexpr BoundingBox(Vector3 const& min, Vector3 const& max):
Min(min), Max(max){}
constexpr bool operator==(BoundingBox const& other) const {
return Min == other.Min && Max == other.Max;
}
void SupportMapping(Vector3 const& v, Vector3& result) const {
constexpr void GetCorners(std::vector<Vector3>& corners) const;
}
static constexpr BoundingBox CreateMerged(BoundingBox const& original, BoundingBox const& additional);
static constexpr BoundingBox CreateFromSphere(BoundingSphere const& sphere);
static constexpr BoundingBox CreateFromPoints(std::vector<Vector3> const& points);
constexpr bool Intersects(BoundingBox const& box) const;
bool Intersects(BoundingFrustum& frustum) const;
constexpr PlaneIntersectionType Intersects(Plane const& plane) const;
std::optional<float> Intersects(Ray const& ray) const;
constexpr bool Intersects(BoundingSphere const& sphere) const;
constexpr ContainmentType Contains(BoundingBox const& box) const;
ContainmentType Contains(BoundingFrustum& frustum) const;
constexpr ContainmentType Contains(Vector3 const& point) const;
constexpr ContainmentType Contains(BoundingSphere const& sphere) const;
constexpr void SupportMapping(Vector3 const& v, Vector3& result) const;
};
struct BoundingSphere {
@ -234,6 +267,137 @@ namespace xna {
corners[5] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
corners[6] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2);
}
constexpr void BoundingBox::GetCorners(std::vector<Vector3>& corners) const {
if (corners.size() < 8)
corners.resize(CornerCount);
corners[0].X = Min.X;
corners[0].Y = Max.Y;
corners[0].Z = Max.Z;
corners[1].X = Max.X;
corners[1].Y = Max.Y;
corners[1].Z = Max.Z;
corners[2].X = Max.X;
corners[2].Y = Min.Y;
corners[2].Z = Max.Z;
corners[3].X = Min.X;
corners[3].Y = Min.Y;
corners[3].Z = Max.Z;
corners[4].X = Min.X;
corners[4].Y = Max.Y;
corners[4].Z = Min.Z;
corners[5].X = Max.X;
corners[5].Y = Max.Y;
corners[5].Z = Min.Z;
corners[6].X = Max.X;
corners[6].Y = Min.Y;
corners[6].Z = Min.Z;
corners[7].X = Min.X;
corners[7].Y = Min.Y;
corners[7].Z = Min.Z;
}
constexpr BoundingBox BoundingBox::CreateMerged(BoundingBox const& original, BoundingBox const& additional) {
BoundingBox merged;
merged.Min = Vector3::Min(original.Min, additional.Min);
merged.Max = Vector3::Max(original.Max, additional.Max);
return merged;
}
constexpr BoundingBox BoundingBox::CreateFromSphere(BoundingSphere const& sphere) {
BoundingBox fromSphere;
fromSphere.Min.X = sphere.Center.X - sphere.Radius;
fromSphere.Min.Y = sphere.Center.Y - sphere.Radius;
fromSphere.Min.Z = sphere.Center.Z - sphere.Radius;
fromSphere.Max.X = sphere.Center.X + sphere.Radius;
fromSphere.Max.Y = sphere.Center.Y + sphere.Radius;
fromSphere.Max.Z = sphere.Center.Z + sphere.Radius;
return fromSphere;
}
constexpr BoundingBox BoundingBox::CreateFromPoints(std::vector<Vector3> const& points) {
Vector3 result1 = Vector3(FloatMaxValue);
Vector3 result2 = Vector3(FloatMinValue);
for (size_t i = 0; i < points.size(); ++i) {
const auto& point = points[i];
result1 = Vector3::Min(result1, point);
result2 = Vector3::Max(result2, point);
}
return BoundingBox(result1, result2);
}
constexpr bool BoundingBox::Intersects(BoundingBox const& box) const {
return Max.X >= box.Min.X
&& Min.X <= box.Max.X
&& Max.Y >= box.Min.Y
&& Min.Y <= box.Max.Y
&& Max.Z >= box.Min.Z
&& Min.Z <= box.Max.Z;
}
inline bool BoundingBox::Intersects(BoundingFrustum& frustum) const {
return frustum.Intersects(*this);
}
constexpr PlaneIntersectionType BoundingBox::Intersects(Plane const& plane) const {
Vector3 vector3_1;
vector3_1.X = plane.Normal.X >= 0.0 ? Min.X : Max.X;
vector3_1.Y = plane.Normal.Y >= 0.0 ? Min.Y : Max.Y;
vector3_1.Z = plane.Normal.Z >= 0.0 ? Min.Z : Max.Z;
Vector3 vector3_2;
vector3_2.X = plane.Normal.X >= 0.0 ? Max.X : Min.X;
vector3_2.Y = plane.Normal.Y >= 0.0 ? Max.Y : Min.Y;
vector3_2.Z = plane.Normal.Z >= 0.0 ? Max.Z : Min.Z;
if (plane.Normal.X * vector3_1.X + plane.Normal.Y * vector3_1.Y + plane.Normal.Z * vector3_1.Z + plane.D > 0.0)
return PlaneIntersectionType::Front;
return plane.Normal.X * vector3_2.X + plane.Normal.Y * vector3_2.Y + plane.Normal.Z * vector3_2.Z + plane.D < 0.0
? PlaneIntersectionType::Back
: PlaneIntersectionType::Intersecting;
}
constexpr bool BoundingBox::Intersects(BoundingSphere const& sphere) const {
const auto result1 = Vector3::Clamp(sphere.Center, Min, Max);
const auto result2 = Vector3::DistanceSquared(sphere.Center, result1);
return result2 <= sphere.Radius * sphere.Radius;
}
constexpr ContainmentType BoundingBox::Contains(BoundingBox const& box) const {
if (Max.X < box.Min.X || Min.X > box.Max.X || Max.Y < box.Min.Y || Min.Y > box.Max.Y || Max.Z < box.Min.Z || Min.Z > box.Max.Z)
return ContainmentType::Disjoint;
return Min.X > box.Min.X || box.Max.X > Max.X || Min.Y > box.Min.Y || box.Max.Y > Max.Y || Min.Z > box.Min.Z || box.Max.Z > Max.Z
? ContainmentType::Intersects
: ContainmentType::Contains;
}
constexpr ContainmentType BoundingBox::Contains(Vector3 const& point) const {
return Min.X > point.X || point.X > Max.X || Min.Y > point.Y || point.Y > Max.Y || Min.Z > point.Z || point.Z > Max.Z
? ContainmentType::Disjoint
: ContainmentType::Contains;
}
constexpr ContainmentType BoundingBox::Contains(BoundingSphere const& sphere) const {
Vector3 result1 = Vector3::Clamp(sphere.Center, Min, Max);
float result2 = Vector3::DistanceSquared(sphere.Center, result1);
float radius = sphere.Radius;
if (result2 > radius * radius)
return ContainmentType::Disjoint;
return Min.X + radius > sphere.Center.X || sphere.Center.X > Max.X - radius || Max.X - Min.X <= radius || Min.Y + radius > sphere.Center.Y || sphere.Center.Y > Max.Y - radius || Max.Y - Min.Y <= radius || Min.Z + radius > sphere.Center.Z || sphere.Center.Z > Max.Z - radius || Max.X - Min.X <= radius
? ContainmentType::Intersects
: ContainmentType::Contains;
}
constexpr void BoundingBox::SupportMapping(Vector3 const& v, Vector3& result) const {
result.X = v.X >= 0.0 ? Max.X : Min.X;
result.Y = v.Y >= 0.0 ? Max.Y : Min.Y;
result.Z = v.Z >= 0.0 ? Max.Z : Min.Z;
}
}
#endif