BsSphere.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Math/BsSphere.h"
  4. #include "Math/BsRay.h"
  5. #include "Math/BsPlane.h"
  6. #include "Math/BsAABox.h"
  7. #include "Math/BsMath.h"
  8. namespace bs
  9. {
  10. void Sphere::merge(const Sphere& rhs)
  11. {
  12. Vector3 newCenter = (mCenter + rhs.mCenter) * 0.5f;
  13. float newRadiusA = newCenter.distance(mCenter) + getRadius();
  14. float newRadiusB = newCenter.distance(rhs.mCenter) + rhs.getRadius();
  15. mCenter = newCenter;
  16. mRadius = std::max(newRadiusA, newRadiusB);
  17. }
  18. void Sphere::merge(const Vector3& point)
  19. {
  20. float dist = point.distance(mCenter);
  21. mRadius = std::max(mRadius, dist);
  22. }
  23. void Sphere::transform(const Matrix4& matrix)
  24. {
  25. float lengthSqrd[3];
  26. for(UINT32 i = 0; i < 3; i++)
  27. {
  28. Vector3 column = matrix.getColumn(i);
  29. lengthSqrd[i] = column.dot(column);
  30. }
  31. float maxLengthSqrd = std::max(lengthSqrd[0], std::max(lengthSqrd[1], lengthSqrd[2]));
  32. mCenter = matrix.multiplyAffine(mCenter);
  33. mRadius *= sqrt(maxLengthSqrd);
  34. }
  35. bool Sphere::contains(const Vector3& v) const
  36. {
  37. return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
  38. }
  39. bool Sphere::intersects(const Sphere& s) const
  40. {
  41. return (s.mCenter - mCenter).squaredLength() <=
  42. Math::sqr(s.mRadius + mRadius);
  43. }
  44. std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
  45. {
  46. const Vector3& raydir = ray.getDirection();
  47. const Vector3& rayorig = ray.getOrigin() - getCenter();
  48. float radius = getRadius();
  49. // Check origin inside first
  50. if (rayorig.squaredLength() <= radius*radius && discardInside)
  51. {
  52. return std::pair<bool, float>(true, 0.0f);
  53. }
  54. // t = (-b +/- sqrt(b*b + 4ac)) / 2a
  55. float a = raydir.dot(raydir);
  56. float b = 2 * rayorig.dot(raydir);
  57. float c = rayorig.dot(rayorig) - radius*radius;
  58. // Determinant
  59. float d = (b*b) - (4 * a * c);
  60. if (d < 0)
  61. {
  62. // No intersection
  63. return std::pair<bool, float>(false, 0.0f);
  64. }
  65. else
  66. {
  67. // If d == 0 there is one intersection, if d > 0 there are 2.
  68. // We only return the first one.
  69. float t = ( -b - Math::sqrt(d) ) / (2 * a);
  70. if (t < 0)
  71. t = ( -b + Math::sqrt(d) ) / (2 * a);
  72. return std::pair<bool, float>(true, t);
  73. }
  74. }
  75. bool Sphere::intersects(const Plane& plane) const
  76. {
  77. return (Math::abs(plane.getDistance(getCenter())) <= getRadius());
  78. }
  79. bool Sphere::intersects(const AABox& box) const
  80. {
  81. return box.intersects(*this);
  82. }
  83. }