From 71d936f8d1fc86f0e43b4ec8272e60be95724612 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 13 Jan 2016 17:53:54 +0100 Subject: [PATCH] Start of a movement system with collisions against AABBs --- .../Engine/Collision/CollidableOctreeSystem.h | 7 +++- include/Engine/Collision/Collision.h | 6 +++ include/Engine/Core/EComponentAttached.h | 20 ++++++++++ include/Engine/Core/Entity.h | 18 +++++++++ include/Game/PlayerMovementSystem.h | 12 ++++++ resources/Schema/Entities/CollisionTest1.xml | 38 ++++++++++++++++++ resources/Schema/Entities/OctreeTest.xml | 26 +++++------- src/Engine/Collision/Collision.cpp | 40 +++++++++++++++++++ src/Engine/Collision/CollisionSystem.cpp | 23 +++++++++++ src/Game/PlayerMovementSystem.cpp | 7 ++++ 10 files changed, 179 insertions(+), 18 deletions(-) create mode 100644 include/Engine/Core/EComponentAttached.h create mode 100644 include/Game/PlayerMovementSystem.h create mode 100644 resources/Schema/Entities/CollisionTest1.xml create mode 100644 src/Game/PlayerMovementSystem.cpp diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/CollidableOctreeSystem.h index b7a77346..760503e9 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/CollidableOctreeSystem.h @@ -1,3 +1,6 @@ +#ifndef CollidableOctreeSystem_h__ +#define CollidableOctreeSystem_h__ + #include "../Core/System.h" #include "../Core/Octree.h" #include "Collision.h" @@ -16,4 +19,6 @@ public: private: Octree* m_Octree; -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 18520243..2854d07b 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -45,6 +45,12 @@ bool RayVsModel(const Ray& ray, float& outUCoord, float& outVCoord); +bool AABBvsTriangles(const AABB& box, + const std::vector& modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix, + glm::vec3& outResolutionVector); + //Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); //Return true if the boxes are intersecting. diff --git a/include/Engine/Core/EComponentAttached.h b/include/Engine/Core/EComponentAttached.h new file mode 100644 index 00000000..b4ab9f78 --- /dev/null +++ b/include/Engine/Core/EComponentAttached.h @@ -0,0 +1,20 @@ +#ifndef EComponentAttached_h__ +#define EComponentAttached_h__ + +#include "EventBroker.h" +#include "World.h" +#include "Entity.h" +#include "ComponentWrapper.h" + +namespace Events +{ + +struct ComponentAttached : Event +{ + EntityWrapper Entity; + ComponentWrapper Component; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/Entity.h b/include/Engine/Core/Entity.h index 1f40b9b7..c6730924 100644 --- a/include/Engine/Core/Entity.h +++ b/include/Engine/Core/Entity.h @@ -4,4 +4,22 @@ typedef unsigned int EntityID; const static unsigned int EntityID_Invalid = -1; +class World; +struct EntityWrapper +{ + EntityWrapper(::World* world, EntityID id) + : World(world) + , ID(id) + { } + + ::World* World; + EntityID ID; + + bool operator==(const EntityWrapper& e) + { + return (this->World == e.World) && (this->ID == e.ID); + } + operator EntityID() { return this->ID; } +}; + #endif \ No newline at end of file diff --git a/include/Game/PlayerMovementSystem.h b/include/Game/PlayerMovementSystem.h new file mode 100644 index 00000000..aa40b5f6 --- /dev/null +++ b/include/Game/PlayerMovementSystem.h @@ -0,0 +1,12 @@ +#include "Common.h" +#include "Core/System.h" + +class PlayerMovementSystem : public PureSystem +{ +public: + PlayerMovementSystem(EventBroker* eventBroker) + : PureSystem(eventBroker, "Player") + { } + + virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt); +}; \ No newline at end of file diff --git a/resources/Schema/Entities/CollisionTest1.xml b/resources/Schema/Entities/CollisionTest1.xml new file mode 100644 index 00000000..f0b310e1 --- /dev/null +++ b/resources/Schema/Entities/CollisionTest1.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + false + + + + + + + + + + + false + + + Models/Core/UnitCube.obj + + + + + + + + + + + diff --git a/resources/Schema/Entities/OctreeTest.xml b/resources/Schema/Entities/OctreeTest.xml index 819159d0..4d7fe709 100644 --- a/resources/Schema/Entities/OctreeTest.xml +++ b/resources/Schema/Entities/OctreeTest.xml @@ -15,7 +15,7 @@ - + @@ -23,38 +23,30 @@ - + + false + Models/Core/UnitCube.obj - + - - + + false + Models/Core/UnitCube.obj - - - - - - - - - Models/Core/UnitCube.obj - - - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 1af09382..a1f24f59 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -199,6 +199,46 @@ 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 hit = false; + + const glm::vec3& origin = box.Origin(); + const glm::vec3& min = box.MinCorner(); + const glm::vec3& max = box.MaxCorner(); + + outResolutionVector.x = INFINITY; + + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 p = modelVertices[i].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; + } + hit = true; + } + //glm::vec3 pLocal = origin - p; + //for (int axis = 0; axis < 3; ++axis) { + // if (p[axis] < min[axis] || p[axis] > max[axis]) { + // continue; + // } + + // if (glm::abs(pLocal[axis]) < box.HalfSize()[axis]) { + // outResolutionVector[axis] = (glm::sign(pLocal[axis]) * box.HalfSize()[axis]) - pLocal[axis]; + // hit = true; + // } + //} + } + + return hit; +} + bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) { const glm::vec3& ma1 = first.MaxCorner(); diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 4ce514da..ec2f14a7 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -17,6 +17,7 @@ void CollisionSystem::UpdateComponent(World* world, ComponentWrapper& cAABB, dou return; } + // Collide against octree std::vector octreeResult; m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); for (auto& boxB : octreeResult) { @@ -28,6 +29,28 @@ void CollisionSystem::UpdateComponent(World* world, ComponentWrapper& cAABB, dou (glm::vec3&)cTransform["Position"] += resolutionVector; } } + + // 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"]); + // glm::vec3 resolutionVector; + // if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + // (glm::vec3&)cTransform["Position"] += resolutionVector; + // } + //} } bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) diff --git a/src/Game/PlayerMovementSystem.cpp b/src/Game/PlayerMovementSystem.cpp new file mode 100644 index 00000000..f9ffac44 --- /dev/null +++ b/src/Game/PlayerMovementSystem.cpp @@ -0,0 +1,7 @@ +#include "RaptorCopterSystem.h" + +void PlayerMovementSystem::UpdateComponent(World* world, ComponentWrapper& player, double dt) +{ + +} +