From 71404c882819a10a4016cf95b032f67736911d11 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sat, 23 Jan 2016 14:01:54 +0100 Subject: [PATCH] Special case for collision vs ground (upward facing) triangles. --- .../Schema/Entities/CollisionTestLevel.xml | 186 ++++++------------ src/Engine/Collision/Collision.cpp | 92 ++++++--- src/Engine/Collision/CollisionSystem.cpp | 1 + 3 files changed, 134 insertions(+), 145 deletions(-) diff --git a/resources/Schema/Entities/CollisionTestLevel.xml b/resources/Schema/Entities/CollisionTestLevel.xml index d5e932c2..76a3b6e6 100644 --- a/resources/Schema/Entities/CollisionTestLevel.xml +++ b/resources/Schema/Entities/CollisionTestLevel.xml @@ -1,122 +1,66 @@ - + + - - - - - - - Models/DummyScene.obj - - - - - - - - - - - Models/Core/UnitSphere.obj - - - - - - - - - - - Models/RotationWidgetX.obj - - - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitRaptor.obj - - - - - - - - - - - - 20 - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + ../assets\Models\Test/ObstacleCourse.obj + + + + + + + + + + + 0.46000027656555176 + + + + + + + + + + + + + ../assets\Models\Core\UnitCube.obj + + + false + + + + + + + + + + + + + + ../assets\Models\Core\colorbox.obj + + + + + + + + + + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index f040ccd5..d134a5d8 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -4,6 +4,7 @@ #include "Engine/GLM.h" #include "Core/World.h" #include "Rendering/Model.h" +#include "imgui/imgui.h" namespace Collision { @@ -248,12 +249,21 @@ bool vectorHasLength(const glm::vec3& vec) return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); } +enum BoxTriHit +{ + Line0 = 0, + Line1, + Line2, + Ground, + Corner +}; + bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outVector, - int& lineHit) + BoxTriHit& outHit) { //Check so we don't have a zero area triangle when calculating the normal. glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); @@ -266,6 +276,23 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); + //Check if normal faces upwards, and if so, just push the box upwards on collision. + triNormal = glm::normalize(triNormal); + if (triNormal.y > 0.5f || true) { + //TODO: Optimize calculation since x, z is 0. + //Ray ray(glm::vec3(origin.x, origin.y + half.y, origin.z), glm::vec3(0, -1, 0)); + //float dist = INFINITY, u, v; + //if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < 2.0f * half.y) { + Ray ray(origin, glm::vec3(0, -1, 0)); + float dist = INFINITY, u, v; + if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < half.y) { + outVector = glm::vec3(0, half.y - dist, 0); + outHit = Ground; + return true; + } + //return false; //TODO: Uncomment? + } + const glm::vec3 triPos[] = { v0, v1, v2 }; @@ -291,7 +318,6 @@ bool AABBvsTriangle(const AABB& box, return false; //If a triangle is completely inside the box, we call it a non-intersection. } - triNormal = glm::normalize(triNormal); Ray ray; //All triangle edges. //Check if any edge on the triangle intersects the box. @@ -302,7 +328,7 @@ bool AABBvsTriangle(const AABB& box, float dist; if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) { outVector = triNormal; - lineHit = l; + outHit = (BoxTriHit)l; return true; } } @@ -341,6 +367,7 @@ bool AABBvsTriangle(const AABB& box, //Distance between triangle plane, and the diagonal corner, multiplied by the normal. //Signed distance, positive if on the same side as the normal. outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; + outHit = Corner; return true; } return false; @@ -348,6 +375,7 @@ bool AABBvsTriangle(const AABB& box, bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) { + AABB newBox = box; struct Triangle { glm::vec3 v0, v1, v2; @@ -362,45 +390,61 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - int lineHit = -1; - if (AABBvsTriangle(box, v0, v1, v2, outVec, lineHit)) + BoxTriHit hitCase; + if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase)) { hit = true; - if (lineHit == -1) { - outResolutionVector += outVec; - //TODO: We might be able to return here instead, having only convex geometry. - cornerHitTODO = true; - //return true; - } - else { - const glm::vec3 triPos[] = { - v0, v1, v2 - }; - glm::vec3 edge = triPos[(lineHit + 1) % 3] - triPos[lineHit]; + switch (hitCase) { + case Collision::Line0: + case Collision::Line1: + case Collision::Line2: + //TODO: Resolve. + //const glm::vec3 triPos[] = { + // v0, v1, v2 + //}; + //glm::vec3 edge = triPos[(hitCase + 1) % 3] - triPos[hitCase]; hitTriangles.push_back({v0, v1, v2}); hitNormals.push_back(outVec); + ImGui::Text("triangle edge collision."); + break; + case Collision::Corner: + //TODO: We might be able to return here instead, having only convex geometry. + cornerHitTODO = true; + //outResolutionVector += outVec; + //return true; + ImGui::Text("triangle corner collision."); + outResolutionVector += outVec; + newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); + break; + case Collision::Ground: + default: + outResolutionVector += outVec; + newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); + ImGui::Text("triangle ground collision."); + break; } } } if (hitTriangles.size() > 0) { if (cornerHitTODO) { - LOG_DEBUG("Both edges and corners was hit on the same model."); + ImGui::Text("Both edges and corners was hit on the same model."); return true; } + glm::vec3 lineResolve(0.f); for (const glm::vec3& norm : hitNormals) { - outResolutionVector += norm; + lineResolve += norm; } //Normalize. - outResolutionVector /= hitNormals.size(); - const glm::vec3& origin = box.Origin(); - const glm::vec3& half = box.HalfSize(); + lineResolve /= hitNormals.size(); + const glm::vec3& origin = newBox.Origin(); + const glm::vec3& half = newBox.HalfSize(); float maxDist = -10; for (const Triangle& tri : hitTriangles) { - float d = glm::dot(outResolutionVector, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); + float d = glm::dot(lineResolve, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); maxDist = std::max(maxDist, d); } - glm::vec3 tmp = glm::clamp(2.0f * outResolutionVector, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); - outResolutionVector *= maxDist + glm::length(tmp * half); + glm::vec3 tmp = glm::clamp(2.0f * lineResolve, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); + outResolutionVector += lineResolve * (maxDist + glm::length(tmp * half)); } return hit; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 452a73ef..20854c12 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -56,6 +56,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::vec3 resolutionVector; if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; + cPhysics["Velocity"] = glm::vec3(0, 0, 0); } } }