WIP on ModelBoxCollision. Octree works in Release mode.
This commit is contained in:
@@ -17,20 +17,13 @@ public:
|
|||||||
: System(world, eventBroker)
|
: System(world, eventBroker)
|
||||||
, PureSystem("Collidable")
|
, PureSystem("Collidable")
|
||||||
, m_Octree(octree)
|
, m_Octree(octree)
|
||||||
, zPress(false)
|
|
||||||
{
|
{
|
||||||
//TODO: Debug stuff, remove later.
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
|
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Octree<AABB>* m_Octree;
|
Octree<AABB>* m_Octree;
|
||||||
bool zPress;
|
|
||||||
|
|
||||||
EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
|
|
||||||
bool OnKeyUp(const Events::KeyUp &event);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -111,7 +111,7 @@ struct Child
|
|||||||
std::vector<ContainedObject>& m_StaticObjectsRef;
|
std::vector<ContainedObject>& m_StaticObjectsRef;
|
||||||
std::vector<ContainedObject>& m_DynamicObjectsRef;
|
std::vector<ContainedObject>& m_DynamicObjectsRef;
|
||||||
|
|
||||||
inline bool hasChildren() const;
|
inline bool hasChildren() const { return m_Children[0] != nullptr; }
|
||||||
int childIndexContainingPoint(const glm::vec3& point) const;
|
int childIndexContainingPoint(const glm::vec3& point) const;
|
||||||
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<Components>
|
<Components>
|
||||||
<c:Collidable/>
|
<c:Collidable/>
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>../assets/Models/Core/UnitQuad.obj</Resource>
|
<Resource>../assets/Models/Core/Tri.obj</Resource>
|
||||||
<Color A="1" B="1" G="0.392156869" R="0"/>
|
<Color A="1" B="1" G="0.392156869" R="0"/>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
@@ -36,11 +36,11 @@
|
|||||||
<Entity>
|
<Entity>
|
||||||
<Components>
|
<Components>
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>../assets/Models/Core/UnitQuad.obj</Resource>
|
<Resource>../assets/Models/Core/Tri.obj</Resource>
|
||||||
<Color A="1" B="0" G="0" R="1"/>
|
<Color A="1" B="0" G="0" R="1"/>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Orientation X="0" Y="3.1415927" Z="4.71238898"/>
|
<Orientation X="0" Y="3.14159274" Z="4.71238899"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
</Components>
|
</Components>
|
||||||
<Children/>
|
<Children/>
|
||||||
|
|||||||
@@ -248,7 +248,12 @@ 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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector)
|
bool AABBvsTriangle(const AABB& box,
|
||||||
|
const glm::vec3& v0,
|
||||||
|
const glm::vec3& v1,
|
||||||
|
const glm::vec3& v2,
|
||||||
|
glm::vec3& outVector,
|
||||||
|
int& lineHit)
|
||||||
{
|
{
|
||||||
//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);
|
||||||
@@ -283,23 +288,22 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c
|
|||||||
insideAllPlanes[ax] = glm::all(insidePlanes);
|
insideAllPlanes[ax] = glm::all(insidePlanes);
|
||||||
}
|
}
|
||||||
if (glm::all(insideAllPlanes)) {
|
if (glm::all(insideAllPlanes)) {
|
||||||
outResolutionVector = glm::vec3(0.f);
|
return false; //If a triangle is completely inside the box, we call it a non-intersection.
|
||||||
LOG_DEBUG("Triangle collision inside");
|
|
||||||
return true; //TODO: Resolve.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triNormal = glm::normalize(triNormal);
|
||||||
Ray ray;
|
Ray ray;
|
||||||
//All triangle lines.
|
//All triangle edges.
|
||||||
//Check if each line on the triangle intersects any plane on the box.
|
//Check if any edge on the triangle intersects the box.
|
||||||
for (int l = 0; l < 3; ++l) {
|
for (int l = 0; l < 3; ++l) {
|
||||||
glm::vec3 edge = triPos[(l + 1) % 3] - triPos[l];
|
glm::vec3 edge = triPos[(l + 1) % 3] - triPos[l];
|
||||||
ray.SetOrigin(triPos[l]);
|
ray.SetOrigin(triPos[l]);
|
||||||
ray.SetDirection(edge);
|
ray.SetDirection(edge);
|
||||||
float dist;
|
float dist;
|
||||||
if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) {
|
if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) {
|
||||||
outResolutionVector = glm::vec3(0.f);
|
outVector = triNormal;
|
||||||
LOG_DEBUG("Triangle collision lines");
|
lineHit = l;
|
||||||
return true; //TODO: Resolve.
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +313,6 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c
|
|||||||
//intersect the cube diagonal that comes
|
//intersect the cube diagonal that comes
|
||||||
//closest to being perpendicular to the plane of the polygon.
|
//closest to being perpendicular to the plane of the polygon.
|
||||||
|
|
||||||
triNormal = glm::normalize(triNormal);
|
|
||||||
glm::vec3 diagonal = -signNonZero(triNormal) * half;
|
glm::vec3 diagonal = -signNonZero(triNormal) * half;
|
||||||
#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //TODO: We should probably performance test with this on/off.
|
#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //TODO: We should probably performance test with this on/off.
|
||||||
#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK
|
#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK
|
||||||
@@ -337,7 +340,7 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c
|
|||||||
#endif
|
#endif
|
||||||
//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.
|
||||||
outResolutionVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal;
|
outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -345,28 +348,59 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
struct Triangle
|
||||||
|
{
|
||||||
|
glm::vec3 v0, v1, v2;
|
||||||
|
};
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
outResolutionVector = glm::vec3(INFINITY);
|
bool cornerHitTODO = false;
|
||||||
|
outResolutionVector = glm::vec3(0.f);
|
||||||
|
std::vector<Triangle> hitTriangles;
|
||||||
|
std::vector<glm::vec3> hitNormals;
|
||||||
for (int i = 0; i < modelIndices.size(); i += 3) {
|
for (int i = 0; i < modelIndices.size(); i += 3) {
|
||||||
glm::vec3 resVec;
|
glm::vec3 outVec;
|
||||||
if (AABBvsTriangle(
|
glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix);
|
||||||
box,
|
glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix);
|
||||||
Transform::TransformPoint(modelVertices[modelIndices[i]].Position, modelMatrix),
|
glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix);
|
||||||
Transform::TransformPoint(modelVertices[modelIndices[i + 1]].Position, modelMatrix),
|
int lineHit = -1;
|
||||||
Transform::TransformPoint(modelVertices[modelIndices[i + 2]].Position, modelMatrix),
|
if (AABBvsTriangle(box, v0, v1, v2, outVec, lineHit))
|
||||||
resVec
|
|
||||||
))
|
|
||||||
{
|
{
|
||||||
hit = true;
|
hit = true;
|
||||||
//If resolution distance is smaller than previous, and is non-zero.
|
if (lineHit == -1) {
|
||||||
if (glm::length(resVec) < glm::length(outResolutionVector) && vectorHasLength(resVec)) {
|
outResolutionVector += outVec;
|
||||||
outResolutionVector = resVec;
|
//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];
|
||||||
|
hitTriangles.push_back({v0, v1, v2});
|
||||||
|
hitNormals.push_back(outVec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO: Unnecessary later, remove it.
|
if (hitTriangles.size() > 0) {
|
||||||
if (glm::any(glm::isinf(outResolutionVector))) {
|
if (cornerHitTODO) {
|
||||||
outResolutionVector = glm::vec3(0, 0, 0);
|
LOG_DEBUG("Both edges and corners was hit on the same model.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const glm::vec3& norm : hitNormals) {
|
||||||
|
outResolutionVector += norm;
|
||||||
|
}
|
||||||
|
//Normalize.
|
||||||
|
outResolutionVector /= hitNormals.size();
|
||||||
|
const glm::vec3& origin = box.Origin();
|
||||||
|
const glm::vec3& half = box.HalfSize();
|
||||||
|
float maxDist = -10;
|
||||||
|
for (const Triangle& tri : hitTriangles) {
|
||||||
|
float d = glm::dot(outResolutionVector, 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);
|
||||||
}
|
}
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,6 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
|||||||
ComponentWrapper& cTransform = entity["Transform"];
|
ComponentWrapper& cTransform = entity["Transform"];
|
||||||
AABB& boxA = *boundingBox;
|
AABB& boxA = *boundingBox;
|
||||||
|
|
||||||
//Press 'Z' to enable/disable collision.
|
|
||||||
if (zPress) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collide against octree
|
// Collide against octree
|
||||||
//std::vector<AABB> octreeResult;
|
//std::vector<AABB> octreeResult;
|
||||||
//m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult);
|
//m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult);
|
||||||
@@ -64,11 +59,3 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionSystem::OnKeyUp(const Events::KeyUp & event)
|
|
||||||
{
|
|
||||||
if (event.KeyCode == GLFW_KEY_Z) {
|
|
||||||
zPress = !zPress;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -276,9 +276,4 @@ std::vector<int> Child::childIndicesContainingBox(const AABB& box) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Child::hasChildren() const
|
|
||||||
{
|
|
||||||
return m_Children[0] != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user