123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #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);
- }
|