WIP, should take shortest resolution even if forced upwards because of slopes, not solving the jittering problem though. + debug code.
This commit is contained in:
@@ -380,11 +380,11 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
|
|
||||||
enum BoxTriResolveCase
|
enum BoxTriResolveCase
|
||||||
{
|
{
|
||||||
ResolveDimX,
|
EResolveDimX,
|
||||||
ResolveDimY,
|
EResolveDimY,
|
||||||
ResolveDimZ,
|
EResolveDimZ,
|
||||||
Line, //Box edge colliding with triangle line.
|
ELine, //Box edge colliding with triangle line.
|
||||||
Corner //Box corner colliding with the triangle face.
|
ECorner //Box corner colliding with the triangle face.
|
||||||
};
|
};
|
||||||
struct Resolution
|
struct Resolution
|
||||||
{
|
{
|
||||||
@@ -396,10 +396,55 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
float DistanceSq;
|
float DistanceSq;
|
||||||
glm::vec3 Vector;
|
glm::vec3 Vector;
|
||||||
};
|
};
|
||||||
|
struct CaseResolutions
|
||||||
|
{
|
||||||
|
Resolution Vertex;
|
||||||
|
Resolution Line;
|
||||||
|
Resolution Corner;
|
||||||
|
Resolution* Shortest = &Vertex;
|
||||||
|
|
||||||
|
void AddResolution(BoxTriResolveCase resCase, float distanceSq, const glm::vec3& resVec)
|
||||||
|
{
|
||||||
|
switch (resCase) {
|
||||||
|
case EResolveDimY:
|
||||||
|
case EResolveDimX:
|
||||||
|
case EResolveDimZ:
|
||||||
|
if (distanceSq < Vertex.DistanceSq) {
|
||||||
|
Vertex.Vector = resVec;
|
||||||
|
Vertex.DistanceSq = distanceSq;
|
||||||
|
Vertex.Case = resCase;
|
||||||
|
if (distanceSq < Line.DistanceSq) {
|
||||||
|
Shortest = &Vertex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ELine:
|
||||||
|
if (distanceSq < Vertex.DistanceSq && distanceSq < Line.DistanceSq) {
|
||||||
|
Line.Vector = resVec;
|
||||||
|
Line.DistanceSq = distanceSq;
|
||||||
|
Line.Case = resCase;
|
||||||
|
Shortest = &Line;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ECorner:
|
||||||
|
//NOTE: It is assumed that the Corner is less than the
|
||||||
|
//added resolution, since only one corner should be added per triangle.
|
||||||
|
if (distanceSq < Vertex.DistanceSq && distanceSq < Line.DistanceSq) {
|
||||||
|
Corner.Vector = resVec;
|
||||||
|
Corner.DistanceSq = distanceSq;
|
||||||
|
Corner.Case = resCase;
|
||||||
|
Shortest = &Corner;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
//The smallest resolution that solves the collision.
|
//The smallest resolution that solves the collision.
|
||||||
Resolution resolveShortest;
|
CaseResolutions resolveShortest;
|
||||||
//The smallest resolution that solves the collision, that resolves upwards.
|
//The smallest resolution that solves the collision, that resolves upwards.
|
||||||
Resolution resolveUpwards;
|
CaseResolutions resolveUpwards;
|
||||||
//If player stands on the ground and collides with a ground triangle,
|
//If player stands on the ground and collides with a ground triangle,
|
||||||
//we might step up onto it if the step is small enough.
|
//we might step up onto it if the step is small enough.
|
||||||
bool canStairStepUp = isOnGround && FaceIsGround(triNormal.y);
|
bool canStairStepUp = isOnGround && FaceIsGround(triNormal.y);
|
||||||
@@ -421,34 +466,27 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
//Project box.
|
//Project box.
|
||||||
glm::vec2 boxMin(min[dim.first], min[dim.second]);
|
glm::vec2 boxMin(min[dim.first], min[dim.second]);
|
||||||
glm::vec2 boxMax(max[dim.first], max[dim.second]);
|
glm::vec2 boxMax(max[dim.first], max[dim.second]);
|
||||||
glm::vec2 resolutionVector;
|
glm::vec2 resolutionVector2D;
|
||||||
float resolutionDist;
|
float resolutionDistSq;
|
||||||
bool pushedFromTriangleLine;
|
bool pushedFromTriangleLine;
|
||||||
//if projections don't overlap, return false.
|
//if projections don't overlap, return false.
|
||||||
if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist, pushedFromTriangleLine)) {
|
if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector2D, resolutionDistSq, pushedFromTriangleLine)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (resolveCollision) {
|
} else if (resolveCollision) {
|
||||||
|
glm::vec3 resolve3D = glm::vec3(0.f);
|
||||||
|
resolve3D[dim.first] = resolutionVector2D.x;
|
||||||
|
resolve3D[dim.second] = resolutionVector2D.y;
|
||||||
|
//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).
|
||||||
|
BoxTriResolveCase resCase = pushedFromTriangleLine ? ELine : static_cast<BoxTriResolveCase>((abs(resolve3D[dim.first]) < 0.0001f) ? dim.second : dim.first);
|
||||||
//Overwrite the smallest resolution if this is smaller.
|
//Overwrite the smallest resolution if this is smaller.
|
||||||
if (resolutionDist < resolveShortest.DistanceSq) {
|
resolveShortest.AddResolution(resCase, resolutionDistSq, resolve3D);
|
||||||
resolveShortest.Vector = glm::vec3(0.f);
|
|
||||||
resolveShortest.Vector[dim.first] = resolutionVector.x;
|
|
||||||
resolveShortest.Vector[dim.second] = resolutionVector.y;
|
|
||||||
resolveShortest.DistanceSq = resolutionDist;
|
|
||||||
//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).
|
|
||||||
resolveShortest.Case = pushedFromTriangleLine ? Line : static_cast<BoxTriResolveCase>((abs(resolveShortest.Vector[dim.first]) < 0.0001f) ? dim.second : dim.first);
|
|
||||||
}
|
|
||||||
//Overwrite the smallest upward resolution if this is smaller, and resolves upwards.
|
//Overwrite the smallest upward resolution if this is smaller, and resolves upwards.
|
||||||
constexpr int yAxis = 1;
|
constexpr int yAxis = 1;
|
||||||
bool resIsUpwardsIn3D = dim.first == yAxis && resolutionVector.x > 0 || dim.second == yAxis && resolutionVector.y > 0;
|
bool resIsUpwardsIn3D = dim.first == yAxis && resolutionVector2D.x > 0 || dim.second == yAxis && resolutionVector2D.y > 0;
|
||||||
if (canStairStepUp && resIsUpwardsIn3D && resolutionDist < resolveUpwards.DistanceSq) {
|
if (canStairStepUp && resIsUpwardsIn3D) {
|
||||||
resolveUpwards.Vector = glm::vec3(0.f);
|
resolveUpwards.AddResolution(resCase, resolutionDistSq, resolve3D);
|
||||||
resolveUpwards.Vector[dim.first] = resolutionVector.x;
|
|
||||||
resolveUpwards.Vector[dim.second] = resolutionVector.y;
|
|
||||||
resolveUpwards.DistanceSq = resolutionDist;
|
|
||||||
//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).
|
|
||||||
resolveUpwards.Case = pushedFromTriangleLine ? Line : static_cast<BoxTriResolveCase>((abs(resolveUpwards.Vector[dim.first]) < 0.0001f) ? dim.second : dim.first);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,37 +510,40 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
glm::vec3 cornerResolution = (1+t) * diagonal;
|
glm::vec3 cornerResolution = (1+t) * diagonal;
|
||||||
//Overwrite the smallest resolution if cornerResolution is smaller.
|
//Overwrite the smallest resolution if cornerResolution is smaller.
|
||||||
float lenSq = glm::length2(cornerResolution);
|
float lenSq = glm::length2(cornerResolution);
|
||||||
if (lenSq < resolveShortest.DistanceSq) {
|
resolveShortest.AddResolution(ECorner, lenSq, cornerResolution);
|
||||||
resolveShortest.Vector = cornerResolution;
|
if (canStairStepUp && cornerResolution.y > 0) {
|
||||||
resolveShortest.Case = Corner;
|
resolveUpwards.AddResolution(ECorner, lenSq, cornerResolution);
|
||||||
}
|
|
||||||
if (canStairStepUp && cornerResolution.y > 0 && lenSq < resolveUpwards.DistanceSq) {
|
|
||||||
resolveUpwards.Vector = cornerResolution;
|
|
||||||
resolveUpwards.Case = Corner;
|
|
||||||
resolveUpwards.DistanceSq = lenSq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Force the resolution upwards if it is smaller than the threshold verticalStepHeight.
|
//Force the resolution upwards if it is smaller than the threshold verticalStepHeight.
|
||||||
//Else take the shortest resolution.
|
//Else take the shortest resolution.
|
||||||
bool takeUp = resolveUpwards.Vector.y > 0 && resolveUpwards.Vector.y < verticalStepHeight;
|
bool takeUp = resolveUpwards.Shortest->Vector.y > 0 && resolveUpwards.Shortest->Vector.y < verticalStepHeight;
|
||||||
Resolution& bestResolve = takeUp ? resolveUpwards : resolveShortest;
|
CaseResolutions& bestResolve = takeUp ? resolveUpwards : resolveShortest;
|
||||||
outResolution = bestResolve.Vector;
|
outResolution = bestResolve.Shortest->Vector;
|
||||||
|
|
||||||
|
std::string dbgString = "";
|
||||||
glm::vec3 projNorm;
|
glm::vec3 projNorm;
|
||||||
switch (bestResolve.Case) {
|
switch (bestResolve.Shortest->Case) {
|
||||||
case ResolveDimY:
|
case EResolveDimY:
|
||||||
boxVelocity.y = 0.f;
|
boxVelocity.y = 0.f;
|
||||||
if (outResolution.y > 0)
|
if (outResolution.y > 0)
|
||||||
isOnGround = true;
|
isOnGround = true;
|
||||||
case ResolveDimX:
|
case EResolveDimX:
|
||||||
case ResolveDimZ:
|
case EResolveDimZ:
|
||||||
//If we get here, the resolution is along one coordinate axis.
|
//If we get here, the resolution is along one coordinate axis.
|
||||||
//set velocity to 0 in y if it is along y-axis.
|
//set velocity to 0 in y if it is along y-axis.
|
||||||
|
dbgString = "Vertex Collision";
|
||||||
|
dbgString += isOnGround ? " Ground" : " Air";
|
||||||
|
dbgString += takeUp ? " Force up" : " Normal";
|
||||||
|
std::cout << (dbgString.c_str()) << std::endl;
|
||||||
|
ImGui::Text(dbgString.c_str());
|
||||||
return true;
|
return true;
|
||||||
case Line:
|
case ELine:
|
||||||
|
dbgString = "Line Collision";
|
||||||
projNorm = glm::normalize(outResolution);
|
projNorm = glm::normalize(outResolution);
|
||||||
break;
|
break;
|
||||||
case Corner:
|
case ECorner:
|
||||||
|
dbgString = "Corner Collision";
|
||||||
projNorm = triNormal;
|
projNorm = triNormal;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -519,6 +560,23 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
outResolution.y = len / glm::sin(ang);
|
outResolution.y = len / glm::sin(ang);
|
||||||
outResolution.z = 0;
|
outResolution.z = 0;
|
||||||
}
|
}
|
||||||
|
float y;
|
||||||
|
if (bestResolve.Shortest->Case == ECorner) {
|
||||||
|
len = glm::length(bestResolve.Line.Vector);
|
||||||
|
ang = glm::half_pi<float>() - glm::acos(bestResolve.Line.Vector.y / len);
|
||||||
|
if (len > 0.0000001f && ang > 0.0000001f) {
|
||||||
|
y = len / glm::sin(ang);
|
||||||
|
if (y < outResolution.y) {
|
||||||
|
outResolution.x = 0;
|
||||||
|
outResolution.y = y;
|
||||||
|
outResolution.z = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y = bestResolve.Vertex.Vector.y;
|
||||||
|
if (bestResolve.Vertex.Case == EResolveDimY && y < outResolution.y) {
|
||||||
|
outResolution.y = y;
|
||||||
|
}
|
||||||
//Also zero the vertical velocity, if it is positive, else project it onto the normal.
|
//Also zero the vertical velocity, if it is positive, else project it onto the normal.
|
||||||
//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.
|
||||||
@@ -533,6 +591,10 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm;
|
boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dbgString += isOnGround ? " Ground" : " Air";
|
||||||
|
dbgString += takeUp ? " Force up" : " Normal";
|
||||||
|
std::cout << (dbgString.c_str()) << std::endl;
|
||||||
|
ImGui::Text(dbgString.c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,6 +608,7 @@ bool AABBvsTriangles(const AABB& box,
|
|||||||
glm::vec3& outResolutionVector,
|
glm::vec3& outResolutionVector,
|
||||||
bool resolveCollision)
|
bool resolveCollision)
|
||||||
{
|
{
|
||||||
|
std::cout << ("---->>>--AABBvsTriangles--------") << std::endl;
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
|
|
||||||
bool everHitTheGround = false;
|
bool everHitTheGround = false;
|
||||||
@@ -573,6 +636,9 @@ bool AABBvsTriangles(const AABB& box,
|
|||||||
if (!everHitTheGround) {
|
if (!everHitTheGround) {
|
||||||
isOnGround = false;
|
isOnGround = false;
|
||||||
}
|
}
|
||||||
|
std::cout << (isOnGround ? "Hit Ground" : "In Air") << std::endl;
|
||||||
|
ImGui::Text(isOnGround ? "Hit Ground" : "In Air");
|
||||||
|
std::cout << ("--------AABBvsTriangles---->>>--") << std::endl;
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
|||||||
if (!boundingBox) {
|
if (!boundingBox) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::cout << "---->>>--Start Update--------" << std::endl;
|
||||||
ComponentWrapper& cTransform = entity["Transform"];
|
ComponentWrapper& cTransform = entity["Transform"];
|
||||||
EntityAABB& boxA = *boundingBox;
|
EntityAABB& boxA = *boundingBox;
|
||||||
bool everHitTheGround = false;
|
bool everHitTheGround = false;
|
||||||
@@ -115,4 +116,5 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_PrevPositions[entity] = boxA.Origin();
|
m_PrevPositions[entity] = boxA.Origin();
|
||||||
|
std::cout << "--------End Update---->>>--" << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user