Sphere.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include "Sphere.h"
  2. #include "Matrix4.h"
  3. USING_NS_BF;
  4. static const float radiusEpsilon = 1e-4f; // NOTE: To avoid numerical inaccuracies
  5. Sphere::Sphere()
  6. {
  7. mRadius = -1;
  8. }
  9. Sphere::Sphere(const Sphere& S)
  10. {
  11. mRadius = S.mRadius;
  12. mCenter = S.mCenter;
  13. }
  14. Sphere::Sphere(const Vector3& O)
  15. {
  16. mRadius = 0 + radiusEpsilon;
  17. mCenter = O;
  18. }
  19. Sphere::Sphere(const Vector3& O, float R)
  20. {
  21. mRadius = R;
  22. mCenter = O;
  23. }
  24. Sphere::Sphere(const Vector3& O, const Vector3& A)
  25. {
  26. Vector3 a = A - O;
  27. Vector3 o = a * 0.5f;
  28. mRadius = o.GetMagnitude() + radiusEpsilon;
  29. mCenter = O + o;
  30. }
  31. Sphere::Sphere(const Vector3& O, const Vector3& A, const Vector3& B)
  32. {
  33. Vector3 a = A - O;
  34. Vector3 b = B - O;
  35. Vector3 axb = Vector3::CrossProduct(a, b);
  36. float Denominator = 2.0f * Vector3::Dot(axb, axb);
  37. Vector3 o =
  38. ((Vector3::CrossProduct(axb, a) * Vector3::Dot(b, b)) +
  39. (Vector3::CrossProduct(b, axb) * Vector3::Dot(a, a))) / Denominator;
  40. mRadius = o.GetMagnitude() + radiusEpsilon;
  41. mCenter = O + o;
  42. }
  43. Sphere::Sphere(const Vector3& O, const Vector3& A, const Vector3& B, const Vector3& C)
  44. {
  45. Vector3 a = A - O;
  46. Vector3 b = B - O;
  47. Vector3 c = C - O;
  48. float Denominator = 2.0f * Matrix4::Determinant(
  49. a.mX, a.mY, a.mZ,
  50. b.mX, b.mY, b.mZ,
  51. c.mX, c.mY, c.mZ);
  52. Vector3 o = (
  53. (Vector3::CrossProduct(a, b) * Vector3::Dot(c, c)) +
  54. (Vector3::CrossProduct(c, a) * Vector3::Dot(b, b)) +
  55. (Vector3::CrossProduct(b, c) * Vector3::Dot(a, a))) / Denominator;
  56. mRadius = o.GetMagnitude() + radiusEpsilon;
  57. mCenter = O + o;
  58. }
  59. Sphere& Sphere::operator=(const Sphere& S)
  60. {
  61. mRadius = S.mRadius;
  62. mCenter = S.mCenter;
  63. return *this;
  64. }
  65. float Sphere::GetDistance(const Vector3& P) const
  66. {
  67. return Vector3::GetDistance(P, mCenter) - mRadius;
  68. }
  69. float Sphere::GetDistanceSquare(const Vector3& P) const
  70. {
  71. return Vector3::GetDistanceSquare(P, mCenter) - mRadius * mRadius;
  72. }
  73. float Sphere::GetDistance(const Sphere& S, const Vector3& P)
  74. {
  75. return Vector3::GetDistance(P, S.mCenter) - S.mRadius;
  76. }
  77. float Sphere::GetDistance(const Vector3& P, const Sphere& S)
  78. {
  79. return Vector3::GetDistance(P, S.mCenter) - S.mRadius;
  80. }
  81. float Sphere::GetDistanceSquare(const Sphere& S, const Vector3& P)
  82. {
  83. return Vector3::GetDistanceSquare(P, S.mCenter) - S.mRadius * S.mRadius;
  84. }
  85. float Sphere::GetDistanceSquare(const Vector3& P, const Sphere& S)
  86. {
  87. return Vector3::GetDistanceSquare(P, S.mCenter) - S.mRadius * S.mRadius;
  88. }
  89. Sphere Sphere::RecurseMini(Vector3* P[], int p, int b)
  90. {
  91. Sphere MB;
  92. switch (b)
  93. {
  94. case 0:
  95. MB = Sphere();
  96. break;
  97. case 1:
  98. MB = Sphere(*P[-1]);
  99. break;
  100. case 2:
  101. MB = Sphere(*P[-1], *P[-2]);
  102. break;
  103. case 3:
  104. MB = Sphere(*P[-1], *P[-2], *P[-3]);
  105. break;
  106. case 4:
  107. MB = Sphere(*P[-1], *P[-2], *P[-3], *P[-4]);
  108. return MB;
  109. }
  110. for (int i = 0; i < p; i++)
  111. {
  112. if (MB.GetDistanceSquare(*P[i]) > 0) // Signed square distance to sphere
  113. {
  114. for (int j = i; j > 0; j--)
  115. {
  116. Vector3* T = P[j];
  117. P[j] = P[j - 1];
  118. P[j - 1] = T;
  119. }
  120. MB = RecurseMini(P + 1, i, b + 1);
  121. }
  122. }
  123. return MB;
  124. }
  125. Sphere Sphere::MiniBall(Vector3 P[], int p)
  126. {
  127. Vector3** L = new Vector3* [p];
  128. for (int i = 0; i < p; i++)
  129. L[i] = &P[i];
  130. Sphere MB = RecurseMini(L, p);
  131. delete[] L;
  132. return MB;
  133. }
  134. Sphere Sphere::SmallBall(Vector3 P[], int p)
  135. {
  136. Vector3 mCenter;
  137. float mRadius = -1;
  138. if (p > 0)
  139. {
  140. for (int i = 0; i < p; i++)
  141. mCenter += P[i];
  142. mCenter /= (float)p;
  143. for (int i = 0; i < p; i++)
  144. {
  145. float d2 = Vector3::GetDistanceSquare(P[i], mCenter);
  146. if (d2 > mRadius)
  147. mRadius = d2;
  148. }
  149. mRadius = sqrtf(mRadius) + radiusEpsilon;
  150. }
  151. return Sphere(mCenter, mRadius);
  152. }