Working on OctTree tests

This commit is contained in:
verysecrethero
2015-12-09 10:08:08 +01:00
parent 7ac2aaef15
commit 75402b0f93
6 changed files with 445 additions and 22 deletions
+28 -21
View File
@@ -7,17 +7,17 @@
namespace
{
//To be able to sort nodes based on distance to ray origin.
struct ChildInfo
{
int Index;
float Distance;
};
//To be able to sort nodes based on distance to ray origin.
struct ChildInfo
{
int Index;
float Distance;
};
bool isFirstLower(const ChildInfo& first, const ChildInfo& second)
{
return first.Distance < second.Distance;
}
bool isFirstLower(const ChildInfo& first, const ChildInfo& second)
{
return first.Distance < second.Distance;
}
}
@@ -32,28 +32,31 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions)
for (OctTree*& c : m_Children) {
c = nullptr;
}
} else {
}
else {
--subDivisions;
const glm::vec3& parentMin = m_Box.MinCorner();
const glm::vec3& parentMax = m_Box.MaxCorner();
const glm::vec3& parentCenter = m_Box.Center();
for (int i = 0; i < 8; ++i) {
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();
std::bitset<3> bits(i);
//If child is 4,5,6,7.
if (bits.test(2)) {
minPos.x = parentCenter.x;
maxPos.x = parentMax.x;
} else {
}
else {
minPos.x = parentMin.x;
maxPos.x = parentCenter.x;
}
//If child is 2,3,6,7
if (bits.test(1)) {
minPos.y = parentCenter.y;
maxPos.y = parentMax.y;
} else {
}
else {
minPos.y = parentMin.y;
maxPos.y = parentCenter.y;
}
@@ -61,7 +64,8 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions)
if (bits.test(0)) {
minPos.z = parentCenter.z;
maxPos.z = parentMax.z;
} else {
}
else {
minPos.z = parentMin.z;
maxPos.z = parentCenter.z;
}
@@ -107,7 +111,8 @@ bool OctTree::rayCollides(const Ray& ray, Output& data) const
return true;
}
}
} else {
}
else {
//Check against boxes in the node.
float minDist = INFINITY;
bool intersected = false;
@@ -162,7 +167,8 @@ void OctTree::AddBox(const AABB& box)
default:
break;
}
} else {
}
else {
m_ContainingBoxes.push_back(box);
}
}
@@ -175,7 +181,8 @@ void OctTree::ClearBoxes()
for (OctTree*& c : m_Children) {
c->ClearBoxes();
}
} else {
}
else {
m_ContainingBoxes.clear();
}
}
+5 -1
View File
@@ -2,6 +2,7 @@
using boost::unit_test_framework::test_suite;
using boost::unit_test_framework::test_case;
#include <stdlib.h>//srand
#include "OctTreeTestGameClass.h"
//HACK! Needed for white box testing
//else we would have to "open up" the octTree class more with get/sets, public methods, etc. which is not good encapsulation-wise
//friend class and refactoringIntoNewClass is some extra work and needs to be updated when the original class is updated, and can contain bugs that
@@ -10,7 +11,6 @@ using boost::unit_test_framework::test_case;
//http://stackoverflow.com/questions/6778496/how-to-do-unit-testing-on-private-members-and-methods-of-c-classes
//http://stackoverflow.com/questions/3676664/unit-testing-of-private-methods
#define private public
#include <Engine\Core\OctTree.h>
BOOST_AUTO_TEST_SUITE(octTreeTests)
@@ -55,6 +55,10 @@ BOOST_AUTO_TEST_CASE(octTreeTest)
BOOST_AUTO_TEST_CASE(octTreeTest2)
{
Game game(0, nullptr);
while (game.Running()) {
game.Tick();
}
}
+78
View File
@@ -0,0 +1,78 @@
#include "OctTreeTestGameClass.h"
Game::Game(int argc, char* argv[])
{
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<Model>("Model");
ResourceManager::RegisterType<Texture>("Texture");
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
// Create the core event broker
m_EventBroker = new EventBroker();
m_RenderQueueFactory = new RenderQueueFactory();
// Create the renderer
m_Renderer = new Renderer();
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
m_Renderer->SetResolution(Rectangle(
0,
0,
m_Config->Get<int>("Video.Width", 1280),
m_Config->Get<int>("Video.Height", 720)
));
m_Renderer->Initialize();
// Create input manager
m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker);
// Create the root level GUI frame
m_FrameStack = new GUI::Frame(m_EventBroker);
m_FrameStack->Width = m_Renderer->Resolution().Width;
m_FrameStack->Height = m_Renderer->Resolution().Height;
// Create a TEST WORLD
m_World = new HardcodedTestWorld();
m_LastTime = glfwGetTime();
}
Game::~Game()
{
delete m_FrameStack;
delete m_EventBroker;
}
void Game::Tick()
{
double currentTime = glfwGetTime();
double dt = currentTime - m_LastTime;
m_LastTime = currentTime;
m_EventBroker->Swap();
m_InputManager->Update(dt);
m_Renderer->Update(dt);
m_EventBroker->Swap();
//movement
//auto transf = m_World->GetComponent(m_World->OctTreeEntityIdSaved, "Transform");
//((glm::vec3&)transf["Position"]).x += 0.001f;
m_RenderQueueFactory->Update(m_World);
//wireframe
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
m_EventBroker->Swap();
m_EventBroker->Clear();
glfwPollEvents();
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef Game_h__
#define Game_h__
#include "Core/ResourceManager.h"
#include "Core/ConfigFile.h"
#include "Core/EventBroker.h"
#include "Rendering/Renderer.h"
#include "Core/InputManager.h"
#include "GUI/Frame.h"
#include "Core/World.h"
#include "Rendering/RenderQueueFactory.h"
#include "OctTreeTestHardCodedTestWorld.h"
class Game
{
public:
Game(int argc, char* argv[]);
~Game();
bool Running() const { return !glfwWindowShouldClose(m_Renderer->Window()); }
void Tick();
private:
double m_LastTime;
ConfigFile* m_Config = nullptr;
EventBroker* m_EventBroker;
IRenderer* m_Renderer;
InputManager* m_InputManager;
GUI::Frame* m_FrameStack;
HardcodedTestWorld* m_World;
RenderQueueFactory* m_RenderQueueFactory;
};
#endif
+104
View File
@@ -0,0 +1,104 @@
//#define BOOST_TEST_MODULE collTest
#include <boost/test/unit_test.hpp>
#include <boost/test/execution_monitor.hpp>
using boost::unit_test_framework::test_suite;
using boost::unit_test_framework::test_case;
#include <Engine\Core\Collision.h>
#include "Engine/Core/AABB.h"
#include "Engine/Core/Ray.h"
#include <stdlib.h>//srand
#include "Engine/Core/OctTree.h"
//vs memleaks
//#define _CRTDBG_MAP_ALLOC
//#include <stdlib.h>
//#include <crtdbg.h>
//#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
//#define new DEBUG_CLIENTBLOCK
BOOST_AUTO_TEST_SUITE(collisionTests)
BOOST_AUTO_TEST_CASE(collisionTest)
{
//memleak
int* globalLeak = new int[5];
//fixed seed
srand(2);
Ray ray;
AABB someAABB;
glm::vec3 minPos;
glm::vec3 maxPos;
bool z;
int test = 0;
for (size_t i = 0; i < 10; i++)
{
ray.Origin.x = rand() % 100;
ray.Origin.y = rand() % 100;
ray.Origin.z = rand() % 100;
ray.Direction.x = rand() % 100;
ray.Direction.y = rand() % 100;
ray.Direction.z = rand() % 100;
minPos.x = rand() % 100;
minPos.y = rand() % 100;
minPos.z = rand() % 100;
maxPos.x = rand() % 100;
maxPos.y = rand() % 100;
maxPos.z = rand() % 100;
someAABB = AABB(minPos, maxPos);
z = Collision::RayVsAABB(ray, someAABB);
if (z) ++test;
}
BOOST_CHECK(test >= 0);
//_CrtDumpMemoryLeaks();
}
BOOST_AUTO_TEST_CASE(collisionTest2)
{
//fixed seed
srand(2);
Ray ray;
AABB someAABB;
glm::vec3 minPos;
glm::vec3 maxPos;
bool z;
int test = 0;
for (size_t i = 0; i < 1000000; i++)
{
ray.Origin.x = rand() % 100;
ray.Origin.y = rand() % 100;
ray.Origin.z = rand() % 100;
ray.Direction.x = rand() % 100;
ray.Direction.y = rand() % 100;
ray.Direction.z = rand() % 100;
minPos.x = rand() % 100;
minPos.y = rand() % 100;
minPos.z = rand() % 100;
maxPos.x = rand() % 100;
maxPos.y = rand() % 100;
maxPos.z = rand() % 100;
someAABB = AABB(minPos, maxPos);
z = Collision::RayAABBIntr(ray, someAABB);
if (z) ++test;
}
BOOST_CHECK(test >= 0);
}
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));
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));
}
BOOST_AUTO_TEST_SUITE_END()
+195
View File
@@ -0,0 +1,195 @@
#include <list>
#include <tuple>
#include <boost/any.hpp>
#include "GLM.h"
#include "Core/World.h"
#include "Core/Util/Any.h"
//octTree
//#include <windows.h>
//last!
#define private public
#include <Engine\Core\OctTree.h>
class HardcodedTestWorld : public World
{
public:
EntityID OctTreeEntityIdSaved;
//constructor
HardcodedTestWorld()
: World()
{
registerTestComponents();
createTestEntities();
}
private:
void registerTestComponents()
{
ComponentWrapperFactory f;
f = ComponentWrapperFactory("Test");
f.AddProperty("TestInteger", 1337);
f.AddProperty("TestFloat", 13.37f);
f.AddProperty("TestString", std::string("Carlito"));
RegisterComponent(f);
f = ComponentWrapperFactory("Debug");
f.AddProperty("Name", std::string("Unnamed"));
RegisterComponent(f);
f = ComponentWrapperFactory("Transform");
f.AddProperty("Position", glm::vec3(0.f, 0.f, 0.f));
f.AddProperty("Orientation", glm::quat());
f.AddProperty("Scale", glm::vec3(1.f, 1.f, 1.f));
RegisterComponent(f);
f = ComponentWrapperFactory("Model");
f.AddProperty("Resource", std::string());
f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f));
f.AddProperty("Visible", true);
RegisterComponent(f);
}
void createTestEntities()
{
World& world = *this;
// Create an entity
EntityID e = world.CreateEntity();
// Attach a Debug component
ComponentWrapper debug = world.AttachComponent(e, "Debug");
// Set the Name field of the Debug component using subscript operator
debug["Name"] = "Carlito";
// Attach a Transform component
world.AttachComponent(e, "Transform");
// Fetch the component based on EntityID and component type
ComponentWrapper transform = world.GetComponent(e, "Transform");
// Set the fields of the Transform component
transform["Position"] = glm::vec3(0.f, 0.f, 0.f);
transform["Scale"] = glm::vec3(1.f, 1.f, 1.f);
// Move on the X axis by fetching field as reference
((glm::vec3&)transform["Position"]).x += 10.f;
// Shrink by a factor of 100
((glm::vec3&)transform["Scale"]) /= 100.f;
// Loop through all Transform components and print them
for (auto& transform : world.GetComponents("Transform")) {
glm::vec3 pos = transform["Position"];
std::cout << "Position: " << pos.x << " " << pos.y << " " << pos.z << std::endl;
glm::vec3 scale = transform["Scale"];
std::cout << "Scale: " << scale.x << " " << scale.y << " " << scale.z << std::endl;
// Fetch the Debug component also present in this entity
ComponentWrapper debug = world.GetComponent(transform.EntityID, "Debug");
std::cout << "Name: " << (std::string)debug["Name"] << std::endl;
}
//Create some test widgets
//{
// EntityID entityScaleWidget = world.CreateEntity();
// ComponentWrapper transform = world.AttachComponent(entityScaleWidget, "Transform");
// transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
// ComponentWrapper model = world.AttachComponent(entityScaleWidget, "Model");
// model["Resource"] = "Models/ScaleWidget.obj";
//}
//{
// EntityID entityRotationWidget = world.CreateEntity();
// ComponentWrapper transform = world.AttachComponent(entityRotationWidget, "Transform");
// transform["Position"] = glm::vec3(1.5f, 0.f, 0.f);
// ComponentWrapper model = world.AttachComponent(entityRotationWidget, "Model");
// model["Resource"] = "Models/RotationWidget.obj";
//}
//{
// EntityID entityDummyScene = world.CreateEntity();
// ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
// transform["Position"] = glm::vec3(0, 0.f, 0.f);
// ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
// model["Resource"] = "Models/DummyScene.obj";
//}
//add octTree
{
//ComponentWrapper debug = world.AttachComponent(e, "Debug");
//// Set the Name field of the Debug component using subscript operator
//debug["Name"] = "Blah";
auto minCorner = glm::vec3(0.0f, 0.0f, 0.0f);
auto maxCorner = glm::vec3(1.0f, 1.0f, 1.0f);
auto someAABB = AABB(minCorner, maxCorner);
auto someOctTree = OctTree(someAABB, 2);
//auto min1 = someOctTree.m_Children[i]->m_Box.MinCorner();
//auto max1 = someOctTree.m_Children[i]->m_Box.MaxCorner();
float boxDrawFactor = 1.05f;
auto halfSizeFactor = 0.0f;
halfSizeFactor = someAABB.HalfSize().x;
//the first box first
EntityID entityDummyScene = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
transform["Position"] = someAABB.Center()*1.0f;
transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSizeFactor*boxDrawFactor;
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
model["Resource"] = "Models/Core/UnitBox.obj";
model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
//just draw the first 8 children - looks nicer in code if i split it this way
for (size_t i = 0; i < 8; i++)
{
auto cen1 = someOctTree.m_Children[i]->m_Box.Center();
halfSizeFactor = someOctTree.m_Children[i]->m_Box.HalfSize().x;
EntityID entityDummyScene = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
transform["Position"] = cen1*1.0f;
transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*0.97f*halfSizeFactor*boxDrawFactor;
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
model["Resource"] = "Models/Core/UnitBox.obj";
model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
//OutputDebugStringA((std::to_string(cen1.x) + std::to_string(cen1.y) + std::to_string(cen1.z)).c_str());
//OctTreeEntityIdSaved = entityDummyScene;
}
//then draw the childrens children
//for (size_t j = 0; j < 8; j++)
//{
// auto someChild = someOctTree.m_Children[j];
// for (size_t i = 0; i < 8; i++)
// {
// auto cen1 = someChild->m_Children[i]->m_Box.Center();
// auto boxScale = someChild->m_Children[i]->m_Box.HalfSize();
// EntityID entityDummyScene = world.CreateEntity();
// ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
// transform["Position"] = cen1*1.0f;
// transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*0.97f*boxScale*boxDrawFactor;
// ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
// model["Resource"] = "Models/Core/UnitBox.obj";
// model["Color"] = glm::vec4(0.0f, 1.0f, 0.0f, 1.0f);
// //OctTreeEntityIdSaved = entityDummyScene;
// }
//}
}
}
};