BsSphere.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsSphere.h"
  4. #include "BsRay.h"
  5. #include "BsPlane.h"
  6. #include "BsAABox.h"
  7. #include "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. Vector3 edge = mCenter + Vector3::UNIT_X * mRadius;
  26. mCenter = matrix.multiplyAffine(mCenter);
  27. edge = matrix.multiplyAffine(edge);
  28. mRadius = mCenter.distance(edge);
  29. }
  30. bool Sphere::contains(const Vector3& v) const
  31. {
  32. return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
  33. }
  34. bool Sphere::intersects(const Sphere& s) const
  35. {
  36. return (s.mCenter - mCenter).squaredLength() <=
  37. Math::sqr(s.mRadius + mRadius);
  38. }
  39. std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
  40. {
  41. const Vector3& raydir = ray.getDirection();
  42. const Vector3& rayorig = ray.getOrigin() - getCenter();
  43. float radius = getRadius();
  44. // Check origin inside first
  45. if (rayorig.squaredLength() <= radius*radius && discardInside)
  46. {
  47. return std::pair<bool, float>(true, 0.0f);
  48. }
  49. // t = (-b +/- sqrt(b*b + 4ac)) / 2a
  50. float a = raydir.dot(raydir);
  51. float b = 2 * rayorig.dot(raydir);
  52. float c = rayorig.dot(rayorig) - radius*radius;
  53. // Determinant
  54. float d = (b*b) - (4 * a * c);
  55. if (d < 0)
  56. {
  57. // No intersection
  58. return std::pair<bool, float>(false, 0.0f);
  59. }
  60. else
  61. {
  62. // If d == 0 there is one intersection, if d > 0 there are 2.
  63. // We only return the first one.
  64. float t = ( -b - Math::sqrt(d) ) / (2 * a);
  65. if (t < 0)
  66. t = ( -b + Math::sqrt(d) ) / (2 * a);
  67. return std::pair<bool, float>(true, t);
  68. }
  69. }
  70. bool Sphere::intersects(const Plane& plane) const
  71. {
  72. return (Math::abs(plane.getDistance(getCenter())) <= getRadius());
  73. }
  74. bool Sphere::intersects(const AABox& box) const
  75. {
  76. return box.intersects(*this);
  77. }
  78. }