From bad42fae1c00b2e5a6f9c3d996d75d94266dde71 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 9 Dec 2015 13:27:00 +0100 Subject: [PATCH] OctTree differentiates between static/dynamic objects now. Added a general BoxesInSameRegion method. --- include/Engine/Core/OctTree.h | 27 +++++++++--- src/Engine/Core/OctTree.cpp | 82 +++++++++++++++++++++++++++-------- src/Tests/CollisionTest.cpp | 10 +++-- 3 files changed, 92 insertions(+), 27 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 6279e93c..911375d5 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -16,8 +16,21 @@ public: ~OctTree(); //For the root OctTree, [octTreeBounds] should be a box containing the entire level. OctTree(const AABB& octTreeBounds, int subDivisions); - void AddBox(const AABB& box); - void ClearBoxes(); + + //We should only ever need one OctTree in the game, and it should not need to be copied. + //Define these if the OctTree suddenly needs to be copied, think of the children OctTree* ptrs. + OctTree(const OctTree& other) = delete; + OctTree(const OctTree&& other) = delete; + OctTree& operator= (const OctTree& other) = delete; + + void AddDynamicObject(const AABB& box); + void AddStaticObject(const AABB& box); + + void BoxesInSameRegion(const AABB& box, std::vector& outBoxes) const; + + void ClearObjects(); + void ClearDynamicObjects(); + //Returns true if the ray collides with something in the tree. Result is written to [data]. bool RayCollides(const Ray& ray, Output& data) const; //Returns true if the box collides with something in the tree. @@ -26,10 +39,12 @@ public: private: OctTree* m_Children[8]; - //TODO: Do derived class from AABB with a bool Tested, falsify at - //start of Collision test, set on check, don't check if set already. Solves duplicate boxes in tree. - //TODO: Boxes collide with themselves? Fix somehow, maybe float epsilon stuff. - std::vector m_ContainingBoxes; + //WTODO: Do -derived class from AABB- struct containing AABB, with a bool Tested, falsify at + //start of Collision test, set on check, don't check if set already. Solves duplicate boxes in tree. + //Store indices in the struct, pointing to grand ancestor list of boxes, need the same AABB not copies to save Tested. + //WTODO: Boxes collide with themselves? Fix somehow, maybe float epsilon stuff. + std::vector m_StaticObjects; + std::vector m_DynamicObjects; AABB m_Box; inline bool hasChildren() const; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index de38b143..66355580 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -88,10 +88,16 @@ bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const return true; } } else { - for (const auto& objBox : m_ContainingBoxes) { - if (Collision::AABBVsAABB(boxToTest, objBox)) { - outBoxIntersected = objBox; - return true; + std::vector> objVectors = { + m_StaticObjects, + m_DynamicObjects + }; + for (const auto& objVector : objVectors) { + for (const auto& obj : objVector) { + if (Collision::AABBVsAABB(boxToTest, obj)) { + outBoxIntersected = obj; + return true; + } } } } @@ -121,13 +127,20 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const //Check against boxes in the node. float minDist = INFINITY; bool intersected = false; - for (const auto& objBox : m_ContainingBoxes) { - float dist; - if (Collision::RayVsAABB(ray, objBox, dist)) { - minDist = std::min(dist, minDist); - intersected = true; + std::vector> objVectors = { + m_StaticObjects, + m_DynamicObjects + }; + for (const auto& objVector : objVectors) { + for (const auto& obj : objVector) { + float dist; + if (Collision::RayVsAABB(ray, obj, dist)) { + minDist = std::min(dist, minDist); + intersected = true; + } } } + data.CollideDistance = minDist; return intersected; } @@ -135,26 +148,61 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const return false; } -void OctTree::AddBox(const AABB& box) + +void OctTree::AddDynamicObject(const AABB& box) { if (hasChildren()) { for (auto i : childIndicesContainingBox(box)) { - m_Children[i]->AddBox(box); + m_Children[i]->AddDynamicObject(box); } } else { - m_ContainingBoxes.push_back(box); + m_DynamicObjects.push_back(box); } } -//TODO: Only clear dynamic boxes, AddDynamic, AddStatic -void OctTree::ClearBoxes() +void OctTree::AddStaticObject(const AABB& box) +{ + if (hasChildren()) { + for (auto i : childIndicesContainingBox(box)) { + m_Children[i]->AddStaticObject(box); + } + } else { + m_StaticObjects.push_back(box); + } +} + +void OctTree::BoxesInSameRegion(const AABB& box, std::vector& outBoxes) const +{ + if (hasChildren()) { + for (auto i : childIndicesContainingBox(box)) { + m_Children[i]->BoxesInSameRegion(box, outBoxes); + } + } else { + outBoxes.insert(outBoxes.end(), m_StaticObjects.begin(), m_StaticObjects.end()); + outBoxes.insert(outBoxes.end(), m_DynamicObjects.begin(), m_DynamicObjects.end()); + } +} + +void OctTree::ClearObjects() { if (hasChildren()) { for (OctTree*& c : m_Children) { - c->ClearBoxes(); + c->ClearObjects(); } } else { - m_ContainingBoxes.clear(); + m_DynamicObjects.clear(); + m_StaticObjects.clear(); + } +} + +void OctTree::ClearDynamicObjects() +{ + if (hasChildren()) { + for (OctTree*& c : m_Children) { + c->ClearObjects(); + } + } else { + m_DynamicObjects.clear(); } } @@ -194,7 +242,7 @@ std::vector OctTree::childIndicesContainingBox(const AABB& box) const case 2: { std::vector ret; - //Bit-hax to calculate the right 4 cildren containing the box. + //Bit-hax to calculate the correct 4 children containing the box. //This works because of the childrens index determine what part of //the dimensions they are responsible for (which octant). bits.flip(); diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index ab13e930..eef24e61 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -92,12 +92,14 @@ BOOST_AUTO_TEST_CASE(octTest) glm::vec3 mini = glm::vec3(-1, -1, -1); glm::vec3 maxi = glm::vec3(1, 1, 1); OctTree tree(AABB(mini, maxi), 2); - tree.AddBox(AABB(mini, -0.9f*maxi)); + tree.AddDynamicObject(AABB(mini, -0.9f*maxi)); OctTree::Output data; glm::vec3 origin = 3.0f * mini; - BOOST_CHECK(tree.RayCollides({origin , glm::normalize(mini - origin) }, data)); - tree.ClearBoxes(); - BOOST_CHECK(!tree.RayCollides({ origin , glm::normalize(mini - origin) }, data)); + bool rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data); + BOOST_CHECK(rayIntersected); + tree.ClearDynamicObjects(); + rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data); + BOOST_CHECK(!rayIntersected); } BOOST_AUTO_TEST_SUITE_END()