diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml new file mode 100644 index 00000000..46746264 --- /dev/null +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.obj + + + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.obj + + + + + + + + + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index b30ae927..c351d9fa 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -199,30 +199,93 @@ bool RayVsModel(const Ray& ray, return hit; } -bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) +bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector) { - bool hit = false; - const glm::vec3& origin = box.Origin(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); + const glm::vec3& half = box.HalfSize(); - outResolutionVector.x = INFINITY; + const glm::vec3 triPos[] = { + v0, v1, v2 + }; - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 p = modelVertices[i].Position; + for (int ax = 0; ax < 3; ++ax) { + auto outsideMinPlane = glm::tvec3(false); + auto outsideMaxPlane = glm::tvec3(false); + for (int pos = 0; pos < 3; ++pos) { + outsideMinPlane[pos] = (min[ax] > triPos[pos][ax]); + outsideMaxPlane[pos] = (triPos[pos][ax] > max[ax]); + } + if (glm::all(outsideMinPlane) || glm::all(outsideMaxPlane)) { + return false; + } + } + return true; +} + +bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) +{ + bool hit = false; + for (int i = 0; i < modelIndices.size(); i += 3) { + glm::vec3 resVec; + hit = AABBvsTriangle( + box, + modelVertices[modelIndices[i]].Position, + modelVertices[modelIndices[i + 1]].Position, + modelVertices[modelIndices[i + 2]].Position, + resVec + ); + if (hit) { + break; + } + } + return hit; + //TODO: Remove old code. + + /* + auto hit = glm::tvec3(false); + const glm::vec3& origin = box.Origin(); + const glm::vec3& min = box.MinCorner(); + const glm::vec3& max = box.MaxCorner(); + const glm::vec3& half = box.HalfSize(); + + float minResolution = INFINITY; + outResolutionVector = glm::vec3(0.f); + //TODO: Don't need indices? Remove? + for (const auto& v : modelVertices) { + glm::vec3 p = v.Position; p = glm::vec3(modelMatrix * glm::vec4(p.x, p.y, p.z, 1)); - float distFromOrigin = glm::abs(origin.x - p.x); - float penetration = box.HalfSize().x - distFromOrigin; - if (penetration > 0 && penetration < glm::abs(outResolutionVector.x)) { - if (p.x > origin.x) { - outResolutionVector.x = -penetration; - } else { - outResolutionVector.x = penetration; + const glm::vec3 diffO = origin - p; + const glm::vec3 distO = glm::abs(diffO); + for (int axis = 0; axis < 3; ++axis) { + float penetration = half[axis] - distO[axis]; + if (penetration > 0){ + if (penetration < minResolution) { + minResolution = penetration; + outResolutionVector = glm::vec3(0.f); + if (p[axis] > origin[axis]) { + outResolutionVector[axis] = -penetration; + } else { + outResolutionVector[axis] = penetration; + } + } + hit[axis] = true; } - hit = true; } + + //float distFromOrigin = glm::abs(origin.x - p.x); + //float penetration = box.HalfSize().x - distFromOrigin; + //if (penetration > 0 && penetration < glm::abs(outResolutionVector.x)) { + // if (p.x > origin.x) { + // outResolutionVector.x = -penetration; + // } else { + // outResolutionVector.x = penetration; + // } + // hit = true; + //} + //glm::vec3 pLocal = origin - p; //for (int axis = 0; axis < 3; ++axis) { // if (p[axis] < min[axis] || p[axis] > max[axis]) { @@ -236,7 +299,13 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model //} } - return hit; + //for (int axis = 0; axis < 3; ++axis) { + // if (glm::isinf(outResolutionVector[axis])) { + // outResolutionVector[axis] = 0.f; + // } + //} + + return glm::all(hit);*/ } bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index d841c75e..58e48357 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -1,6 +1,7 @@ #include "Collision/Collision.h" #include "Collision/CollisionSystem.h" #include "Core/AABB.h" +#include "Rendering/Model.h" void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) { @@ -22,40 +23,42 @@ void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, Compo } // Collide against octree - std::vector octreeResult; - m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); - for (auto& boxB : octreeResult) { - glm::vec3 resolutionVector; - if (Collision::IsSameBoxProbably(boxA, boxB)) { - continue; - } - if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { - (glm::vec3&)cTransform["Position"] += resolutionVector; - cPhysics["Velocity"] = glm::vec3(0, 0, 0); - } - } - - // HACK: Temporarily collide against all collidable models since they're not in the octree yet - //auto otherCollidables = world->GetComponents("Model"); - //for (auto& cModel : *otherCollidables) { - // if (cModel.EntityID == entity) { - // continue; - // } - // if (!world->HasComponent(cModel.EntityID, "Collidable")) { - // continue; - // } - - // auto absPosition = RenderQueueFactory::AbsolutePosition(world, cModel.EntityID); - // auto absOrientation = RenderQueueFactory::AbsoluteOrientation(world, cModel.EntityID); - // auto absScale = RenderQueueFactory::AbsoluteScale(world, cModel.EntityID); - // glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); - - // auto model = ResourceManager::Load(cModel["Resource"]); + //std::vector octreeResult; + //m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); + //for (auto& boxB : octreeResult) { // glm::vec3 resolutionVector; - // if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + // if (Collision::IsSameBoxProbably(boxA, boxB)) { + // continue; + // } + // if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { // (glm::vec3&)cTransform["Position"] += resolutionVector; + // cPhysics["Velocity"] = glm::vec3(0, 0, 0); // } //} + + // HACK: Temporarily collide against all collidable models since they're not in the octree yet + auto otherCollidables = world->GetComponents("Model"); + for (auto& cModel : *otherCollidables) { + if (cModel.EntityID == EntityID(entity)) { + continue; + } + if (!world->HasComponent(cModel.EntityID, "Collidable")) { + continue; + } + + auto absPosition = Transform::AbsolutePosition(world, cModel.EntityID); + auto absOrientation = Transform::AbsoluteOrientation(world, cModel.EntityID); + auto absScale = Transform::AbsoluteScale(world, cModel.EntityID); + glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); + + RawModel* model = ResourceManager::Load(cModel["Resource"]); + glm::vec3 resolutionVector; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + //TODO: remove Temp. + (glm::vec3&)cTransform["Position"] = glm::vec3(2, 2, 2); + //(glm::vec3&)cTransform["Position"] += resolutionVector; + } + } } bool CollisionSystem::OnKeyUp(const Events::KeyUp & event)