Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
EPAPenetrationDepth Class Reference

#include <EPAPenetrationDepth.h>

Public Types

enum class  EStatus { NotColliding , Colliding , Indeterminate }
 Return code for GetPenetrationDepthStepGJK. More...
 

Public Member Functions

template<typename AE , typename BE >
EStatus GetPenetrationDepthStepGJK (const AE &inAExcludingConvexRadius, float inConvexRadiusA, const BE &inBExcludingConvexRadius, float inConvexRadiusB, float inTolerance, Vec3 &ioV, Vec3 &outPointA, Vec3 &outPointB)
 
template<typename AI , typename BI >
bool GetPenetrationDepthStepEPA (const AI &inAIncludingConvexRadius, const BI &inBIncludingConvexRadius, float inTolerance, Vec3 &outV, Vec3 &outPointA, Vec3 &outPointB)
 
template<typename AE , typename AI , typename BE , typename BI >
bool GetPenetrationDepth (const AE &inAExcludingConvexRadius, const AI &inAIncludingConvexRadius, float inConvexRadiusA, const BE &inBExcludingConvexRadius, const BI &inBIncludingConvexRadius, float inConvexRadiusB, float inCollisionToleranceSq, float inPenetrationTolerance, Vec3 &ioV, Vec3 &outPointA, Vec3 &outPointB)
 
template<typename A , typename B >
bool CastShape (Mat44Arg inStart, Vec3Arg inDirection, float inCollisionTolerance, float inPenetrationTolerance, const A &inA, const B &inB, float inConvexRadiusA, float inConvexRadiusB, bool inReturnDeepestPoint, float &ioLambda, Vec3 &outPointA, Vec3 &outPointB, Vec3 &outContactNormal)
 

Detailed Description

Implementation of Expanding Polytope Algorithm as described in:

Proximity Queries and Penetration Depth Computation on 3D Game Objects - Gino van den Bergen

The implementation of this algorithm does not completely follow the article, instead of splitting triangles at each edge as in fig. 7 in the article, we build a convex hull (removing any triangles that are facing the new point, thereby avoiding the problem of getting really oblong triangles as mentioned in the article).

The algorithm roughly works like:

  • Start with a simplex of the Minkowski sum (difference) of two objects that was calculated by GJK
  • This simplex should contain the origin (or else GJK would have reported: no collision)
  • In cases where the simplex consists of 1 - 3 points, find some extra support points (of the Minkowski sum) to get to at least 4 points
  • Convert this into a convex hull with non-zero volume (which includes the origin)
  • A: Calculate the closest point to the origin for all triangles of the hull and take the closest one
  • Calculate a new support point (of the Minkowski sum) in this direction and add this point to the convex hull
  • This will remove all faces that are facing the new point and will create new triangles to fill up the hole
  • Loop to A until no closer point found
  • The closest point indicates the position / direction of least penetration

Member Enumeration Documentation

◆ EStatus

enum class EPAPenetrationDepth::EStatus
strong

Return code for GetPenetrationDepthStepGJK.

Enumerator
NotColliding 

Returned if the objects don't collide, in this case outPointA/outPointB are invalid.

Colliding 

Returned if the objects penetrate.

Indeterminate 

Returned if the objects penetrate further than the convex radius. In this case you need to call GetPenetrationDepthStepEPA to get the actual penetration depth.

Member Function Documentation

◆ CastShape()

template<typename A , typename B >
bool EPAPenetrationDepth::CastShape ( Mat44Arg  inStart,
Vec3Arg  inDirection,
float  inCollisionTolerance,
float  inPenetrationTolerance,
const A &  inA,
const B &  inB,
float  inConvexRadiusA,
float  inConvexRadiusB,
bool  inReturnDeepestPoint,
float &  ioLambda,
Vec3 outPointA,
Vec3 outPointB,
Vec3 outContactNormal 
)
inline

Test if a cast shape inA moving from inStart to lambda * inStart.GetTranslation() + inDirection where lambda e [0, ioLambda> intersects inB

Parameters
inStartStart position and orientation of the convex object
inDirectionDirection of the sweep (ioLambda * inDirection determines length)
inCollisionToleranceThe minimal distance between A and B before they are considered colliding
inPenetrationToleranceA factor that determines the accuracy of the result. If the change of the squared distance is less than inTolerance * current_penetration_depth^2 the algorithm will terminate. Should be bigger or equal to FLT_EPSILON.
inAThe convex object A, must support the GetSupport(Vec3) function.
inBThe convex object B, must support the GetSupport(Vec3) function.
inConvexRadiusAThe convex radius of A, this will be added on all sides to pad A.
inConvexRadiusBThe convex radius of B, this will be added on all sides to pad B.
inReturnDeepestPointIf the shapes are initially intersecting this determines if the EPA algorithm will run to find the deepest point
ioLambdaThe max fraction along the sweep, on output updated with the actual collision fraction.
outPointAis the contact point on A
outPointBis the contact point on B
outContactNormalis either the contact normal when the objects are touching or the penetration axis when the objects are penetrating at the start of the sweep (pointing from A to B, length will not be 1)
Returns
true if the a hit was found, in which case ioLambda, outPointA, outPointB and outSurfaceNormal are updated.

◆ GetPenetrationDepth()

template<typename AE , typename AI , typename BE , typename BI >
bool EPAPenetrationDepth::GetPenetrationDepth ( const AE &  inAExcludingConvexRadius,
const AI &  inAIncludingConvexRadius,
float  inConvexRadiusA,
const BE &  inBExcludingConvexRadius,
const BI &  inBIncludingConvexRadius,
float  inConvexRadiusB,
float  inCollisionToleranceSq,
float  inPenetrationTolerance,
Vec3 ioV,
Vec3 outPointA,
Vec3 outPointB 
)
inline

This function combines the GJK and EPA steps and is provided as a convenience function. Note: less performant since you're providing all support functions in one go Note 2: You need to initialize ioV, see documentation at GetPenetrationDepthStepGJK!

◆ GetPenetrationDepthStepEPA()

template<typename AI , typename BI >
bool EPAPenetrationDepth::GetPenetrationDepthStepEPA ( const AI &  inAIncludingConvexRadius,
const BI &  inBIncludingConvexRadius,
float  inTolerance,
Vec3 outV,
Vec3 outPointA,
Vec3 outPointB 
)
inline

Calculates penetration depth between two objects, second step (the EPA step)

Parameters
inAIncludingConvexRadiusObject A with convex radius
inBIncludingConvexRadiusObject B with convex radius
inToleranceA factor that determines the accuracy of the result. If the change of the squared distance is less than inTolerance * current_penetration_depth^2 the algorithm will terminate. Should be bigger or equal to FLT_EPSILON.
outVDirection to move B out of collision along the shortest path (magnitude is meaningless)
outPointAPosition on A that has the least amount of penetration
outPointBPosition on B that has the least amount of penetration Use |outPointB - outPointA| to get the distance of penetration
Returns
False if the objects don't collide, in this case outPointA/outPointB are invalid. True if the objects penetrate

◆ GetPenetrationDepthStepGJK()

template<typename AE , typename BE >
EStatus EPAPenetrationDepth::GetPenetrationDepthStepGJK ( const AE &  inAExcludingConvexRadius,
float  inConvexRadiusA,
const BE &  inBExcludingConvexRadius,
float  inConvexRadiusB,
float  inTolerance,
Vec3 ioV,
Vec3 outPointA,
Vec3 outPointB 
)
inline

Calculates penetration depth between two objects, first step of two (the GJK step)

Parameters
inAExcludingConvexRadiusObject A without convex radius.
inBExcludingConvexRadiusObject B without convex radius.
inConvexRadiusAConvex radius for A.
inConvexRadiusBConvex radius for B.
ioVPass in previously returned value or (1, 0, 0). On return this value is changed to direction to move B out of collision along the shortest path (magnitude is meaningless).
inToleranceMinimal distance before A and B are considered colliding.
outPointAPosition on A that has the least amount of penetration.
outPointBPosition on B that has the least amount of penetration. Use |outPointB - outPointA| to get the distance of penetration.

The documentation for this class was generated from the following file: