Created
September 24, 2015 06:25
-
-
Save holland01/12821e9477b4506df86c to your computer and use it in GitHub Desktop.
Quick face-point projection algorithm incorporating SAT concepts for OBB intersection tests. It's pretty primitive, and not full-proof, but it worked well for a time...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
glm::vec3 fetch_point( const point_project_pair& ppp ) | |
{ | |
return ppp.mProjected; | |
} | |
// Returns true if a intersects b | |
bool pointset_intersects( cardinal_plane_normal_t planeType, | |
contact::list_t& contacts, | |
const obb& a, | |
const obb& b, | |
const obb::pointset3D_t& aPointsProj, | |
const obb::pointset3D_t& bPointsProj ) | |
{ | |
uint32_t axis0 = ( ( uint32_t ) planeType + 1 ) % 3; | |
uint32_t axis1 = ( ( uint32_t ) planeType + 2 ) % 3; | |
// The algorithm to compute the max and min of b's cardinal points | |
// is dependent on vector lengths and distances bounded by bPointsProj | |
glm::ext::vec3_maxmin_pair_t mm = | |
glm::ext::maxmin_from_list< obb::pointset3D_t, point_project_pair >( bPointsProj, | |
fetch_point ); | |
bool success = false; | |
// In order to determine whether or not there's in intersection | |
// between aPointsProj and bPointsProj, we use max and min tests | |
// for the axes of the points NOT corresponding to planeType. | |
// For example, if the YZ plane is the cardinal plane whose normal | |
// is most perpendicular to the normal of the face we've projected onto, | |
// then we don't involve a comparison for the x-values of the points | |
// within this set, as they could produce false positives. | |
for ( auto i = aPointsProj.begin(); i != aPointsProj.end(); ++i ) | |
{ | |
const glm::vec3& u = ( *i ).mProjected; | |
if ( glm::ext::range( u, mm.min, mm.max, axis0 ) | |
&& glm::ext::range( u, mm.min, mm.max, axis1 ) ) | |
{ | |
if ( glm::distance( ( *i ).mWorldPointRef, b.origin() ) | |
< glm::distance( a.origin(), b.origin() ) ) | |
{ | |
contacts.insert( std::move( contact( ( *i ).mWorldPointRef ) ) ); | |
} | |
success = true; | |
} | |
} | |
return success; | |
} | |
bool face_intersects( obb::face_type face, | |
contact::list_t& contacts, | |
const obb& a, | |
const obb& b, | |
const obb::pointlist3D_t& aPoints, | |
const obb::pointlist3D_t& bPoints ) | |
{ | |
plane facePlane; | |
b.face_plane( face, facePlane ); | |
// Perform a projection for both point sets, since we need to be comparing in the same plane | |
// in order to know that our tests are accurate | |
obb::pointset3D_t a0( std::move( b.face_project( facePlane, aPoints ) ) ); | |
obb::pointset3D_t b0( std::move( b.face_project( facePlane, bPoints ) ) ); | |
// Find the cardinal plane which is most parallel to the face plane's normal; this | |
// allows us to omit a comparison for one of the points' components. | |
cardinal_plane_normal_t cp = glm::ext::best_cardinal_plane_normal( facePlane.mNormal ); | |
return pointset_intersects( cp, contacts, a, b, a0, b0 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment