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">
|
||||||
|
|
||||||
<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>
|
||||||
<Components>
|
<c:Transform/>
|
||||||
<c:Transform>
|
</Components>
|
||||||
<Orientation X="0" Y="0" Z="0"/>
|
|
||||||
</c:Transform>
|
<Children>
|
||||||
<c:Model>
|
<Entity>
|
||||||
<Resource>Models/DummyScene.obj</Resource>
|
<Components>
|
||||||
</c:Model>
|
<c:AABB/>
|
||||||
</Components>
|
<c:Collidable/>
|
||||||
<Children>
|
<c:Model>
|
||||||
<Entity>
|
<Resource>../assets\Models\Test/ObstacleCourse.obj</Resource>
|
||||||
<Components>
|
</c:Model>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="-1.5"/>
|
<Position X="0" Y="0" Z="0.00638055196"/>
|
||||||
<Scale X="1" Y="1" Z="1"/>
|
</c:Transform>
|
||||||
</c:Transform>
|
</Components>
|
||||||
<c:Model>
|
<Children/>
|
||||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
</Entity>
|
||||||
</c:Model>
|
<Entity>
|
||||||
</Components>
|
<Components>
|
||||||
</Entity>
|
<c:DirectionalLight>
|
||||||
<Entity>
|
<Intensity>0.46000027656555176</Intensity>
|
||||||
<Components>
|
</c:DirectionalLight>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="1.5"/>
|
<Orientation X="0" Y="2.59000015" Z="0.799000025"/>
|
||||||
<Scale X="2" Y="2" Z="2"/>
|
</c:Transform>
|
||||||
</c:Transform>
|
</Components>
|
||||||
<c:Model>
|
<Children/>
|
||||||
<Resource>Models/RotationWidgetX.obj</Resource>
|
</Entity>
|
||||||
</c:Model>
|
<Entity>
|
||||||
<c:Trigger>
|
<Components>
|
||||||
</c:Trigger>
|
<c:AABB/>
|
||||||
</Components>
|
<c:Collidable/>
|
||||||
</Entity>
|
<c:Model>
|
||||||
<Entity>
|
<Resource>../assets\Models\Core\UnitCube.obj</Resource>
|
||||||
<Components>
|
</c:Model>
|
||||||
<c:Player>
|
<c:Physics>
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
<Gravity>false</Gravity>
|
||||||
</c:Player>
|
</c:Physics>
|
||||||
<c:Transform>
|
<c:Player/>
|
||||||
<Position X="2.5"/>
|
<c:Transform>
|
||||||
</c:Transform>
|
<Position X="-2.31658864" Y="2.02328157" Z="4.50379515"/>
|
||||||
<c:Model>
|
</c:Transform>
|
||||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
</Components>
|
||||||
</c:Model>
|
<Children/>
|
||||||
<c:AABB>
|
</Entity>
|
||||||
</c:AABB>
|
<Entity>
|
||||||
</Components>
|
<Components>
|
||||||
</Entity>
|
<c:AABB/>
|
||||||
<Entity>
|
<c:Collidable/>
|
||||||
<Components>
|
<c:Model>
|
||||||
<c:Transform>
|
<Resource>../assets\Models\Core\colorbox.obj</Resource>
|
||||||
<Position X="0" Y="-0"/>
|
</c:Model>
|
||||||
<Scale X="1" Y="1" Z="1"/>
|
<c:Transform>
|
||||||
</c:Transform>
|
<Position X="-1.52309108" Y="5.72108126" Z="0"/>
|
||||||
<!--<c:Move>
|
<Scale X="5" Y="5" Z="5"/>
|
||||||
<Speed>1</Speed>
|
</c:Transform>
|
||||||
<Direction X="-1"/>
|
</Components>
|
||||||
<Rotation Y="3.14"/>
|
<Children/>
|
||||||
</c:Move>-->
|
</Entity>
|
||||||
</Components>
|
</Children>
|
||||||
<Children>
|
|
||||||
<Entity>
|
</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 "Engine/GLM.h"
|
||||||
#include "Core/World.h"
|
#include "Core/World.h"
|
||||||
#include "Rendering/Model.h"
|
#include "Rendering/Model.h"
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
namespace Collision
|
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)));
|
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,
|
bool AABBvsTriangle(const AABB& box,
|
||||||
const glm::vec3& v0,
|
const glm::vec3& v0,
|
||||||
const glm::vec3& v1,
|
const glm::vec3& v1,
|
||||||
const glm::vec3& v2,
|
const glm::vec3& v2,
|
||||||
glm::vec3& outVector,
|
glm::vec3& outVector,
|
||||||
int& lineHit)
|
BoxTriHit& outHit)
|
||||||
{
|
{
|
||||||
//Check so we don't have a zero area triangle when calculating the normal.
|
//Check so we don't have a zero area triangle when calculating the normal.
|
||||||
glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0);
|
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& min = box.MinCorner();
|
||||||
const glm::vec3& max = box.MaxCorner();
|
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[] = {
|
const glm::vec3 triPos[] = {
|
||||||
v0, v1, v2
|
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.
|
return false; //If a triangle is completely inside the box, we call it a non-intersection.
|
||||||
}
|
}
|
||||||
|
|
||||||
triNormal = glm::normalize(triNormal);
|
|
||||||
Ray ray;
|
Ray ray;
|
||||||
//All triangle edges.
|
//All triangle edges.
|
||||||
//Check if any edge on the triangle intersects the box.
|
//Check if any edge on the triangle intersects the box.
|
||||||
@@ -302,7 +328,7 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
float dist;
|
float dist;
|
||||||
if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) {
|
if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) {
|
||||||
outVector = triNormal;
|
outVector = triNormal;
|
||||||
lineHit = l;
|
outHit = (BoxTriHit)l;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,6 +367,7 @@ bool AABBvsTriangle(const AABB& box,
|
|||||||
//Distance between triangle plane, and the diagonal corner, multiplied by the normal.
|
//Distance between triangle plane, and the diagonal corner, multiplied by the normal.
|
||||||
//Signed distance, positive if on the same side as the normal.
|
//Signed distance, positive if on the same side as the normal.
|
||||||
outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal;
|
outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal;
|
||||||
|
outHit = Corner;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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)
|
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
|
struct Triangle
|
||||||
{
|
{
|
||||||
glm::vec3 v0, v1, v2;
|
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 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix);
|
||||||
glm::vec3 v1 = 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);
|
glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix);
|
||||||
int lineHit = -1;
|
BoxTriHit hitCase;
|
||||||
if (AABBvsTriangle(box, v0, v1, v2, outVec, lineHit))
|
if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase))
|
||||||
{
|
{
|
||||||
hit = true;
|
hit = true;
|
||||||
if (lineHit == -1) {
|
switch (hitCase) {
|
||||||
outResolutionVector += outVec;
|
case Collision::Line0:
|
||||||
//TODO: We might be able to return here instead, having only convex geometry.
|
case Collision::Line1:
|
||||||
cornerHitTODO = true;
|
case Collision::Line2:
|
||||||
//return true;
|
//TODO: Resolve.
|
||||||
}
|
//const glm::vec3 triPos[] = {
|
||||||
else {
|
// v0, v1, v2
|
||||||
const glm::vec3 triPos[] = {
|
//};
|
||||||
v0, v1, v2
|
//glm::vec3 edge = triPos[(hitCase + 1) % 3] - triPos[hitCase];
|
||||||
};
|
|
||||||
glm::vec3 edge = triPos[(lineHit + 1) % 3] - triPos[lineHit];
|
|
||||||
hitTriangles.push_back({v0, v1, v2});
|
hitTriangles.push_back({v0, v1, v2});
|
||||||
hitNormals.push_back(outVec);
|
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 (hitTriangles.size() > 0) {
|
||||||
if (cornerHitTODO) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
glm::vec3 lineResolve(0.f);
|
||||||
for (const glm::vec3& norm : hitNormals) {
|
for (const glm::vec3& norm : hitNormals) {
|
||||||
outResolutionVector += norm;
|
lineResolve += norm;
|
||||||
}
|
}
|
||||||
//Normalize.
|
//Normalize.
|
||||||
outResolutionVector /= hitNormals.size();
|
lineResolve /= hitNormals.size();
|
||||||
const glm::vec3& origin = box.Origin();
|
const glm::vec3& origin = newBox.Origin();
|
||||||
const glm::vec3& half = box.HalfSize();
|
const glm::vec3& half = newBox.HalfSize();
|
||||||
float maxDist = -10;
|
float maxDist = -10;
|
||||||
for (const Triangle& tri : hitTriangles) {
|
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);
|
maxDist = std::max(maxDist, d);
|
||||||
}
|
}
|
||||||
glm::vec3 tmp = glm::clamp(2.0f * outResolutionVector, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1));
|
glm::vec3 tmp = glm::clamp(2.0f * lineResolve, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1));
|
||||||
outResolutionVector *= maxDist + glm::length(tmp * half);
|
outResolutionVector += lineResolve * (maxDist + glm::length(tmp * half));
|
||||||
}
|
}
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
|||||||
glm::vec3 resolutionVector;
|
glm::vec3 resolutionVector;
|
||||||
if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) {
|
if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) {
|
||||||
(glm::vec3&)cTransform["Position"] += resolutionVector;
|
(glm::vec3&)cTransform["Position"] += resolutionVector;
|
||||||
|
cPhysics["Velocity"] = glm::vec3(0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user