Special case for collision vs ground (upward facing) triangles.
This commit is contained in:
@@ -1,122 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>../assets\Models\Test/ObstacleCourse.obj</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0" Z="0.00638055196"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:DirectionalLight>
|
||||
<Intensity>0.46000027656555176</Intensity>
|
||||
</c:DirectionalLight>
|
||||
<c:Transform>
|
||||
<Orientation X="0" Y="2.59000015" Z="0.799000025"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>../assets\Models\Core\UnitCube.obj</Resource>
|
||||
</c:Model>
|
||||
<c:Physics>
|
||||
<Gravity>false</Gravity>
|
||||
</c:Physics>
|
||||
<c:Player/>
|
||||
<c:Transform>
|
||||
<Position X="-2.31658864" Y="2.02328157" Z="4.50379515"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>../assets\Models\Core\colorbox.obj</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-1.52309108" Y="5.72108126" Z="0"/>
|
||||
<Scale X="5" Y="5" Z="5"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/DummyScene.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="-1.5"/>
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="1.5"/>
|
||||
<Scale X="2" Y="2" Z="2"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidgetX.obj</Resource>
|
||||
</c:Model>
|
||||
<c:Trigger>
|
||||
</c:Trigger>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Player>
|
||||
<Velocity X="0" Y="0" Z="0"/>
|
||||
</c:Player>
|
||||
<c:Transform>
|
||||
<Position X="2.5"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
</c:Model>
|
||||
<c:AABB>
|
||||
</c:AABB>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="-0"/>
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</c:Transform>
|
||||
<!--<c:Move>
|
||||
<Speed>1</Speed>
|
||||
<Direction X="-1"/>
|
||||
<Rotation Y="3.14"/>
|
||||
</c:Move>-->
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Orientation X="0.0" Y="0" Z="1.0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitRaptor.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="-0.01" Y="0.55"/>
|
||||
<Orientation X="0" Y="0" Z="-1"/>
|
||||
</c:Transform>
|
||||
<c:RaptorCopter>
|
||||
<Speed>20</Speed>
|
||||
<Axis Y="1"/>
|
||||
</c:RaptorCopter>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Scale X="1.7" Y="0.03" Z="0.1"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Scale X="1.7" Y="0.03" Z="0.1"/>
|
||||
<Orientation X="0" Y="1.57" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
@@ -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<RawModel::Vertex>& modelVertices, const std::vector<unsigned int>& 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<RawModel::Vertex>& 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user