13#ifndef TOYMAKERENGINE_SPATIALQUERYMATH_H
14#define TOYMAKERENGINE_SPATIALQUERYMATH_H
22 static constexpr uint8_t kMaxIterations { 64 };
73 bool overlaps(
const Ray& ray,
const ObjectBounds& bounds);
86 bool overlaps(
const glm::vec3& point,
const AxisAlignedBounds& bounds);
100 bool overlaps(
const Ray& ray,
const AxisAlignedBounds& bounds);
114 bool overlaps(
const AxisAlignedBounds& one,
const AxisAlignedBounds& two);
120 bool overlaps(
const ObjectBounds& one,
const ObjectBounds& two);
126 bool overlaps(
const AxisAlignedBounds& one,
const ObjectBounds& two);
151 template <
typename T,
typename U>
152 std::pair<bool, Simplex>
gjkOverlaps(
const T& one,
const U& two);
166 template <
typename T,
typename U>
167 Polytope
buildPolytope(
const T& one,
const U& two,
const Simplex& gjkSimplex);
185 template <
typename T,
typename U>
193 bool contains(
const glm::vec3& point,
const ObjectBounds& bounds);
199 bool contains(
const glm::vec3& point,
const AxisAlignedBounds& bounds);
205 bool contains(
const Ray& ray,
const AxisAlignedBounds& bounds);
211 bool contains(
const Ray& ray,
const ObjectBounds& bounds);
217 bool contains(
const AxisAlignedBounds& one,
const AxisAlignedBounds& two);
223 bool contains(
const ObjectBounds& one,
const AxisAlignedBounds& two);
234 assert(
isFinite(vector) &&
"Vector must be finite");
235 assert(squareDistance(vector) &&
"Zero vectors are invalid as basis for tangents");
237 const auto normalized { glm::normalize(vector) };
238 const glm::vec3 tangentPrelim { ((glm::abs(normalized.x) >= .57735f) ?
239 glm::vec3{ normalized.y, -normalized.x, 0.f } : glm::vec3{ 0.f, normalized.z, -normalized.y }
241 const glm::vec3 tangent2 {
242 glm::normalize(glm::cross(tangentPrelim, normalized))
245 return { glm::normalize(glm::cross(normalized, tangent2)), tangent2 };
257 template<
typename T,
typename U>
259 const glm::vec3 supportOne { one.getSupportAlong(along) };
260 const glm::vec3 supportTwo { two.getSupportAlong(-along) };
261 return supportOne - supportTwo;
275 template<
typename T,
typename U>
276 inline std::tuple<glm::vec3, glm::vec3, glm::vec3>
minkowskiDifferenceFull(
const T& one,
const U& two,
const glm::vec3& along) {
277 const glm::vec3 supportOne { one.getSupportAlong(along) };
278 const glm::vec3 supportTwo { two.getSupportAlong(-along) };
279 return { supportOne - supportTwo, supportOne, supportTwo };
282 template <
typename T,
typename U>
283 inline std::pair<bool, Simplex>
gjkOverlaps(
const T& one,
const U& two) {
284 assert(one.isSensible() && two.isSensible() &&
"Invalid object bounds provided");
287 if(!one.isPositiveStrict() || !two.isPositiveStrict()) {
292 glm::vec3 searchDirection { two.getComputedWorldPosition() - one.getComputedWorldPosition() };
295 if(squareDistance(searchDirection) == 0.f) {
301 const auto& candidatePoint { std::get<0>(fullDifference) };
302 const auto& supportA { std::get<1>(fullDifference) };
303 const auto& supportB { std::get<2>(fullDifference) };
304 simplex.
append(candidatePoint, supportA, supportB);
307 searchDirection = squareDistance(simplex.
mPoints[0]) ? -simplex.
mPoints[0]: glm::vec3 { 1.f, 0.f, 0.f };
308 bool found {
false };
309 for(uint8_t iteration { 0 }; iteration < kMaxIterations; ++iteration) {
313 if(!squareDistance(searchDirection)) {
314 const float signMult { (iteration & 1)? -1.f: 1.f };
318 const float signMult2 { (iteration & 2)? -1.f: 1.f };
319 const glm::vec3 dirAB { glm::normalize(simplex.
mPoints[1] - simplex.
mPoints[0]) };
320 assert(squareDistance(dirAB) > 0 &&
"A and B should never be the same point");
322 const glm::vec3 dirOffset { (dirAB.x != 0.f || dirAB.z != 0.f)?
323 glm::vec3{ 0.f, signMult * 1.f, 0.f } : glm::vec3{ signMult2 * 1.f, 0.f, signMult * 1.f }
326 searchDirection = -dirAB + dirOffset;
330 const glm::vec3 normABC { glm::normalize(glm::cross(simplex.
mPoints[1] - simplex.
mPoints[0], simplex.
mPoints[2] - simplex.
mPoints[0])) };
331 searchDirection = signMult * normABC;
334 assert(
false &&
"A simplex with 4 points is not degenerate, and there's no solving necessary here");
341 if(glm::dot(candidatePoint, searchDirection) <= 0) {
342 return {
false, simplex };
348 if(!simplex.
append(candidatePoint, supportA, supportB)) {
349 searchDirection = glm::vec3 { 0.f, 0.f, 0.f };
353 const auto result { simplex.
evaluate() };
355 return {
true, simplex };
358 searchDirection = result.second;
360 assert(
false &&
"We should not have exited the loop without finding a simplex");
361 return {
false, simplex };
364 template <
typename T,
typename U>
367 const std::pair<bool, Simplex> overlapResult {
gjkOverlaps(one, two) };
368 if(!overlapResult.first) {
370 .mCollided {
false },
388 const glm::mat3 barycentricSolver { glm::inverse(glm::mat3 {
391 const glm::vec3 barycentricCoordinates {
392 barycentricSolver * closestPoint
402 const glm::mat3 barycentricOne {
405 const glm::mat3 barycentricTwo {
408 collisionResult.
mContactA.
mPoint = barycentricOne * barycentricCoordinates;
409 collisionResult.
mContactB.
mPoint = barycentricTwo * barycentricCoordinates;
423 return collisionResult;
426 template <
typename T,
typename U>
430 assert(squareDistance(searchDirection) > 0 &&
"Search direction should always be non-zero");
431 assert(
isFinite(searchDirection) &&
"Search direction should always be finite");
434 std::tuple<glm::vec3, glm::vec3, glm::vec3> differenceFull {
minkowskiDifferenceFull(one, two, searchDirection) };
438 const glm::vec3& supportA { std::get<1>(differenceFull) };
439 const glm::vec3& supportB { std::get<2>(differenceFull) };
440 const glm::vec3& difference { std::get<0>(differenceFull) };
443 uint8_t iterationsLeft { kMaxIterations };
444 while(polytope.
append(difference, supportA, supportB) && iterationsLeft--) {
An object containing a coarse simplified representation, AABB, of spatially queryable objects.
Definition types.hpp:1138
Primitive for EPA algorithm.
Definition types.hpp:708
AreaTriangle getClosestTriangle() const
Returns the closest polytope triangle.
Definition types.cpp:88
AreaTriangle getClosestTriangleSupportB() const
Gets the points of shape B that were responsible for generating the closest triangle of the polytope.
Definition types.cpp:106
bool append(const glm::vec3 &newPoint, const glm::vec3 &supportA, const glm::vec3 &supportB)
Appends a new point, replacing the topmost triangle in the polygon with 3 more triangles including th...
Definition types.cpp:138
glm::vec3 getClosestPoint() const
Returns the closest point to the origin on the triangle face closest to the origin.
Definition types.cpp:74
AreaTriangle getClosestTriangleSupportA() const
Gets the points of shape A that were responsible for generating the closest triangle of the polytope.
Definition types.cpp:97
glm::vec3 getNextSearch() const
Returns the next search direction for a point to add to the polytope.
Definition types.cpp:63
bool contains(const glm::vec3 &point, const ObjectBounds &bounds)
Returns whether point is contained by bounds.
Definition math.cpp:289
std::pair< bool, glm::vec3 > computeIntersection(const Ray &ray, const Plane &plane)
Returns a bool-vector pair, with bool indicating whether a point of intersection was found,...
Definition math.cpp:44
glm::vec3 minkowskiDifference(const T &one, const U &two, const glm::vec3 &along)
Closely associated with GJK; finds the Minkowski difference between two shapes situated somewhere in ...
Definition math.hpp:258
std::pair< uint8_t, std::pair< glm::vec3, glm::vec3 > > computeIntersections(const Ray &ray, const AxisAlignedBounds &axisAlignedBounds)
Returns an unsigned int and vector-pair pair, with unsigned indicating whether any and how many point...
Definition math.cpp:127
bool overlaps(const glm::vec3 &point, const ObjectBounds &bounds)
Returns a bool value indicating whether point is contained by bounds.
Definition math.cpp:168
std::pair< glm::vec3, glm::vec3 > deriveTangents(const glm::vec3 &vector)
Returns a pair of tangents to an input vector.
Definition math.hpp:233
std::tuple< glm::vec3, glm::vec3, glm::vec3 > minkowskiDifferenceFull(const T &one, const U &two, const glm::vec3 &along)
Closely associated with GJK; finds the Minkowski difference between two shapes situated somewhere in ...
Definition math.hpp:276
bool isFinite(float number)
Tests whether a given number is finite.
Definition types.hpp:57
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition application.hpp:24
std::pair< bool, Simplex > gjkOverlaps(const T &one, const U &two)
GJK implementation based on Casey Muratori's video lecture, which is available here.
Definition math.hpp:283
Collision checkCollision(const T &one, const U &two)
Checks whether a pair of convex 3D shapes are colliding, returning information about the collision if...
Definition math.hpp:365
Polytope buildPolytope(const T &one, const U &two, const Simplex &gjkSimplex)
EPA implementation, used to derive contact information for intersections between convex shapes.
Definition math.hpp:427
A set of 3 points located in the world forming a (hopefully sensible) triangle.
Definition types.hpp:392
std::array< glm::vec3, 3 > mPoints
The points of the triangle, where each point has 3 components.
Definition types.hpp:397
Data representing everything about a collision.
Definition types.hpp:888
Contact mContactA
Contact information relative to the first collision shape.
Definition types.hpp:899
Contact mContactB
Contact information relative to the second collision shape.
Definition types.hpp:905
A component defining the true bounds of a spatially queryable object situated somewhere in the world.
Definition types.hpp:917
A set of numbers describing a plane situated somewhere in the world.
Definition types.hpp:564
A set of numbers describing a ray with its source at some finite point in the world,...
Definition types.hpp:511
Primitive for GJK algorithm.
Definition types.hpp:613
std::pair< bool, glm::vec3 > evaluate()
Tries to find a 3-simplex that encloses the origin.
Definition types.cpp:581
bool append(const glm::vec3 &candidatePoint, const glm::vec3 &supportA, const glm::vec3 &supportB)
Adds a new point to the simplex.
Definition types.hpp:645
uint8_t mNPoints
The number of points in this simplex.
Definition types.hpp:637
std::array< glm::vec3, 4 > mPoints
Points representing the simplex, derived by finding the Minksowski difference of support points on tw...
Definition types.hpp:619
Classes and structs representing data related to the engine's spatial query system (the precursor to ...