Special case for collision vs ground (upward facing) triangles.

This commit is contained in:
William Moberg
2016-01-23 14:01:54 +01:00
parent 3974c649ab
commit 71404c8828
3 changed files with 134 additions and 145 deletions
+65 -121
View File
@@ -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">
<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>
<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>
+68 -24
View File
@@ -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;
}
+1
View File
@@ -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);
}
}
}