diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 6e4858b2..6d16e090 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -78,6 +78,8 @@ bool AABBVsAABB(const AABB& a, const AABB& b); //Also outputs the minimum translation that box [a] would need in order to resolve collision. bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); +//Attaches an AABB which contains all vertices in the entitys Model. +bool AttachAABBComponentFromModel(EntityWrapper entity); // Calculates an absolute AABB from an entity AABB component boost::optional EntityAbsoluteAABB(EntityWrapper& entity); diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/FillOctreeSystem.h similarity index 66% rename from include/Engine/Collision/CollidableOctreeSystem.h rename to include/Engine/Collision/FillOctreeSystem.h index 0aa01d2e..9fd87b94 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/FillOctreeSystem.h @@ -6,12 +6,12 @@ #include "Collision.h" #include "EntityAABB.h" -class CollidableOctreeSystem : public ImpureSystem, public PureSystem +class FillOctreeSystem : public ImpureSystem, public PureSystem { public: - CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree, const std::string& componentType) + FillOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree, const std::string& fillComponentType) : System(world, eventBroker) - , PureSystem(componentType) + , PureSystem(fillComponentType) , m_Octree(octree) { } diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index bf34b9be..087471c0 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -25,6 +25,7 @@ struct EntityWrapper const std::string Name(); bool HasComponent(const std::string& componentType); + void AttachComponent(const char* componentName); EntityWrapper Parent(); EntityWrapper FirstChildByName(const std::string& name); EntityWrapper FirstParentWithComponent(const std::string& componentType); diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index e73cb69d..5c1fbacc 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -9,7 +9,8 @@ - + + diff --git a/src/Engine/Collision/CollidableOctreeSystem.cpp b/src/Engine/Collision/CollidableOctreeSystem.cpp deleted file mode 100644 index 476414dd..00000000 --- a/src/Engine/Collision/CollidableOctreeSystem.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Collision/CollidableOctreeSystem.h" - -void CollidableOctreeSystem::Update(double dt) -{ - m_Octree->ClearDynamicObjects(); -} - -void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) -{ - if (entity.HasComponent("AABB")) { - boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); - if (absoluteAABB) { - m_Octree->AddDynamicObject(*absoluteAABB); - } - } else if (entity.HasComponent("Model")) { - // TODO: Derive AABB from model - } -} \ No newline at end of file diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index fe4eb5e0..b150d667 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -564,33 +564,29 @@ bool AABBvsTriangles(const AABB& box, return hit; } -bool attachAABBComponentFromModel(World* world, EntityID id) +bool AttachAABBComponentFromModel(EntityWrapper entity) { - if (!world->HasComponent(id, "Model")) { + if (!entity.HasComponent("Model")) { return false; } - ComponentWrapper model = world->GetComponent(id, "Model"); - ComponentWrapper collision = world->AttachComponent(id, "AABB"); - Model* modelRes = ResourceManager::Load(model["Resource"]); - if (modelRes == nullptr) { + //Derive AABB from model + RawModel* model; + try { + model = ResourceManager::Load(entity["Model"]["Resource"]); + } catch (const std::exception&) { return false; } - glm::mat4 modelMatrix = modelRes->Matrix(); - - glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); - glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); - for (const auto& v : modelRes->Vertices()) { - const auto& wPos = modelMatrix * glm::vec4(v.Position.x, v.Position.y, v.Position.z, 1); - maxi.x = std::max(wPos.x, maxi.x); - maxi.y = std::max(wPos.y, maxi.y); - maxi.z = std::max(wPos.z, maxi.z); - mini.x = std::min(wPos.x, mini.x); - mini.y = std::min(wPos.y, mini.y); - mini.z = std::min(wPos.z, mini.z); + glm::vec3 mini(INFINITY); + glm::vec3 maxi(-INFINITY); + for (const auto& v : model->m_Vertices) { + mini = glm::min(mini, v.Position); + maxi = glm::max(maxi, v.Position); } - collision["Origin"] = 0.5f * (maxi + mini); - collision["Size"] = maxi - mini; + + entity.AttachComponent("AABB"); + entity["AABB"]["Origin"] = 0.5f * (maxi + mini); + entity["AABB"]["Size"] = maxi - mini; return true; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index b5d7a1f0..7d8905a8 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -20,6 +20,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c // Collide against octree items m_OctreeResult.clear(); m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); + bool everHitTheGround = false; for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; if (boxA.Entity == boxB.Entity) { @@ -43,17 +44,24 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = inOutVelocity; - (bool)cPhysics["IsOnGround"] = isOnGround; - } else { - (bool)cPhysics["IsOnGround"] = false; + if (isOnGround) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; + } } } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { //Enter here if boxB has no Model. (glm::vec3&)cTransform["Position"] += resolutionVector; - (bool)cPhysics["IsOnGround"] = resolutionVector.y > 0; - if ((bool)cPhysics["IsOnGround"]){ + if (resolutionVector.y > 0) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; } } } + + //This should apply air friction and such, iff zero models were hit. + if (!everHitTheGround) { + (bool)cPhysics["IsOnGround"] = false; + } } diff --git a/src/Engine/Collision/FillOctreeSystem.cpp b/src/Engine/Collision/FillOctreeSystem.cpp new file mode 100644 index 00000000..8c03b5c2 --- /dev/null +++ b/src/Engine/Collision/FillOctreeSystem.cpp @@ -0,0 +1,20 @@ +#include "Collision/FillOctreeSystem.h" + +void FillOctreeSystem::Update(double dt) +{ + m_Octree->ClearDynamicObjects(); +} + +void FillOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +{ + if (!entity.HasComponent("AABB")) { + //Derive AABB from model. + if (!Collision::AttachAABBComponentFromModel(entity)) { + return; + } + } + boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); + if (absoluteAABB) { + m_Octree->AddDynamicObject(*absoluteAABB); + } +} \ No newline at end of file diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 410a7fa1..adc778e5 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -6,6 +6,10 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapper& cTrigger, double dt) { // The trigger *should* have a bounding box, or something, to test against so it can be triggered. + // If it doesn't, add one as big as the model for now, then size can be modified in editor if necessary. + if (!triggerEntity.HasComponent("AABB")) { + Collision::AttachAABBComponentFromModel(triggerEntity); + } boost::optional triggerBox = Collision::EntityAbsoluteAABB(triggerEntity); if (!triggerBox) { return; diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 071329a3..b0d08e66 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -16,6 +16,15 @@ bool EntityWrapper::HasComponent(const std::string& componentName) return World->HasComponent(ID, componentName); } +void EntityWrapper::AttachComponent(const char* componentName) +{ + if (!Valid()) { + LOG_WARNING("Could not attach \"%s\" component to #%i, component is not valid.", componentName, ID); + return; + } + World->AttachComponent(ID, componentName); +} + EntityWrapper EntityWrapper::Parent() { if (this->World == nullptr || this->ID == EntityID_Invalid) { diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d3c2eb57..669e48d0 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,5 @@ #include "Game.h" -#include "Collision/CollidableOctreeSystem.h" +#include "Collision/FillOctreeSystem.h" #include "Collision/EntityAABB.h" #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" @@ -98,8 +98,8 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); - m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger, "Player"); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger, "Player"); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeFrustrumCulling, "Model"); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel);