mirror of
https://github.com/borgesdan/xn65
synced 2024-12-29 21:54:47 +01:00
Implementa BoundingBox
This commit is contained in:
parent
887dbe7b49
commit
9cdd69562d
@ -196,4 +196,87 @@ namespace xna {
|
|||||||
}
|
}
|
||||||
return containmentType;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,6 +17,11 @@ namespace xna {
|
|||||||
inline static constexpr int CornerCount = 8;
|
inline static constexpr int CornerCount = 8;
|
||||||
inline static constexpr int PlaneCount = 6;
|
inline static constexpr int PlaneCount = 6;
|
||||||
|
|
||||||
|
constexpr BoundingFrustum() = default;
|
||||||
|
constexpr BoundingFrustum(Matrix const& matrix) {
|
||||||
|
SetMatrix(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
Plane Near() { return planes[0]; }
|
Plane Near() { return planes[0]; }
|
||||||
Plane Far() { return planes[1]; }
|
Plane Far() { return planes[1]; }
|
||||||
Plane Left() { return planes[2]; }
|
Plane Left() { return planes[2]; }
|
||||||
@ -28,6 +33,13 @@ namespace xna {
|
|||||||
return matrix == other.matrix;
|
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 void GetCorners(std::vector<Vector3>& destination) const;
|
||||||
constexpr Matrix GetMatrix() const { return matrix; }
|
constexpr Matrix GetMatrix() const { return matrix; }
|
||||||
constexpr void SetMatrix(Matrix const& value);
|
constexpr void SetMatrix(Matrix const& value);
|
||||||
@ -40,11 +52,11 @@ namespace xna {
|
|||||||
ContainmentType Contains(BoundingFrustum const& box);
|
ContainmentType Contains(BoundingFrustum const& box);
|
||||||
constexpr ContainmentType Contains(Vector3 const& point) const;
|
constexpr ContainmentType Contains(Vector3 const& point) const;
|
||||||
constexpr ContainmentType Contains(BoundingSphere const& box) 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:
|
private:
|
||||||
std::vector<Plane> planes{ 6 };
|
|
||||||
std::vector<Vector3> corners{ 8 };
|
std::vector<Vector3> corners{ 8 };
|
||||||
|
std::vector<Plane> planes{ 6 };
|
||||||
Matrix matrix{ Matrix::Identity() };
|
Matrix matrix{ Matrix::Identity() };
|
||||||
Gjk gjk{};
|
Gjk gjk{};
|
||||||
|
|
||||||
@ -54,16 +66,37 @@ namespace xna {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct BoundingBox {
|
struct BoundingBox {
|
||||||
|
inline static constexpr int CornerCount = 8;
|
||||||
|
|
||||||
Vector3 Min{};
|
Vector3 Min{};
|
||||||
Vector3 Max{};
|
Vector3 Max{};
|
||||||
|
|
||||||
constexpr PlaneIntersectionType Intersects(Plane const& plane) const {
|
constexpr BoundingBox() = default;
|
||||||
return PlaneIntersectionType::Intersecting;
|
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 {
|
struct BoundingSphere {
|
||||||
@ -234,6 +267,137 @@ namespace xna {
|
|||||||
corners[5] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
|
corners[5] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
|
||||||
corners[6] = BoundingFrustum::ComputeIntersection(planes[5], 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
|
#endif
|
Loading…
x
Reference in New Issue
Block a user