diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/CollidableOctreeSystem.h new file mode 100644 index 00000000..b7a77346 --- /dev/null +++ b/include/Engine/Collision/CollidableOctreeSystem.h @@ -0,0 +1,19 @@ +#include "../Core/System.h" +#include "../Core/Octree.h" +#include "Collision.h" + +class CollidableOctreeSystem : public ImpureSystem, public PureSystem +{ +public: + CollidableOctreeSystem(EventBroker* eventBroker, Octree* octree) + : System(eventBroker) + , PureSystem("Collidable") + , m_Octree(octree) + { } + + virtual void Update(World* world, double dt) override; + virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) override; + +private: + Octree* m_Octree; +}; \ No newline at end of file diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 714cee3f..18520243 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -6,11 +6,13 @@ //or you will get "fatal error C1189: #error: gl.h included before glew.h" #include +#include -#include "Core/Ray.h" -#include "Core/AABB.h" -#include "Engine/Rendering/RawModel.h" -#include "Core/Entity.h" +#include "../Core/Ray.h" +#include "../Core/AABB.h" +#include "../Rendering/RawModel.h" +#include "../Rendering/RenderQueueFactory.h" +#include "../Core/Entity.h" class World; struct ComponentWrapper; @@ -50,9 +52,8 @@ bool AABBVsAABB(const AABB& a, const AABB& b); bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f); -//Returns true if the entity has a boundingbox. Outputs the aabb in [outBox]. -bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel = false); -bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox); +// Calculates an absolute AABB from an entity AABB component +boost::optional EntityAbsoluteAABB(World* world, EntityID entity); } diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index 254a2461..b4e25072 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -4,16 +4,19 @@ #include #include -#include "Common.h" -#include "Core/System.h" -#include "Core/EventBroker.h" -#include "Core/EKeyUp.h" +#include "../Common.h" +#include "../Core/System.h" +#include "../Core/EventBroker.h" +#include "../Core/EKeyUp.h" +#include "../Core/Octree.h" class CollisionSystem : public PureSystem { public: - CollisionSystem(EventBroker* eventBroker) - : PureSystem(eventBroker, "AABB") + CollisionSystem(EventBroker* eventBroker, Octree* octree) + : System(eventBroker) + , PureSystem("AABB") + , m_Octree(octree) , zPress(false) { //TODO: Debug stuff, remove later. @@ -23,7 +26,9 @@ public: virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override; private: + Octree* m_Octree; bool zPress; + EventRelay m_EKeyUp; bool OnKeyUp(const Events::KeyUp &event); }; diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index 7e6ef008..7856a09d 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -4,8 +4,9 @@ #include #include -#include "Core/System.h" -#include "Core/EventBroker.h" +#include "../Core/System.h" +#include "../Core/EventBroker.h" +#include "../Core/Octree.h" #include "ETrigger.h" class AABB; @@ -13,13 +14,16 @@ class AABB; class TriggerSystem : public PureSystem { public: - TriggerSystem(EventBroker* eventBroker) - : PureSystem(eventBroker, "Trigger") - {} + TriggerSystem(EventBroker* eventBroker, Octree* octree) + : System(eventBroker) + , PureSystem("Trigger") + , m_Octree(octree) + { } virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override; private: + Octree* m_Octree; std::unordered_map> m_EntitiesTouchingTrigger; std::unordered_map> m_EntitiesCompletelyInTrigger; diff --git a/include/Engine/Core/AABB.h b/include/Engine/Core/AABB.h index c8e05248..5b9c6485 100644 --- a/include/Engine/Core/AABB.h +++ b/include/Engine/Core/AABB.h @@ -11,18 +11,18 @@ public: AABB(const glm::vec3& minPos, const glm::vec3& maxPos); AABB(const glm::vec4& minPos, const glm::vec4& maxPos); //No checks are made. Size must consist of non-negative numbers. - virtual void CreateFromCenter(const glm::vec3& center, const glm::vec3& size); + static AABB FromOriginSize(const glm::vec3& origin, const glm::vec3& size); virtual ~AABB(); const glm::vec3& MinCorner() const { return m_MinCorner; } const glm::vec3& MaxCorner() const { return m_MaxCorner; } - const glm::vec3& Center() const { return m_Center; } + const glm::vec3& Origin() const { return m_Origin; } const glm::vec3 Size() const { return 2.0f * m_HalfSize; } const glm::vec3& HalfSize() const { return m_HalfSize; } private: glm::vec3 m_MinCorner; glm::vec3 m_MaxCorner; - glm::vec3 m_Center; + glm::vec3 m_Origin; glm::vec3 m_HalfSize; }; diff --git a/include/Engine/Core/Octree.h b/include/Engine/Core/Octree.h index a2f358ae..954dbcbc 100644 --- a/include/Engine/Core/Octree.h +++ b/include/Engine/Core/Octree.h @@ -2,7 +2,7 @@ #define Octree_h__ #include "../Common.h" -#include "Core/AABB.h" +#include "AABB.h" class Ray; @@ -14,7 +14,7 @@ public: float CollideDistance; }; - Octree(); + Octree() = delete; ~Octree(); //For the root Octree, [octreeBounds] should be a box containing the entire level. Octree(const AABB& octreeBounds, int subDivisions); diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index 75bd3882..cd8e9fc7 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -10,6 +10,9 @@ class System friend class SystemPipeline; protected: + System() + : m_EventBroker(nullptr) + { } System(EventBroker* eventBroker) : m_EventBroker(eventBroker) { } @@ -18,14 +21,13 @@ protected: EventBroker* m_EventBroker; }; -class PureSystem : public System +class PureSystem : public virtual System { friend class SystemPipeline; protected: - PureSystem(EventBroker* eventBroker, std::string componentType) - : System(eventBroker) - , m_ComponentType(componentType) + PureSystem(std::string componentType) + : m_ComponentType(componentType) { } virtual ~PureSystem() = default; @@ -34,14 +36,12 @@ protected: virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) = 0; }; -class ImpureSystem : public System +class ImpureSystem : public virtual System { friend class SystemPipeline; protected: - ImpureSystem(EventBroker* eventBroker) - : System(eventBroker) - { } + ImpureSystem() = default; virtual ~ImpureSystem() = default; virtual void Update(World* world, double dt) = 0; diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index d6a6b371..79d4ace4 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -32,8 +32,8 @@ public: System* system = new T(m_EventBroker, args...); group.Systems[typeid(T).name()] = system; - if (std::is_base_of::value) { - PureSystem* pureSystem = static_cast(system); + PureSystem* pureSystem = dynamic_cast(system); + if (pureSystem != nullptr) { if (!pureSystem->m_ComponentType.empty()) { group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem); } else { @@ -41,8 +41,8 @@ public: } } - if (std::is_base_of::value) { - ImpureSystem* impureSystem = static_cast(system); + ImpureSystem* impureSystem = dynamic_cast(system); + if (impureSystem != nullptr) { group.ImpureSystems.push_back(impureSystem); } } @@ -56,6 +56,9 @@ public: } // Update + for (auto& system : group.ImpureSystems) { + system->Update(world, dt); + } for (auto& pair : group.PureSystems) { const std::string& componentName = pair.first; auto& systems = pair.second; @@ -69,9 +72,6 @@ public: } } } - for (auto& system : group.ImpureSystems) { - system->Update(world, dt); - } } } diff --git a/include/Game/Game.h b/include/Game/Game.h index 1c19aac2..de45c558 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -20,6 +20,7 @@ #include "Editor/EditorSystem.h" #include "Core/EntityFile.h" #include "Core/EntityFileParser.h" +#include "Core/Octree.h" // Network #include @@ -46,6 +47,8 @@ private: InputProxy* m_InputProxy; GUI::Frame* m_FrameStack; World* m_World; + Octree* m_OctreeCollision; + Octree* m_OctreeFrustrumCulling; SystemPipeline* m_SystemPipeline; RenderQueueFactory* m_RenderQueueFactory; // Network variables diff --git a/include/Game/PlayerSystem.h b/include/Game/PlayerSystem.h index 577fbbb0..50492617 100644 --- a/include/Game/PlayerSystem.h +++ b/include/Game/PlayerSystem.h @@ -12,7 +12,8 @@ class PlayerSystem : public PureSystem { public: PlayerSystem(EventBroker* eventBroker) - : PureSystem(eventBroker, "Player") + : System(eventBroker) + , PureSystem("Player") { EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch); EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter); diff --git a/include/Game/RaptorCopterSystem.h b/include/Game/RaptorCopterSystem.h index 913efdb3..14b49f4d 100644 --- a/include/Game/RaptorCopterSystem.h +++ b/include/Game/RaptorCopterSystem.h @@ -5,7 +5,8 @@ class RaptorCopterSystem : public PureSystem { public: RaptorCopterSystem(EventBroker* eventBroker) - : PureSystem(eventBroker, "RaptorCopter") + : System(eventBroker) + , PureSystem("RaptorCopter") { } virtual void UpdateComponent(World* world, ComponentWrapper& raptorCopter, double dt) override diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 7fcdd565..4f32b477 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -9,4 +9,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/AABB.xml b/resources/Schema/Components/AABB.xml index 341d1d0d..6996b3dc 100644 --- a/resources/Schema/Components/AABB.xml +++ b/resources/Schema/Components/AABB.xml @@ -1,4 +1,4 @@ - - + + \ No newline at end of file diff --git a/resources/Schema/Components/AABB.xsd b/resources/Schema/Components/AABB.xsd index 8fac860e..daa633a6 100644 --- a/resources/Schema/Components/AABB.xsd +++ b/resources/Schema/Components/AABB.xsd @@ -6,8 +6,12 @@ - - + + Middle point of the bounding box + + + Size of the bounding box + diff --git a/resources/Schema/Components/Collidable.xml b/resources/Schema/Components/Collidable.xml new file mode 100644 index 00000000..0d1bb9b3 --- /dev/null +++ b/resources/Schema/Components/Collidable.xml @@ -0,0 +1,3 @@ + + true + \ No newline at end of file diff --git a/resources/Schema/Components/Collidable.xsd b/resources/Schema/Components/Collidable.xsd new file mode 100644 index 00000000..f835d9a6 --- /dev/null +++ b/resources/Schema/Components/Collidable.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/CollisionTestLevel.xml b/resources/Schema/Entities/CollisionTestLevel.xml index 99842b88..52420d14 100644 --- a/resources/Schema/Entities/CollisionTestLevel.xml +++ b/resources/Schema/Entities/CollisionTestLevel.xml @@ -1,122 +1,20 @@ - + + - - - - - - - Models/DummyScene.obj - - - - - - - - - - - Models/ScaleWidget.obj - - - - - - - - - - - Models/RotationWidgetX.obj - - - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitRaptor.obj - - - - - - - - - - - - 20 - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + Models/Test/ObstacleCourse.obj + + + + + + + + diff --git a/resources/Schema/Entities/Empty.xml b/resources/Schema/Entities/Empty.xml index 70581847..6efd8318 100644 --- a/resources/Schema/Entities/Empty.xml +++ b/resources/Schema/Entities/Empty.xml @@ -1,6 +1,10 @@ - + + - \ No newline at end of file + + + + diff --git a/resources/Schema/Entities/OctreeTest.xml b/resources/Schema/Entities/OctreeTest.xml new file mode 100644 index 00000000..819159d0 --- /dev/null +++ b/resources/Schema/Entities/OctreeTest.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + Models/Core/UnitCube.obj + + + + + + + + + + + + + + Models/Core/UnitCube.obj + + + + + + + + + + + + + + Models/Core/UnitCube.obj + + + + + + + + + + + + Models/Core/UnitCube.obj + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 6562f3ed..8790d8a9 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -15,7 +15,10 @@ + + + diff --git a/src/Engine/Collision/CollidableOctreeSystem.cpp b/src/Engine/Collision/CollidableOctreeSystem.cpp new file mode 100644 index 00000000..c7fed0a0 --- /dev/null +++ b/src/Engine/Collision/CollidableOctreeSystem.cpp @@ -0,0 +1,20 @@ +#include "Collision/CollidableOctreeSystem.h" + +void CollidableOctreeSystem::Update(World* world, double dt) +{ + m_Octree->ClearDynamicObjects(); +} + +void CollidableOctreeSystem::UpdateComponent(World* world, ComponentWrapper& cCollidable, double dt) +{ + EntityID entity = cCollidable.EntityID; + + if (world->HasComponent(entity, "AABB")) { + boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(world, entity); + if (absoluteAABB) { + m_Octree->AddDynamicObject(*absoluteAABB); + } + } else if (world->HasComponent(entity, "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 620e9639..1af09382 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -13,7 +13,7 @@ bool RayAABBIntr(const Ray& ray, const AABB& box) { glm::vec3 w = 75.0f * ray.Direction(); glm::vec3 v = glm::abs(w); - glm::vec3 c = ray.Origin() - box.Center() + w; + glm::vec3 c = ray.Origin() - box.Origin() + w; glm::vec3 half = box.HalfSize(); if (abs(c.x) > v.x + half.x) { @@ -68,8 +68,8 @@ bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) bool AABBVsAABB(const AABB& a, const AABB& b) { - const glm::vec3& aCenter = a.Center(); - const glm::vec3& bCenter = b.Center(); + const glm::vec3& aCenter = a.Origin(); + const glm::vec3& bCenter = b.Origin(); const glm::vec3& aHSize = a.HalfSize(); const glm::vec3& bHSize = b.HalfSize(); //Test will probably exit because of the X and Z axes more often, so test them first. @@ -202,8 +202,8 @@ bool RayVsModel(const Ray& ray, bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) { const glm::vec3& ma1 = first.MaxCorner(); - const glm::vec3& ma2 = first.MaxCorner(); - const glm::vec3& mi1 = second.MinCorner(); + const glm::vec3& ma2 = second.MaxCorner(); + const glm::vec3& mi1 = first.MinCorner(); const glm::vec3& mi2 = second.MinCorner(); return (std::abs(ma1.x - ma2.x) < epsilon) && (std::abs(mi1.x - mi2.x) < epsilon) && @@ -238,45 +238,23 @@ bool attachAABBComponentFromModel(World* world, EntityID id) mini.y = std::min(wPos.y, mini.y); mini.z = std::min(wPos.z, mini.z); } - collision["BoxCenter"] = 0.5f * (maxi + mini); - collision["BoxSize"] = maxi - mini; + collision["Origin"] = 0.5f * (maxi + mini); + collision["Size"] = maxi - mini; return true; } -bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox) -{ - ComponentWrapper& cTrans = world->GetComponent(AABBComponent.EntityID, "Transform"); - ComponentWrapper model = world->GetComponent(AABBComponent.EntityID, "Model"); - Model* modelRes = ResourceManager::Load(model["Resource"]); - outBox.CreateFromCenter(AABBComponent["BoxCenter"], AABBComponent["BoxSize"]); - glm::vec3 mini = outBox.MinCorner(); - glm::vec3 maxi = outBox.MaxCorner(); - - if (modelRes == nullptr) { - return false; - } - glm::mat4 modelMatrix = modelRes->m_Matrix * - glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) * - glm::scale((glm::vec3)cTrans["Scale"]); - - outBox = AABB(modelMatrix * glm::vec4(mini.x, mini.y, mini.z, 1), - modelMatrix * glm::vec4(maxi.x, maxi.y, maxi.z, 1)); - return true; -} - -bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel) +boost::optional EntityAbsoluteAABB(World* world, EntityID entity) { if (!world->HasComponent(entity, "AABB")) { - if (forceBoxFromModel) { - if (!attachAABBComponentFromModel(world, entity)) - return false; - } else { - return false; - } + return boost::none; } - ComponentWrapper& cBox = world->GetComponent(entity, "AABB"); - return GetEntityBox(world, cBox, outBox); + ComponentWrapper& cAABB = world->GetComponent(entity, "AABB"); + glm::vec3 absPosition = RenderQueueFactory::AbsolutePosition(world, entity); + glm::vec3 absScale = RenderQueueFactory::AbsoluteScale(world, entity); + glm::vec3 origin = absPosition + (glm::vec3)cAABB["Origin"]; + glm::vec3 size = (glm::vec3)cAABB["Size"] * absScale; + return AABB::FromOriginSize(origin, size); } } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 69929c6d..4ce514da 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -2,31 +2,30 @@ #include "Collision/CollisionSystem.h" #include "Core/AABB.h" -void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt) +void CollisionSystem::UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) { - //Right now, cAABB is a component attached to any entity that should be collideable. - AABB thisBox; - if (!Collision::GetEntityBox(world, cAABB, thisBox)) { + EntityID entity = cAABB.EntityID; + boost::optional boundingBox = Collision::EntityAbsoluteAABB(world, entity); + if (!boundingBox) { return; } + ComponentWrapper& cTransform = world->GetComponent(entity, "Transform"); + AABB& boxA = *boundingBox; + //Press 'Z' to enable/disable collision. if (zPress) { return; } - //Here, mover should be an object that moves, currently only players. - for (auto& mover : *world->GetComponents("Player")) { - if (cAABB.EntityID == mover.EntityID) { + + std::vector octreeResult; + m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); + for (auto& boxB : octreeResult) { + glm::vec3 resolutionVector; + if (Collision::IsSameBoxProbably(boxA, boxB)) { continue; } - AABB otherBox; - if (!Collision::GetEntityBox(world, mover.EntityID, otherBox)) { - continue; - } - glm::vec3 resolveTranslation; - if (Collision::AABBVsAABB(otherBox, thisBox, resolveTranslation)) { - ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform"); - //TODO: Special treatment if both are movers. - trans["Position"] = (glm::vec3)trans["Position"] + resolveTranslation; + if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { + (glm::vec3&)cTransform["Position"] += resolutionVector; } } } diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 09092461..2c8c7540 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -3,27 +3,27 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& trigger, double dt) +void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& cTrigger, double dt) { //Currently only players can trigger things. auto players = world->GetComponents("Player"); if (players == nullptr) { return; } - EntityID tId = trigger.EntityID; - AABB triggerBox; + EntityID tId = cTrigger.EntityID; + boost::optional triggerBox = Collision::EntityAbsoluteAABB(world, tId); //The trigger *should* have a bounding box, or something, to test against so it can be triggered. - if (!Collision::GetEntityBox(world, tId, triggerBox, true)) { + if (!triggerBox) { return; } for (auto& pc : *players) { EntityID pId = pc.EntityID; - AABB playerBox; + boost::optional playerBox = Collision::EntityAbsoluteAABB(world, pId); //The player can't trigger anything without an AABB. - if (!Collision::GetEntityBox(world, pId, playerBox, true)) { + if (!playerBox) { continue; } - if (!Collision::AABBVsAABB(triggerBox, playerBox)) { + if (!Collision::AABBVsAABB(*triggerBox, *playerBox)) { //Entity is not touching the trigger, //Throw event if it was previously. if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) { @@ -34,10 +34,9 @@ void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& trigger, dou throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId); } else { //Entity is at least touching the trigger. - AABB completelyInsideBox; - completelyInsideBox.CreateFromCenter(triggerBox.Center(), triggerBox.Size() - 2.0f * playerBox.Size()); - if (Collision::AABBVsAABB(completelyInsideBox, playerBox) && - glm::all(glm::greaterThan(triggerBox.Size(), playerBox.Size()))) { + AABB completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size()); + if (Collision::AABBVsAABB(completelyInsideBox, *playerBox) && + glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size()))) { //Entity is completely inside the trigger. //If it was only touching before, it is erased. m_EntitiesTouchingTrigger[tId].erase(pId); diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index 0df56229..22272104 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -4,7 +4,7 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) : m_MinCorner(minPos) , m_MaxCorner(maxPos) - , m_Center(0.5f * (maxPos + minPos)) + , m_Origin(0.5f * (maxPos + minPos)) , m_HalfSize(0.5f * (maxPos - minPos)) { DEBUG_IF(glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) { @@ -20,15 +20,12 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos) : AABB(glm::vec3(minPos), glm::vec3(maxPos)) -{} +{ } -void AABB::CreateFromCenter(const glm::vec3& center, const glm::vec3& size) +AABB AABB::FromOriginSize(const glm::vec3& origin, const glm::vec3& size) { - m_Center = center; - m_HalfSize = 0.5f * size; - m_MinCorner = m_Center - m_HalfSize; - m_MaxCorner = m_Center + m_HalfSize; + return AABB(origin - (size/2.f), origin + (size/2.f)); } AABB::~AABB() -{} +{ } diff --git a/src/Engine/Core/Octree.cpp b/src/Engine/Core/Octree.cpp index dca30cd7..47d06add 100644 --- a/src/Engine/Core/Octree.cpp +++ b/src/Engine/Core/Octree.cpp @@ -21,14 +21,10 @@ bool isFirstLower(const ChildInfo& first, const ChildInfo& second) } -Octree::Octree() - : Octree(AABB(), 0) -{} - Octree::Octree(const AABB& octTreeBounds, int subDivisions) : m_Root(new Child(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects)) , m_UpdatedOnce(false) -{} +{ } Octree::~Octree() { @@ -107,7 +103,7 @@ Octree::Child::Child(const AABB& octTreeBounds, glm::vec3 minPos, maxPos; const glm::vec3& parentMin = m_Box.MinCorner(); const glm::vec3& parentMax = m_Box.MaxCorner(); - const glm::vec3& parentCenter = m_Box.Center(); + const glm::vec3& parentCenter = m_Box.Origin(); std::bitset<3> bits(i); //If child is 4,5,6,7. if (bits.test(2)) { @@ -192,7 +188,7 @@ bool Octree::Child::RayCollides(const Ray& ray, Output& data) const std::vector childInfos; childInfos.reserve(8); for (int i = 0; i < 8; ++i) { - childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Center()) }); + childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Origin()) }); } std::sort(childInfos.begin(), childInfos.end(), isFirstLower); //Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit. @@ -329,7 +325,7 @@ void Octree::Child::ClearDynamicObjects() // z : - + - + - + - + int Octree::Child::childIndexContainingPoint(const glm::vec3& point) const { - const glm::vec3& c = m_Box.Center(); + const glm::vec3& c = m_Box.Origin(); return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index b49cf555..6d3dff3d 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -3,7 +3,8 @@ #include EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer) - : ImpureSystem(eventBroker) + : System(eventBroker) + , ImpureSystem() , m_Renderer(renderer) { auto config = ResourceManager::Load("Config.ini"); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index c84c556b..1865dd6c 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,4 +1,5 @@ #include "Game.h" +#include "Collision/CollidableOctreeSystem.h" #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" #include "Game/HealthSystem.h" @@ -56,20 +57,25 @@ Game::Game(int argc, char* argv[]) fp.MergeEntities(m_World); } + // Create Octrees + m_OctreeCollision = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); + m_OctreeFrustrumCulling = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); + // Create system pipeline m_SystemPipeline = new SystemPipeline(m_EventBroker); - - //All systems with orderlevel 0 will be updated first. + // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); - - //Collision and TriggerSystem should update after player. + // Populate Octree with collidables ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); + // Collision and TriggerSystem should update after player. + ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { @@ -82,6 +88,8 @@ Game::Game(int argc, char* argv[]) Game::~Game() { delete m_SystemPipeline; + delete m_OctreeFrustrumCulling; + delete m_OctreeCollision; delete m_World; delete m_FrameStack; delete m_InputProxy; diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp index 7a1d5005..858355fc 100644 --- a/src/Game/HealthSystem.cpp +++ b/src/Game/HealthSystem.cpp @@ -2,7 +2,8 @@ #include HealthSystem::HealthSystem(EventBroker* eventBroker) - : PureSystem(eventBroker, "Health") + : System(eventBroker) + , PureSystem("Health") { //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged); diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index f437bde0..3a130354 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -21,9 +21,9 @@ BOOST_AUTO_TEST_CASE(octSameRegionTest) tree.BoxesInSameRegion(testBox, region); BOOST_REQUIRE(region.size() == 1); AABB& box = region[0]; - BOOST_CHECK_CLOSE_FRACTION(box.Center().x, firstQuadrant.Center().x, 0.00001f); - BOOST_CHECK_CLOSE_FRACTION(box.Center().y, firstQuadrant.Center().y, 0.00001f); - BOOST_CHECK_CLOSE_FRACTION(box.Center().z, firstQuadrant.Center().z, 0.00001f); + BOOST_CHECK_CLOSE_FRACTION(box.Origin().x, firstQuadrant.Origin().x, 0.00001f); + BOOST_CHECK_CLOSE_FRACTION(box.Origin().y, firstQuadrant.Origin().y, 0.00001f); + BOOST_CHECK_CLOSE_FRACTION(box.Origin().z, firstQuadrant.Origin().z, 0.00001f); BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().x, firstQuadrant.HalfSize().x, 0.00001f); BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().y, firstQuadrant.HalfSize().y, 0.00001f); BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().z, firstQuadrant.HalfSize().z, 0.00001f); diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 10d4d6a5..2c45d897 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -91,7 +91,7 @@ void Game::Tick() frameCounter = 0; } ComponentWrapper transform = m_World->GetComponent(m_World->anotherBoxTransformId, "Transform"); - transform["Position"] = boxi.Center(); + transform["Position"] = boxi.Origin(); //check all children again in the tree if they have a box in them or not, and colormark them if they do //contentboxarna får man ut - inte childboxarna! @@ -110,7 +110,7 @@ void Game::Tick() //REQUIRED: childIndicesContainingBox must be public to test this! for each (auto someBoxIndex in boxIndex) { - glm::vec3 pos = m_World->someOctTree.m_Root->m_Children[someBoxIndex]->m_Box.Center(); + glm::vec3 pos = m_World->someOctTree.m_Root->m_Children[someBoxIndex]->m_Box.Origin(); if (abs(pos.x - oneLinkedObject.posxyz.x) < 0.005f && abs(pos.y - oneLinkedObject.posxyz.y) < 0.005f && abs(pos.z - oneLinkedObject.posxyz.z) < 0.005f) { diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index 7fcae0b2..db0b3b3c 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -77,7 +77,7 @@ private: auto someAABB = AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); //draw main box first - AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, someOctTree.m_Root, tempId); + AddBoxModel(someAABB.Origin(), someAABB.HalfSize().x, someOctTree.m_Root, tempId); //add anotherbox in octTree auto anotherBox = AABB(glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.2f, 0.2f, 0.2f)); @@ -85,19 +85,19 @@ private: someOctTree.AddDynamicObject(anotherBox); //draw anotherbox and save it in anotherBoxTransformId - AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, someOctTree.m_Root, anotherBoxTransformId); + AddBoxModel(anotherBox.Origin(), anotherBox.HalfSize().x, someOctTree.m_Root, anotherBoxTransformId); //draw the octTree for (size_t j = 0; j < 8; j++) { - AddBoxModel(someOctTree.m_Root->m_Children[j]->m_Box.Center(), + AddBoxModel(someOctTree.m_Root->m_Children[j]->m_Box.Origin(), someOctTree.m_Root->m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Root->m_Children[j], tempId); auto someChild = someOctTree.m_Root->m_Children[j]; for (size_t i = 0; i < 8; i++) { - AddBoxModel(someChild->m_Children[i]->m_Box.Center(), + AddBoxModel(someChild->m_Children[i]->m_Box.Origin(), someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i], tempId); } } diff --git a/src/Tests/OldOctTree.cpp b/src/Tests/OldOctTree.cpp index d3738ee6..0fb92e18 100644 --- a/src/Tests/OldOctTree.cpp +++ b/src/Tests/OldOctTree.cpp @@ -54,7 +54,7 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) glm::vec3 minPos, maxPos; const glm::vec3& parentMin = m_Box.MinCorner(); const glm::vec3& parentMax = m_Box.MaxCorner(); - const glm::vec3& parentCenter = m_Box.Center(); + const glm::vec3& parentCenter = m_Box.Origin(); std::bitset<3> bits(i); //If child is 4,5,6,7. if (bits.test(2)) { @@ -172,7 +172,7 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const std::vector childInfos; childInfos.reserve(8); for (int i = 0; i < 8; ++i) { - childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Center()) }); + childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Origin()) }); } std::sort(childInfos.begin(), childInfos.end(), isFirstLower); //Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit. @@ -279,7 +279,7 @@ void OctTree::ClearDynamicObjects() // z : - + - + - + - + int OctTree::childIndexContainingPoint(const glm::vec3& point) const { - const glm::vec3& c = m_Box.Center(); + const glm::vec3& c = m_Box.Origin(); return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); }