More efficient collision resolution case + comments.

This commit is contained in:
William Moberg
2016-02-01 18:06:28 +01:00
parent 5a45f778e6
commit 30b1dab764
+25 -18
View File
@@ -336,6 +336,11 @@ bool rectangleVsTriangle(const glm::vec2& boxMin,
return true; return true;
} }
constexpr float SlopeConstant(float degrees)
{
return (1.0 - degrees / 90.f);
}
//An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 }
constexpr std::array<std::pair<int, int>, 3> dimensionPairs({ std::pair<int, int>(0, 2), std::pair<int, int>(0, 1), std::pair<int, int>(1, 2) }); constexpr std::array<std::pair<int, int>, 3> dimensionPairs({ std::pair<int, int>(0, 2), std::pair<int, int>(0, 1), std::pair<int, int>(1, 2) });
@@ -355,9 +360,11 @@ bool AABBvsTriangle(const AABB& box,
enum BoxTriResolveCase enum BoxTriResolveCase
{ {
Vertex, ResolveDimX,
Line, ResolveDimY,
Corner ResolveDimZ,
Line, //Box edge colliding with triangle line.
Corner //Box corner colliding with the triangle face.
} resolveCase; } resolveCase;
const glm::vec3& origin = box.Origin(); const glm::vec3& origin = box.Origin();
@@ -389,7 +396,9 @@ bool AABBvsTriangle(const AABB& box,
outVector[dim.first] = resolutionVector.x; outVector[dim.first] = resolutionVector.x;
outVector[dim.second] = resolutionVector.y; outVector[dim.second] = resolutionVector.y;
minimumTranslation = resolutionDist; minimumTranslation = resolutionDist;
resolveCase = pushedFromTriangleLine ? Line : Vertex; //If we pushed away from triangle line (edge), or if we
//move the player along one coordinate axis (pick the dimension that isn't zero).
resolveCase = pushedFromTriangleLine ? Line : static_cast<BoxTriResolveCase>((abs(outVector[dim.first]) < 0.0001f) ? dim.second : dim.first);
} }
} }
@@ -411,22 +420,15 @@ bool AABBvsTriangle(const AABB& box,
resolveCase = Corner; resolveCase = Corner;
} }
bool groundCollision = triNormal.y > 0.5f;
glm::vec3 projNorm; glm::vec3 projNorm;
switch (resolveCase) { switch (resolveCase) {
case Vertex: case ResolveDimX:
case ResolveDimY:
case ResolveDimZ:
{ {
int maxD = 0; //If we get here, the resolution is along one coordinate axis.
float maxResolution = 0.f; //set velocity to 0 in that dimension.
for (int d = 0; d < 3; ++d) { boxVelocity[resolveCase] = 0.f;
float resolve = glm::abs(outVector[d]);
if (resolve > maxResolution) {
maxResolution = resolve;
maxD = d;
}
}
boxVelocity[maxD] = 0.f;
return true; return true;
} }
case Line: case Line:
@@ -442,12 +444,17 @@ bool AABBvsTriangle(const AABB& box,
//Project the velocity onto the normal of the hit line/face. //Project the velocity onto the normal of the hit line/face.
//w = v - <v,n>*n, |n|==1. //w = v - <v,n>*n, |n|==1.
boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm;
if (groundCollision) { //If the collision was not on steep wall or similarly (e.g. walking on the ground), do special treatment.
//Magic value that makes condition correspond to:
//if the angle between horizon and the collision surface is less than 45 degrees.
if (projNorm.y > SlopeConstant(45.0f)) {
//Make sure the player keeps moving in their desired direction, just slower.
float len = glm::length2(boxVelocity); float len = glm::length2(boxVelocity);
if (len > 0.0001f) { if (len > 0.0001f) {
boxVelocity = glm::sqrt(len) * wantDirection; boxVelocity = glm::sqrt(len) * wantDirection;
} }
//Ensure that the player always is moved upwards, instead of sliding down.
len = glm::length(outVector); len = glm::length(outVector);
float ang = glm::half_pi<float>() - glm::acos(outVector.y / len); float ang = glm::half_pi<float>() - glm::acos(outVector.y / len);
if (len > 0.0000001f && ang > 0.0000001f) { if (len > 0.0000001f && ang > 0.0000001f) {