mirror of
https://github.com/borgesdan/xn65
synced 2024-12-29 21:54:47 +01:00
Implementa BoundingFrustum
This commit is contained in:
parent
fd32d56715
commit
887dbe7b49
@ -47,7 +47,11 @@ add_executable (xna WIN32
|
||||
"platform/init-dx.cpp"
|
||||
"game/servicecontainer.cpp"
|
||||
"common/color.cpp"
|
||||
"common/math.cpp" "common/quaternion.cpp")
|
||||
"common/math.cpp"
|
||||
"common/quaternion.cpp"
|
||||
"common/collision.cpp"
|
||||
"common/gjk.cpp"
|
||||
)
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
set_property(TARGET xna PROPERTY CXX_STANDARD 20)
|
||||
|
199
framework/common/collision.cpp
Normal file
199
framework/common/collision.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
#include "common/collision.hpp"
|
||||
|
||||
namespace xna {
|
||||
bool BoundingFrustum::Intersects(BoundingBox const& box) {
|
||||
gjk.Reset();
|
||||
Vector3 result1 = Vector3::Subtract(corners[0], box.Min);
|
||||
|
||||
if (result1.LengthSquared() < 9.9999997473787516E-06)
|
||||
result1 = Vector3::Subtract(corners[0], box.Max);
|
||||
|
||||
auto num1 = FloatMaxValue;
|
||||
float num2 = 0;
|
||||
do
|
||||
{
|
||||
Vector3 v;
|
||||
v.X = -result1.X;
|
||||
v.Y = -result1.Y;
|
||||
v.Z = -result1.Z;
|
||||
Vector3 result2;
|
||||
SupportMapping(v, result2);
|
||||
Vector3 result3;
|
||||
box.SupportMapping(result1, result3);
|
||||
Vector3 result4 = Vector3::Subtract(result2, result3);
|
||||
|
||||
if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0)
|
||||
return false;
|
||||
|
||||
gjk.AddSupportPoint(result4);
|
||||
result1 = gjk.ClosestPoint();
|
||||
float num3 = num1;
|
||||
num1 = result1.LengthSquared();
|
||||
|
||||
if (num3 - num1 <= 9.9999997473787516E-06 * num3)
|
||||
return false;
|
||||
|
||||
num2 = 4E-05f * gjk.MaxLengthSquared();
|
||||
} while (!gjk.FullSimplex() && num1 >= num2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<float> BoundingFrustum::Intersects(Ray const& ray) const {
|
||||
auto result1 = Contains(ray.Position);
|
||||
|
||||
if (result1 == ContainmentType::Contains)
|
||||
return 0.0F;
|
||||
|
||||
auto num1 = FloatMinValue;
|
||||
auto num2 = FloatMaxValue;
|
||||
|
||||
for (size_t i = 0; i < planes.size(); ++i) {
|
||||
const auto& plane = planes[i];
|
||||
|
||||
Vector3 normal = plane.Normal;
|
||||
const auto result2 = Vector3::Dot(ray.Direction, normal);
|
||||
float result3 = Vector3::Dot(ray.Position, normal);
|
||||
|
||||
result3 += plane.D;
|
||||
|
||||
if (std::abs(static_cast<double>(result2)) < 9.9999997473787516E-06)
|
||||
{
|
||||
if (result3 > 0.0)
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto num3 = -result3 / result2;
|
||||
if (result2 < 0.0)
|
||||
{
|
||||
if (num3 > num2)
|
||||
return {};
|
||||
if (num3 > num1)
|
||||
num1 = num3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num3 < num1)
|
||||
return {};
|
||||
if (num3 < num2)
|
||||
num2 = num3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto num4 = num1 >= 0.0F ? num1 : num2;
|
||||
|
||||
if (num4 < 0.0)
|
||||
return{};
|
||||
|
||||
return num4;
|
||||
}
|
||||
|
||||
bool BoundingFrustum::Intersects(BoundingSphere const& sphere) {
|
||||
gjk.Reset();
|
||||
auto result1 = Vector3::Subtract(corners[0], sphere.Center);
|
||||
|
||||
if (result1.LengthSquared() < 9.9999997473787516E-06)
|
||||
result1 = Vector3::UnitX();
|
||||
|
||||
auto num1 = FloatMaxValue;
|
||||
auto num2 = 0.0F;
|
||||
|
||||
do
|
||||
{
|
||||
Vector3 v;
|
||||
v.X = -result1.X;
|
||||
v.Y = -result1.Y;
|
||||
v.Z = -result1.Z;
|
||||
|
||||
Vector3 result2;
|
||||
SupportMapping(v, result2);
|
||||
|
||||
Vector3 result3;
|
||||
sphere.SupportMapping(result1, result3);
|
||||
|
||||
Vector3 result4 = Vector3::Subtract(result2, result3);
|
||||
|
||||
if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0)
|
||||
return false;
|
||||
|
||||
gjk.AddSupportPoint(result4);
|
||||
|
||||
result1 = gjk.ClosestPoint();
|
||||
|
||||
auto num3 = num1;
|
||||
|
||||
num1 = result1.LengthSquared();
|
||||
|
||||
if (num3 - num1 <= 9.9999997473787516E-06 * num3)
|
||||
return false;
|
||||
|
||||
num2 = 4E-05f * gjk.MaxLengthSquared();
|
||||
|
||||
} while (!gjk.FullSimplex() && num1 >= num2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BoundingFrustum::Intersects(BoundingFrustum const& frustum) {
|
||||
gjk.Reset();
|
||||
Vector3 result1 = Vector3::Subtract(corners[0], frustum.corners[0]);
|
||||
|
||||
if (result1.LengthSquared() < 9.9999997473787516E-06)
|
||||
result1 = Vector3::Subtract(corners[0], frustum.corners[1]);
|
||||
|
||||
float num1 = FloatMaxValue;
|
||||
float num2 = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Vector3 v;
|
||||
v.X = -result1.X;
|
||||
v.Y = -result1.Y;
|
||||
v.Z = -result1.Z;
|
||||
|
||||
Vector3 result2;
|
||||
SupportMapping(v, result2);
|
||||
|
||||
Vector3 result3;
|
||||
frustum.SupportMapping(result1, result3);
|
||||
|
||||
const auto result4 = Vector3::Subtract(result2, result3);
|
||||
|
||||
if (result1.X * result4.X + result1.Y * result4.Y + result1.Z * result4.Z > 0.0)
|
||||
return false;
|
||||
|
||||
gjk.AddSupportPoint(result4);
|
||||
|
||||
result1 = gjk.ClosestPoint();
|
||||
|
||||
const auto num3 = num1;
|
||||
|
||||
num1 = result1.LengthSquared();
|
||||
num2 = 4E-05f * gjk.MaxLengthSquared();
|
||||
|
||||
if (num3 - num1 <= 9.9999997473787516E-06 * num3)
|
||||
return false;
|
||||
|
||||
} while (!gjk.FullSimplex() && num1 >= num2);
|
||||
return true;
|
||||
}
|
||||
|
||||
ContainmentType BoundingFrustum::Contains(BoundingFrustum const& frustum) {
|
||||
ContainmentType containmentType = ContainmentType::Disjoint;
|
||||
|
||||
if (Intersects(frustum)) {
|
||||
containmentType = ContainmentType::Contains;
|
||||
|
||||
for (size_t index = 0; index < corners.size(); ++index) {
|
||||
if (Contains(frustum.corners[index]) == ContainmentType::Disjoint)
|
||||
{
|
||||
containmentType = ContainmentType::Intersects;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return containmentType;
|
||||
}
|
||||
}
|
104
framework/common/gjk.cpp
Normal file
104
framework/common/gjk.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include "common/gjk.hpp"
|
||||
|
||||
namespace xna {
|
||||
Vector3 Gjk::ComputeClosestPoint() {
|
||||
auto num1 = 0.0f;
|
||||
Vector3 zero = Vector3::Zero();
|
||||
maxLengthSq = 0.0f;
|
||||
|
||||
for (auto bitsToIndex = Gjk::BitsToIndices[simplexBits]; bitsToIndex != 0; bitsToIndex >>= 3)
|
||||
{
|
||||
auto index = (bitsToIndex & 7) - 1;
|
||||
auto num2 = det[simplexBits][index];
|
||||
num1 += num2;
|
||||
zero += y[index] * num2;
|
||||
maxLengthSq = MathHelper::Max(maxLengthSq, yLengthSq[index]);
|
||||
}
|
||||
|
||||
return zero / num1;
|
||||
}
|
||||
|
||||
bool Gjk::UpdateSimplex(Int newIndex) {
|
||||
auto yBits = simplexBits | 1 << newIndex;
|
||||
auto xBits = 1 << newIndex;
|
||||
for (auto sb = simplexBits; sb != 0; --sb)
|
||||
{
|
||||
if ((sb & yBits) == sb && IsSatisfiesRule(sb | xBits, yBits))
|
||||
{
|
||||
simplexBits = sb | xBits;
|
||||
closestPoint = ComputeClosestPoint();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool flag = false;
|
||||
|
||||
if (IsSatisfiesRule(xBits, yBits)) {
|
||||
simplexBits = xBits;
|
||||
closestPoint = y[newIndex];
|
||||
maxLengthSq = yLengthSq[newIndex];
|
||||
flag = true;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
void Gjk::UpdateDeterminant(Int xmIdx) {
|
||||
auto index1 = 1 << xmIdx;
|
||||
det[index1][xmIdx] = 1.0f;
|
||||
auto bitsToIndex = Gjk::BitsToIndices[simplexBits];
|
||||
auto num1 = bitsToIndex;
|
||||
auto num2 = 0;
|
||||
while (num1 != 0)
|
||||
{
|
||||
auto index2 = (num1 & 7) - 1;
|
||||
auto num3 = 1 << index2;
|
||||
auto index3 = num3 | index1;
|
||||
det[index3][index2] = Vector3::Dot(edges[xmIdx][index2], y[xmIdx]);
|
||||
det[index3][xmIdx] = Vector3::Dot(edges[index2][xmIdx], y[index2]);
|
||||
auto num4 = bitsToIndex;
|
||||
for (auto index4 = 0; index4 < num2; ++index4)
|
||||
{
|
||||
auto index5 = (num4 & 7) - 1;
|
||||
auto num5 = 1 << index5;
|
||||
auto index6 = index3 | num5;
|
||||
auto index7 = Gjk::edgeLengthSq[index2][index5] < Gjk::edgeLengthSq[xmIdx][index5] ? index2 : xmIdx;
|
||||
det[index6][index5] = (Gjk::det[index3][index2] * Vector3::Dot(edges[index7][index5], y[index2]) + Gjk::det[index3][xmIdx] * Vector3::Dot(edges[index7][index5], y[xmIdx]));
|
||||
auto index8 = Gjk::edgeLengthSq[index5][index2] < Gjk::edgeLengthSq[xmIdx][index2] ? index5 : xmIdx;
|
||||
det[index6][index2] = (Gjk::det[num5 | index1][index5] * Vector3::Dot(edges[index8][index2], y[index5]) + Gjk::det[num5 | index1][xmIdx] * Vector3::Dot(edges[index8][index2], y[xmIdx]));
|
||||
auto index9 = Gjk::edgeLengthSq[index2][xmIdx] < Gjk::edgeLengthSq[index5][xmIdx] ? index2 : index5;
|
||||
det[index6][xmIdx] = (Gjk::det[num3 | num5][index5] * Vector3::Dot(edges[index9][xmIdx], y[index5]) + Gjk::det[num3 | num5][index2] * Vector3::Dot(edges[index9][xmIdx], y[index2]));
|
||||
num4 >>= 3;
|
||||
}
|
||||
num1 >>= 3;
|
||||
++num2;
|
||||
}
|
||||
|
||||
if ((simplexBits | index1) != 15)
|
||||
return;
|
||||
auto index10 = Gjk::edgeLengthSq[1][0] < Gjk::edgeLengthSq[2][0] ? (Gjk::edgeLengthSq[1][0] < Gjk::edgeLengthSq[3][0] ? 1 : 3) : (Gjk::edgeLengthSq[2][0] < Gjk::edgeLengthSq[3][0] ? 2 : 3);
|
||||
det[15][0] = (Gjk::det[14][1] * Vector3::Dot(edges[index10][0], y[1]) + Gjk::det[14][2] * Vector3::Dot(edges[index10][0], y[2]) + Gjk::det[14][3] * Vector3::Dot(edges[index10][0], y[3]));
|
||||
auto index11 = Gjk::edgeLengthSq[0][1] < Gjk::edgeLengthSq[2][1] ? (Gjk::edgeLengthSq[0][1] < Gjk::edgeLengthSq[3][1] ? 0 : 3) : (Gjk::edgeLengthSq[2][1] < Gjk::edgeLengthSq[3][1] ? 2 : 3);
|
||||
det[15][1] = (Gjk::det[13][0] * Vector3::Dot(edges[index11][1], y[0]) + Gjk::det[13][2] * Vector3::Dot(edges[index11][1], y[2]) + Gjk::det[13][3] * Vector3::Dot(edges[index11][1], y[3]));
|
||||
auto index12 = Gjk::edgeLengthSq[0][2] < Gjk::edgeLengthSq[1][2] ? (Gjk::edgeLengthSq[0][2] < Gjk::edgeLengthSq[3][2] ? 0 : 3) : (Gjk::edgeLengthSq[1][2] < Gjk::edgeLengthSq[3][2] ? 1 : 3);
|
||||
det[15][2] = (Gjk::det[11][0] * Vector3::Dot(edges[index12][2], y[0]) + Gjk::det[11][1] * Vector3::Dot(edges[index12][2], y[1]) + Gjk::det[11][3] * Vector3::Dot(edges[index12][2], y[3]));
|
||||
auto index13 = Gjk::edgeLengthSq[0][3] < Gjk::edgeLengthSq[1][3] ? (Gjk::edgeLengthSq[0][3] < Gjk::edgeLengthSq[2][3] ? 0 : 2) : (Gjk::edgeLengthSq[1][3] < Gjk::edgeLengthSq[2][3] ? 1 : 2);
|
||||
det[15][3] = (Gjk::det[7][0] * Vector3::Dot(edges[index13][3], y[0]) + Gjk::det[7][1] * Vector3::Dot(edges[index13][3], y[1]) + Gjk::det[7][2] * Vector3::Dot(edges[index13][3], y[2]));
|
||||
}
|
||||
|
||||
bool Gjk::AddSupportPoint(Vector3 const& newPoint) {
|
||||
auto index1 = (Gjk::BitsToIndices[simplexBits ^ 15] & 7) - 1;
|
||||
y[index1] = newPoint;
|
||||
yLengthSq[index1] = newPoint.LengthSquared();
|
||||
for (auto bitsToIndex = Gjk::BitsToIndices[simplexBits]; bitsToIndex != 0; bitsToIndex >>= 3)
|
||||
{
|
||||
auto index2 = (bitsToIndex & 7) - 1;
|
||||
Vector3 vector3 = y[index2] - newPoint;
|
||||
edges[index2][index1] = vector3;
|
||||
edges[index1][index2] = -vector3;
|
||||
edgeLengthSq[index1][index2] = edgeLengthSq[index2][index1] = vector3.LengthSquared();
|
||||
}
|
||||
UpdateDeterminant(index1);
|
||||
return UpdateSimplex(index1);
|
||||
}
|
||||
}
|
239
inc/common/collision.hpp
Normal file
239
inc/common/collision.hpp
Normal file
@ -0,0 +1,239 @@
|
||||
#ifndef XNA_COMMON_SHAPES_HPP
|
||||
#define XNA_COMMON_SHAPES_HPP
|
||||
|
||||
#include "default.hpp"
|
||||
#include "vectors.hpp"
|
||||
#include "matrix.hpp"
|
||||
#include "gjk.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace xna {
|
||||
struct Plane {
|
||||
Vector3 Normal{ 0 };
|
||||
float D{ 0 };
|
||||
};
|
||||
|
||||
struct BoundingFrustum {
|
||||
inline static constexpr int CornerCount = 8;
|
||||
inline static constexpr int PlaneCount = 6;
|
||||
|
||||
Plane Near() { return planes[0]; }
|
||||
Plane Far() { return planes[1]; }
|
||||
Plane Left() { return planes[2]; }
|
||||
Plane Right() { return planes[3]; }
|
||||
Plane Top() { return planes[4]; }
|
||||
Plane Bottom() { return planes[5]; }
|
||||
|
||||
constexpr bool operator==(BoundingFrustum const& other) const {
|
||||
return matrix == other.matrix;
|
||||
}
|
||||
|
||||
constexpr void GetCorners(std::vector<Vector3>& destination) const;
|
||||
constexpr Matrix GetMatrix() const { return matrix; }
|
||||
constexpr void SetMatrix(Matrix const& value);
|
||||
bool Intersects(BoundingBox const& box);
|
||||
bool Intersects(BoundingSphere const& box);
|
||||
constexpr PlaneIntersectionType Intersects(Plane const& plane) const;
|
||||
bool Intersects(BoundingFrustum const& frustum);
|
||||
std::optional<float> Intersects(Ray const& ray) const;
|
||||
constexpr ContainmentType Contains(BoundingBox const& box) const;
|
||||
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;
|
||||
|
||||
private:
|
||||
std::vector<Plane> planes{ 6 };
|
||||
std::vector<Vector3> corners{ 8 };
|
||||
Matrix matrix{ Matrix::Identity() };
|
||||
Gjk gjk{};
|
||||
|
||||
private:
|
||||
static constexpr Ray ComputeIntersectionLine(Plane const& p1, Plane const& p2);
|
||||
static constexpr Vector3 ComputeIntersection(Plane const& plane, Ray const& ray);
|
||||
};
|
||||
|
||||
struct BoundingBox {
|
||||
Vector3 Min{};
|
||||
Vector3 Max{};
|
||||
|
||||
constexpr PlaneIntersectionType Intersects(Plane const& plane) const {
|
||||
return PlaneIntersectionType::Intersecting;
|
||||
}
|
||||
|
||||
void SupportMapping(Vector3 const& v, Vector3& result) const {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct BoundingSphere {
|
||||
Vector3 Center{};
|
||||
float Radius{ 0 };
|
||||
|
||||
void SupportMapping(Vector3 const& v, Vector3& result) const {
|
||||
//TODO
|
||||
}
|
||||
};
|
||||
|
||||
struct Ray {
|
||||
Vector3 Position{};
|
||||
Vector3 Direction{};
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------//
|
||||
// IMPLEMENTATIONS //
|
||||
//---------------------------------------------------------------------------------//
|
||||
|
||||
constexpr void BoundingFrustum::GetCorners(std::vector<Vector3>& destination) const {
|
||||
if (destination.size() < CornerCount)
|
||||
destination.resize(CornerCount);
|
||||
|
||||
for (size_t i = 0; i < CornerCount; ++i)
|
||||
destination[i] = corners[i];
|
||||
}
|
||||
|
||||
constexpr Ray BoundingFrustum::ComputeIntersectionLine(Plane const& p1, Plane const& p2) {
|
||||
Ray intersectionLine{};
|
||||
intersectionLine.Direction = Vector3::Cross(p1.Normal, p2.Normal);
|
||||
const auto num = intersectionLine.Direction.LengthSquared();
|
||||
intersectionLine.Position = Vector3::Cross(-p1.D * p2.Normal + p2.D * p1.Normal, intersectionLine.Direction) / num;
|
||||
return intersectionLine;
|
||||
}
|
||||
|
||||
constexpr Vector3 BoundingFrustum::ComputeIntersection(Plane const& plane, Ray const& ray) {
|
||||
const auto num = (-plane.D - Vector3::Dot(plane.Normal, ray.Position)) / Vector3::Dot(plane.Normal, ray.Direction);
|
||||
return ray.Position + ray.Direction * num;
|
||||
}
|
||||
|
||||
constexpr void BoundingFrustum::SupportMapping(Vector3 const& v, Vector3& result) const {
|
||||
size_t index1 = 0;
|
||||
auto result1 = Vector3::Dot(corners[0], v);
|
||||
|
||||
for (size_t index2 = 1; index2 < CornerCount; ++index2)
|
||||
{
|
||||
auto result2 = Vector3::Dot(corners[index2], v);
|
||||
if (result2 > result1)
|
||||
{
|
||||
index1 = index2;
|
||||
result1 = result2;
|
||||
}
|
||||
}
|
||||
result = corners[index1];
|
||||
}
|
||||
|
||||
constexpr PlaneIntersectionType BoundingFrustum::Intersects(Plane const& plane) const {
|
||||
int num = 0;
|
||||
for (size_t index = 0; index < CornerCount; ++index)
|
||||
{
|
||||
auto result = Vector3::Dot(corners[index], plane.Normal);
|
||||
|
||||
if (result + plane.D > 0.0F)
|
||||
num |= 1;
|
||||
else
|
||||
num |= 2;
|
||||
|
||||
if (num == 3)
|
||||
return PlaneIntersectionType::Intersecting;
|
||||
}
|
||||
return num != 1 ? PlaneIntersectionType::Back : PlaneIntersectionType::Front;
|
||||
}
|
||||
|
||||
constexpr ContainmentType BoundingFrustum::Contains(Vector3 const& point) const {
|
||||
for (size_t i = 0; i < PlaneCount; ++i) {
|
||||
const auto& plane = planes[i];
|
||||
|
||||
if ((static_cast<double>(plane.Normal.X * point.X + plane.Normal.Y * point.Y + plane.Normal.Z * point.Z) + plane.D) > 9.9999997473787516E-06)
|
||||
return ContainmentType::Disjoint;
|
||||
}
|
||||
|
||||
return ContainmentType::Contains;
|
||||
}
|
||||
|
||||
constexpr ContainmentType BoundingFrustum::Contains(BoundingBox const& box) const {
|
||||
bool flag = false;
|
||||
for (size_t i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
const auto& plane = planes[i];
|
||||
|
||||
switch (box.Intersects(plane))
|
||||
{
|
||||
case PlaneIntersectionType::Front:
|
||||
return ContainmentType::Disjoint;
|
||||
case PlaneIntersectionType::Intersecting:
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !flag ? ContainmentType::Contains : ContainmentType::Intersects;
|
||||
}
|
||||
|
||||
constexpr ContainmentType BoundingFrustum::Contains(BoundingSphere const& sphere) const {
|
||||
auto center = sphere.Center;
|
||||
auto radius = sphere.Radius;
|
||||
auto num1 = 0;
|
||||
for (size_t i = 0; i < PlaneCount; ++i)
|
||||
{
|
||||
const auto& plane = planes[i];
|
||||
|
||||
auto num2 = (plane.Normal.X * center.X + plane.Normal.Y * center.Y + plane.Normal.Z * center.Z) + plane.D;
|
||||
|
||||
if (num2 > radius)
|
||||
return ContainmentType::Disjoint;
|
||||
|
||||
if (num2 < -radius)
|
||||
++num1;
|
||||
}
|
||||
|
||||
return num1 != 6 ? ContainmentType::Intersects : ContainmentType::Contains;
|
||||
}
|
||||
|
||||
constexpr void BoundingFrustum::SetMatrix(Matrix const& value) {
|
||||
matrix = value;
|
||||
planes[2].Normal.X = -value.M14 - value.M11;
|
||||
planes[2].Normal.Y = -value.M24 - value.M21;
|
||||
planes[2].Normal.Z = -value.M34 - value.M31;
|
||||
planes[2].D = -value.M44 - value.M41;
|
||||
planes[3].Normal.X = -value.M14 + value.M11;
|
||||
planes[3].Normal.Y = -value.M24 + value.M21;
|
||||
planes[3].Normal.Z = -value.M34 + value.M31;
|
||||
planes[3].D = -value.M44 + value.M41;
|
||||
planes[4].Normal.X = -value.M14 + value.M12;
|
||||
planes[4].Normal.Y = -value.M24 + value.M22;
|
||||
planes[4].Normal.Z = -value.M34 + value.M32;
|
||||
planes[4].D = -value.M44 + value.M42;
|
||||
planes[5].Normal.X = -value.M14 - value.M12;
|
||||
planes[5].Normal.Y = -value.M24 - value.M22;
|
||||
planes[5].Normal.Z = -value.M34 - value.M32;
|
||||
planes[5].D = -value.M44 - value.M42;
|
||||
planes[0].Normal.X = -value.M13;
|
||||
planes[0].Normal.Y = -value.M23;
|
||||
planes[0].Normal.Z = -value.M33;
|
||||
planes[0].D = -value.M43;
|
||||
planes[1].Normal.X = -value.M14 + value.M13;
|
||||
planes[1].Normal.Y = -value.M24 + value.M23;
|
||||
planes[1].Normal.Z = -value.M34 + value.M33;
|
||||
planes[1].D = -value.M44 + value.M43;
|
||||
|
||||
for (size_t index = 0; index < PlaneCount; ++index)
|
||||
{
|
||||
const auto num = planes[index].Normal.Length();
|
||||
planes[index].Normal = planes[index].Normal / num;
|
||||
planes[index].D /= num;
|
||||
}
|
||||
|
||||
Ray intersectionLine1 = BoundingFrustum::ComputeIntersectionLine(planes[0], planes[2]);
|
||||
corners[0] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine1);
|
||||
corners[3] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine1);
|
||||
Ray intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[3], planes[0]);
|
||||
corners[1] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
|
||||
corners[2] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2);
|
||||
intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[2], planes[1]);
|
||||
corners[4] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
|
||||
corners[7] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2);
|
||||
intersectionLine2 = BoundingFrustum::ComputeIntersectionLine(planes[1], planes[3]);
|
||||
corners[5] = BoundingFrustum::ComputeIntersection(planes[4], intersectionLine2);
|
||||
corners[6] = BoundingFrustum::ComputeIntersection(planes[5], intersectionLine2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
71
inc/common/gjk.hpp
Normal file
71
inc/common/gjk.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef XNA_COMMON_GDK_HPP
|
||||
#define XNA_COMMON_GDK_HPP
|
||||
|
||||
#include "default.hpp"
|
||||
#include "vectors.hpp"
|
||||
#include "math.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Gjk {
|
||||
public:
|
||||
constexpr Gjk() = default;
|
||||
|
||||
constexpr bool FullSimplex() const { return simplexBits == 15; }
|
||||
constexpr float MaxLengthSquared() const { return maxLengthSq; }
|
||||
constexpr Vector3 ClosestPoint() const { return closestPoint; }
|
||||
|
||||
constexpr void Reset() {
|
||||
simplexBits = 0;
|
||||
maxLengthSq = 0.0f;
|
||||
}
|
||||
|
||||
bool AddSupportPoint(Vector3 const& newPoint);
|
||||
|
||||
private:
|
||||
using listv3 = std::vector<Vector3>;
|
||||
using listv3v3 = std::vector<std::vector<Vector3>>;
|
||||
using listf = std::vector<float>;
|
||||
using listff = std::vector<std::vector<float>>;
|
||||
|
||||
void UpdateDeterminant(Int xmIdx);
|
||||
bool UpdateSimplex(Int newIndex);
|
||||
Vector3 ComputeClosestPoint();
|
||||
|
||||
constexpr bool IsSatisfiesRule(Int xBits, Int yBits) const {
|
||||
bool flag = true;
|
||||
for (auto bitsToIndex = Gjk::BitsToIndices[yBits]; bitsToIndex != 0; bitsToIndex >>= 3)
|
||||
{
|
||||
auto index = (bitsToIndex & 7) - 1;
|
||||
auto num = 1 << index;
|
||||
|
||||
if ((num & xBits) != 0) {
|
||||
if (static_cast<float>(det[xBits][index]) <= 0.0F) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (static_cast<float>(det[xBits | num][index]) > 0.0F) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static auto BitsToIndices = std::vector<Int> {
|
||||
0, 1, 2, 17, 3, 25, 26, 209, 4, 33, 34, 273, 35, 281, 282, 2257
|
||||
};
|
||||
|
||||
Vector3 closestPoint{};
|
||||
Int simplexBits{0};
|
||||
float maxLengthSq{0};
|
||||
listv3 y = listv3(4);
|
||||
listf yLengthSq = listf(4);
|
||||
listv3v3 edges = listv3v3(4, listv3(4));
|
||||
listff edgeLengthSq = listff(4, listf(4));
|
||||
listff det = listff(16, listf(4));
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -6,16 +6,16 @@
|
||||
|
||||
namespace xna {
|
||||
struct MathHelper {
|
||||
static constexpr double E = 2.7182818284590452354;
|
||||
static constexpr double PI = 3.14159265358979323846;
|
||||
static constexpr double TAU = PI * 2;
|
||||
static constexpr double EPSILON = std::numeric_limits<double>::epsilon();
|
||||
static constexpr double E = 2.7182818284590451;
|
||||
static constexpr double PI = 3.1415926535897931;
|
||||
static constexpr double TAU = 6.2831853071795862;
|
||||
static constexpr double EPSILON = 4.94065645841247E-324;
|
||||
|
||||
static constexpr float ToRadians(float degrees) { return degrees * (static_cast<float>(PI) / 180.0f); }
|
||||
static constexpr float ToDegrees(float radians) { return radians * 57.2957764F; }
|
||||
static float Distance(float value1, float value2) { return std::abs(value1 - value2); }
|
||||
static float Min(float value1, float value2) { return (std::min)(value1, value2); }
|
||||
static float Max(float value1, float value2) { return (std::max)(value1, value2); }
|
||||
static constexpr float Min(float value1, float value2) { return (std::min)(value1, value2); }
|
||||
static constexpr float Max(float value1, float value2) { return (std::max)(value1, value2); }
|
||||
|
||||
static constexpr float Clamp(float value, float min, float max) {
|
||||
value = value > max ? max : value;
|
||||
|
@ -4,19 +4,7 @@
|
||||
#include "../types.hpp"
|
||||
|
||||
namespace xna {
|
||||
struct Point {
|
||||
Int X{0};
|
||||
Int Y{ 0 };
|
||||
|
||||
constexpr Point() = default;
|
||||
|
||||
constexpr Point(const Int& X, const Int& Y)
|
||||
: X(X), Y(Y) {}
|
||||
|
||||
constexpr bool operator==(const Point& other) const {
|
||||
return X == other.X && Y == other.Y;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -2,9 +2,22 @@
|
||||
#define XNA_COMMON_RECTANGLE_HPP
|
||||
|
||||
#include "../types.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
namespace xna {
|
||||
struct Point {
|
||||
Int X{ 0 };
|
||||
Int Y{ 0 };
|
||||
|
||||
constexpr Point() = default;
|
||||
|
||||
constexpr Point(const Int& X, const Int& Y)
|
||||
: X(X), Y(Y) {}
|
||||
|
||||
constexpr bool operator==(const Point& other) const {
|
||||
return X == other.X && Y == other.Y;
|
||||
}
|
||||
};
|
||||
|
||||
struct Rectangle {
|
||||
Int X{ 0 };
|
||||
Int Y{ 0 };
|
||||
|
@ -263,7 +263,7 @@ namespace xna {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
static float Dot(Vector3 const& vector1, Vector3 const& vector2) {
|
||||
static constexpr float Dot(Vector3 const& vector1, Vector3 const& vector2) {
|
||||
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
|
||||
}
|
||||
|
||||
@ -487,6 +487,20 @@ namespace xna {
|
||||
friend constexpr Vector3 operator/(float divider, Vector3 const& value) {
|
||||
return Vector3::Divide(value, divider);
|
||||
}
|
||||
|
||||
friend constexpr Vector3 operator+=(Vector3 const& value1, Vector3 const& value2) {
|
||||
auto vec = value1;
|
||||
vec.X += value2.X;
|
||||
vec.Y += value2.Y;
|
||||
return vec;
|
||||
}
|
||||
|
||||
friend constexpr Vector3 operator-=(Vector3 const& value1, Vector3 const& value2) {
|
||||
auto vec = value1;
|
||||
vec.X -= value2.X;
|
||||
vec.Y -= value2.Y;
|
||||
return vec;
|
||||
}
|
||||
};
|
||||
|
||||
struct Vector4 {
|
||||
|
@ -114,7 +114,13 @@ namespace xna {
|
||||
Blue,
|
||||
Alpha,
|
||||
All
|
||||
};
|
||||
};
|
||||
|
||||
enum class ContainmentType {
|
||||
Disjoint,
|
||||
Contains,
|
||||
Intersects,
|
||||
};
|
||||
|
||||
enum class ComparisonFunction {
|
||||
Never,
|
||||
@ -379,6 +385,12 @@ namespace xna {
|
||||
Down,
|
||||
};
|
||||
|
||||
enum class PlaneIntersectionType {
|
||||
Front,
|
||||
Back,
|
||||
Intersecting,
|
||||
};
|
||||
|
||||
enum class PlayerIndex
|
||||
{
|
||||
One,
|
||||
|
@ -24,20 +24,20 @@ namespace xna {
|
||||
class ContentTypeReader;
|
||||
class ContentTypeReaderManager;
|
||||
|
||||
//Framework
|
||||
class BoundingBox;
|
||||
class BoundingFrustum;
|
||||
class BoundinSphere;
|
||||
//Common
|
||||
struct BoundingBox;
|
||||
struct BoundingFrustum;
|
||||
struct BoundingSphere;
|
||||
struct Color;
|
||||
class Curve;
|
||||
class CurveContinuity;
|
||||
class CurveKey;
|
||||
class CurveKeyCollection;
|
||||
struct Curve;
|
||||
struct CurveContinuity;
|
||||
struct CurveKey;
|
||||
struct CurveKeyCollection;
|
||||
struct Matrix;
|
||||
class Plane;
|
||||
struct Plane;
|
||||
struct Point;
|
||||
struct Quaternion;
|
||||
class Ray;
|
||||
struct Ray;
|
||||
struct Rectangle;
|
||||
struct Vector2;
|
||||
struct Vector3;
|
||||
|
@ -3,16 +3,17 @@
|
||||
#include "helpers.hpp"
|
||||
#include "forward.hpp"
|
||||
#include "enums.hpp"
|
||||
#include "default.hpp"
|
||||
#include "audio/audioengine.hpp"
|
||||
#include "audio/soundeffect.hpp"
|
||||
#include "common/color.hpp"
|
||||
#include "common/gjk.hpp"
|
||||
#include "common/math.hpp"
|
||||
#include "common/matrix.hpp"
|
||||
#include "common/packedvalue.hpp"
|
||||
#include "common/point.hpp"
|
||||
#include "common/quaternion.hpp"
|
||||
#include "common/rectangle.hpp"
|
||||
#include "common/collision.hpp"
|
||||
#include "common/vectors.hpp"
|
||||
#include "content/defaultreaders.hpp"
|
||||
#include "content/manager.hpp"
|
||||
|
Loading…
x
Reference in New Issue
Block a user