| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- /*
- Copyright (c) 2013 Daniele Bartolini, Michele Rossi
- Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
- #pragma once
- #include "Ray.h"
- #include "Plane.h"
- #include "Sphere.h"
- #include "Frustum.h"
- #include "MathUtils.h"
- #include "Types.h"
- #include "Triangle.h"
- #include "Circle.h"
- #include "Rect.h"
- namespace crown
- {
- /// Intersection test utils.
- /// Table of Intersection tests (3d)
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | | Ray | Plane | Sphere | Box | Frustum | Triangle |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Ray | No | Yes | Yes | No | No | Yes |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Plane | - | Yes (1) | Yes (+) | No | No | No |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Sphere | - | - | Yes (+) | No | Yes | Yes (+) |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Box | - | - | - | Yes (+) | Yes | No |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Frustum | - | - | - | - | No | No |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// | Triangle | - | - | - | - | - | No |
- /// +----------+----------+----------+----------+----------+----------+----------+
- /// Notes:
- /// (1): Intersection of three planes
- /// (-): Static intersection only
- /// (+): Static/Dynamic intersection
- /// Table of Intersection tests (2d)
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | | Circle | Rect | O Rect | Segment | Ray 2d |
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | Circle | Yes (p-) | No | No | No | No |
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | Rect | - | Yes | No | No | No | <- Axis Aligned Rect
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | O Rect | - | - | No | No | No | <- Oriented Rect
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | Segment | - | - | - | No | No |
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// | Ray 2d | - | - | - | - | No |
- /// +---------------+----------+-------------+-------------+----------+----------+
- /// Notes:
- /// (p): Penetration vector
- /// (-): Static intersection only
- /// (+): Static/Dynamic intersection
- class Intersection
- {
- public:
- static bool test_ray_plane(const Ray& r, const Plane& p, float& distance, Vec3& inttersectionPoint_t);
- static bool test_ray_sphere(const Ray& r, const Sphere& s, float& distance, Vec3& intersectionPoint);
- static bool test_ray_box(const Ray& r, const Box& b, float& distance, Vec3& intersectionPoint);
- static bool test_ray_triangle(const Ray& r, const Triangle& t, float& distance, Vec3& intersectionPoint);
- static bool test_plane_3(const Plane& p1, const Plane& p2, const Plane& p3, Vec3& ip);
- static bool test_static_sphere_plane(const Sphere& s, const Plane& p);
- static bool test_static_sphere_sphere(const Sphere& a, const Sphere& b);
- static bool test_dynamic_sphere_plane(const Sphere& s, const Vec3& d, const Plane& p, float& it, Vec3& intersectionPoint);
- static bool test_dynamic_sphere_triangle(const Sphere& s, const Vec3& d, const Triangle& tri, float& it, Vec3& intersectionPoint);
- static bool test_dynamic_sphere_sphere(const Sphere& s1, const Vec3& d1, const Sphere& s2, const Vec3& d2, float& it, Vec3& intersectionPoint);
- static bool test_static_box_box(const Box& b1, const Box& b2);
- static bool test_dynamic_box_box(const Box& b1, const Vec3& v1, const Box& b2, const Vec3& v2, float& it);
- static bool test_frustum_sphere(const Frustum& f, const Sphere& s);
- static bool test_frustum_box(const Frustum& f, const Box& box);
- static bool test_circle_circle(const Circle& c1, const Circle& c2, Vec2& penetration);
- static bool test_dynamic_circle_circle(const Circle& c1, const Vec2& d1, const Circle& c2, const Vec2& d2, float& it);
- static bool test_rect_rect(const Rect& r1, const Rect& r2, Vec2& penetration);
- static bool test_circle_rect(const Circle& c1, const Rect& r2, Vec2& penetration);
- private:
- // Disable construction
- Intersection();
- };
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_ray_plane(const Ray& r, const Plane& p, float& distance, Vec3& intersectionPoint)
- {
- float nd = r.direction().dot(p.n);
- float orpn = r.origin().dot(p.n);
- if (nd < 0.0)
- {
- float dist = (-p.d - orpn) / nd;
- if (dist > 0.0)
- {
- distance = dist;
- intersectionPoint = r.origin() + r.direction() * distance;
- return true;
- }
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_ray_sphere(const Ray& r, const Sphere& s, float& distance, Vec3& intersectionPoint)
- {
- Vec3 v = s.center() - r.origin();
- float b = v.dot(r.direction());
- float det = (s.radius() * s.radius()) - v.dot(v) + (b * b);
- if (det < 0.0 || b < s.radius())
- {
- return false;
- }
- distance = b - math::sqrt(det);
- intersectionPoint = r.origin() + r.direction() * distance;
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_ray_box(const Ray& r, const Box& b, float& /*distance*/, Vec3& /*intersectionPoint*/)
- {
- if (r.origin().x < b.min().x)
- {
- if (r.direction().x < 0.0)
- {
- return false;
- }
- }
- if (r.origin().x > b.max().x)
- {
- if (r.direction().x > 0.0)
- {
- return false;
- }
- }
- if (r.origin().y < b.min().y)
- {
- if (r.direction().y < 0.0)
- {
- return false;
- }
- }
- if (r.origin().y > b.max().y)
- {
- if (r.direction().y > 0.0)
- {
- return false;
- }
- }
- if (r.origin().z < b.min().z)
- {
- if (r.direction().z < 0.0)
- {
- return false;
- }
- }
- if (r.origin().z > b.max().z)
- {
- if (r.direction().z > 0.0)
- {
- return false;
- }
- }
- // Possibly int32_tersects
- return true;
- // TODO
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_ray_triangle(const Ray& r, const Triangle& t, float& distance, Vec3& intersectionPoint)
- {
- if (Intersection::test_ray_plane(r, t.to_plane(), distance, intersectionPoint))
- {
- if (t.contains_point(intersectionPoint))
- {
- return true;
- }
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_plane_3(const Plane& p1, const Plane& p2, const Plane& p3, Vec3& ip)
- {
- const Vec3& n1 = p1.n;
- const Vec3& n2 = p2.n;
- const Vec3& n3 = p3.n;
- float den = -n1.cross(n2).dot(n3);
- if (math::equals(den, (float)0.0))
- {
- return false;
- }
- Vec3 res = p1.d * n2.cross(n3) + p2.d * n3.cross(n1) + p3.d * n1.cross(n2);
- ip = res / den;
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_static_sphere_plane(const Sphere& s, const Plane& p)
- {
- if (math::abs(p.distance_to_point(s.center())) < s.radius())
- {
- return true;
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_static_sphere_sphere(const Sphere& a, const Sphere& b)
- {
- float dist = (b.center() - a.center()).squared_length();
- return (dist < (b.radius() + a.radius()) * (b.radius() + a.radius()));
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_dynamic_sphere_plane(const Sphere& s, const Vec3& d, const Plane& p, float& it, Vec3& intersectionPoint)
- {
- const Vec3& sphereCenter = s.center();
- const float sphereRadius = s.radius();
- float t0; // Time at which the sphere int32_tersects the plane remaining at the front side of the plane
- float t1; // Time at which the sphere int32_tersects the plane remaining at the back side of the plane
- float sphereToPlaneDistance = p.distance_to_point(sphereCenter);
- float planeNormalDotVelocity = p.n.dot(d);
- if (planeNormalDotVelocity > 0.0)
- {
- return false;
- }
- // If the sphere is travelling parallel to the plane
- if (planeNormalDotVelocity == 0.0)
- {
- // If the sphere is embedded in the plane
- if (math::abs(sphereToPlaneDistance) < sphereRadius)
- {
- t0 = 0.0;
- t1 = 1.0;
- it = t0;
- intersectionPoint = s.center() - p.n * s.radius();
- return true;
- }
- return false;
- }
- t0 = (sphereRadius - sphereToPlaneDistance) / planeNormalDotVelocity;
- t1 = (-sphereRadius - sphereToPlaneDistance) / planeNormalDotVelocity;
- // If _both_ t0 and t1 are outside [0,1] then collision can never happen
- if (t0 >= 0.0 && t0 <= 1.0)
- {
- it = math::min(t0, t1);
- intersectionPoint = s.center() - p.n * s.radius() + (d * it);
- return true;
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_dynamic_sphere_triangle(const Sphere& s, const Vec3& d, const Triangle& tri, float& it, Vec3& intersectionPoint)
- {
- Plane triPlane = tri.to_plane();
- // Test against the plane containing the triangle
- float spherePlaneIt;
- if (!test_dynamic_sphere_plane(s, d, triPlane, spherePlaneIt, intersectionPoint))
- {
- return false;
- }
- // Check if the int32_tersection point32_t lies inside the triangle
- if (tri.contains_point(intersectionPoint))
- {
- it = spherePlaneIt;
- // intersectionPoint is already returned by the above call to test_dynamic_sphere_plane
- return true;
- }
- it = spherePlaneIt;
- // Sweep test
- // Check for collision against the vertices
- bool collisionFound = false;
- float a, b, c;
- float x1, x2;
- // v1
- a = d.dot(d);
- b = 2.0 * (d.dot(s.center() - tri.m_vertex[0]));
- c = (tri.m_vertex[0] - s.center()).dot(tri.m_vertex[0] - s.center()) - (s.radius() * s.radius());
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[0];
- collisionFound = true;
- }
- // v2
- b = 2.0 * (d.dot(s.center() - tri.m_vertex[1]));
- c = (tri.m_vertex[1] - s.center()).dot(tri.m_vertex[1] - s.center()) - (s.radius() * s.radius());
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[1];
- collisionFound = true;
- }
- // v3
- b = 2.0 * (d.dot(s.center() - tri.m_vertex[2]));
- c = (tri.m_vertex[2] - s.center()).dot(tri.m_vertex[2] - s.center()) - (s.radius() * s.radius());
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[2];
- collisionFound = true;
- }
- // Check for collisions against the edges
- Vec3 edge;
- Vec3 centerToVertex;
- float edgeDotVelocity;
- float edgeDotCenterToVertex;
- float edgeSquaredLength;
- float velocitySquaredLength;
- velocitySquaredLength = d.squared_length();
- // e1
- edge = tri.m_vertex[1] - tri.m_vertex[0];
- centerToVertex = tri.m_vertex[0] - s.center();
- edgeDotVelocity = edge.dot(d);
- edgeDotCenterToVertex = edge.dot(centerToVertex);
- edgeSquaredLength = edge.squared_length();
- a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
- b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
- c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
- if (f0 >= 0.0 && f0 <= 1.0)
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[0] + f0 * edge;
- collisionFound = true;
- }
- }
- // e2
- edge = tri.m_vertex[2] - tri.m_vertex[1];
- centerToVertex = tri.m_vertex[1] - s.center();
- edgeDotVelocity = edge.dot(d);
- edgeDotCenterToVertex = edge.dot(centerToVertex);
- edgeSquaredLength = edge.squared_length();
- a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
- b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
- c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
- if (f0 >= 0.0 && f0 <= 1.0)
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[1] + f0 * edge;
- collisionFound = true;
- }
- }
- // e3
- edge = tri.m_vertex[0] - tri.m_vertex[2];
- centerToVertex = tri.m_vertex[2] - s.center();
- edgeDotVelocity = edge.dot(d);
- edgeDotCenterToVertex = edge.dot(centerToVertex);
- edgeSquaredLength = edge.squared_length();
- a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
- b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
- c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
- if (math::solve_quadratic_equation(a, b, c, x1, x2))
- {
- float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
- if (f0 >= 0.0 && f0 <= 1.0)
- {
- it = math::min(x1, it);
- intersectionPoint = tri.m_vertex[2] + f0 * edge;
- collisionFound = true;
- }
- }
- return collisionFound;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_dynamic_sphere_sphere(const Sphere& s1, const Vec3& d1, const Sphere& s2, const Vec3& d2, float& it, Vec3& /*intersectionPoint*/)
- {
- // s1 == static sphere
- // s2 == moving sphere
- Vec3 d = d2 - d1;
- d.normalize();
- const Vec3& cs = s1.center();
- const Vec3& cm = s2.center();
- Vec3 e = cs - cm;
- float r = s1.radius() + s2.radius();
- // If ||e|| < r, int32_tersection occurs at t = 0
- if (e.length() < r)
- {
- it = 0.0;
- return true;
- }
- // it == Intersection Time
- float ed = e.dot(d);
- float squared = (ed * ed) + (r * r) - e.dot(e);
- // If the value inside the square root is neg, then no int32_tersection
- if (squared < 0.0)
- {
- return false;
- }
- float t = ed - math::sqrt(squared);
- float l = (d2 - d1).length();
- // If t < 0 || t > l, then non int32_tersection in the considered period of time
- if (t < 0.0 || t > l)
- {
- return false;
- }
- it = t / l;
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_static_box_box(const Box& b1, const Box& b2)
- {
- if (b1.min().x > b2.max().x || b1.max().x < b2.min().x)
- {
- return false;
- }
- if (b1.min().y > b2.max().y || b1.max().y < b2.min().y)
- {
- return false;
- }
- if (b1.min().z > b2.max().z || b1.max().z < b2.min().z)
- {
- return false;
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_dynamic_box_box(const Box& b1, const Vec3& v1, const Box& b2, const Vec3& v2, float& it)
- {
- // b1 == static box
- // b2 == moving box
- Vec3 d = v2 - v1;
- // Start time of int32_tersection aint64_t each axis
- Vec3 tEnterXYZ(0.0, 0.0, 0.0);
- // Stop time of int32_tersection aint64_t each axis
- Vec3 tLeaveXYZ(1.0, 1.0, 1.0);
- // If the resulting displacement equals zero, then fallback to static int32_tersection test
- if (math::equals(d.x, (float)0.0))
- {
- if (b1.min().x > b2.max().x || b1.max().x < b2.min().x)
- {
- return false;
- }
- }
- if (math::equals(d.y, (float)0.0))
- {
- if (b1.min().y > b2.max().y || b1.max().y < b2.min().y)
- {
- return false;
- }
- }
- if (math::equals(d.z, (float)0.0))
- {
- if (b1.min().z > b2.max().z || b1.max().z < b2.min().z)
- {
- return false;
- }
- }
- // Otherwise, compute the enter/leave times aint64_t each axis
- float oneOverD = (float)(1.0 / d.x);
- tEnterXYZ.x = (b1.min().x - b2.max().x) * oneOverD;
- tLeaveXYZ.x = (b1.max().x - b2.min().x) * oneOverD;
- oneOverD = (float)(1.0 / d.y);
- tEnterXYZ.y = (b1.min().y - b2.max().y) * oneOverD;
- tLeaveXYZ.y = (b1.max().y - b2.min().y) * oneOverD;
- oneOverD = (float)(1.0 / d.z);
- tEnterXYZ.z = (b1.min().z - b2.max().z) * oneOverD;
- tLeaveXYZ.z = (b1.max().z - b2.min().z) * oneOverD;
- // We must ensure that enter time < leave time
- if (tLeaveXYZ.x < tEnterXYZ.x)
- {
- math::swap(tLeaveXYZ.x, tEnterXYZ.x);
- }
- if (tLeaveXYZ.y < tEnterXYZ.y)
- {
- math::swap(tLeaveXYZ.y, tEnterXYZ.y);
- }
- if (tLeaveXYZ.z < tEnterXYZ.z)
- {
- math::swap(tLeaveXYZ.z, tEnterXYZ.z);
- }
- float tEnter = math::max(tEnterXYZ.x, math::max(tEnterXYZ.y, tEnterXYZ.z));
- float tLeave = math::min(tLeaveXYZ.x, math::min(tLeaveXYZ.y, tLeaveXYZ.z));
- // If tEnter > 1, then there is no int32_tersection in the period
- // of time cosidered
- if (tEnter > 1.0)
- {
- return false;
- }
- it = tEnter;
- return tEnter < tLeave;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_frustum_sphere(const Frustum& f, const Sphere& s)
- {
- if (f.m_planes[0].distance_to_point(s.center()) < -s.radius() || f.m_planes[1].distance_to_point(s.center()) < -s.radius())
- {
- return false;
- }
- if (f.m_planes[2].distance_to_point(s.center()) < -s.radius() || f.m_planes[3].distance_to_point(s.center()) < -s.radius())
- {
- return false;
- }
- if (f.m_planes[4].distance_to_point(s.center()) < -s.radius() || f.m_planes[5].distance_to_point(s.center()) < -s.radius())
- {
- return false;
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_frustum_box(const Frustum& f, const Box& b)
- {
- uint32_t vertexOutCount;
- for (uint32_t i = 0; i < 6; i++)
- {
- vertexOutCount = 0;
- for (uint32_t j = 0; j < 8; j++)
- {
- if (f.m_planes[i].distance_to_point(b.vertex(j)) < 0.0)
- {
- vertexOutCount++;
- }
- }
- // If all vertices are outside one face, then the box doesn't int32_tersect the frustum
- if (vertexOutCount == 8)
- {
- return false;
- }
- }
- // If we are here, is because either the box int32_tersects or it is contained in the frustum
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_circle_circle(const Circle& c1, const Circle& c2, Vec2& penetration)
- {
- Vec2 distance = c1.center() - c2.center();
- float distanceLen2 = distance.squared_length();
- float radiusSum = c1.radius() + c2.radius();
- if (distanceLen2 > radiusSum*radiusSum)
- {
- return false;
- }
- if (distanceLen2 < 0.001)
- {
- penetration = Vec2(c1.radius(), 0.0);
- }
- else
- {
- distanceLen2 = math::sqrt(distanceLen2);
- penetration = distance * ((radiusSum - distanceLen2) / distanceLen2);
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_dynamic_circle_circle(const Circle& c1, const Vec2& d1, const Circle& c2, const Vec2& d2, float& it)
- {
- // c1 == static circle
- // c2 == moving circle
- Vec2 d = d2 - d1;
- d.normalize();
- const Vec2& cs = c1.center();
- const Vec2& cm = c2.center();
- Vec2 e = cs - cm;
- float r = c1.radius() + c2.radius();
- // If ||e|| < r, int32_tersection occurs at t = 0
- if (e.length() < r)
- {
- it = 0.0;
- return true;
- }
- // it == Intersection Time
- float ed = e.dot(d);
- float squared = (ed * ed) + (r * r) - e.dot(e);
- // If the value inside the square root is neg, then no int32_tersection
- if (squared < 0.0)
- {
- return false;
- }
- float t = ed - math::sqrt(squared);
- float l = (d2 - d1).length();
- // If t < 0 || t > l, then non int32_tersection in the considered period of time
- if (t < 0.0 || t > l)
- {
- return false;
- }
- it = t / l;
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_rect_rect(const Rect& r1, const Rect& r2, Vec2& penetration)
- {
- //x
- float min1MinusMax2 = r1.min().x - r2.max().x;
- float min2MinusMax1 = r2.min().x - r1.max().x;
- if (min1MinusMax2 > min2MinusMax1)
- {
- if (min1MinusMax2 > 0)
- {
- return false;
- }
- penetration.x = -min1MinusMax2;
- }
- else
- {
- if (min2MinusMax1 > 0)
- {
- return false;
- }
- penetration.x = min2MinusMax1;
- }
- //y
- min1MinusMax2 = r1.min().y - r2.max().y;
- min2MinusMax1 = r2.min().y - r1.max().y;
- if (min1MinusMax2 > min2MinusMax1)
- {
- if (min1MinusMax2 > 0)
- {
- return false;
- }
- penetration.y = -min1MinusMax2;
- }
- else
- {
- if (min2MinusMax1 > 0)
- {
- return false;
- }
- penetration.y = min2MinusMax1;
- }
- if (math::abs(penetration.x) < math::abs(penetration.y))
- {
- penetration.y = 0.0;
- }
- else
- {
- penetration.x = 0.0;
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- inline bool Intersection::test_circle_rect(const Circle& c1, const Rect& r2, Vec2& penetration)
- {
- bool circleIsAtRight;
- if (c1.center().x > (r2.min().x + r2.max().x) / 2)
- {
- penetration.x = (c1.center().x - c1.radius()) - r2.max().x;
- circleIsAtRight = true;
- }
- else
- {
- penetration.x = r2.min().x - (c1.center().x + c1.radius());
- circleIsAtRight = false;
- }
- bool circleIsAtTop;
- if (c1.center().y > (r2.min().y + r2.max().y) / 2)
- {
- penetration.y = (c1.center().y - c1.radius()) - r2.max().y;
- circleIsAtTop = true;
- }
- else
- {
- penetration.y = r2.min().y - (c1.center().y + c1.radius());
- circleIsAtTop = false;
- }
- if (penetration.x < -c1.radius() || penetration.y < -c1.radius())
- {
- if (penetration.y > 0 || penetration.x > 0)
- {
- return false;
- }
- if (penetration.x > penetration.y)
- {
- penetration.y = 0;
- }
- else
- {
- penetration.x = 0;
- }
- }
- //else if (penetration.y < -c1.radius())
- //{
- // if (penetration.x > 0)
- // {
- // return false;
- // }
- // penetration.y = 0;
- //}
- else
- {
- penetration += Vec2(c1.radius(), c1.radius());
- float len = math::sqrt(penetration.squared_length());
- if (len > c1.radius())
- {
- return false;
- }
- //The - is to point32_t outwards
- penetration *= - (c1.radius() - len) / len;
- }
- if (circleIsAtRight)
- {
- penetration.x *= -1;
- }
- if (circleIsAtTop)
- {
- penetration.y *= -1;
- }
-
- return true;
- }
- } // namespace crown
|