Collision affects velocity correctly, no wierd ice cream sliding along walls.
This commit is contained in:
@@ -344,9 +344,10 @@ constexpr float SlopeConstant(float degrees)
|
|||||||
//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) });
|
||||||
|
|
||||||
|
//TODO: Prefer to move in y - if the resolution is small enough, value in physics comp.
|
||||||
|
//TODO: Walking down slopes correctly.
|
||||||
bool AABBvsTriangle(const AABB& box,
|
bool AABBvsTriangle(const AABB& box,
|
||||||
const std::array<glm::vec3, 3>& triPos,
|
const std::array<glm::vec3, 3>& triPos,
|
||||||
const glm::vec3& wantDirection,
|
|
||||||
glm::vec3& boxVelocity,
|
glm::vec3& boxVelocity,
|
||||||
glm::vec3& outVector)
|
glm::vec3& outVector)
|
||||||
{
|
{
|
||||||
@@ -354,7 +355,7 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
//Also, don't check a triangle facing away from the player.
|
//Also, don't check a triangle facing away from the player.
|
||||||
//Less checks, and we should be able to walk out from models if we are trapped inside.
|
//Less checks, and we should be able to walk out from models if we are trapped inside.
|
||||||
glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]);
|
glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]);
|
||||||
if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0) && vectorHasLength(boxVelocity)) {
|
if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,40 +429,56 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
{
|
{
|
||||||
//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 that dimension.
|
//set velocity to 0 in that dimension.
|
||||||
|
//projNorm = glm::vec3(0.f);
|
||||||
|
//projNorm[resolveCase] = 1;
|
||||||
|
//ImGui::Text(("Axis " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z);
|
||||||
boxVelocity[resolveCase] = 0.f;
|
boxVelocity[resolveCase] = 0.f;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Line:
|
case Line:
|
||||||
projNorm = glm::normalize(outVector);
|
projNorm = glm::normalize(outVector);
|
||||||
|
//ImGui::Text(("Line " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z);
|
||||||
break;
|
break;
|
||||||
case Corner:
|
case Corner:
|
||||||
projNorm = triNormal;
|
projNorm = triNormal;
|
||||||
|
//ImGui::Text(("Corner " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Project the velocity onto the normal of the hit line/face.
|
|
||||||
//w = v - <v,n>*n, |n|==1.
|
|
||||||
boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm;
|
|
||||||
//If the collision was not on steep wall or similarly (e.g. walking on the ground), do special treatment.
|
//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:
|
//Magic value that makes condition correspond to:
|
||||||
//if the angle between horizon and the collision surface is less than 45 degrees.
|
//if the angle between horizon and the collision surface is less than 45 degrees.
|
||||||
if (projNorm.y > SlopeConstant(45.0f)) {
|
if (projNorm.y > SlopeConstant(45.0f)) {
|
||||||
//Make sure the player keeps moving in their desired direction, just slower.
|
|
||||||
float len = glm::length2(boxVelocity);
|
|
||||||
if (len > 0.0001f) {
|
|
||||||
boxVelocity = glm::sqrt(len) * wantDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Ensure that the player always is moved upwards, instead of sliding down.
|
//Ensure that the player always is moved upwards, instead of sliding down.
|
||||||
len = glm::length(outVector);
|
//Also zero the vertical velocity.
|
||||||
|
float 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) {
|
||||||
outVector.x = 0;
|
outVector.x = 0;
|
||||||
outVector.y = len / glm::sin(ang);
|
outVector.y = len / glm::sin(ang);
|
||||||
outVector.z = 0;
|
outVector.z = 0;
|
||||||
|
boxVelocity.y = 0.f;
|
||||||
}
|
}
|
||||||
|
} else if (projNorm.y > 0) {
|
||||||
|
//Enter here if the triangle is a steep slope, and it is not facing downwards.
|
||||||
|
//Project the velocity onto the normal of the hit line/face.
|
||||||
|
//w = v - <v,n>*n, |n|==1.
|
||||||
|
boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm;
|
||||||
|
|
||||||
|
//Ensure that the player will be pushed in the xz-plane.
|
||||||
|
//glm::vec3 moveDir(outVector);
|
||||||
|
//moveDir.y = 0;
|
||||||
|
//if (vectorHasLength(moveDir)) {
|
||||||
|
// moveDir = glm::normalize(moveDir);
|
||||||
|
// float len = glm::length(outVector);
|
||||||
|
// float dotMoveOut = moveDir.x * outVector.x + moveDir.z * outVector.z;
|
||||||
|
// float ang = glm::half_pi<float>() - glm::acos(dotMoveOut / len);
|
||||||
|
// if (len > 0.0000001f && ang > 0.0000001f) {
|
||||||
|
// outVector = (len / glm::sin(ang)) * moveDir;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -477,11 +494,6 @@ bool AABBvsTriangles(const AABB& box,
|
|||||||
|
|
||||||
AABB newBox = box;
|
AABB newBox = box;
|
||||||
outResolutionVector = glm::vec3(0.f);
|
outResolutionVector = glm::vec3(0.f);
|
||||||
glm::vec3 wantDirection(boxVelocity);
|
|
||||||
wantDirection.y = 0;
|
|
||||||
if (vectorHasLength(wantDirection)) {
|
|
||||||
wantDirection = glm::normalize(wantDirection);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < modelIndices.size(); ) {
|
for (int i = 0; i < modelIndices.size(); ) {
|
||||||
std::array<glm::vec3, 3> triVertices = {
|
std::array<glm::vec3, 3> triVertices = {
|
||||||
Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix),
|
Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix),
|
||||||
@@ -489,7 +501,7 @@ bool AABBvsTriangles(const AABB& box,
|
|||||||
Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix)
|
Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix)
|
||||||
};
|
};
|
||||||
glm::vec3 outVec;
|
glm::vec3 outVec;
|
||||||
if (AABBvsTriangle(newBox, triVertices, wantDirection, boxVelocity, outVec)) {
|
if (AABBvsTriangle(newBox, triVertices, boxVelocity, outVec)) {
|
||||||
hit = true;
|
hit = true;
|
||||||
outResolutionVector += outVec;
|
outResolutionVector += outVec;
|
||||||
newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size());
|
newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size());
|
||||||
|
|||||||
Reference in New Issue
Block a user