BsSphere.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. Matrix3 rotMatrix;
  26. float lengthSqrd[3];
  27. for(UINT32 i = 0; i < 3; i++)
  28. {
  29. Vector3 column = rotMatrix.getColumn(i);
  30. lengthSqrd[i] = column.dot(column);
  31. }
  32. float maxLengthSqrd = std::max(lengthSqrd[0], std::max(lengthSqrd[1], lengthSqrd[2]));
  33. mCenter = matrix.multiplyAffine(mCenter);
  34. mRadius *= sqrt(maxLengthSqrd);
  35. }
  36. bool Sphere::contains(const Vector3& v) const
  37. {
  38. return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
  39. }
  40. bool Sphere::intersects(const Sphere& s) const
  41. {
  42. return (s.mCenter - mCenter).squaredLength() <=
  43. Math::sqr(s.mRadius + mRadius);
  44. }
  45. std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
  46. {
  47. const Vector3& raydir = ray.getDirection();
  48. const Vector3& rayorig = ray.getOrigin() - getCenter();
  49. float radius = getRadius();
  50. // Check origin inside first
  51. if (rayorig.squaredLength() <= radius*radius && discardInside)
  52. {
  53. return std::pair<bool, float>(true, 0.0f);
  54. }
  55. // t = (-b +/- sqrt(b*b + 4ac)) / 2a
  56. float a = raydir.dot(raydir);
  57. float b = 2 * rayorig.dot(raydir);
  58. float c = rayorig.dot(rayorig) - radius*radius;
  59. // Determinant
  60. float d = (b*b) - (4 * a * c);
  61. if (d < 0)
  62. {
  63. // No intersection
  64. return std::pair<bool, float>(false, 0.0f);
  65. }
  66. else
  67. {
  68. // If d == 0 there is one intersection, if d > 0 there are 2.
  69. // We only return the first one.
  70. float t = ( -b - Math::sqrt(d) ) / (2 * a);
  71. if (t < 0)
  72. t = ( -b + Math::sqrt(d) ) / (2 * a);
  73. return std::pair<bool, float>(true, t);
  74. }
  75. }
  76. bool Sphere::intersects(const Plane& plane) const
  77. {
  78. return (Math::abs(plane.getDistance(getCenter())) <= getRadius());
  79. }
  80. bool Sphere::intersects(const AABox& box) const
  81. {
  82. return box.intersects(*this);
  83. }
  84. }