1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
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
9namespace bs
10{
11 void Sphere::merge(const Sphere& rhs)
12 {
13 Vector3 newCenter = (mCenter + rhs.mCenter) * 0.5f;
14
15 float newRadiusA = newCenter.distance(mCenter) + getRadius();
16 float newRadiusB = newCenter.distance(rhs.mCenter) + rhs.getRadius();
17
18 mCenter = newCenter;
19 mRadius = std::max(newRadiusA, newRadiusB);
20 }
21
22 void Sphere::merge(const Vector3& point)
23 {
24 float dist = point.distance(mCenter);
25 mRadius = std::max(mRadius, dist);
26 }
27
28 void Sphere::transform(const Matrix4& matrix)
29 {
30 float lengthSqrd[3];
31 for(UINT32 i = 0; i < 3; i++)
32 {
33 Vector3 column = matrix.getColumn(i);
34 lengthSqrd[i] = column.dot(column);
35 }
36
37 float maxLengthSqrd = std::max(lengthSqrd[0], std::max(lengthSqrd[1], lengthSqrd[2]));
38
39 mCenter = matrix.multiplyAffine(mCenter);
40 mRadius *= sqrt(maxLengthSqrd);
41 }
42
43 bool Sphere::contains(const Vector3& v) const
44 {
45 return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
46 }
47
48 bool Sphere::intersects(const Sphere& s) const
49 {
50 return (s.mCenter - mCenter).squaredLength() <=
51 Math::sqr(s.mRadius + mRadius);
52 }
53
54 std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
55 {
56 const Vector3& raydir = ray.getDirection();
57 const Vector3& rayorig = ray.getOrigin() - getCenter();
58 float radius = getRadius();
59
60 // Check origin inside first
61 if (rayorig.squaredLength() <= radius*radius && discardInside)
62 {
63 return std::pair<bool, float>(true, 0.0f);
64 }
65
66 // t = (-b +/- sqrt(b*b + 4ac)) / 2a
67 float a = raydir.dot(raydir);
68 float b = 2 * rayorig.dot(raydir);
69 float c = rayorig.dot(rayorig) - radius*radius;
70
71 // Determinant
72 float d = (b*b) - (4 * a * c);
73 if (d < 0)
74 {
75 // No intersection
76 return std::pair<bool, float>(false, 0.0f);
77 }
78 else
79 {
80 // If d == 0 there is one intersection, if d > 0 there are 2.
81 // We only return the first one.
82
83 float t = ( -b - Math::sqrt(d) ) / (2 * a);
84 if (t < 0)
85 t = ( -b + Math::sqrt(d) ) / (2 * a);
86
87 return std::pair<bool, float>(true, t);
88 }
89 }
90
91 bool Sphere::intersects(const Plane& plane) const
92 {
93 return (Math::abs(plane.getDistance(getCenter())) <= getRadius());
94 }
95
96 bool Sphere::intersects(const AABox& box) const
97 {
98 return box.intersects(*this);
99 }
100}