1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00
Beef/BeefySysLib/util/Sphere.cpp

196 lines
3.5 KiB
C++
Raw Normal View History

2021-05-25 10:57:22 -04:00
#include "Sphere.h"
#include "Matrix4.h"
USING_NS_BF;
static const float radiusEpsilon = 1e-4f; // NOTE: To avoid numerical inaccuracies
Sphere::Sphere()
{
mRadius = -1;
}
Sphere::Sphere(const Sphere& S)
{
mRadius = S.mRadius;
mCenter = S.mCenter;
}
Sphere::Sphere(const Vector3& O)
{
mRadius = 0 + radiusEpsilon;
mCenter = O;
}
Sphere::Sphere(const Vector3& O, float R)
{
mRadius = R;
mCenter = O;
}
Sphere::Sphere(const Vector3& O, const Vector3& A)
{
Vector3 a = A - O;
Vector3 o = a * 0.5f;
mRadius = o.GetMagnitude() + radiusEpsilon;
mCenter = O + o;
}
Sphere::Sphere(const Vector3& O, const Vector3& A, const Vector3& B)
{
Vector3 a = A - O;
Vector3 b = B - O;
Vector3 axb = Vector3::CrossProduct(a, b);
float Denominator = 2.0f * Vector3::Dot(axb, axb);
Vector3 o =
((Vector3::CrossProduct(axb, a) * Vector3::Dot(b, b)) +
(Vector3::CrossProduct(b, axb) * Vector3::Dot(a, a))) / Denominator;
mRadius = o.GetMagnitude() + radiusEpsilon;
mCenter = O + o;
}
Sphere::Sphere(const Vector3& O, const Vector3& A, const Vector3& B, const Vector3& C)
{
Vector3 a = A - O;
Vector3 b = B - O;
Vector3 c = C - O;
float Denominator = 2.0f * Matrix4::Determinant(
a.mX, a.mY, a.mZ,
b.mX, b.mY, b.mZ,
c.mX, c.mY, c.mZ);
Vector3 o = (
(Vector3::CrossProduct(a, b) * Vector3::Dot(c, c)) +
(Vector3::CrossProduct(c, a) * Vector3::Dot(b, b)) +
(Vector3::CrossProduct(b, c) * Vector3::Dot(a, a))) / Denominator;
mRadius = o.GetMagnitude() + radiusEpsilon;
mCenter = O + o;
}
Sphere& Sphere::operator=(const Sphere& S)
{
mRadius = S.mRadius;
mCenter = S.mCenter;
return *this;
}
float Sphere::GetDistance(const Vector3& P) const
{
return Vector3::GetDistance(P, mCenter) - mRadius;
}
float Sphere::GetDistanceSquare(const Vector3& P) const
{
return Vector3::GetDistanceSquare(P, mCenter) - mRadius * mRadius;
}
float Sphere::GetDistance(const Sphere& S, const Vector3& P)
{
return Vector3::GetDistance(P, S.mCenter) - S.mRadius;
}
float Sphere::GetDistance(const Vector3& P, const Sphere& S)
{
return Vector3::GetDistance(P, S.mCenter) - S.mRadius;
}
float Sphere::GetDistanceSquare(const Sphere& S, const Vector3& P)
{
return Vector3::GetDistanceSquare(P, S.mCenter) - S.mRadius * S.mRadius;
}
float Sphere::GetDistanceSquare(const Vector3& P, const Sphere& S)
{
return Vector3::GetDistanceSquare(P, S.mCenter) - S.mRadius * S.mRadius;
}
Sphere Sphere::RecurseMini(Vector3* P[], int p, int b)
{
Sphere MB;
switch (b)
{
case 0:
MB = Sphere();
break;
case 1:
MB = Sphere(*P[-1]);
break;
case 2:
MB = Sphere(*P[-1], *P[-2]);
break;
case 3:
MB = Sphere(*P[-1], *P[-2], *P[-3]);
break;
case 4:
MB = Sphere(*P[-1], *P[-2], *P[-3], *P[-4]);
return MB;
}
for (int i = 0; i < p; i++)
{
if (MB.GetDistanceSquare(*P[i]) > 0) // Signed square distance to sphere
{
for (int j = i; j > 0; j--)
{
Vector3* T = P[j];
P[j] = P[j - 1];
P[j - 1] = T;
}
MB = RecurseMini(P + 1, i, b + 1);
}
}
return MB;
}
Sphere Sphere::MiniBall(Vector3 P[], int p)
{
Vector3** L = new Vector3* [p];
for (int i = 0; i < p; i++)
L[i] = &P[i];
Sphere MB = RecurseMini(L, p);
delete[] L;
return MB;
}
Sphere Sphere::SmallBall(Vector3 P[], int p)
{
Vector3 mCenter;
float mRadius = -1;
if (p > 0)
{
for (int i = 0; i < p; i++)
mCenter += P[i];
mCenter /= (float)p;
for (int i = 0; i < p; i++)
{
float d2 = Vector3::GetDistanceSquare(P[i], mCenter);
if (d2 > mRadius)
mRadius = d2;
}
mRadius = sqrtf(mRadius) + radiusEpsilon;
}
return Sphere(mCenter, mRadius);
}