From 1d19c6901eadce9dc0b40fe552020164a9a4f134 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 2 Dec 2015 11:18:52 +0100 Subject: [PATCH 001/185] Added collision files. --- include/Engine/Core/Collision.h | 9 +++++++++ src/Engine/Core/Collision.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 include/Engine/Core/Collision.h create mode 100644 src/Engine/Core/Collision.cpp diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h new file mode 100644 index 00000000..407f2096 --- /dev/null +++ b/include/Engine/Core/Collision.h @@ -0,0 +1,9 @@ +#ifndef Collision_h__ +#define Collision_h__ + +namespace Collision +{ +//bool RayAABBIntr(float3 origin, float3 direction, float3 center, float3 h); +} + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp new file mode 100644 index 00000000..699d3b81 --- /dev/null +++ b/src/Engine/Core/Collision.cpp @@ -0,0 +1,27 @@ + +namespace Collision +{ + +/*bool RayAABBIntr(float3 origin, float3 direction, float3 center, float3 h) +{ +float3 w = 75.0f * direction; +float3 v = abs(w); +float3 c = origin - center + w; + +//This is better if we hit often, do comparisons simultanously. +//if (any(abs(c) > v + h)) +// return false; +// +//return !(any(abs(c.yxx*w.zzy - c.zzy*w.yxx) > h.yxx*v.zzy + h.zzy*v.yxx)); + +//This is better if we miss often, reject test and exit early. +if (abs(c.x) > v.x + h.x) return false; +if (abs(c.y) > v.y + h.y) return false; +if (abs(c.z) > v.z + h.z) return false; + +if (abs(c.y*w.z - c.z*w.y) > h.y*v.z + h.z*v.y) return false; +if (abs(c.x*w.z - c.z*w.x) > h.x*v.z + h.z*v.x) return false; +return !(abs(c.x*w.y - c.y*w.x) > h.x*v.y + h.y*v.x); +}*/ + +} \ No newline at end of file From fa0ace8c68dc0c25b8f8298d63e8b98086ee9d8d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 2 Dec 2015 11:32:56 +0100 Subject: [PATCH 002/185] Added empty OctTree files. --- include/Engine/Core/OctTree.h | 5 +++++ src/Engine/Core/OctTree.cpp | 0 2 files changed, 5 insertions(+) create mode 100644 include/Engine/Core/OctTree.h create mode 100644 src/Engine/Core/OctTree.cpp diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h new file mode 100644 index 00000000..5fd553d6 --- /dev/null +++ b/include/Engine/Core/OctTree.h @@ -0,0 +1,5 @@ +#ifndef OctTree_h__ +#define OctTree_h__ + + +#endif \ No newline at end of file diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp new file mode 100644 index 00000000..e69de29b From c698149bddcb79c4076c125e02901136c0174ded Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 2 Dec 2015 14:24:21 +0100 Subject: [PATCH 003/185] Added Ray, AABB structs, and basic rayVsAABB test function. --- include/Engine/Core/Collision.h | 27 +++++++++++++++++- src/Engine/Core/Collision.cpp | 50 ++++++++++++++++++++------------- tools/CodeRules.h | 3 +- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index 407f2096..113a4a39 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -1,9 +1,34 @@ #ifndef Collision_h__ #define Collision_h__ +#include "../GLM.h" + namespace Collision { -//bool RayAABBIntr(float3 origin, float3 direction, float3 center, float3 h); +struct Ray +{ + glm::vec3 Origin; + glm::vec3 Direction; +}; + +class AABB +{ +public: + AABB() = default; + AABB(const glm::vec3& minPos, const glm::vec3& maxPos); + + 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& HalfSize() const { return m_HalfSize; } +private: + glm::vec3 m_MinCorner; + glm::vec3 m_MaxCorner; + glm::vec3 m_Center; + glm::vec3 m_HalfSize; +}; + +bool RayAABBIntr(const Ray& ray, const AABB& box); } #endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index 699d3b81..4ccd1ccd 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -1,27 +1,39 @@ +#include "Core\Collision.h" namespace Collision { -/*bool RayAABBIntr(float3 origin, float3 direction, float3 center, float3 h) +AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) + : m_MinCorner(minPos) + , m_MaxCorner(maxPos) + , m_Center(0.5f * (maxPos + minPos)) + , m_HalfSize(0.5f * (maxPos - minPos)) +{ } + +bool RayAABBIntr(const Ray& ray, const AABB& box) { -float3 w = 75.0f * direction; -float3 v = abs(w); -float3 c = origin - center + w; + glm::vec3 w = 75.0f * ray.Direction; + glm::vec3 v = glm::abs(w); + glm::vec3 c = ray.Origin - box.Center() + w; + glm::vec3 half = box.HalfSize(); + + if (abs(c.x) > v.x + half.x) { + return false; + } + if (abs(c.y) > v.y + half.y) { + return false; + } + if (abs(c.z) > v.z + half.z) { + return false; + } -//This is better if we hit often, do comparisons simultanously. -//if (any(abs(c) > v + h)) -// return false; -// -//return !(any(abs(c.yxx*w.zzy - c.zzy*w.yxx) > h.yxx*v.zzy + h.zzy*v.yxx)); - -//This is better if we miss often, reject test and exit early. -if (abs(c.x) > v.x + h.x) return false; -if (abs(c.y) > v.y + h.y) return false; -if (abs(c.z) > v.z + h.z) return false; - -if (abs(c.y*w.z - c.z*w.y) > h.y*v.z + h.z*v.y) return false; -if (abs(c.x*w.z - c.z*w.x) > h.x*v.z + h.z*v.x) return false; -return !(abs(c.x*w.y - c.y*w.x) > h.x*v.y + h.y*v.x); -}*/ + if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) { + return false; + } + if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) { + return false; + } + return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); +} } \ No newline at end of file diff --git a/tools/CodeRules.h b/tools/CodeRules.h index f09ae81d..8d72a6f2 100755 --- a/tools/CodeRules.h +++ b/tools/CodeRules.h @@ -86,8 +86,7 @@ T* ClassType::PublicMemberFunction(bool value) if (m_PrivateMember2->PublicMember == 1) { return new T(); - } - else { + } else { return nullptr; } } From fd99562c7a7f32301724d92eec105853884156fa Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 2 Dec 2015 15:03:55 +0100 Subject: [PATCH 004/185] yrryr567yry567 --- include/Engine/Core/Collision.h | 3 +++ src/Engine/Core/Collision.cpp | 23 +++++++++++++++++++++++ src/Tests/CollisionTest.cpp | 18 ++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/Tests/CollisionTest.cpp diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index 113a4a39..f67a1c67 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -2,11 +2,13 @@ #define Collision_h__ #include "../GLM.h" +#include namespace Collision { struct Ray { +public: glm::vec3 Origin; glm::vec3 Direction; }; @@ -29,6 +31,7 @@ private: }; bool RayAABBIntr(const Ray& ray, const AABB& box); +bool RayVsAABB(const Ray& ray, const AABB& box); } #endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index 4ccd1ccd..fd79b8bc 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -1,4 +1,5 @@ #include "Core\Collision.h" +#include namespace Collision { @@ -36,4 +37,26 @@ bool RayAABBIntr(const Ray& ray, const AABB& box) return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); } +bool RayVsAABB(const Ray& ray, const AABB& box) +{ + glm::vec3 invdir = 1.0f / ray.Direction; + glm::vec3 bMin = box.MinCorner(); + glm::vec3 bMax = box.MaxCorner(); + + float t1 = (bMin.x - ray.Origin.x)*invdir.x; + float t2 = (bMax.x - ray.Origin.x)*invdir.x; + float t3 = (bMin.y - ray.Origin.y)*invdir.y; + float t4 = (bMax.y - ray.Origin.y)*invdir.y; + float t5 = (bMin.z - ray.Origin.z)*invdir.z; + float t6 = (bMax.z - ray.Origin.z)*invdir.z; + + float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); + float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); + + if (tmax < 0 || tmin > tmax) + return false; + + return true; +} + } \ No newline at end of file diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp new file mode 100644 index 00000000..ef02cb66 --- /dev/null +++ b/src/Tests/CollisionTest.cpp @@ -0,0 +1,18 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include + +BOOST_AUTO_TEST_SUITE(collisionTests) + +BOOST_AUTO_TEST_CASE(collisionTest) +{ + Collision::Ray ray; + ray.Origin = glm::vec3(0, 0, 0); + ray.Direction = glm::vec3(0, 0, 0); + auto someAABB = Collision::AABB(glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)); + bool z = Collision::RayVsAABB(ray, someAABB); +} + +BOOST_AUTO_TEST_SUITE_END() + From af294f78b7622ac5ec0ad21faa2ef571bb9fb5c3 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 2 Dec 2015 16:26:30 +0100 Subject: [PATCH 005/185] czdxvxdfvxvxvc --- src/Engine/Core/Collision.cpp | 16 ++++----- src/Tests/CollisionTest.cpp | 64 ++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index fd79b8bc..ff38c8a2 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -40,15 +40,13 @@ bool RayAABBIntr(const Ray& ray, const AABB& box) bool RayVsAABB(const Ray& ray, const AABB& box) { glm::vec3 invdir = 1.0f / ray.Direction; - glm::vec3 bMin = box.MinCorner(); - glm::vec3 bMax = box.MaxCorner(); - - float t1 = (bMin.x - ray.Origin.x)*invdir.x; - float t2 = (bMax.x - ray.Origin.x)*invdir.x; - float t3 = (bMin.y - ray.Origin.y)*invdir.y; - float t4 = (bMax.y - ray.Origin.y)*invdir.y; - float t5 = (bMin.z - ray.Origin.z)*invdir.z; - float t6 = (bMax.z - ray.Origin.z)*invdir.z; + + float t1 = (box.MinCorner().x - ray.Origin.x)*invdir.x; + float t2 = (box.MaxCorner().x - ray.Origin.x)*invdir.x; + float t3 = (box.MinCorner().y - ray.Origin.y)*invdir.y; + float t4 = (box.MaxCorner().y - ray.Origin.y)*invdir.y; + float t5 = (box.MinCorner().z - ray.Origin.z)*invdir.z; + float t6 = (box.MaxCorner().z - ray.Origin.z)*invdir.z; float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index ef02cb66..426b9722 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -2,16 +2,72 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include +#include //srand BOOST_AUTO_TEST_SUITE(collisionTests) BOOST_AUTO_TEST_CASE(collisionTest) { + //fixed seed + srand(2); Collision::Ray ray; - ray.Origin = glm::vec3(0, 0, 0); - ray.Direction = glm::vec3(0, 0, 0); - auto someAABB = Collision::AABB(glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)); - bool z = Collision::RayVsAABB(ray, someAABB); + Collision::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 = Collision::AABB(minPos, maxPos); + z = Collision::RayVsAABB(ray, someAABB); + if (z) ++test; + } + BOOST_CHECK(test >= 0); +} + +BOOST_AUTO_TEST_CASE(collisionTest2) +{ + //fixed seed + srand(2); + Collision::Ray ray; + Collision::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 = Collision::AABB(minPos, maxPos); + z = Collision::RayAABBIntr(ray, someAABB); + if (z) ++test; + } + BOOST_CHECK(test >= 0); } BOOST_AUTO_TEST_SUITE_END() From 464650c370e78ef13baa01b38fc9c3ff6972f695 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 2 Dec 2015 16:31:39 +0100 Subject: [PATCH 006/185] more tests added --- src/Tests/ObjectPoolTest.cpp | 476 +++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 src/Tests/ObjectPoolTest.cpp diff --git a/src/Tests/ObjectPoolTest.cpp b/src/Tests/ObjectPoolTest.cpp new file mode 100644 index 00000000..adea33eb --- /dev/null +++ b/src/Tests/ObjectPoolTest.cpp @@ -0,0 +1,476 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include "../wmem/MemPrototype/ObjectPool.h" +#include + +struct S +{ + S() = default; + S(int i, float ff) : k(i), f(ff) { } + ~S() { } + int k; + float f; +}; + +//BOOST_GLOBAL_FIXTURE(S); +BOOST_AUTO_TEST_SUITE(memProtoTypeTestSuite) + +BOOST_AUTO_TEST_CASE(testPool) +{ + ObjectPool pool(32);//32 true/false values = 32 slots + BOOST_CHECK(pool.empty() == true); + + const size_t size = 12;//12 platser i structen addresses, som håller en int, en float vardera + S* addresses[size]; + addresses[0] = pool.New(7, 0.035f); + //"Not empty after allocating one element." + BOOST_CHECK(!pool.empty()); + + //"Element created correctly with k==7" + BOOST_CHECK(addresses[0]->k == 7); + //"Element created correctly with f==0.035f" + BOOST_CHECK_CLOSE_FRACTION(addresses[0]->f, 0.035f, 0.0001f); + addresses[0]->k = 5; + BOOST_CHECK(addresses[0]->k == 5); + + //"Empty after delete" + pool.Delete(addresses[0]); + BOOST_CHECK(pool.empty()); + + addresses[0] = pool.New(7, 0.035f); + addresses[1] = pool.New(5, 0.035f); + pool.Delete(addresses[1]); + BOOST_CHECK(!pool.empty()); + pool.Delete(addresses[0]); + BOOST_CHECK(pool.empty()); + + //INT32_MAX, FLT_MAX test + addresses[0] = pool.New(INT32_MAX, FLT_MAX); + BOOST_CHECK(!pool.empty()); + BOOST_CHECK(addresses[0]->k == INT32_MAX); + BOOST_CHECK_CLOSE_FRACTION(addresses[0]->f, FLT_MAX, 0.0001f); +} +/* +BOOST_AUTO_TEST_CASE(testPoolArray) +{ +ObjectPool pool(32); +S* addresses; + +//Add array size 5 to pool." +addresses = pool.NewArray(5);// <-> addresses = new S[5]; +addresses[0] = S(12, 0.030f); +addresses[1] = S(13, 0.031f); +addresses[2] = S(14, 0.032f); +addresses[3] = S(15, 0.033f); +addresses[4] = S(16, 0.034f); + +//"Not empty after allocating +BOOST_CHECK(!pool.empty()); +//"Element created correctly with k==12" +BOOST_CHECK(addresses->k == 12); +//"Element created correctly with f==0.030f" +BOOST_CHECK_CLOSE_FRACTION(addresses->f, 0.030f, 0.0001f); + +//add a few other structs so it becomes bigger than the original size (32), +//which means it must push back the rest of the values into a vector +S* test2, *test3, *test4, *test5; +test2 = pool.NewArray(5);// <-> test2 = new S[5]; +test3 = pool.NewArray(40);//+40 +test4 = pool.NewArray(40);//+40 +test5 = pool.NewArray(40);//+40=120 +BOOST_CHECK(pool.ExtraSize() == 120); +BOOST_CHECK(pool.PoolSize() == 10); +BOOST_CHECK(pool.size() == 120 + 10); + +//testar "perfekt delete", dvs bryr mig inte om att testa att deleta bara 38 om storleken egentligen är 40 osv +pool.DeleteArray(test2, 5);//callar destructorn på test2 också +pool.DeleteArray(test3, 40); + +pool.DeleteArray(addresses, 5); + +//add / del array +S* another = pool.NewArray(64); +for (int i = 0; i < 64; ++i) +another[i] = S(i, 0.1f*i); +pool.DeleteArray(another, 64); +} +*/ +BOOST_AUTO_TEST_CASE(testIterationNormal) +{ + //extra vector check + S* test4, *test5; + ObjectPool pool(4); + test4 = pool.New(); + test5 = pool.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : pool) + o.k = 14; + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test4[i].k == 14); + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test5[i].k == 14); +} + +BOOST_AUTO_TEST_CASE(testOutOfScopeDelete) +{ + //extra vector check + S* test4, *test5; + { + ObjectPool pool(4); + test4 = pool.New(); + test5 = pool.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : pool) + o.k = 14; + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test4[i].k == 14); + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test5[i].k == 14); + } + //pool goes out of scope here, and thus the test4 values become undefined (memory is killed at out of scope) + BOOST_CHECK(test4[0].k != 14); + BOOST_CHECK(test5[0].k != 15); +} + +BOOST_AUTO_TEST_CASE(testIterationOneExtra) +{ + //extra vector check + ObjectPool pool(1); + S* test4, *test5; + test4 = pool.New(); + test5 = pool.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : pool) + o.k = 14; + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test4[i].k == 14); + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test5[i].k == 14); +} + +BOOST_AUTO_TEST_CASE(testIterationTwoExtra) +{ + //extra vector check + ObjectPool pool(1); + S* test4, *test5; + test4 = pool.New(); + test5 = pool.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : pool) + o.k = 14; + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test4[i].k == 14); + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test5[i].k == 14); +} +/* +BOOST_AUTO_TEST_CASE(releaseModeTest_RandomAllocateDeallocate) +{ +//run this in releasemode +struct I +{ +I() = default; +I(size_t i, size_t ff) : k(i), f(ff) { } +~I() { } +size_t k; +size_t f; +}; +srand((unsigned int)time(nullptr)); + +const size_t SIZE = 128; +ObjectPool pool(SIZE); +I* addresses[SIZE]; +std::vector allocated(SIZE, false); +std::vector arrSizes(SIZE, 0); +size_t slotsAlloced = 0; +size_t superCount = 0; +size_t slot; +size_t i; + +while (superCount++ < 1000) { +if (rand() % 2 == 0) { +i = 0; +//ta slumpmässig slot som inte är allokerad +do { +slot = (size_t)((SIZE - 1) * ((float)rand() / RAND_MAX)); +} while (allocated[slot] && ++i < 512); + +if (i < 512) { +arrSizes[slot] = 1 + (size_t)((24 - 1) * ((float)rand() / RAND_MAX)); +addresses[slot] = pool.NewArray(arrSizes[slot]); +for (size_t a = 0; a < arrSizes[slot]; ++a) +addresses[slot][a] = I(slot, a); +allocated[slot] = true; +++slotsAlloced; +} +} +//Deallocate +else { +i = 0; +//ta slumpmässig slot som är allokerad +do { +slot = (size_t)((SIZE - 1) * ((float)rand() / RAND_MAX)); +} while (!allocated[slot] && ++i < 512); + +if (i < 512) { +pool.DeleteArray(addresses[slot], arrSizes[slot]); +arrSizes[slot] = 0; +allocated[slot] = false; +--slotsAlloced; +} +} +//Check content. +for (size_t a = 0; a < SIZE; ++a) { +if (allocated[a]) { +for (size_t e = 0; e < arrSizes[a]; ++e) { +BOOST_CHECK(!(addresses[a][e].k != a || addresses[a][e].f != e)); +} +} +} +} +} +*/ + +BOOST_AUTO_TEST_CASE(testConstructors) +{ + //http://stackoverflow.com/questions/357929/is-it-important-to-unit-test-a-constructor + //"If your constructor has, for example, an if (condition), you need to test both flows (true,false). + //If your constructor does some kind of job before setting. You should check the job is done" + + //testing the constructors with different T values and a small check so size is initialized to 0 + MemoryPool memPoolI; + BOOST_CHECK(memPoolI.empty()); + BOOST_CHECK(memPoolI.size() == 0); + MemoryPool memPoolF; + BOOST_CHECK(memPoolF.empty()); + BOOST_CHECK(memPoolF.size() == 0); + MemoryPool memPoolD; + BOOST_CHECK(memPoolD.empty()); + BOOST_CHECK(memPoolD.size() == 0); + MemoryPool memPoolS; + BOOST_CHECK(memPoolS.empty()); + BOOST_CHECK(memPoolS.size() == 0); + + ObjectPool objPoolI(64); + BOOST_CHECK(objPoolI.empty()); + BOOST_CHECK(objPoolI.size() == 0); + ObjectPool objPoolF(32); + BOOST_CHECK(objPoolF.empty()); + BOOST_CHECK(objPoolF.size() == 0); + ObjectPool objPoolD(16); + BOOST_CHECK(objPoolD.empty()); + BOOST_CHECK(objPoolD.size() == 0); + ObjectPool objPoolS(128); + BOOST_CHECK(objPoolS.empty()); + BOOST_CHECK(objPoolS.size() == 0); +} + +BOOST_AUTO_TEST_CASE(testOperators) +{ + ObjectPool pool(100); + // S* s[12] = pool.NewArray(12); + S* s[12]; + s[0] = pool.New(); + s[11] = pool.New(); + + s[0]->k = 2; + s[11]->k = 3; + //testing operators: ++i,!= + auto& iter = pool.begin(); + for (iter; iter != pool.end(); ++iter) { + //testing operators:*,== + auto dereferencedIterator = *iter; + if (iter == pool.begin()) { + BOOST_CHECK(dereferencedIterator.k == 2); + } + if (iter == pool.end()) { + BOOST_CHECK(dereferencedIterator.k == 3); + } + //testing operators:-> + iter->k += 2; + } + BOOST_CHECK(s[0]->k == 4); + BOOST_CHECK(s[11]->k == 5); + BOOST_CHECK(iter == pool.end()); + + //testing operators:i++ + s[0]->k = 2; + s[11]->k = 2; + for (auto& iter = pool.begin(); iter != pool.end(); iter++) + iter->k += 2; + BOOST_CHECK(s[0]->k == 4); + BOOST_CHECK(s[11]->k == 4); +} +/* +BOOST_AUTO_TEST_CASE(testBranchFree) +{ +//testing Free , which is the only untested +//via delete/deletearray + +//1. no extra memory delete +ObjectPool pool(32);//32 true/false values = 32 slots +S* addresses[12]; +addresses[0] = pool.New(7, 0.035f); +pool.Delete(addresses[0]); +BOOST_CHECK(pool.empty()); + +//1b. no extra memory deleteArray +ObjectPool pool1b(32);//32 true/false values = 32 slots +S* test1b; +test1b = pool1b.NewArray(5);// <-> test2 = new S[5]; +BOOST_CHECK(pool1b.size() == 5); +pool1b.DeleteArray(test1b, 5);//callar destructorn på test2 också +BOOST_CHECK(pool1b.empty()); + +//2. extra memory delete +ObjectPool pool2(2); +S* addresses2[12]; +addresses2[0] = pool2.New(7, 0.035f); +addresses2[1] = pool2.New(7, 0.035f); +addresses2[2] = pool2.New(7, 0.035f); +addresses2[3] = pool2.New(7, 0.035f); +addresses2[4] = pool2.New(7, 0.035f); +BOOST_CHECK(pool2.size() == 5); +pool2.Delete(addresses2[0]); +BOOST_CHECK(pool2.size() == 4); +pool2.Delete(addresses2[1]); +BOOST_CHECK(pool2.size() == 3); +pool2.Delete(addresses2[2]); +BOOST_CHECK(pool2.size() == 2); +pool2.Delete(addresses2[3]); +BOOST_CHECK(pool2.size() == 1); +pool2.Delete(addresses2[4]); +BOOST_CHECK(pool2.empty()); +//reverse delete +addresses2[0] = pool2.New(7, 0.035f); +addresses2[1] = pool2.New(7, 0.035f); +addresses2[2] = pool2.New(7, 0.035f); +addresses2[3] = pool2.New(7, 0.035f); +addresses2[4] = pool2.New(7, 0.035f); +BOOST_CHECK(pool2.size() == 5); +pool2.Delete(addresses2[4]); +BOOST_CHECK(pool2.size() == 4); +pool2.Delete(addresses2[3]); +BOOST_CHECK(pool2.size() == 3); +pool2.Delete(addresses2[2]); +BOOST_CHECK(pool2.size() == 2); +pool2.Delete(addresses2[1]); +BOOST_CHECK(pool2.size() == 1); +pool2.Delete(addresses2[0]); +BOOST_CHECK(pool2.empty()); + +//2b. extra memory deleteArray +ObjectPool pool2b(32);//32 true/false values = 32 slots +S* test2b,*test2bb; +test2b = pool2b.NewArray(5);// <-> test2 = new S[5]; +BOOST_CHECK(pool2b.size() == 5); +test2bb = pool2b.NewArray(40);// <-> test2 = new S[5]; +BOOST_CHECK(pool2b.size() == 45); +pool2b.DeleteArray(test2b, 5);//callar destructorn på test2 också +BOOST_CHECK(pool2b.size() == 40); +pool2b.DeleteArray(test2bb, 40);//callar destructorn på test2 också +BOOST_CHECK(pool2b.empty()); +} +*/ +BOOST_AUTO_TEST_CASE(testBranchAllocate) +{ + //1 slot else many slots + //see testBranchFree + + //out of mem vs not out of mem allocate + //see testBranchFree +} +BOOST_AUTO_TEST_CASE(testEdgeCase) +{ + //test with a very small pool + ObjectPool pool(1); + BOOST_CHECK(pool.empty()); + S* test4; + test4 = pool.New(7, 0.035f); + BOOST_CHECK(!pool.empty()); + BOOST_CHECK(test4->k == 7); + BOOST_CHECK_CLOSE_FRACTION(test4->f, 0.035f, 0.0001f); + + //test with a very small pool and array, iterating + ObjectPool poolA(1); + S* test5; + test5 = poolA.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : poolA) + o.k = 14; + for (size_t i = 0; i < 1; ++i) + BOOST_CHECK(test5[i].k == 14); +} + +BOOST_AUTO_TEST_CASE(testBadlyAlignedData) +{ + //small test with non-aligned data 4+1bytes + struct S + { + S() = default; + S(float f, char c) : m_f(f), m_c(c) { } + ~S() { } + float m_f; + char m_c; + }; + MemoryPool memPoolS; + BOOST_CHECK(memPoolS.empty()); + BOOST_CHECK(memPoolS.size() == 0); + ObjectPool objPoolS(64); + BOOST_CHECK(objPoolS.empty()); + BOOST_CHECK(objPoolS.size() == 0); + S* test4; + test4 = objPoolS.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : objPoolS) { + o.m_c = 'v'; + o.m_f = 0.15534543f; + } + for (size_t i = 0; i < 1; ++i) { + BOOST_CHECK(test4[i].m_c == 'v'); + BOOST_CHECK_CLOSE_FRACTION(test4[i].m_f, 0.15534543f, 0.0001f); + } +} +BOOST_AUTO_TEST_CASE(testBadlyAlignedData2) +{ + //small test with non-aligned data 1+1+1bytes + struct S + { + S() = default; + S(char c, char c2, char c3) : m_c(c), m_c2(c2), m_c3(c3) { } + ~S() { } + char m_c; + char m_c2; + char m_c3; + }; + MemoryPool memPoolS; + BOOST_CHECK(memPoolS.empty()); + BOOST_CHECK(memPoolS.size() == 0); + ObjectPool objPoolS(64); + BOOST_CHECK(objPoolS.empty()); + BOOST_CHECK(objPoolS.size() == 0); + S* test4; + test4 = objPoolS.New(); + //Check so iterate over pool doesn't throw compile-time errors. + for (auto &o : objPoolS) { + o.m_c = 'v'; + o.m_c2 = 'w'; + o.m_c3 = 'x'; + } + for (size_t i = 0; i < 1; ++i) { + BOOST_CHECK(test4[i].m_c == 'v'); + BOOST_CHECK(test4[i].m_c2 == 'w'); + BOOST_CHECK(test4[i].m_c3 == 'x'); + } +} + +BOOST_AUTO_TEST_CASE(testWrongData) +{ +} +BOOST_AUTO_TEST_CASE(testFillDeleteFillAgain) { + //already done in BOOST_AUTO_TEST_CASE(releaseModeTest_RandomAllocateDeallocate) + +} + +BOOST_AUTO_TEST_SUITE_END() From 2f13f5da7a99ed5137f54d77d5d7cc878d93ba4b Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 3 Dec 2015 17:03:27 +0100 Subject: [PATCH 007/185] Relocated AABB and Ray in Collision.h to their own files. Started implementation on OctTree. --- include/Engine/Core/AABB.h | 24 ++++ include/Engine/Core/Collision.h | 26 +---- include/Engine/Core/OctTree.h | 29 +++++ include/Engine/Core/Ray.h | 12 ++ src/Engine/Core/AABB.cpp | 11 ++ src/Engine/Core/Collision.cpp | 10 +- src/Engine/Core/OctTree.cpp | 191 ++++++++++++++++++++++++++++++++ src/Engine/Core/Ray.cpp | 0 8 files changed, 272 insertions(+), 31 deletions(-) create mode 100644 include/Engine/Core/AABB.h create mode 100644 include/Engine/Core/Ray.h create mode 100644 src/Engine/Core/AABB.cpp create mode 100644 src/Engine/Core/Ray.cpp diff --git a/include/Engine/Core/AABB.h b/include/Engine/Core/AABB.h new file mode 100644 index 00000000..7d0a46ea --- /dev/null +++ b/include/Engine/Core/AABB.h @@ -0,0 +1,24 @@ +#ifndef AABB_h__ +#define AABB_h__ + +#include "../GLM.h" + +class AABB +{ +public: + AABB() = default; + AABB(const glm::vec3& minPos, const glm::vec3& maxPos); + 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& HalfSize() const { return m_HalfSize; } +private: + glm::vec3 m_MinCorner; + glm::vec3 m_MaxCorner; + glm::vec3 m_Center; + glm::vec3 m_HalfSize; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index 113a4a39..8cc98043 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -1,34 +1,14 @@ #ifndef Collision_h__ #define Collision_h__ -#include "../GLM.h" +#include "Core/Ray.h" +#include "Core/AABB.h" namespace Collision { -struct Ray -{ - glm::vec3 Origin; - glm::vec3 Direction; -}; - -class AABB -{ -public: - AABB() = default; - AABB(const glm::vec3& minPos, const glm::vec3& maxPos); - - 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& HalfSize() const { return m_HalfSize; } -private: - glm::vec3 m_MinCorner; - glm::vec3 m_MaxCorner; - glm::vec3 m_Center; - glm::vec3 m_HalfSize; -}; bool RayAABBIntr(const Ray& ray, const AABB& box); + } #endif \ No newline at end of file diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 5fd553d6..0554b12f 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -1,5 +1,34 @@ #ifndef OctTree_h__ #define OctTree_h__ +#include "Core/Collision.h" + +class OctTree +{ +public: + struct Output + { + float CollideDistance; + }; + OctTree(); + ~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(); + //Returns true if the ray collides with something in the tree. Result is written to [data]. + bool RayCollides(const Ray& ray, Output& data) const; + +private: + OctTree* m_Children[8]; + std::vector m_ContainingBoxes; + //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. + AABB m_Box; + + bool rayCollides(const Ray& ray, Output& data, const OctTree* const tree) const; + inline bool hasChildren() const; + int childIndexContainingPoint(const glm::vec3& point) const; +}; #endif \ No newline at end of file diff --git a/include/Engine/Core/Ray.h b/include/Engine/Core/Ray.h new file mode 100644 index 00000000..64392cbc --- /dev/null +++ b/include/Engine/Core/Ray.h @@ -0,0 +1,12 @@ +#ifndef Ray_h__ +#define Ray_h__ + +#include "../GLM.h" + +struct Ray +{ + glm::vec3 Origin; + glm::vec3 Direction; +}; + +#endif // Ray_h__ diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp new file mode 100644 index 00000000..8a364ce5 --- /dev/null +++ b/src/Engine/Core/AABB.cpp @@ -0,0 +1,11 @@ +#include "Core/AABB.h" + +AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) + : m_MinCorner(minPos) + , m_MaxCorner(maxPos) + , m_Center(0.5f * (maxPos + minPos)) + , m_HalfSize(0.5f * (maxPos - minPos)) +{} + +AABB::~AABB() +{} diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index 4ccd1ccd..f16dd0df 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -1,15 +1,9 @@ -#include "Core\Collision.h" +#include "Core/Collision.h" +#include "Engine/GLM.h" namespace Collision { -AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) - : m_MinCorner(minPos) - , m_MaxCorner(maxPos) - , m_Center(0.5f * (maxPos + minPos)) - , m_HalfSize(0.5f * (maxPos - minPos)) -{ } - bool RayAABBIntr(const Ray& ray, const AABB& box) { glm::vec3 w = 75.0f * ray.Direction; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index e69de29b..29575ac7 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -0,0 +1,191 @@ +#include +#include +#include + +#include "Core/OctTree.h" + +namespace +{ +//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; +} + +} + +OctTree::OctTree() + : OctTree(AABB(), 0) +{} + +OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) + : m_Box(octTreeBounds) +{ + if (subDivisions == 0) { + for (OctTree*& c : m_Children) { + c = nullptr; + } + } else { + --subDivisions; + 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.MaxCorner(); + 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 { + 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 { + minPos.y = parentMin.y; + maxPos.y = parentCenter.y; + } + //If child is 1,3,5,7 + if (bits.test(0)) { + minPos.z = parentCenter.z; + maxPos.z = parentMax.z; + } else { + minPos.z = parentMin.z; + maxPos.z = parentCenter.z; + } + m_Children[i] = new OctTree(AABB(minPos, maxPos), subDivisions); + } + } +} + +OctTree::~OctTree() +{ + for (OctTree*& c : m_Children) { + if (c != nullptr) { + delete c; + c = nullptr; + } + } +} + + +bool OctTree::RayCollides(const Ray& ray, Output& data) const +{ + data.CollideDistance = -1; + return rayCollides(ray, data, this); +} + +//Currently all Nodes must have exactly 0 or 8 children, and objectdata should only exist in the last bottom nodes. +bool OctTree::rayCollides(const Ray& ray, Output& data, const OctTree* const tree) const +{ + //If the node AABB is missed, everything it contains is missed. + if (Collision::RayAABBIntr(ray, tree->m_Box)) { + //If the ray shoots the tree, and it is a parent to 8 children :o + if (tree->hasChildren()) { + //Sort children according to their distance from the ray origin. + std::vector childInfos; + childInfos.reserve(8); + for (int i = 0; i < 8; ++i) { + childInfos.push_back({ i, glm::distance(ray.Origin, tree->m_Children[i]->m_Box.Center()) }); + } + 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. + for (const ChildInfo& info : childInfos) { + if (rayCollides(ray, data, tree->m_Children[info.Index])) { + return true; + } + } + } else { + ////TODO: Check against objects in the node. + //float minDist = INFINITY; + //for (const auto& obj : m_ObjectsInBox) { + // float dist = Collide(ray, obj); + // minDist = min(dist, minDist); + //} + //data.CollideDistance = minDist; + //if minDist != Collide()'s non-collide value: return false; + return true; + } + } + return false; +} + +void OctTree::AddBox(const AABB& box) +{ + if (hasChildren()) { + int minInd = childIndexContainingPoint(box.MinCorner()); + int maxInd = childIndexContainingPoint(box.MaxCorner()); + std::bitset<3> bits(minInd ^ maxInd); + switch (bits.count()) { + case 0: //Box contained completely in one child. + m_Children[minInd]->AddBox(box); + break; + case 1: //Two children. + m_Children[minInd]->AddBox(box); + m_Children[maxInd]->AddBox(box); + break; + case 2: //Four children. + bits.flip(); + for (int c = 0; c < 8; ++c) { + if ((bits & std::bitset<3>(c))[0]) { + m_Children[c]->AddBox(box); + } + } + break; + case 3: //Eight children. + for (OctTree*& c : m_Children) { + c->AddBox(box); + } + break; + default: + break; + } + } else { + m_ContainingBoxes.push_back(box); + } +} + +void OctTree::ClearBoxes() +{ + if (hasChildren()) { + for (OctTree*& c : m_Children) { + c->ClearBoxes(); + } + } else { + m_ContainingBoxes.clear(); + } +} + +//: 3 7 +//: +//: 2 6 +//: | +//: 1 5 \ y +//: z +//: 0 4 0 x--> +// +// child: 0 1 2 3 4 5 6 7 +// x : - - - - + + + + +// y : - - + + - - + + +// z : - + - + - + - + +int OctTree::childIndexContainingPoint(const glm::vec3& point) const +{ + const glm::vec3& c = m_Box.Center(); + return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); +} + +inline bool OctTree::hasChildren() const +{ + return m_Children[0] != nullptr; +} \ No newline at end of file diff --git a/src/Engine/Core/Ray.cpp b/src/Engine/Core/Ray.cpp new file mode 100644 index 00000000..e69de29b From af5b3a93028d84911fde5b69fb5c00e1b38f96ff Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 3 Dec 2015 17:24:53 +0100 Subject: [PATCH 008/185] Fixed wrong paths and added an outDistance to RayVsAABB. --- include/Engine/Core/Collision.h | 3 ++- src/Engine/Core/Collision.cpp | 7 +++++++ src/Tests/CollisionTest.cpp | 14 ++++++++------ src/Tests/ObjectPoolTest.cpp | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index bbcad66e..67a9e808 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -3,13 +3,14 @@ #include "Core/Ray.h" #include "Core/AABB.h" -#include namespace Collision { bool RayAABBIntr(const Ray& ray, const AABB& box); bool RayVsAABB(const Ray& ray, const AABB& box); +bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); + } #endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index bce61aeb..fda895a4 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -32,6 +32,12 @@ bool RayAABBIntr(const Ray& ray, const AABB& box) } bool RayVsAABB(const Ray& ray, const AABB& box) +{ + float dummy; + return RayVsAABB(ray, box, dummy); +} + +bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) { glm::vec3 invdir = 1.0f / ray.Direction; @@ -48,6 +54,7 @@ bool RayVsAABB(const Ray& ray, const AABB& box) if (tmax < 0 || tmin > tmax) return false; + outDistance = (tmin > 0) ? tmin : tmax; return true; } diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 426b9722..c8260e39 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -2,6 +2,8 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include +#include "Engine/Core/AABB.h" +#include "Engine/Core/Ray.h" #include //srand BOOST_AUTO_TEST_SUITE(collisionTests) @@ -10,8 +12,8 @@ BOOST_AUTO_TEST_CASE(collisionTest) { //fixed seed srand(2); - Collision::Ray ray; - Collision::AABB someAABB; + Ray ray; + AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; bool z; @@ -31,7 +33,7 @@ BOOST_AUTO_TEST_CASE(collisionTest) maxPos.y = rand() % 100; maxPos.z = rand() % 100; - someAABB = Collision::AABB(minPos, maxPos); + someAABB = AABB(minPos, maxPos); z = Collision::RayVsAABB(ray, someAABB); if (z) ++test; } @@ -42,8 +44,8 @@ BOOST_AUTO_TEST_CASE(collisionTest2) { //fixed seed srand(2); - Collision::Ray ray; - Collision::AABB someAABB; + Ray ray; + AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; bool z; @@ -63,7 +65,7 @@ BOOST_AUTO_TEST_CASE(collisionTest2) maxPos.y = rand() % 100; maxPos.z = rand() % 100; - someAABB = Collision::AABB(minPos, maxPos); + someAABB = AABB(minPos, maxPos); z = Collision::RayAABBIntr(ray, someAABB); if (z) ++test; } diff --git a/src/Tests/ObjectPoolTest.cpp b/src/Tests/ObjectPoolTest.cpp index adea33eb..e136da70 100644 --- a/src/Tests/ObjectPoolTest.cpp +++ b/src/Tests/ObjectPoolTest.cpp @@ -1,7 +1,7 @@ #include using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; -#include "../wmem/MemPrototype/ObjectPool.h" +#include "Engine/Core/ObjectPool.h" #include struct S From 28a290600bf74f9f2a94a5446f12a31866be20d9 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 3 Dec 2015 17:30:12 +0100 Subject: [PATCH 009/185] BOOST MEM LEAK VS VISUAL STUDIO MEM LEAKS COMMENTED TESTS --- src/Tests/CollisionTest.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 426b9722..90eb8e47 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -1,13 +1,25 @@ +//#define BOOST_TEST_MODULE collTest #include +#include using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include #include //srand +//vs memleaks +//#define _CRTDBG_MAP_ALLOC +//#include +//#include +//#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); Collision::Ray ray; @@ -16,7 +28,7 @@ BOOST_AUTO_TEST_CASE(collisionTest) glm::vec3 maxPos; bool z; int test = 0; - for (size_t i = 0; i < 1000000; i++) + for (size_t i = 0; i < 10; i++) { ray.Origin.x = rand() % 100; ray.Origin.y = rand() % 100; @@ -36,6 +48,8 @@ BOOST_AUTO_TEST_CASE(collisionTest) if (z) ++test; } BOOST_CHECK(test >= 0); + + //_CrtDumpMemoryLeaks(); } BOOST_AUTO_TEST_CASE(collisionTest2) From 8e21b1fe35579f5cc54f8eddb30269247020258d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 3 Dec 2015 19:25:40 +0100 Subject: [PATCH 010/185] Added ray collision detection in leaf nodes. Fixed possible bug in OctTree::AddBox --- include/Engine/Core/OctTree.h | 2 +- src/Engine/Core/OctTree.cpp | 36 ++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 0554b12f..2c54513e 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -26,7 +26,7 @@ private: //start of Collision test, set on check, don't check if set already. Solves duplicate boxes in tree. AABB m_Box; - bool rayCollides(const Ray& ray, Output& data, const OctTree* const tree) const; + bool rayCollides(const Ray& ray, Output& data) const; inline bool hasChildren() const; int childIndexContainingPoint(const glm::vec3& point) const; }; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 29575ac7..af222039 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -79,43 +79,45 @@ OctTree::~OctTree() } } - bool OctTree::RayCollides(const Ray& ray, Output& data) const { data.CollideDistance = -1; - return rayCollides(ray, data, this); + return rayCollides(ray, data); } //Currently all Nodes must have exactly 0 or 8 children, and objectdata should only exist in the last bottom nodes. -bool OctTree::rayCollides(const Ray& ray, Output& data, const OctTree* const tree) const +bool OctTree::rayCollides(const Ray& ray, Output& data) const { //If the node AABB is missed, everything it contains is missed. - if (Collision::RayAABBIntr(ray, tree->m_Box)) { + if (Collision::RayAABBIntr(ray, m_Box)) { //If the ray shoots the tree, and it is a parent to 8 children :o - if (tree->hasChildren()) { + if (hasChildren()) { //Sort children according to their distance from the ray origin. std::vector childInfos; childInfos.reserve(8); for (int i = 0; i < 8; ++i) { - childInfos.push_back({ i, glm::distance(ray.Origin, tree->m_Children[i]->m_Box.Center()) }); + childInfos.push_back({ i, glm::distance(ray.Origin, m_Children[i]->m_Box.Center()) }); } 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. for (const ChildInfo& info : childInfos) { - if (rayCollides(ray, data, tree->m_Children[info.Index])) { + if (m_Children[info.Index]->rayCollides(ray, data)) { return true; } } } else { - ////TODO: Check against objects in the node. - //float minDist = INFINITY; - //for (const auto& obj : m_ObjectsInBox) { - // float dist = Collide(ray, obj); - // minDist = min(dist, minDist); - //} - //data.CollideDistance = minDist; - //if minDist != Collide()'s non-collide value: return false; - return true; + //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; + } + } + data.CollideDistance = minDist; + return intersected; } } return false; @@ -138,7 +140,7 @@ void OctTree::AddBox(const AABB& box) case 2: //Four children. bits.flip(); for (int c = 0; c < 8; ++c) { - if ((bits & std::bitset<3>(c))[0]) { + if ((bits & std::bitset<3>(c)).any()) { m_Children[c]->AddBox(box); } } From f0e407bec29d01242daec3939be1aa64c2ef4e9c Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 7 Dec 2015 10:03:36 +0100 Subject: [PATCH 011/185] Started on OctTreeTest (Merging with OctTree) --- src/Tests/OctTreeTest.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/Tests/OctTreeTest.cpp diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp new file mode 100644 index 00000000..5392e63c --- /dev/null +++ b/src/Tests/OctTreeTest.cpp @@ -0,0 +1,20 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include //srand +#include + +BOOST_AUTO_TEST_SUITE(octTreeTests) + +BOOST_AUTO_TEST_CASE(octTreeTest) +{ + +} + +BOOST_AUTO_TEST_CASE(octTreeTest2) +{ + +} + +BOOST_AUTO_TEST_SUITE_END() + From e8d23f3b3f4ec58d1b4d0cbde079c340f836476e Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 7 Dec 2015 15:59:41 +0100 Subject: [PATCH 012/185] Added AABBVsAABB function. --- include/Engine/Core/Collision.h | 2 ++ src/Engine/Core/Collision.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index 67a9e808..2e90b8bf 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -11,6 +11,8 @@ bool RayAABBIntr(const Ray& ray, const AABB& box); bool RayVsAABB(const Ray& ray, const AABB& box); bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); +bool AABBVsAABB(const AABB& a, const AABB& b); +bool AABBVsAABBTst(const AABB& a, const AABB& b); } #endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index fda895a4..07e37085 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -58,4 +58,20 @@ bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) return true; } +bool AABBVsAABB(const AABB& a, const AABB& b) +{ + const glm::vec3& aCenter = a.Center(); + const glm::vec3& bCenter = b.Center(); + 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. + if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) { + return false; + } + if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) { + return false; + } + return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); +} + } \ No newline at end of file From 955c9ce5340327eed2be0a5558c604632e2c8013 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 7 Dec 2015 16:00:34 +0100 Subject: [PATCH 013/185] Removed superfluous function declaration. --- include/Engine/Core/Collision.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index 2e90b8bf..b23b33cc 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -12,7 +12,6 @@ bool RayVsAABB(const Ray& ray, const AABB& box); bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); bool AABBVsAABB(const AABB& a, const AABB& b); -bool AABBVsAABBTst(const AABB& a, const AABB& b); } #endif \ No newline at end of file From d8d63f804a9b11405d15e1ee4ff1794f596ed1a1 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 7 Dec 2015 16:11:27 +0100 Subject: [PATCH 014/185] Added utility headers for network interface. --- include/Engine/Network/MessageType.h | 17 +++++++++++++++++ include/Engine/Network/NetworkDefines.h | 15 +++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 include/Engine/Network/MessageType.h create mode 100644 include/Engine/Network/NetworkDefines.h diff --git a/include/Engine/Network/MessageType.h b/include/Engine/Network/MessageType.h new file mode 100644 index 00000000..8d09c7ee --- /dev/null +++ b/include/Engine/Network/MessageType.h @@ -0,0 +1,17 @@ +#ifndef MessageType_h__ +#define MessageType_h__ + +// Message types used by both server and client. +// Used to determine what type of message was sent. +enum class MessageType +{ + Connect, + Disconnect, + ClientPing, + ServerPing, + Message, + Snapshot, + Event, +}; + +#endif diff --git a/include/Engine/Network/NetworkDefines.h b/include/Engine/Network/NetworkDefines.h new file mode 100644 index 00000000..4d37733e --- /dev/null +++ b/include/Engine/Network/NetworkDefines.h @@ -0,0 +1,15 @@ +#ifndef MessageType_h__ +#define MessageType_h__ + +#include +#include + +#define BOARDSIZE 16 +#define MAXCONNECTIONS 8 +#define INPUTSIZE 128 + +typedef boost::shared_ptr socket_ptr; +typedef boost::shared_ptr string_ptr; +typedef boost::shared_ptr> messageQueue_ptr; + +#endif \ No newline at end of file From 04a8eeebe8445df9a985d8488988115e79508349 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 7 Dec 2015 16:25:01 +0100 Subject: [PATCH 015/185] Added test get methods and some comments. --- include/Engine/Core/OctTree.h | 11 +++++++++-- src/Engine/Core/OctTree.cpp | 12 ++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 2c54513e..6e80fa24 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -1,7 +1,9 @@ #ifndef OctTree_h__ #define OctTree_h__ -#include "Core/Collision.h" +#include "Core/AABB.h" + +struct Ray; class OctTree { @@ -19,13 +21,18 @@ public: //Returns true if the ray collides with something in the tree. Result is written to [data]. bool RayCollides(const Ray& ray, Output& data) const; + //Test Getters. + OctTree** Children() { return m_Children; } + const AABB& Box() { return m_Box; } + const std::vector& ContainingBoxes() { return m_ContainingBoxes; } + private: OctTree* m_Children[8]; std::vector m_ContainingBoxes; //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. AABB m_Box; - + bool rayCollides(const Ray& ray, Output& data) const; inline bool hasChildren() const; int childIndexContainingPoint(const glm::vec3& point) const; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index af222039..f98720be 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -3,6 +3,7 @@ #include #include "Core/OctTree.h" +#include "Core/Collision.h" namespace { @@ -37,7 +38,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.MaxCorner(); + const glm::vec3& parentCenter = m_Box.Center(); std::bitset<3> bits(i); //If child is 4,5,6,7. if (bits.test(2)) { @@ -128,6 +129,8 @@ void OctTree::AddBox(const AABB& box) if (hasChildren()) { int minInd = childIndexContainingPoint(box.MinCorner()); int maxInd = childIndexContainingPoint(box.MaxCorner()); + //Because of the predictable ordering of the child indices, + //the number of bits set when xor:ing the indices will determine the number of children containing the box. std::bitset<3> bits(minInd ^ maxInd); switch (bits.count()) { case 0: //Box contained completely in one child. @@ -138,9 +141,14 @@ void OctTree::AddBox(const AABB& box) m_Children[maxInd]->AddBox(box); break; case 2: //Four children. + //Bit-hax to calculate the right 4 cildren containing the box. + //This works because of the childrens index determine what part of + //the dimensions they are responsible for (which octant). bits.flip(); + //At this point the bits necessarily have exactly one bit set. for (int c = 0; c < 8; ++c) { - if ((bits & std::bitset<3>(c)).any()) { + //If the child index have the same bit set as the bits, add box to it. + if (bits.to_ulong() & c) { m_Children[c]->AddBox(box); } } From de5bdef58cf40e756b53de7cc73e3fbf3d6e9306 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 7 Dec 2015 16:52:42 +0100 Subject: [PATCH 016/185] Rectangle definition conflicted with a definition included by . --- include/Engine/Rendering/IRenderer.h | 2 +- src/Game/Game.cpp | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 1acb2454..5dce14c7 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -35,7 +35,7 @@ public: virtual void Draw(RenderQueueCollection& rq) = 0; protected: - Rectangle m_Resolution = Rectangle(1280, 720); + Rectangle m_Resolution = Rectangle::Rectangle(1280, 720); bool m_Fullscreen = false; bool m_VSYNC = false; int m_GLVersion[2]; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 10d19baf..611aa328 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,6 @@ #include "Game.h" #include "HardcodedTestWorld.h" +#include "Network/Client.h" Game::Game(int argc, char* argv[]) { @@ -17,12 +18,12 @@ Game::Game(int argc, char* argv[]) m_Renderer = new Renderer(); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); - m_Renderer->SetResolution(Rectangle( + m_Renderer->SetResolution(Rectangle::Rectangle( 0, 0, m_Config->Get("Video.Width", 1280), m_Config->Get("Video.Height", 720) - )); + )); m_Renderer->Initialize(); // Create input manager @@ -36,6 +37,15 @@ Game::Game(int argc, char* argv[]) // Create a TEST WORLD m_World = new HardcodedTestWorld(); + // TEMP: Invoke network + std::string inputMessage; + std::cout << "Start client or server? (c/s)" << std::endl; + std::cin >> inputMessage; + if (inputMessage == "c" || inputMessage == "C") { + Client client; + client.Start(); + } + m_LastTime = glfwGetTime(); } From cbbb7deaea10a5e52cb1bbbfbe4f05c9009851d9 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 7 Dec 2015 16:53:33 +0100 Subject: [PATCH 017/185] Copy pasta error. Corrected #ifndef --- include/Engine/Network/NetworkDefines.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Engine/Network/NetworkDefines.h b/include/Engine/Network/NetworkDefines.h index 4d37733e..e9da132f 100644 --- a/include/Engine/Network/NetworkDefines.h +++ b/include/Engine/Network/NetworkDefines.h @@ -1,7 +1,7 @@ -#ifndef MessageType_h__ -#define MessageType_h__ +#ifndef NetworkDefines_h__ +#define NetworkDefines_h__ -#include +#include #include #define BOARDSIZE 16 From 2c993e82d65589080108eb55ce3bab74af70cb80 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 7 Dec 2015 16:55:12 +0100 Subject: [PATCH 018/185] Added the old prototype logic to Client.h. Can now communicate with a external server(on prototype). --- include/Engine/Network/Client.h | 44 ++++- src/Engine/Network/Client.cpp | 317 +++++++++++++++++++++++++++++++- src/Engine/Network/Server.cpp | 2 +- 3 files changed, 358 insertions(+), 5 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index af7c9072..66bb30ed 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -1,14 +1,56 @@ #ifndef Client_h__ #define Client_h__ -#include +#include +#include + +#include +#include +#include + +#include "Network/MessageType.h" +#include "Network/NetworkDefines.h" + class Client { +public: Client(); ~Client(); + void Start(); +private: + // Threaded + void DisplayLoop(); + void ReadFromServer(); + void InputLoop(); + int Receive(char* data, size_t length); + int CreateMessage(MessageType type, std::string message, char* data); + void MoveMessageHead(char*& data, size_t& length, size_t stepSize); + void ParseMessageType(char* data, size_t length); + void ParseEventMessage(char* data, size_t length); + void ParseConnect(char* data, size_t length); + void ParsePing(); + void ParseServerPing(); + void ParseSnapshot(char* data, size_t length); + void SendInput(); + void SendDebugInput(); + void DrawBoard(); + + // udp stuff + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::io_service m_IOService; + boost::asio::ip::udp::socket m_Socket; + + int m_PlayerID = -1; + char m_GameBoard[BOARDSIZE][BOARDSIZE]; + glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; + std::string m_PlayerNames[MAXCONNECTIONS]; + std::clock_t m_StartPingTime; + double m_DurationOfPingTime; + bool m_ShouldDrawGameBoard = true; + std::string m_PlayerName; }; #endif diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index bc513799..bdb8eebb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -1,11 +1,322 @@ -#include "Network\Client.h" +#include "Network/Client.h" -Client::Client() +using namespace boost::asio::ip; + + +Client::Client() : m_Socket(m_IOService) { - + // Set up network stream + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + //Start(); // All logic happens here } Client::~Client() { } + +void Client::Start() +{ + std::cout << "Please enter you name: "; + std::cin >> m_PlayerName; + while (m_PlayerName.size() > 7) { + std::cout << "Please enter you name(No longer than 7 characters): "; + std::cin >> m_PlayerName; + } + + boost::thread_group threads; + socket_ptr sock(new udp::socket(m_IOService)); + + for (size_t i = 0; i < BOARDSIZE; i++) { + for (size_t j = 0; j < BOARDSIZE; j++) { + m_GameBoard[j][i] = ' '; + } + } + + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + m_PlayerPositions[i].x = -1; + m_PlayerPositions[i].y = -1; + m_PlayerNames[i] = "X"; + } + + m_Socket.connect(m_ReceiverEndpoint); + std::cout << "I am client. BIP BOP\n"; + + threads.create_thread(boost::bind(&Client::DisplayLoop, this)); + threads.create_thread(boost::bind(&Client::ReadFromServer, this)); + threads.create_thread(boost::bind(&Client::InputLoop, this)); + + threads.join_all(); +} + +void Client::InputLoop() +{ + int intervallMs = 33; // ~30 times per second + int commandInterval = 200; // for commands like ping and connect, name might be ambigiuos + std::clock_t previousInputTime = std::clock(); + std::clock_t previousCommandTime = std::clock(); + + while (true) { + + std::clock_t currentTime = std::clock(); + int testTimeShit = (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC); + if (commandInterval < (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC)) { + SendDebugInput(); + previousCommandTime = currentTime; + } + + int testTimeShit2 = (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC); + if (intervallMs < (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC)) { + if (m_PlayerID != -1) { + SendInput(); + } + previousInputTime = currentTime; + } + } +} + +void Client::DisplayLoop() +{ + while (true) { + // Update gameboard + for (size_t i = 0; i < BOARDSIZE; i++) { + for (size_t j = 0; j < BOARDSIZE; j++) { + m_GameBoard[j][i] = ' '; + } + } + if (m_ShouldDrawGameBoard) + DrawBoard(); + boost::this_thread::sleep(boost::posix_time::millisec(100)); + } +} + +void Client::ReadFromServer() +{ + int bytesRead = -1; + char readBuf[1024] = { 0 }; + + for (;;) { + if (m_Socket.available()) { + bytesRead = Receive(readBuf, INPUTSIZE); + ParseMessageType(readBuf, bytesRead); + } + } +} + +void Client::ParseMessageType(char* data, size_t length) +{ + int messageType = -1; + memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server + MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + + switch (static_cast(messageType)) { + case MessageType::Connect: + ParseConnect(data, length); + break; + case MessageType::ClientPing: + ParsePing(); + break; + case MessageType::ServerPing: + ParseServerPing(); + break; + case MessageType::Message: + break; + case MessageType::Snapshot: + ParseSnapshot(data, length); + break; + case MessageType::Disconnect: + break; + case MessageType::Event: + ParseEventMessage(data, length); + break; + default: + break; + } +} + +void Client::ParseConnect(char* data, size_t len) +{ + memcpy(&m_PlayerID, data, sizeof(int)); + std::cout << "I am player: " << m_PlayerID << std::endl; +} + +void Client::ParsePing() +{ + m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + std::cout << "response time with ctime(ms): " << m_DurationOfPingTime << std::endl; +} + +void Client::ParseServerPing() +{ + char* testMsg = new char[128]; + int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMsg); + + //std::cout << "Parsing ping." << std::endl; + + m_Socket.send_to(boost::asio::buffer( + testMsg, + testOffset), + m_ReceiverEndpoint, 0); +} + +void Client::ParseEventMessage(char* data, size_t length) +{ + int Id = -1; + std::string command = std::string(data); + if (command.find("+Player") != std::string::npos) { + MoveMessageHead(data, length, command.size() + 1); + memcpy(&Id, data, sizeof(int)); + MoveMessageHead(data, length, sizeof(int)); + // Sett Player name + m_PlayerNames[Id] = command.erase(0, 7); + } + else { + std::cout << "Event message: " << std::string(data) << std::endl; + } + + MoveMessageHead(data, length, std::string(data).size() + 1); +} + +void Client::ParseSnapshot(char* data, size_t length) +{ + std::string tempName; + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + memcpy(&m_PlayerPositions[i].x, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + memcpy(&m_PlayerPositions[i].y, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + tempName = std::string(data); + m_PlayerNames[i] = tempName; + // +1 for null terminator + MoveMessageHead(data, length, tempName.size() + 1); + } +} + +void Client::DrawBoard() +{ + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + if (m_PlayerPositions[i].x != -1 && m_PlayerPositions[i].y != -1) { + m_GameBoard[static_cast(m_PlayerPositions[i].x)][static_cast(m_PlayerPositions[i].y)] = m_PlayerNames[i][0]; + } + } + + system("cls"); + for (size_t i = 0; i < BOARDSIZE; i++) { + std::cout << '_'; + } + + std::cout << std::endl; + for (size_t i = 0; i < BOARDSIZE; i++) { + for (size_t j = 0; j < BOARDSIZE; j++) { + std::cout << m_GameBoard[j][i]; + } + std::cout << std::endl; + } + + for (size_t i = 0; i < BOARDSIZE; i++) { + std::cout << "^"; + } +} + +int Client::Receive(char* data, size_t length) +{ + int bytesReceived = m_Socket.receive_from(boost + ::asio::buffer((void*)data, length), + m_ReceiverEndpoint, + 0); + return bytesReceived; +} + +int Client::CreateMessage(MessageType type, std::string message, char* data) +{ + int lengthOfMessage = 0; + int messageType = static_cast(type); + lengthOfMessage = message.size(); + + int offset = 0; + // Message type + memcpy(data + offset, &messageType, sizeof(int)); + offset += sizeof(int); + // Message, add one extra byte for null terminator + memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); + offset += (lengthOfMessage + 1) * sizeof(char); + + return offset; +} + +void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) +{ + data += stepSize; + length -= stepSize; +} + +void Client::SendDebugInput() +{ + char* dataPackage = new char[INPUTSIZE]; + if (GetAsyncKeyState('P')) { // Maybe use previous key here + int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); + m_StartPingTime = std::clock(); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + length), + m_ReceiverEndpoint, 0); + } + + if (GetAsyncKeyState('C')) { + int length = CreateMessage(MessageType::Connect, m_PlayerName, dataPackage); + m_StartPingTime = std::clock(); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + length), + m_ReceiverEndpoint, 0); + } + + if (GetAsyncKeyState('Q')) { // Does not work. Plez fix + exit(1); + } + memset(dataPackage, 0, INPUTSIZE); + delete[] dataPackage; +} + +void Client::SendInput() +{ + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + if (GetAsyncKeyState('W')) { + int len = CreateMessage(MessageType::Event, "+Forward", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (GetAsyncKeyState('A')) { + int len = CreateMessage(MessageType::Event, "-Right", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (GetAsyncKeyState('S')) { + int len = CreateMessage(MessageType::Event, "-Forward", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (GetAsyncKeyState('D')) { + int len = CreateMessage(MessageType::Event, "+Right", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (GetAsyncKeyState('V')) { + int len = CreateMessage(MessageType::Disconnect, "+Disconnect", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + + memset(dataPackage, 0, INPUTSIZE); + delete[] dataPackage; +} \ No newline at end of file diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index f65dc834..90c728a0 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -1,4 +1,4 @@ -#include "Network\Server.h" +#include "Network/Server.h" Server::Server() { From 648ba502bb5df8f3e8a4eca78927a9220e351308 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 7 Dec 2015 17:27:57 +0100 Subject: [PATCH 019/185] Added small test for OctTree. --- include/Engine/Core/OctTree.h | 5 ----- src/Tests/CollisionTest.cpp | 13 +++++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 6e80fa24..1ae447a9 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -21,11 +21,6 @@ public: //Returns true if the ray collides with something in the tree. Result is written to [data]. bool RayCollides(const Ray& ray, Output& data) const; - //Test Getters. - OctTree** Children() { return m_Children; } - const AABB& Box() { return m_Box; } - const std::vector& ContainingBoxes() { return m_ContainingBoxes; } - private: OctTree* m_Children[8]; std::vector m_ContainingBoxes; diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 4d6e9f8c..762fa24e 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -7,6 +7,7 @@ using boost::unit_test_framework::test_case; #include "Engine/Core/AABB.h" #include "Engine/Core/Ray.h" #include //srand +#include "Engine/Core/OctTree.h" //vs memleaks //#define _CRTDBG_MAP_ALLOC @@ -86,5 +87,17 @@ BOOST_AUTO_TEST_CASE(collisionTest2) 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.1f*maxi)); + OctTree::Output data; + BOOST_CHECK(tree.RayCollides({ glm::vec3(0, 0, 0), glm::normalize(mini) }, data)); + tree.ClearBoxes(); + BOOST_CHECK(!tree.RayCollides({ glm::vec3(0, 0, 0), glm::normalize(mini) }, data)); +} + BOOST_AUTO_TEST_SUITE_END() From fa3816e55d0f111a71d2f46bb73818c14f9e672d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 8 Dec 2015 10:44:12 +0100 Subject: [PATCH 020/185] Fixed flawed unit test. --- src/Engine/Core/OctTree.cpp | 1 + src/Tests/CollisionTest.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index f98720be..e9aeb589 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -166,6 +166,7 @@ void OctTree::AddBox(const AABB& box) } } +//TODO: Only clear dynamic boxes, AddDynamic, AddStatic void OctTree::ClearBoxes() { if (hasChildren()) { diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 762fa24e..ab13e930 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -92,11 +92,12 @@ 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.1f*maxi)); + tree.AddBox(AABB(mini, -0.9f*maxi)); OctTree::Output data; - BOOST_CHECK(tree.RayCollides({ glm::vec3(0, 0, 0), glm::normalize(mini) }, data)); + glm::vec3 origin = 3.0f * mini; + BOOST_CHECK(tree.RayCollides({origin , glm::normalize(mini - origin) }, data)); tree.ClearBoxes(); - BOOST_CHECK(!tree.RayCollides({ glm::vec3(0, 0, 0), glm::normalize(mini) }, data)); + BOOST_CHECK(!tree.RayCollides({ origin , glm::normalize(mini - origin) }, data)); } BOOST_AUTO_TEST_SUITE_END() From b5a010a517f5aabf82c5d25ae74314460b03b876 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 8 Dec 2015 11:02:40 +0100 Subject: [PATCH 021/185] Network now runs on it's own thread. Network now sends Disconnect message when game is terminated. --- include/Engine/Network/Client.h | 3 +++ include/Game/Game.h | 10 ++++++++++ src/Engine/Network/Client.cpp | 28 ++++++++++++++++++++-------- src/Game/Game.cpp | 20 ++++++++++++-------- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 66bb30ed..f1d60c16 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -18,6 +18,7 @@ public: Client(); ~Client(); void Start(); + void Close(); private: // Threaded @@ -27,6 +28,7 @@ private: int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); + void Disconnect(); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); void ParseMessageType(char* data, size_t length); void ParseEventMessage(char* data, size_t length); @@ -51,6 +53,7 @@ private: double m_DurationOfPingTime; bool m_ShouldDrawGameBoard = true; std::string m_PlayerName; + bool m_ThreadIsRunning = true; }; #endif diff --git a/include/Game/Game.h b/include/Game/Game.h index 85c0d6c4..cf0c5e6b 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -8,6 +8,9 @@ #include "Core/InputManager.h" #include "GUI/Frame.h" #include "Core/World.h" +// Network +#include +#include "Network/Client.h" class Game { @@ -26,6 +29,13 @@ private: InputManager* m_InputManager; GUI::Frame* m_FrameStack; World* m_World; + // Network viriables + boost::thread m_NetworkThread; + Client m_Client; + + // Network methods + void NetworkFunction(); + }; #endif diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index bdb8eebb..53ec3d9f 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -49,6 +49,12 @@ void Client::Start() threads.join_all(); } +void Client::Close() +{ + Disconnect(); + m_ThreadIsRunning = false; +} + void Client::InputLoop() { int intervallMs = 33; // ~30 times per second @@ -56,7 +62,7 @@ void Client::InputLoop() std::clock_t previousInputTime = std::clock(); std::clock_t previousCommandTime = std::clock(); - while (true) { + while (m_ThreadIsRunning) { std::clock_t currentTime = std::clock(); int testTimeShit = (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC); @@ -77,7 +83,7 @@ void Client::InputLoop() void Client::DisplayLoop() { - while (true) { + while (m_ThreadIsRunning) { // Update gameboard for (size_t i = 0; i < BOARDSIZE; i++) { for (size_t j = 0; j < BOARDSIZE; j++) { @@ -95,7 +101,7 @@ void Client::ReadFromServer() int bytesRead = -1; char readBuf[1024] = { 0 }; - for (;;) { + while (m_ThreadIsRunning) { if (m_Socket.available()) { bytesRead = Receive(readBuf, INPUTSIZE); ParseMessageType(readBuf, bytesRead); @@ -244,6 +250,16 @@ int Client::CreateMessage(MessageType type, std::string message, char* data) return offset; } +void Client::Disconnect() +{ + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int len = CreateMessage(MessageType::Disconnect, "+Disconnect", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); +} + void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) { data += stepSize; @@ -310,11 +326,7 @@ void Client::SendInput() m_ReceiverEndpoint, 0); } if (GetAsyncKeyState('V')) { - int len = CreateMessage(MessageType::Disconnect, "+Disconnect", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + Disconnect(); } memset(dataPackage, 0, INPUTSIZE); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 611aa328..661cd31a 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,6 +1,5 @@ #include "Game.h" #include "HardcodedTestWorld.h" -#include "Network/Client.h" Game::Game(int argc, char* argv[]) { @@ -38,13 +37,7 @@ Game::Game(int argc, char* argv[]) m_World = new HardcodedTestWorld(); // TEMP: Invoke network - std::string inputMessage; - std::cout << "Start client or server? (c/s)" << std::endl; - std::cin >> inputMessage; - if (inputMessage == "c" || inputMessage == "C") { - Client client; - client.Start(); - } + boost::thread workerThread(&Game::NetworkFunction, this); m_LastTime = glfwGetTime(); } @@ -53,6 +46,7 @@ Game::~Game() { delete m_FrameStack; delete m_EventBroker; + m_Client.Close(); } void Game::Tick() @@ -75,3 +69,13 @@ void Game::Tick() glfwPollEvents(); } + +void Game::NetworkFunction() +{ + std::string inputMessage; + std::cout << "Start client or server? (c/s)" << std::endl; + std::cin >> inputMessage; + if (inputMessage == "c" || inputMessage == "C") { + m_Client.Start(); + } +} \ No newline at end of file From 06f56d13d14cd4b03617f7a2a8cbf6bea0fcc36c Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 8 Dec 2015 11:14:01 +0100 Subject: [PATCH 022/185] added some octTreeTest tests and a few comments in OctTree --- src/Engine/Core/OctTree.cpp | 2 ++ src/Tests/OctTreeTest.cpp | 43 ++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index f98720be..7481e770 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -74,6 +74,7 @@ OctTree::~OctTree() { for (OctTree*& c : m_Children) { if (c != nullptr) { + //recursively delete (this calls the deconstructor again) delete c; c = nullptr; } @@ -166,6 +167,7 @@ void OctTree::AddBox(const AABB& box) } } +//remove the content (boxes) in the tree, but dont rememove the tree-structure void OctTree::ClearBoxes() { if (hasChildren()) { diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 5392e63c..aad95381 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -2,13 +2,55 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include //srand +//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 +//isnt in the original class +//Reflection-inspection seems to be only available for C# +//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 BOOST_AUTO_TEST_SUITE(octTreeTests) BOOST_AUTO_TEST_CASE(octTreeTest) { + //white box testing + //http://softwaretestingfundamentals.com/differences-between-black-box-testing-and-white-box-testing/ + //http://technologyconversations.com/2013/12/11/black-box-vs-white-box-testing/ + //simple AABB constructor check + 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); + BOOST_CHECK(someAABB.MinCorner() == minCorner); + BOOST_CHECK(someAABB.MaxCorner() == maxCorner); + BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); + + //simple OctTree constructor check + auto someOctTree = OctTree(someAABB, 5); + BOOST_CHECK(someOctTree.m_Children[0] != nullptr); + //TODO: a check so it split the tree properly + + + + + //advanced AddBox check + //add a boxcontainer - which crosses the mid-split + auto someAABB2 = AABB(glm::vec3(0.45f, 0.45f, 0.45f), glm::vec3(0.55f, 0.55f, 0.55f)); + someOctTree.AddBox(someAABB2); + //clear the boxcontainer + //need to check so it added the box properly + + + someOctTree.ClearBoxes(); + //add a boxcontainer + someOctTree.AddBox(someAABB2); + + + //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure } BOOST_AUTO_TEST_CASE(octTreeTest2) @@ -17,4 +59,3 @@ BOOST_AUTO_TEST_CASE(octTreeTest2) } BOOST_AUTO_TEST_SUITE_END() - From c48c9e1f86afe933acc6c895fa23d278c990fdb9 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 8 Dec 2015 13:54:18 +0100 Subject: [PATCH 023/185] Added leak check when using windows (WinLeakCheck.h). Added server to project. A server can now be started in the project. --- include/Engine/Network/Client.h | 2 + include/Engine/Network/Server.h | 52 +++- include/Engine/Network/WinLeakCheck.h | 17 ++ include/Game/Game.h | 5 +- src/Engine/Network/Client.cpp | 36 ++- src/Engine/Network/Server.cpp | 390 +++++++++++++++++++++++++- src/Game/Game.cpp | 3 + 7 files changed, 485 insertions(+), 20 deletions(-) create mode 100644 include/Engine/Network/WinLeakCheck.h diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index f1d60c16..fbd590ff 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -10,6 +10,7 @@ #include "Network/MessageType.h" #include "Network/NetworkDefines.h" +#include "Network/WinLeakCheck.h" class Client @@ -28,6 +29,7 @@ private: int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); + void Connect(); void Disconnect(); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); void ParseMessageType(char* data, size_t length); diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index bb198b7e..964f251f 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -1,12 +1,58 @@ #ifndef Server_h__ #define Server_h__ +#include +#include -#include +#include +#include +#include +#include "NetworkDefines.h" +#include "MessageType.h" class Server { - Server(); - ~Server(); +public: + Server(); + ~Server(); + void Start(); + +private: + // udp stuff + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::io_service m_IOService; + boost::asio::ip::udp::socket m_Socket; + boost::asio::ip::udp::endpoint m_Connections[MAXCONNECTIONS]; + //Timers + std::clock_t m_StartPingTime; + std::clock_t m_StopTimes[8]; + // Game logic + std::string m_PlayerNames[MAXCONNECTIONS]; + char m_GameBoard[BOARDSIZE][BOARDSIZE]; + glm::vec2 m_PlayerPositions[8]; + + // Threaded + void DisplayLoop(); + void ReadFromClients(); + void InputLoop(); + + + int Receive(char* data, size_t length); + int CreateMessage(MessageType type, std::string message, char * data); + void MoveMessageHead(char*& data, size_t& length, size_t stepSize); + void Broadcast(std::string message); + void Broadcast(char* data, size_t length); + void SendSnapshot(); + void SendPing(); + void CheckForTimeOuts(); + int CreateHeader(MessageType type, char* data); + void Disconnect(int i); + void ParseMessageType(char* data, size_t length); + void ParseEvent(char* data, size_t length); + void ParseConnect(char* data, size_t length); + void ParseDisconnect(); + void ParseClientPing(); + void ParseServerPing(); + void ParseSnapshot(char* data, size_t length); }; #endif diff --git a/include/Engine/Network/WinLeakCheck.h b/include/Engine/Network/WinLeakCheck.h new file mode 100644 index 00000000..dc1216a7 --- /dev/null +++ b/include/Engine/Network/WinLeakCheck.h @@ -0,0 +1,17 @@ +#if defined (_WIN64) | defined(_WIN32) +#ifndef WinLeakeCheck_h__ +#define WinLeakeCheck_h__ + +//For memory leak checking +#define _CRTDBG_MAP_ALLOC +#include +#include + +#ifdef _DEBUG +#ifndef DBG_NEW +#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) +#define new DBG_NEW +#endif +#endif // _DEBUG +#endif +#endif \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index 04c5cc9d..2931348a 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -9,10 +9,13 @@ #include "GUI/Frame.h" #include "Core/World.h" #include "Rendering/RenderQueueFactory.h" + // Network #include +#include "Network/Server.h" #include "Network/Client.h" + class Game { public: @@ -33,8 +36,8 @@ private: RenderQueueFactory* m_RenderQueueFactory; // Network variables boost::thread m_NetworkThread; + Server m_Server; Client m_Client; - // Network methods void NetworkFunction(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 53ec3d9f..8d4088d3 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -12,7 +12,8 @@ Client::Client() : m_Socket(m_IOService) Client::~Client() { - + // will it work on linux? #if defined (_WIN64) | defined(_WIN32) otherwise. + _CrtDumpMemoryLeaks(); } void Client::Start() @@ -25,7 +26,6 @@ void Client::Start() } boost::thread_group threads; - socket_ptr sock(new udp::socket(m_IOService)); for (size_t i = 0; i < BOARDSIZE; i++) { for (size_t j = 0; j < BOARDSIZE; j++) { @@ -53,6 +53,7 @@ void Client::Close() { Disconnect(); m_ThreadIsRunning = false; + m_Socket.close(); } void Client::InputLoop() @@ -154,15 +155,16 @@ void Client::ParsePing() void Client::ParseServerPing() { - char* testMsg = new char[128]; - int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMsg); + char* testMessage = new char[128]; + int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMessage); //std::cout << "Parsing ping." << std::endl; m_Socket.send_to(boost::asio::buffer( - testMsg, + testMessage, testOffset), m_ReceiverEndpoint, 0); + delete[] testMessage; } void Client::ParseEventMessage(char* data, size_t length) @@ -250,6 +252,18 @@ int Client::CreateMessage(MessageType type, std::string message, char* data) return offset; } +void Client::Connect() +{ + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int length = CreateMessage(MessageType::Connect, m_PlayerName, dataPackage); + m_StartPingTime = std::clock(); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + length), + m_ReceiverEndpoint, 0); + delete[] dataPackage; +} + void Client::Disconnect() { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled @@ -258,6 +272,7 @@ void Client::Disconnect() dataPackage, len), m_ReceiverEndpoint, 0); + delete[] dataPackage; } void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) @@ -279,16 +294,11 @@ void Client::SendDebugInput() } if (GetAsyncKeyState('C')) { - int length = CreateMessage(MessageType::Connect, m_PlayerName, dataPackage); - m_StartPingTime = std::clock(); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - length), - m_ReceiverEndpoint, 0); + Connect(); } - if (GetAsyncKeyState('Q')) { // Does not work. Plez fix - exit(1); + if (GetAsyncKeyState('Q')) { + Disconnect(); } memset(dataPackage, 0, INPUTSIZE); delete[] dataPackage; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 90c728a0..b66bd7b1 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -1,11 +1,395 @@ #include "Network/Server.h" -Server::Server() -{ - +Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 13)) +{ } Server::~Server() { +} + + +void Server::Start() +{ + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + m_StopTimes[i] = std::clock(); + m_PlayerPositions[i].x = -1; + m_PlayerPositions[i].y = -1; + } + m_PlayerPositions[0].x = 0; + m_PlayerPositions[0].y = 0; + boost::thread_group threads; + + std::cout << "I am Server. BIP BOP\n"; + + threads.create_thread(boost::bind(&Server::DisplayLoop, this)); + threads.create_thread(boost::bind(&Server::ReadFromClients, this)); + threads.create_thread(boost::bind(&Server::InputLoop, this)); + + threads.join_all(); +} + +void Server::DisplayLoop() +{ + int lengthOfMsg = -1; + std::clock_t previousePingMessage = std::clock(); + std::clock_t previousSnapshotMessage = std::clock(); + std::clock_t timOutTimer = std::clock(); + int intervallMs = 1000; + int snapshotInterval = 50; + int timeToCheckTimeOutTime = 100; + char* data; + + for (;;) { + + std::clock_t currentTime = std::clock(); + // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + SendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + CheckForTimeOuts(); + timOutTimer = currentTime; + } + } +} + +void Server::ReadFromClients() +{ + char readBuf[1024] = { 0 }; + int bytesRead = 0; + + for (;;) { + if (m_Socket.available()) { + try { + bytesRead = Receive(readBuf, INPUTSIZE); + ParseMessageType(readBuf, bytesRead); + } catch (const std::exception& err) { + // To not spam "socket closed messages" + //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { + std::cout << "Read from client crashed: " << err.what(); + //} + } + } + } +} + +void Server::InputLoop() +{ + char inputBuffer[INPUTSIZE] = { 0 }; + std::string inputMessage; + + for (;;) { + std::cin.getline(inputBuffer, INPUTSIZE); + inputMessage = (std::string)inputBuffer; + + if (!inputMessage.empty()) { + try { + // Broadcast message typed in console + Broadcast(inputMessage); + + } catch (const std::exception& err) { + std::cout << "Read from WriteLoop crashed: " << err.what(); + } + } + if (inputMessage.find("exit") != std::string::npos) + exit(1); + inputMessage.clear(); + memset(inputBuffer, 0, INPUTSIZE); + } +} + +void Server::ParseMessageType(char * data, size_t length) +{ + int messageType = -1; + memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server + MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + + switch (static_cast(messageType)) { + case MessageType::Connect: + ParseConnect(data, length); + break; + case MessageType::ClientPing: + ParseClientPing(); + break; + case MessageType::ServerPing: + ParseServerPing(); + break; + case MessageType::Message: + break; + case MessageType::Snapshot: + ParseSnapshot(data, length); + break; + case MessageType::Disconnect: + ParseDisconnect(); + break; + case MessageType::Event: + ParseEvent(data, length); + break; + default: + break; + } +} + +int Server::Receive(char * data, size_t length) +{ + length = m_Socket.receive_from( + boost::asio::buffer((void*)data + , length) + , m_ReceiverEndpoint, 0); + return length; +} + +int Server::CreateMessage(MessageType type, std::string message, char * data) +{ + int lengthOfMessage = 0; + int offset = 0; + + lengthOfMessage = message.size(); + // Message type + memcpy(data + offset, &type, sizeof(int)); + offset += sizeof(int); + // Message, add one extra byte for null terminator + memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); + offset += (lengthOfMessage + 1) * sizeof(char); + + return offset; +} + +void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) +{ + data += stepSize; + length -= stepSize; +} + +void Server::Broadcast(std::string message) +{ + std::cout << "Broadcast: " << message << std::endl; + char* data = new char[128]; + int offset = CreateMessage(MessageType::Event, message, data); + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() != boost::asio::ip::address()) { + m_Socket.send_to( + boost::asio::buffer(data, offset), + m_Connections[i], + 0); + } + } + delete[] data; +} + +void Server::Broadcast(char * data, size_t length) +{ + for (int i = 0; i < MAXCONNECTIONS; ++i) { + if (m_Connections[i].address() != boost::asio::ip::address()) { + m_Socket.send_to( + boost::asio::buffer(data, length), + m_Connections[i], + 0); + } + } +} + +void Server::SendSnapshot() +{ + char* data = new char[128]; + int offset = CreateHeader(MessageType::Snapshot, data); + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + memcpy(data + offset, &m_PlayerPositions[i].x, sizeof(float)); + offset += sizeof(float); + memcpy(data + offset, &m_PlayerPositions[i].y, sizeof(float)); + offset += sizeof(float); + // +1 for null terminator + memcpy(data + offset, m_PlayerNames[i].data(), m_PlayerNames[i].size() + 1); + offset += (m_PlayerNames[i].size() + 1) * sizeof(char); + } + Broadcast(data, offset); + delete[] data; +} + +void Server::SendPing() +{ + // Prints connected players ping + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() != boost::asio::ip::address()) + std::cout << "Player " << i << "'s ping: " << 1000 * (m_StopTimes[i] - m_StartPingTime) + / static_cast(CLOCKS_PER_SEC) << std::endl; + } + + // Create ping message + char* data = new char[128]; + int len = CreateMessage(MessageType::ServerPing, "Ping from server", data); + // Time message + m_StartPingTime = std::clock(); + // Send message + Broadcast(data, len); + delete[] data; } + +void Server::CheckForTimeOuts() +{ + int timeOutTimeMs = 5000; + + int tempStartPing = 1000 * m_StartPingTime + / static_cast(CLOCKS_PER_SEC); + + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() != boost::asio::ip::address()) { + int tempStopPing = 1000 * m_StopTimes[i] + / static_cast(CLOCKS_PER_SEC); + if (tempStartPing > tempStopPing + timeOutTimeMs) { + std::cout << "player " << i << " timed out!" << std::endl; + Disconnect(i); + } + + } + } +} + +int Server::CreateHeader(MessageType type, char * data) +{ + int messageType = static_cast(type); + int offset = 0; + memcpy(data, &messageType, sizeof(int)); + offset += sizeof(int); + + return offset; +} + +void Server::Disconnect(int i) +{ + Broadcast("A player disconnected"); + std::cout << "Player " << i << " disconnected/Timed out" << std::endl; + m_Connections[i] = boost::asio::ip::udp::endpoint(); + // Reset disconnected players position + m_PlayerPositions[i].x = -1; + m_PlayerPositions[i].y = -1; +} + +void Server::ParseEvent(char * data, size_t length) +{ + size_t i; + for (i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + break; + } + } + + if ("+Forward" == std::string(data)) + if (m_PlayerPositions[i].y > 0) + m_PlayerPositions[i].y--; + if ("-Forward" == std::string(data)) + if (m_PlayerPositions[i].y < BOARDSIZE - 1) + m_PlayerPositions[i].y++; + if ("+Right" == std::string(data)) + if (m_PlayerPositions[i].x < BOARDSIZE - 1) + m_PlayerPositions[i].x++; + if ("-Right" == std::string(data)) + if (m_PlayerPositions[i].x > 0) + m_PlayerPositions[i].x--; +} + +void Server::ParseConnect(char * data, size_t length) +{ + std::cout << "Parsing connection." << std::endl; + + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + return; + } + } + + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() == boost::asio::ip::address()) { + m_Connections[i] = m_ReceiverEndpoint; + + m_PlayerNames[i] = std::string(data); + m_PlayerPositions[i].x = 0; + m_PlayerPositions[i].y = 0; + m_StopTimes[i] = std::clock(); + std::cout << "Player \"" << m_PlayerNames[i] << "\" connected on IP: " << m_Connections[i].address().to_string() << std::endl; + + int offset = 0; + char* temp = new char[sizeof(int) * 2]; + int msgType = 0; + memcpy(temp, &msgType, sizeof(int)); + offset += sizeof(int); + memcpy(temp + offset, &i, sizeof(int)); + + m_Socket.send_to( + boost::asio::buffer(temp, sizeof(int) * 2), + m_Connections[i], + 0); + // Send notification that a player has connected + std::string str = "Player " + m_PlayerNames[i] + " connected on: " + m_ReceiverEndpoint.address().to_string(); + Broadcast(str); + // +1 is the null terminator + MoveMessageHead(data, length, m_PlayerNames[i].size() + 1); + delete[] temp; + break; + } + } +} + +void Server::ParseDisconnect() +{ + std::cout << "Parsing disconnect. \n"; + + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + Disconnect(i); + break; + } + } +} + +void Server::ParseClientPing() +{ + char* testMesssage = new char[128]; + int testOffset = CreateMessage(MessageType::ClientPing, "Ping recieved", testMesssage); + + std::cout << "Parsing ping." << std::endl; + // Return ping + m_Socket.send_to( + boost::asio::buffer( + testMesssage, + testOffset), + m_ReceiverEndpoint, + 0); + delete[] testMesssage; +} + +void Server::ParseServerPing() +{ + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + m_StopTimes[i] = std::clock(); + break; + } + } +} + +void Server::ParseSnapshot(char * data, size_t length) +{ + // Does no logic. Returns snapshot if client request one + // The snapshot is not a real snapshot tho... + for (int i = 0; i < MAXCONNECTIONS; i++) { + if (m_Connections[i].address() != boost::asio::ip::address()) { + m_Socket.send_to( + boost::asio::buffer("I'm sending a snapshot to you guys!"), + m_Connections[i], + 0); + } + } +} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 4f2f0bc5..ffff8fb6 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -80,4 +80,7 @@ void Game::NetworkFunction() if (inputMessage == "c" || inputMessage == "C") { m_Client.Start(); } + if (inputMessage == "s" || inputMessage == "S") { + m_Server.Start(); + } } \ No newline at end of file From e92119c99ea77765e3391aec483b386d209ae91e Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 8 Dec 2015 16:13:53 +0100 Subject: [PATCH 024/185] WIP trying to get Eventsystem to work in client. --- include/Engine/Network/Client.h | 9 ++++++++- include/Game/Game.h | 2 ++ src/Engine/Network/Client.cpp | 19 ++++++++++++++++--- src/Game/Game.cpp | 16 +++++++++------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index f1d60c16..83ec0535 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -10,6 +10,8 @@ #include "Network/MessageType.h" #include "Network/NetworkDefines.h" +#include "Core/EventBroker.h" +#include "Core/EKeyDown.h" class Client @@ -17,7 +19,7 @@ class Client public: Client(); ~Client(); - void Start(); + void Start(EventBroker* eventBroker); void Close(); private: @@ -54,6 +56,11 @@ private: bool m_ShouldDrawGameBoard = true; std::string m_PlayerName; bool m_ThreadIsRunning = true; + + // Events + EventBroker* m_EventBroker; + EventRelay m_EKeyDown; + bool OnKeyDown(const Events::KeyDown &e); }; #endif diff --git a/include/Game/Game.h b/include/Game/Game.h index 04c5cc9d..bb1e3b49 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -37,6 +37,8 @@ private: // Network methods void NetworkFunction(); + // Network events + EventRelay m_EKeyDown; }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 53ec3d9f..602cdbe5 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,9 +5,12 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { + //m_EventBroker = eventBroker; // Set up network stream m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); - //Start(); // All logic happens here + + + //EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Client::OnKeyDown); } Client::~Client() @@ -15,8 +18,12 @@ Client::~Client() } -void Client::Start() +void Client::Start(EventBroker* eventBroker) { + // Subscribe to events + m_EventBroker = eventBroker; + m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); + m_EventBroker->Subscribe(m_EKeyDown); std::cout << "Please enter you name: "; std::cin >> m_PlayerName; while (m_PlayerName.size() > 7) { @@ -91,7 +98,7 @@ void Client::DisplayLoop() } } if (m_ShouldDrawGameBoard) - DrawBoard(); + //DrawBoard(); boost::this_thread::sleep(boost::posix_time::millisec(100)); } } @@ -331,4 +338,10 @@ void Client::SendInput() memset(dataPackage, 0, INPUTSIZE); delete[] dataPackage; +} + +bool Client::OnKeyDown(const Events::KeyDown& event) +{ + std::cout << event.KeyCode; + return true; } \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 4f2f0bc5..9c523c4b 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -39,7 +39,8 @@ Game::Game(int argc, char* argv[]) m_World = new HardcodedTestWorld(); // TEMP: Invoke network - boost::thread workerThread(&Game::NetworkFunction, this); + + boost::thread workerThread(&Game::NetworkFunction, this); m_LastTime = glfwGetTime(); } @@ -56,6 +57,7 @@ void Game::Tick() double currentTime = glfwGetTime(); double dt = currentTime - m_LastTime; m_LastTime = currentTime; + m_EventBroker->Process(); m_EventBroker->Swap(); m_InputManager->Update(dt); @@ -74,10 +76,10 @@ void Game::Tick() void Game::NetworkFunction() { - std::string inputMessage; - std::cout << "Start client or server? (c/s)" << std::endl; - std::cin >> inputMessage; - if (inputMessage == "c" || inputMessage == "C") { - m_Client.Start(); - } + std::string inputMessage; + std::cout << "Start client or server? (c/s)" << std::endl; + std::cin >> inputMessage; + if (inputMessage == "c" || inputMessage == "C") { + m_Client.Start(m_EventBroker); + } } \ No newline at end of file From 94adaf8ae335fdecaf847a17f273aca328fdf10c Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 8 Dec 2015 16:41:22 +0100 Subject: [PATCH 025/185] Added support for multiplayer. Reactored code, clumped together variables in PlayerDefinition.h. Integrated server with entity system. --- include/Engine/Network/PlayerDefinition.h | 11 +++ include/Engine/Network/Server.h | 10 +- src/Engine/Network/Server.cpp | 106 ++++++++++++++-------- src/Game/Game.cpp | 2 +- 4 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 include/Engine/Network/PlayerDefinition.h diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h new file mode 100644 index 00000000..19c2f341 --- /dev/null +++ b/include/Engine/Network/PlayerDefinition.h @@ -0,0 +1,11 @@ +#ifndef PlayerDefinition_h__ +#define PlayerDefinition_h__ +#include + +struct PlayerDefinition { + unsigned int EntityID; + std::string Name; + boost::asio::ip::udp::endpoint Endpoint; +}; + +#endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 964f251f..be2e17a8 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -8,27 +8,31 @@ #include #include "NetworkDefines.h" #include "MessageType.h" +#include "Core/World.h" +#include "Network/PlayerDefinition.h" class Server { public: Server(); ~Server(); - void Start(); + void Start(World* m_world); private: // udp stuff boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; - boost::asio::ip::udp::endpoint m_Connections[MAXCONNECTIONS]; + // boost::asio::ip::udp::endpoint m_Connections[MAXCONNECTIONS]; + PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; //Timers std::clock_t m_StartPingTime; std::clock_t m_StopTimes[8]; // Game logic - std::string m_PlayerNames[MAXCONNECTIONS]; + // std::string m_PlayerNames[MAXCONNECTIONS]; char m_GameBoard[BOARDSIZE][BOARDSIZE]; glm::vec2 m_PlayerPositions[8]; + World* m_World; // Threaded void DisplayLoop(); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index b66bd7b1..1fb87cfa 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -9,8 +9,9 @@ Server::~Server() } -void Server::Start() +void Server::Start(World* world) { + m_World = world; for (size_t i = 0; i < MAXCONNECTIONS; i++) { m_StopTimes[i] = std::clock(); m_PlayerPositions[i].x = -1; @@ -178,10 +179,10 @@ void Server::Broadcast(std::string message) char* data = new char[128]; int offset = CreateMessage(MessageType::Event, message, data); for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() != boost::asio::ip::address()) { + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { m_Socket.send_to( boost::asio::buffer(data, offset), - m_Connections[i], + m_PlayerDefinitions[i].Endpoint, 0); } } @@ -191,10 +192,10 @@ void Server::Broadcast(std::string message) void Server::Broadcast(char * data, size_t length) { for (int i = 0; i < MAXCONNECTIONS; ++i) { - if (m_Connections[i].address() != boost::asio::ip::address()) { + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { m_Socket.send_to( boost::asio::buffer(data, length), - m_Connections[i], + m_PlayerDefinitions[i].Endpoint, 0); } } @@ -210,8 +211,8 @@ void Server::SendSnapshot() memcpy(data + offset, &m_PlayerPositions[i].y, sizeof(float)); offset += sizeof(float); // +1 for null terminator - memcpy(data + offset, m_PlayerNames[i].data(), m_PlayerNames[i].size() + 1); - offset += (m_PlayerNames[i].size() + 1) * sizeof(char); + memcpy(data + offset, m_PlayerDefinitions[i].Name.data(), m_PlayerDefinitions[i].Name.size() + 1); + offset += (m_PlayerDefinitions[i].Name.size() + 1) * sizeof(char); } Broadcast(data, offset); delete[] data; @@ -221,7 +222,7 @@ void Server::SendPing() { // Prints connected players ping for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() != boost::asio::ip::address()) + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) std::cout << "Player " << i << "'s ping: " << 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast(CLOCKS_PER_SEC) << std::endl; } @@ -245,14 +246,13 @@ void Server::CheckForTimeOuts() / static_cast(CLOCKS_PER_SEC); for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() != boost::asio::ip::address()) { + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { int tempStopPing = 1000 * m_StopTimes[i] / static_cast(CLOCKS_PER_SEC); if (tempStartPing > tempStopPing + timeOutTimeMs) { std::cout << "player " << i << " timed out!" << std::endl; Disconnect(i); } - } } } @@ -271,7 +271,9 @@ void Server::Disconnect(int i) { Broadcast("A player disconnected"); std::cout << "Player " << i << " disconnected/Timed out" << std::endl; - m_Connections[i] = boost::asio::ip::udp::endpoint(); + m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); + m_PlayerDefinitions[i].EntityID = -1; + m_PlayerDefinitions[i].Name = "Name not Set"; // Reset disconnected players position m_PlayerPositions[i].x = -1; m_PlayerPositions[i].y = -1; @@ -281,23 +283,37 @@ void Server::ParseEvent(char * data, size_t length) { size_t i; for (i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { break; } } + // If no player matches the ip return. + if (i >= 8) + return; - if ("+Forward" == std::string(data)) - if (m_PlayerPositions[i].y > 0) - m_PlayerPositions[i].y--; - if ("-Forward" == std::string(data)) - if (m_PlayerPositions[i].y < BOARDSIZE - 1) - m_PlayerPositions[i].y++; - if ("+Right" == std::string(data)) - if (m_PlayerPositions[i].x < BOARDSIZE - 1) - m_PlayerPositions[i].x++; - if ("-Right" == std::string(data)) - if (m_PlayerPositions[i].x > 0) - m_PlayerPositions[i].x--; + unsigned int entityId = m_PlayerDefinitions[i].EntityID; + if ("+Forward" == std::string(data)) { + glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + temp.z -= 0.5f; + m_World->GetComponent(entityId, "Transform")["Position"] = temp; + } + if ("-Forward" == std::string(data)) { + glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + temp.z += 0.5f; + m_World->GetComponent(entityId, "Transform")["Position"] = temp; + } + + if ("+Right" == std::string(data)) { + glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + temp.x += 0.5f; + m_World->GetComponent(entityId, "Transform")["Position"] = temp; + } + + if ("-Right" == std::string(data)) { + glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + temp.x -= 0.5f; + m_World->GetComponent(entityId, "Transform")["Position"] = temp; + } } void Server::ParseConnect(char * data, size_t length) @@ -305,37 +321,47 @@ void Server::ParseConnect(char * data, size_t length) std::cout << "Parsing connection." << std::endl; for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { return; } } for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() == boost::asio::ip::address()) { - m_Connections[i] = m_ReceiverEndpoint; + if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { + - m_PlayerNames[i] = std::string(data); - m_PlayerPositions[i].x = 0; - m_PlayerPositions[i].y = 0; + m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); + transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + + m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; + m_PlayerDefinitions[i].Name = std::string(data); m_StopTimes[i] = std::clock(); - std::cout << "Player \"" << m_PlayerNames[i] << "\" connected on IP: " << m_Connections[i].address().to_string() << std::endl; + + std::cout << "Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << + m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; int offset = 0; char* temp = new char[sizeof(int) * 2]; - int msgType = 0; - memcpy(temp, &msgType, sizeof(int)); + int messagType = 0; + + memcpy(temp, &messagType, sizeof(int)); offset += sizeof(int); memcpy(temp + offset, &i, sizeof(int)); m_Socket.send_to( boost::asio::buffer(temp, sizeof(int) * 2), - m_Connections[i], + m_PlayerDefinitions[i].Endpoint, 0); + // Send notification that a player has connected - std::string str = "Player " + m_PlayerNames[i] + " connected on: " + m_ReceiverEndpoint.address().to_string(); + std::string str = "Player " + m_PlayerDefinitions[i].Name + " connected on: " + + m_PlayerDefinitions[i].Endpoint.address().to_string(); Broadcast(str); // +1 is the null terminator - MoveMessageHead(data, length, m_PlayerNames[i].size() + 1); + MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); delete[] temp; break; } @@ -347,7 +373,7 @@ void Server::ParseDisconnect() std::cout << "Parsing disconnect. \n"; for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { Disconnect(i); break; } @@ -373,7 +399,7 @@ void Server::ParseClientPing() void Server::ParseServerPing() { for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() == m_ReceiverEndpoint.address()) { + if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { m_StopTimes[i] = std::clock(); break; } @@ -385,10 +411,10 @@ void Server::ParseSnapshot(char * data, size_t length) // Does no logic. Returns snapshot if client request one // The snapshot is not a real snapshot tho... for (int i = 0; i < MAXCONNECTIONS; i++) { - if (m_Connections[i].address() != boost::asio::ip::address()) { + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { m_Socket.send_to( boost::asio::buffer("I'm sending a snapshot to you guys!"), - m_Connections[i], + m_PlayerDefinitions[i].Endpoint, 0); } } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index ffff8fb6..670d2d13 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -81,6 +81,6 @@ void Game::NetworkFunction() m_Client.Start(); } if (inputMessage == "s" || inputMessage == "S") { - m_Server.Start(); + m_Server.Start(m_World); } } \ No newline at end of file From 27b44d2511e1ce4ad3506f529ba86e090d05a165 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 8 Dec 2015 16:41:48 +0100 Subject: [PATCH 026/185] Input events for Client done. Instead of windows getAsyncKeyState(); --- include/Engine/Network/Client.h | 3 +- src/Engine/Network/Client.cpp | 89 +++++++++++++++------------------ src/Game/Game.cpp | 7 +-- 3 files changed, 46 insertions(+), 53 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 54d83355..b9c1abcc 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -7,6 +7,7 @@ #include #include #include +#include // For input event #include "Network/MessageType.h" #include "Network/NetworkDefines.h" @@ -40,7 +41,7 @@ private: void ParsePing(); void ParseServerPing(); void ParseSnapshot(char* data, size_t length); - void SendInput(); + //void SendInput(); void SendDebugInput(); void DrawBoard(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 7ef2c210..9e9e6ed4 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -51,7 +51,7 @@ void Client::Start(EventBroker* eventBroker) threads.create_thread(boost::bind(&Client::DisplayLoop, this)); threads.create_thread(boost::bind(&Client::ReadFromServer, this)); - threads.create_thread(boost::bind(&Client::InputLoop, this)); + //threads.create_thread(boost::bind(&Client::InputLoop, this)); threads.join_all(); } @@ -82,7 +82,7 @@ void Client::InputLoop() int testTimeShit2 = (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC); if (intervallMs < (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC)) { if (m_PlayerID != -1) { - SendInput(); + //SendInput(); } previousInputTime = currentTime; } @@ -300,58 +300,49 @@ void Client::SendDebugInput() m_ReceiverEndpoint, 0); } - if (GetAsyncKeyState('C')) { - Connect(); - } - - if (GetAsyncKeyState('Q')) { - Disconnect(); - } - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; -} - -void Client::SendInput() -{ - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - if (GetAsyncKeyState('W')) { - int len = CreateMessage(MessageType::Event, "+Forward", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - } - if (GetAsyncKeyState('A')) { - int len = CreateMessage(MessageType::Event, "-Right", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - } - if (GetAsyncKeyState('S')) { - int len = CreateMessage(MessageType::Event, "-Forward", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - } - if (GetAsyncKeyState('D')) { - int len = CreateMessage(MessageType::Event, "+Right", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - } - if (GetAsyncKeyState('V')) { - Disconnect(); - } - memset(dataPackage, 0, INPUTSIZE); delete[] dataPackage; } bool Client::OnKeyDown(const Events::KeyDown& event) { - std::cout << event.KeyCode; + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + if (event.KeyCode == GLFW_KEY_W) { + int len = CreateMessage(MessageType::Event, "+Forward", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (event.KeyCode == GLFW_KEY_A) { + int len = CreateMessage(MessageType::Event, "-Right", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (event.KeyCode == GLFW_KEY_S) { + int len = CreateMessage(MessageType::Event, "-Forward", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (event.KeyCode == GLFW_KEY_D) { + int len = CreateMessage(MessageType::Event, "+Right", dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (event.KeyCode == GLFW_KEY_V) { + Disconnect(); + } + if (event.KeyCode == GLFW_KEY_C) { + Connect(); + } + + memset(dataPackage, 0, INPUTSIZE); + delete[] dataPackage; return true; } \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 53f591ba..b9886c18 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -57,15 +57,16 @@ void Game::Tick() double currentTime = glfwGetTime(); double dt = currentTime - m_LastTime; m_LastTime = currentTime; - m_EventBroker->Process(); m_EventBroker->Swap(); m_InputManager->Update(dt); - m_Renderer->Update(dt); m_EventBroker->Swap(); - m_RenderQueueFactory->Update(m_World); + // DO SYSTEM SHIT HERE + m_EventBroker->Process(); + m_Renderer->Update(dt); + m_RenderQueueFactory->Update(m_World); m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); m_EventBroker->Swap(); From 32d2aa6a93c41a7ae8b9cf0ddbd534e3daf511d7 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 8 Dec 2015 17:01:50 +0100 Subject: [PATCH 027/185] AABB can also be created with center position and its size. --- include/Engine/Core/AABB.h | 4 ++++ src/Engine/Core/AABB.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/include/Engine/Core/AABB.h b/include/Engine/Core/AABB.h index 7d0a46ea..0a0adafa 100644 --- a/include/Engine/Core/AABB.h +++ b/include/Engine/Core/AABB.h @@ -7,12 +7,16 @@ class AABB { public: AABB() = default; + //No checks are made. Values in minPos must be less than values in maxPos, i.e. min.x < max.x, etc. AABB(const glm::vec3& minPos, const glm::vec3& maxPos); + //No checks are made. Size must consist of non-negative numbers. + virtual void CreateFromCenter(const glm::vec3& center, 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& Size() const { return 2.0f * m_HalfSize; } const glm::vec3& HalfSize() const { return m_HalfSize; } private: glm::vec3 m_MinCorner; diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index 8a364ce5..9da2bdb0 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -7,5 +7,13 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) , m_HalfSize(0.5f * (maxPos - minPos)) {} +void AABB::CreateFromCenter(const glm::vec3& center, const glm::vec3& size) +{ + m_Center = center; + m_HalfSize = 0.5f * size; + m_MinCorner = m_Center - m_HalfSize; + m_MaxCorner = m_Center + m_HalfSize; +} + AABB::~AABB() {} From a7fb77d998bda9a745230c84c6d70c6f6c883784 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 8 Dec 2015 17:12:58 +0100 Subject: [PATCH 028/185] OctTree can check if a box collides with a box in the OctTree. --- include/Engine/Core/OctTree.h | 10 ++-- src/Engine/Core/OctTree.cpp | 98 +++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 1ae447a9..6279e93c 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -20,17 +20,21 @@ public: void ClearBoxes(); //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. + //On collision with a box, that box is written to [outBoxIntersected]. + bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const; private: OctTree* m_Children[8]; - std::vector m_ContainingBoxes; //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; AABB m_Box; - - bool rayCollides(const Ray& ray, Output& data) const; + inline bool hasChildren() const; int childIndexContainingPoint(const glm::vec3& point) const; + std::vector childIndicesContainingBox(const AABB& box) const; }; #endif \ No newline at end of file diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index e9aeb589..de38b143 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -48,7 +48,7 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) minPos.x = parentMin.x; maxPos.x = parentCenter.x; } - + //If child is 2,3,6,7 if (bits.test(1)) { minPos.y = parentCenter.y; @@ -80,14 +80,25 @@ OctTree::~OctTree() } } -bool OctTree::RayCollides(const Ray& ray, Output& data) const +bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const { - data.CollideDistance = -1; - return rayCollides(ray, data); + if (hasChildren()) { + for (int i : childIndicesContainingBox(boxToTest)) { + if (m_Children[i]->BoxCollides(boxToTest, outBoxIntersected)) + return true; + } + } else { + for (const auto& objBox : m_ContainingBoxes) { + if (Collision::AABBVsAABB(boxToTest, objBox)) { + outBoxIntersected = objBox; + return true; + } + } + } + return false; } -//Currently all Nodes must have exactly 0 or 8 children, and objectdata should only exist in the last bottom nodes. -bool OctTree::rayCollides(const Ray& ray, Output& data) const +bool OctTree::RayCollides(const Ray& ray, Output& data) const { //If the node AABB is missed, everything it contains is missed. if (Collision::RayAABBIntr(ray, m_Box)) { @@ -102,7 +113,7 @@ bool OctTree::rayCollides(const Ray& ray, Output& data) const 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. for (const ChildInfo& info : childInfos) { - if (m_Children[info.Index]->rayCollides(ray, data)) { + if (m_Children[info.Index]->RayCollides(ray, data)) { return true; } } @@ -127,39 +138,8 @@ bool OctTree::rayCollides(const Ray& ray, Output& data) const void OctTree::AddBox(const AABB& box) { if (hasChildren()) { - int minInd = childIndexContainingPoint(box.MinCorner()); - int maxInd = childIndexContainingPoint(box.MaxCorner()); - //Because of the predictable ordering of the child indices, - //the number of bits set when xor:ing the indices will determine the number of children containing the box. - std::bitset<3> bits(minInd ^ maxInd); - switch (bits.count()) { - case 0: //Box contained completely in one child. - m_Children[minInd]->AddBox(box); - break; - case 1: //Two children. - m_Children[minInd]->AddBox(box); - m_Children[maxInd]->AddBox(box); - break; - case 2: //Four children. - //Bit-hax to calculate the right 4 cildren containing the box. - //This works because of the childrens index determine what part of - //the dimensions they are responsible for (which octant). - bits.flip(); - //At this point the bits necessarily have exactly one bit set. - for (int c = 0; c < 8; ++c) { - //If the child index have the same bit set as the bits, add box to it. - if (bits.to_ulong() & c) { - m_Children[c]->AddBox(box); - } - } - break; - case 3: //Eight children. - for (OctTree*& c : m_Children) { - c->AddBox(box); - } - break; - default: - break; + for (auto i : childIndicesContainingBox(box)) { + m_Children[i]->AddBox(box); } } else { m_ContainingBoxes.push_back(box); @@ -196,6 +176,44 @@ int OctTree::childIndexContainingPoint(const glm::vec3& point) const return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); } +std::vector OctTree::childIndicesContainingBox(const AABB& box) const +{ + int minInd = childIndexContainingPoint(box.MinCorner()); + int maxInd = childIndexContainingPoint(box.MaxCorner()); + //Because of the predictable ordering of the child indices, + //the number of bits set when xor:ing the indices will determine the number of children containing the box. + std::bitset<3> bits(minInd ^ maxInd); + switch (bits.count()) { + //Box contained completely in one child. + case 0: + return{ minInd }; + //Two children. + case 1: + return{ minInd, maxInd }; + //Four children. + case 2: + { + std::vector ret; + //Bit-hax to calculate the right 4 cildren containing the box. + //This works because of the childrens index determine what part of + //the dimensions they are responsible for (which octant). + bits.flip(); + //At this point the bits necessarily have exactly one bit set. + for (int c = 0; c < 8; ++c) { + //If the child index have the same bit set as the bits, add box to it. + if (bits.to_ulong() & c) { + ret.push_back(c); + } + } + return ret; + } + case 3: //Eight children. + return{ 0,1,2,3,4,5,6,7 }; + default: + return std::vector(); + } +} + inline bool OctTree::hasChildren() const { return m_Children[0] != nullptr; From 24dada149f915b15a799b2a14858178073622d3e Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 8 Dec 2015 17:18:03 +0100 Subject: [PATCH 029/185] Cleaned up code in Client.h and Client.cpp. Moved ping code into Ping() function. --- include/Engine/Network/Client.h | 10 +-- src/Engine/Network/Client.cpp | 127 +++++--------------------------- 2 files changed, 20 insertions(+), 117 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index b9c1abcc..e7c346ae 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -4,8 +4,6 @@ #include #include -#include -#include #include #include // For input event @@ -26,14 +24,13 @@ public: private: // Threaded - void DisplayLoop(); void ReadFromServer(); - void InputLoop(); int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); void Connect(); void Disconnect(); + void Ping(); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); void ParseMessageType(char* data, size_t length); void ParseEventMessage(char* data, size_t length); @@ -41,9 +38,6 @@ private: void ParsePing(); void ParseServerPing(); void ParseSnapshot(char* data, size_t length); - //void SendInput(); - void SendDebugInput(); - void DrawBoard(); // udp stuff boost::asio::ip::udp::endpoint m_ReceiverEndpoint; @@ -51,12 +45,10 @@ private: boost::asio::ip::udp::socket m_Socket; int m_PlayerID = -1; - char m_GameBoard[BOARDSIZE][BOARDSIZE]; glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; std::string m_PlayerNames[MAXCONNECTIONS]; std::clock_t m_StartPingTime; double m_DurationOfPingTime; - bool m_ShouldDrawGameBoard = true; std::string m_PlayerName; bool m_ThreadIsRunning = true; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 9e9e6ed4..e1b970a1 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,12 +5,8 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - //m_EventBroker = eventBroker; // Set up network stream m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); - - - //EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Client::OnKeyDown); } Client::~Client() @@ -31,29 +27,10 @@ void Client::Start(EventBroker* eventBroker) std::cout << "Please enter you name(No longer than 7 characters): "; std::cin >> m_PlayerName; } - - boost::thread_group threads; - - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - m_GameBoard[j][i] = ' '; - } - } - - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - m_PlayerPositions[i].x = -1; - m_PlayerPositions[i].y = -1; - m_PlayerNames[i] = "X"; - } - m_Socket.connect(m_ReceiverEndpoint); std::cout << "I am client. BIP BOP\n"; - threads.create_thread(boost::bind(&Client::DisplayLoop, this)); - threads.create_thread(boost::bind(&Client::ReadFromServer, this)); - //threads.create_thread(boost::bind(&Client::InputLoop, this)); - - threads.join_all(); + ReadFromServer(); } void Client::Close() @@ -63,47 +40,6 @@ void Client::Close() m_Socket.close(); } -void Client::InputLoop() -{ - int intervallMs = 33; // ~30 times per second - int commandInterval = 200; // for commands like ping and connect, name might be ambigiuos - std::clock_t previousInputTime = std::clock(); - std::clock_t previousCommandTime = std::clock(); - - while (m_ThreadIsRunning) { - - std::clock_t currentTime = std::clock(); - int testTimeShit = (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC); - if (commandInterval < (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC)) { - SendDebugInput(); - previousCommandTime = currentTime; - } - - int testTimeShit2 = (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC); - if (intervallMs < (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC)) { - if (m_PlayerID != -1) { - //SendInput(); - } - previousInputTime = currentTime; - } - } -} - -void Client::DisplayLoop() -{ - while (m_ThreadIsRunning) { - // Update gameboard - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - m_GameBoard[j][i] = ' '; - } - } - if (m_ShouldDrawGameBoard) - //DrawBoard(); - boost::this_thread::sleep(boost::posix_time::millisec(100)); - } -} - void Client::ReadFromServer() { int bytesRead = -1; @@ -207,32 +143,6 @@ void Client::ParseSnapshot(char* data, size_t length) } } -void Client::DrawBoard() -{ - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerPositions[i].x != -1 && m_PlayerPositions[i].y != -1) { - m_GameBoard[static_cast(m_PlayerPositions[i].x)][static_cast(m_PlayerPositions[i].y)] = m_PlayerNames[i][0]; - } - } - - system("cls"); - for (size_t i = 0; i < BOARDSIZE; i++) { - std::cout << '_'; - } - - std::cout << std::endl; - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - std::cout << m_GameBoard[j][i]; - } - std::cout << std::endl; - } - - for (size_t i = 0; i < BOARDSIZE; i++) { - std::cout << "^"; - } -} - int Client::Receive(char* data, size_t length) { int bytesReceived = m_Socket.receive_from(boost @@ -282,28 +192,27 @@ void Client::Disconnect() delete[] dataPackage; } +void Client::Ping() +{ + char* dataPackage = new char[INPUTSIZE]; + if (GetAsyncKeyState('P')) { // Maybe use previous key here + int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); + m_StartPingTime = std::clock(); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + length), + m_ReceiverEndpoint, 0); + } + memset(dataPackage, 0, INPUTSIZE); + delete[] dataPackage; +} + void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) { data += stepSize; length -= stepSize; } -void Client::SendDebugInput() -{ - char* dataPackage = new char[INPUTSIZE]; - if (GetAsyncKeyState('P')) { // Maybe use previous key here - int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); - m_StartPingTime = std::clock(); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - length), - m_ReceiverEndpoint, 0); - } - - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; -} - bool Client::OnKeyDown(const Events::KeyDown& event) { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled @@ -341,7 +250,9 @@ bool Client::OnKeyDown(const Events::KeyDown& event) if (event.KeyCode == GLFW_KEY_C) { Connect(); } - + if (event.KeyCode == GLFW_KEY_P) { + Ping(); + } memset(dataPackage, 0, INPUTSIZE); delete[] dataPackage; return true; From 9f54a085366ffa15f9e4d37f8903fece1d17dcbc Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 8 Dec 2015 17:57:01 +0100 Subject: [PATCH 030/185] Implemented new version of snapshot for 3D world. Also some cleanup. --- include/Engine/Network/Client.h | 14 +-- include/Engine/Network/PlayerDefinition.h | 4 +- src/Engine/Network/Client.cpp | 133 ++++++---------------- src/Engine/Network/Server.cpp | 11 +- src/Game/Game.cpp | 2 +- 5 files changed, 52 insertions(+), 112 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index b9c1abcc..eb606678 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -11,7 +11,9 @@ #include "Network/MessageType.h" #include "Network/NetworkDefines.h" +#include "Network/PlayerDefinition.h" #include "Network/WinLeakCheck.h" +#include "Core/World.h" #include "Core/EventBroker.h" #include "Core/EKeyDown.h" @@ -21,14 +23,12 @@ class Client public: Client(); ~Client(); - void Start(EventBroker* eventBroker); + void Start(World* world, EventBroker* eventBroker); void Close(); private: // Threaded - void DisplayLoop(); void ReadFromServer(); - void InputLoop(); int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); @@ -41,19 +41,19 @@ private: void ParsePing(); void ParseServerPing(); void ParseSnapshot(char* data, size_t length); - //void SendInput(); - void SendDebugInput(); - void DrawBoard(); + void CreateNewPlayer(int i); // udp stuff boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; + World* m_World; int m_PlayerID = -1; char m_GameBoard[BOARDSIZE][BOARDSIZE]; glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; - std::string m_PlayerNames[MAXCONNECTIONS]; + //std::string m_PlayerNames[MAXCONNECTIONS]; + PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; std::clock_t m_StartPingTime; double m_DurationOfPingTime; bool m_ShouldDrawGameBoard = true; diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index 19c2f341..b35ff463 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -3,8 +3,8 @@ #include struct PlayerDefinition { - unsigned int EntityID; - std::string Name; + unsigned int EntityID = -1; + std::string Name = ""; boost::asio::ip::udp::endpoint Endpoint; }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 9e9e6ed4..d22e4e7c 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -19,10 +19,11 @@ Client::~Client() _CrtDumpMemoryLeaks(); } -void Client::Start(EventBroker* eventBroker) +void Client::Start(World* world, EventBroker* eventBroker) { // Subscribe to events m_EventBroker = eventBroker; + m_World = world; m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EKeyDown); std::cout << "Please enter you name: "; @@ -34,24 +35,10 @@ void Client::Start(EventBroker* eventBroker) boost::thread_group threads; - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - m_GameBoard[j][i] = ' '; - } - } - - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - m_PlayerPositions[i].x = -1; - m_PlayerPositions[i].y = -1; - m_PlayerNames[i] = "X"; - } - m_Socket.connect(m_ReceiverEndpoint); std::cout << "I am client. BIP BOP\n"; - threads.create_thread(boost::bind(&Client::DisplayLoop, this)); threads.create_thread(boost::bind(&Client::ReadFromServer, this)); - //threads.create_thread(boost::bind(&Client::InputLoop, this)); threads.join_all(); } @@ -63,47 +50,6 @@ void Client::Close() m_Socket.close(); } -void Client::InputLoop() -{ - int intervallMs = 33; // ~30 times per second - int commandInterval = 200; // for commands like ping and connect, name might be ambigiuos - std::clock_t previousInputTime = std::clock(); - std::clock_t previousCommandTime = std::clock(); - - while (m_ThreadIsRunning) { - - std::clock_t currentTime = std::clock(); - int testTimeShit = (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC); - if (commandInterval < (1000 * (currentTime - previousCommandTime) / (double)CLOCKS_PER_SEC)) { - SendDebugInput(); - previousCommandTime = currentTime; - } - - int testTimeShit2 = (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC); - if (intervallMs < (1000 * (currentTime - previousInputTime) / (double)CLOCKS_PER_SEC)) { - if (m_PlayerID != -1) { - //SendInput(); - } - previousInputTime = currentTime; - } - } -} - -void Client::DisplayLoop() -{ - while (m_ThreadIsRunning) { - // Update gameboard - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - m_GameBoard[j][i] = ' '; - } - } - if (m_ShouldDrawGameBoard) - //DrawBoard(); - boost::this_thread::sleep(boost::posix_time::millisec(100)); - } -} - void Client::ReadFromServer() { int bytesRead = -1; @@ -183,7 +129,7 @@ void Client::ParseEventMessage(char* data, size_t length) memcpy(&Id, data, sizeof(int)); MoveMessageHead(data, length, sizeof(int)); // Sett Player name - m_PlayerNames[Id] = command.erase(0, 7); + m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { std::cout << "Event message: " << std::string(data) << std::endl; @@ -196,40 +142,37 @@ void Client::ParseSnapshot(char* data, size_t length) { std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { - memcpy(&m_PlayerPositions[i].x, data, sizeof(float)); + // We're checking for empty name for now. This might not be the best way, + // but it is to avoid sending redundant data. + + // Read position data + glm::vec3 playerPos; + memcpy(&playerPos.x, data, sizeof(float)); MoveMessageHead(data, length, sizeof(float)); - memcpy(&m_PlayerPositions[i].y, data, sizeof(float)); + memcpy(&playerPos.y, data, sizeof(float)); MoveMessageHead(data, length, sizeof(float)); + memcpy(&playerPos.z, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + tempName = std::string(data); - m_PlayerNames[i] = tempName; // +1 for null terminator MoveMessageHead(data, length, tempName.size() + 1); - } -} -void Client::DrawBoard() -{ - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerPositions[i].x != -1 && m_PlayerPositions[i].y != -1) { - m_GameBoard[static_cast(m_PlayerPositions[i].x)][static_cast(m_PlayerPositions[i].y)] = m_PlayerNames[i][0]; + // Apply the position data read to the player entity + // New player connected on the server side + if (m_PlayerDefinitions[i].Name == "" && tempName != "") { + CreateNewPlayer(i); } - } - - system("cls"); - for (size_t i = 0; i < BOARDSIZE; i++) { - std::cout << '_'; - } - - std::cout << std::endl; - for (size_t i = 0; i < BOARDSIZE; i++) { - for (size_t j = 0; j < BOARDSIZE; j++) { - std::cout << m_GameBoard[j][i]; + else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { + // Someone disconnected + // TODO: Insert code here } - std::cout << std::endl; - } - - for (size_t i = 0; i < BOARDSIZE; i++) { - std::cout << "^"; + else { + // Not a connected player + break; + } + m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + m_PlayerDefinitions[i].Name = tempName; } } @@ -288,22 +231,6 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) length -= stepSize; } -void Client::SendDebugInput() -{ - char* dataPackage = new char[INPUTSIZE]; - if (GetAsyncKeyState('P')) { // Maybe use previous key here - int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); - m_StartPingTime = std::clock(); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - length), - m_ReceiverEndpoint, 0); - } - - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; -} - bool Client::OnKeyDown(const Events::KeyDown& event) { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled @@ -345,4 +272,12 @@ bool Client::OnKeyDown(const Events::KeyDown& event) memset(dataPackage, 0, INPUTSIZE); delete[] dataPackage; return true; +} + +void Client::CreateNewPlayer(int i) +{ + m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; } \ No newline at end of file diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 1fb87cfa..718cb596 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -203,14 +203,19 @@ void Server::Broadcast(char * data, size_t length) void Server::SendSnapshot() { - char* data = new char[128]; + char* data = new char[INPUTSIZE]; int offset = CreateHeader(MessageType::Snapshot, data); for (size_t i = 0; i < MAXCONNECTIONS; i++) { - memcpy(data + offset, &m_PlayerPositions[i].x, sizeof(float)); + // Pack player pos into data package + glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + memcpy(data + offset, &playerPos.x, sizeof(float)); offset += sizeof(float); - memcpy(data + offset, &m_PlayerPositions[i].y, sizeof(float)); + memcpy(data + offset, &playerPos.y, sizeof(float)); offset += sizeof(float); + memcpy(data + offset, &playerPos.z, sizeof(float)); + offset += sizeof(float); // +1 for null terminator + // Pack player name into data package memcpy(data + offset, m_PlayerDefinitions[i].Name.data(), m_PlayerDefinitions[i].Name.size() + 1); offset += (m_PlayerDefinitions[i].Name.size() + 1) * sizeof(char); } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 36ef8877..d21e64ea 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -81,7 +81,7 @@ void Game::NetworkFunction() std::cout << "Start client or server? (c/s)" << std::endl; std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { - m_Client.Start(m_EventBroker); + m_Client.Start(m_World, m_EventBroker); } if (inputMessage == "s" || inputMessage == "S") { m_Server.Start(m_World); From 58db7b755a0883b78405b593ceb25f3de9932d56 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 8 Dec 2015 18:24:08 +0100 Subject: [PATCH 031/185] Random bugfixes and cleanup. --- include/Engine/Network/Server.h | 5 +---- src/Engine/Network/Server.cpp | 17 +++++++---------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index be2e17a8..9a971f4b 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -23,15 +23,12 @@ private: boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; - // boost::asio::ip::udp::endpoint m_Connections[MAXCONNECTIONS]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; //Timers std::clock_t m_StartPingTime; std::clock_t m_StopTimes[8]; // Game logic - // std::string m_PlayerNames[MAXCONNECTIONS]; - char m_GameBoard[BOARDSIZE][BOARDSIZE]; - glm::vec2 m_PlayerPositions[8]; + World* m_World; // Threaded diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index a6e49560..2e95c0f6 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -14,11 +14,7 @@ void Server::Start(World* world) m_World = world; for (size_t i = 0; i < MAXCONNECTIONS; i++) { m_StopTimes[i] = std::clock(); - m_PlayerPositions[i].x = -1; - m_PlayerPositions[i].y = -1; } - m_PlayerPositions[0].x = 0; - m_PlayerPositions[0].y = 0; boost::thread_group threads; std::cout << "I am Server. BIP BOP\n"; @@ -32,7 +28,7 @@ void Server::Start(World* world) void Server::DisplayLoop() { - int lengthOfMsg = -1; + int lengthOfMessage = -1; std::clock_t previousePingMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock(); std::clock_t timOutTimer = std::clock(); @@ -279,12 +275,13 @@ void Server::Disconnect(int i) { Broadcast("A player disconnected"); std::cout << "Player " << i << " disconnected/Timed out" << std::endl; + + // Remove enteties and stuff m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); - m_PlayerDefinitions[i].EntityID = -1; - m_PlayerDefinitions[i].Name = "Name not Set"; - // Reset disconnected players position - m_PlayerPositions[i].x = -1; - m_PlayerPositions[i].y = -1; + m_PlayerDefinitions[i].EntityID = -1; + m_PlayerDefinitions[i].Name = ""; + + } void Server::ParseEvent(char * data, size_t length) From f83e217638211090b3bd5a3a5d880d26a3a98374 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 8 Dec 2015 18:35:30 +0100 Subject: [PATCH 032/185] Bugfix. if-statement was incorrect --- src/Engine/Network/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 2133e45c..5efa796e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -157,7 +157,7 @@ void Client::ParseSnapshot(char* data, size_t length) // Someone disconnected // TODO: Insert code here } - else { + else if (m_PlayerDefinitions[i].Name == "" && tempName == "") { // Not a connected player break; } From 75402b0f938eb166c5080c37cc7bb2df8750ec1b Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 9 Dec 2015 10:08:08 +0100 Subject: [PATCH 033/185] Working on OctTree tests --- src/Engine/Core/OctTree.cpp | 49 +++--- src/Tests/OctTreeTest.cpp | 6 +- src/Tests/OctTreeTestGameClass.cpp | 78 +++++++++ src/Tests/OctTreeTestGameClass.h | 35 ++++ src/Tests/OctTreeTestGameMain.cpp | 104 ++++++++++++ src/Tests/OctTreeTestHardCodedTestWorld.h | 195 ++++++++++++++++++++++ 6 files changed, 445 insertions(+), 22 deletions(-) create mode 100644 src/Tests/OctTreeTestGameClass.cpp create mode 100644 src/Tests/OctTreeTestGameClass.h create mode 100644 src/Tests/OctTreeTestGameMain.cpp create mode 100644 src/Tests/OctTreeTestHardCodedTestWorld.h diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index af6cc3a8..4e5cdfaa 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -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(); } } diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index aad95381..fee2932f 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -2,6 +2,7 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include //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 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(); + } } diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp new file mode 100644 index 00000000..4a6236c2 --- /dev/null +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -0,0 +1,78 @@ +#include "OctTreeTestGameClass.h" + +Game::Game(int argc, char* argv[]) +{ + ResourceManager::RegisterType("ConfigFile"); + ResourceManager::RegisterType("Model"); + ResourceManager::RegisterType("Texture"); + + m_Config = ResourceManager::Load("Config.ini"); + LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("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("Video.Fullscreen", false)); + m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); + m_Renderer->SetResolution(Rectangle( + 0, + 0, + m_Config->Get("Video.Width", 1280), + m_Config->Get("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(); +} diff --git a/src/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h new file mode 100644 index 00000000..9f4ae8c7 --- /dev/null +++ b/src/Tests/OctTreeTestGameClass.h @@ -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 diff --git a/src/Tests/OctTreeTestGameMain.cpp b/src/Tests/OctTreeTestGameMain.cpp new file mode 100644 index 00000000..ab13e930 --- /dev/null +++ b/src/Tests/OctTreeTestGameMain.cpp @@ -0,0 +1,104 @@ +//#define BOOST_TEST_MODULE collTest +#include +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include +#include "Engine/Core/AABB.h" +#include "Engine/Core/Ray.h" +#include //srand +#include "Engine/Core/OctTree.h" + +//vs memleaks +//#define _CRTDBG_MAP_ALLOC +//#include +//#include +//#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() + diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h new file mode 100644 index 00000000..f5caf308 --- /dev/null +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -0,0 +1,195 @@ +#include +#include +#include +#include "GLM.h" +#include "Core/World.h" +#include "Core/Util/Any.h" + +//octTree +//#include + +//last! +#define private public +#include + +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; + // } + + //} + + + } + + + } +}; \ No newline at end of file From 1d0810db1094e3c67aaefdf8c9a81a7ab6fc167b Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 9 Dec 2015 10:24:06 +0100 Subject: [PATCH 034/185] OctTree is now drawn perfectly --- src/Tests/OctTreeTestHardCodedTestWorld.h | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index f5caf308..4ce0c587 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -128,7 +128,7 @@ private: //auto min1 = someOctTree.m_Children[i]->m_Box.MinCorner(); //auto max1 = someOctTree.m_Children[i]->m_Box.MaxCorner(); - float boxDrawFactor = 1.05f; + float boxDrawFactor = 1.00f; auto halfSizeFactor = 0.0f; halfSizeFactor = someAABB.HalfSize().x; @@ -137,10 +137,10 @@ private: ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform"); transform["Position"] = someAABB.Center()*1.0f; - transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSizeFactor*boxDrawFactor; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSizeFactor*boxDrawFactor*2.0f; ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox.obj"; + model["Resource"] = "Models/Core/UnitBox2.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 @@ -153,10 +153,10 @@ private: 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; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSizeFactor*boxDrawFactor*2.0f; ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox.obj"; + model["Resource"] = "Models/Core/UnitBox2.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()); @@ -164,28 +164,28 @@ private: } //then draw the childrens children - //for (size_t j = 0; j < 8; j++) - //{ - // auto someChild = someOctTree.m_Children[j]; + 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(); + for (size_t i = 0; i < 8; i++) + { + auto cen1 = someChild->m_Children[i]->m_Box.Center(); + halfSizeFactor = someChild->m_Children[i]->m_Box.HalfSize().x; - // EntityID entityDummyScene = world.CreateEntity(); + 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 transform = world.AttachComponent(entityDummyScene, "Transform"); + transform["Position"] = cen1*1.0f; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSizeFactor*boxDrawFactor*2.0f; - // 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; - // } + ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); + model["Resource"] = "Models/Core/UnitBox2.obj"; + model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + //OctTreeEntityIdSaved = entityDummyScene; + } - //} + } } From ce41421dbb81c855e2cea774862017192b77dc73 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 9 Dec 2015 10:37:40 +0100 Subject: [PATCH 035/185] Added a "StartNetwork" bool to DefaultConfig. --- resources/DefaultConfig.ini | 10 +++++++++- src/Game/Game.cpp | 7 ++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index ac7e9ec2..9b81923e 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -1,8 +1,16 @@ [Debug] + LogLevel=1 + [Video] + Fullscreen=false + VSYNC=false + Width=1280 -Height=720 \ No newline at end of file + +Height=720 +[Networking] +StartNetwork=false \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d21e64ea..2f63e294 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -38,9 +38,10 @@ Game::Game(int argc, char* argv[]) // Create a TEST WORLD m_World = new HardcodedTestWorld(); - // TEMP: Invoke network - - boost::thread workerThread(&Game::NetworkFunction, this); + + // Invoke network + if(m_Config->Get("Networking.StartNetwork", false) == true) + boost::thread workerThread(&Game::NetworkFunction, this); m_LastTime = glfwGetTime(); } From 2a35c3055ee9b5ee78b062aeb4f75168df4e735a Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 9 Dec 2015 11:08:57 +0100 Subject: [PATCH 036/185] Renamed NetworkDefines.h --> NetworkDefinitions.h --- include/Engine/Network/Client.h | 2 +- .../Network/{NetworkDefines.h => NetworkDefinitions.h} | 0 include/Engine/Network/Server.h | 8 +++++--- 3 files changed, 6 insertions(+), 4 deletions(-) rename include/Engine/Network/{NetworkDefines.h => NetworkDefinitions.h} (100%) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 2e03f981..94ef3181 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -8,7 +8,7 @@ #include // For input event #include "Network/MessageType.h" -#include "Network/NetworkDefines.h" +#include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Network/WinLeakCheck.h" #include "Core/World.h" diff --git a/include/Engine/Network/NetworkDefines.h b/include/Engine/Network/NetworkDefinitions.h similarity index 100% rename from include/Engine/Network/NetworkDefines.h rename to include/Engine/Network/NetworkDefinitions.h diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 9a971f4b..752edc6f 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -1,15 +1,17 @@ #ifndef Server_h__ #define Server_h__ + #include #include #include #include #include -#include "NetworkDefines.h" -#include "MessageType.h" -#include "Core/World.h" + +#include "Network/MessageType.h" +#include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" +#include "Core/World.h" class Server { From 247ff09743e198ed1c7cb5bb396b731a8f9a068c Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 9 Dec 2015 13:02:39 +0100 Subject: [PATCH 037/185] Smoother movement over network. Some refactoring on client side. Now uses EKeyUp to determine if a key is pressed. --- include/Engine/Network/Client.h | 9 ++- include/Engine/Network/SnapshotDefinitions.h | 12 ++++ src/Engine/Network/Client.cpp | 73 ++++++++++++++------ 3 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 include/Engine/Network/SnapshotDefinitions.h diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 94ef3181..85c106d0 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -10,10 +10,12 @@ #include "Network/MessageType.h" #include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" +#include "Network/SnapshotDefinitions.h" #include "Network/WinLeakCheck.h" #include "Core/World.h" #include "Core/EventBroker.h" #include "Core/EKeyDown.h" +#include "Core/EKeyUp.h" class Client @@ -25,8 +27,8 @@ public: void Close(); private: - // Threaded void ReadFromServer(); + void SendToServer(); int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); @@ -52,6 +54,7 @@ private: glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; //std::string m_PlayerNames[MAXCONNECTIONS]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; + SnapshotDefinitions m_NextSnapshot; std::clock_t m_StartPingTime; double m_DurationOfPingTime; std::string m_PlayerName; @@ -60,7 +63,9 @@ private: // Events EventBroker* m_EventBroker; EventRelay m_EKeyDown; - bool OnKeyDown(const Events::KeyDown &e); + bool OnKeyDown(const Events::KeyDown &e); + EventRelay m_EKeyUp; + bool OnKeyUp(const Events::KeyUp &e); }; #endif diff --git a/include/Engine/Network/SnapshotDefinitions.h b/include/Engine/Network/SnapshotDefinitions.h new file mode 100644 index 00000000..7f9e4ce5 --- /dev/null +++ b/include/Engine/Network/SnapshotDefinitions.h @@ -0,0 +1,12 @@ +#ifndef SnapshotDefinitions_h__ +#define SnapshotDefinitions_h__ + +struct SnapshotDefinitions +{ + // "+Forward" is 8 characters * sizeof(char) = 8 + char* inputForward = new char[8]; + // "+Right" is 6 characters * sizeof(char) = 6 + char* inputRight = new char[6]; +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 5efa796e..9a51202c 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -17,11 +17,15 @@ Client::~Client() void Client::Start(World* world, EventBroker* eventBroker) { - // Subscribe to events m_EventBroker = eventBroker; m_World = world; + + // Subscribe to events m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EKeyDown); + m_EKeyUp = decltype(m_EKeyUp)(std::bind(&Client::OnKeyUp, this, std::placeholders::_1)); + m_EventBroker->Subscribe(m_EKeyUp); + std::cout << "Please enter you name: "; std::cin >> m_PlayerName; while (m_PlayerName.size() > 7) { @@ -46,11 +50,40 @@ void Client::ReadFromServer() int bytesRead = -1; char readBuf[1024] = { 0 }; + int snapshotInterval = 33; + std::clock_t previousSnapshotMessage = std::clock(); + while (m_ThreadIsRunning) { if (m_Socket.available()) { bytesRead = Receive(readBuf, INPUTSIZE); ParseMessageType(readBuf, bytesRead); } + std::clock_t currentTime = std::clock(); + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendToServer(); + previousSnapshotMessage = currentTime; + } + + } +} + +void Client::SendToServer() +{ + if (m_NextSnapshot.inputForward != "") { + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputForward, dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); + } + if (m_NextSnapshot.inputRight != "") { + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputRight, dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); } } @@ -240,33 +273,18 @@ bool Client::OnKeyDown(const Events::KeyDown& event) { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled if (event.KeyCode == GLFW_KEY_W) { - int len = CreateMessage(MessageType::Event, "+Forward", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + m_NextSnapshot.inputForward = "+Forward"; } if (event.KeyCode == GLFW_KEY_A) { - int len = CreateMessage(MessageType::Event, "-Right", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + m_NextSnapshot.inputRight = "-Right"; } if (event.KeyCode == GLFW_KEY_S) { - int len = CreateMessage(MessageType::Event, "-Forward", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + m_NextSnapshot.inputForward = "-Forward"; } if (event.KeyCode == GLFW_KEY_D) { - int len = CreateMessage(MessageType::Event, "+Right", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + m_NextSnapshot.inputRight = "+Right"; } + if (event.KeyCode == GLFW_KEY_V) { Disconnect(); } @@ -281,6 +299,19 @@ bool Client::OnKeyDown(const Events::KeyDown& event) return true; } +bool Client::OnKeyUp(const Events::KeyUp & e) +{ + if (e.KeyCode == GLFW_KEY_W || e.KeyCode == GLFW_KEY_S) { + m_NextSnapshot.inputForward = ""; + return true; + } + if (e.KeyCode == GLFW_KEY_A || e.KeyCode == GLFW_KEY_D) { + m_NextSnapshot.inputRight = ""; + return true; + } + return false; +} + void Client::CreateNewPlayer(int i) { m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); From bad42fae1c00b2e5a6f9c3d996d75d94266dde71 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 9 Dec 2015 13:27:00 +0100 Subject: [PATCH 038/185] 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() From ed5cd392ab46c8cb1b681cbdb969ec258bfbd8a7 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 9 Dec 2015 13:29:15 +0100 Subject: [PATCH 039/185] Further work in testing OctTree --- src/Tests/OctTreeTestGameClass.cpp | 11 ++ src/Tests/OctTreeTestGameClass.h | 3 + src/Tests/OctTreeTestGameMain.cpp | 6 +- src/Tests/OctTreeTestHardCodedTestWorld.h | 163 ++++++---------------- 4 files changed, 60 insertions(+), 123 deletions(-) diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 4a6236c2..918782ec 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -58,9 +58,20 @@ void Game::Tick() m_EventBroker->Swap(); //movement + minPos.x += 0.001f; + //frameCounter++; + //if (frameCounter > 50) { + // m_World->createTestEntities(AABB(minPos, glm::vec3(0.1f, 0.4f, 0.6f))); + // frameCounter = 0; + //} //auto transf = m_World->GetComponent(m_World->OctTreeEntityIdSaved, "Transform"); //((glm::vec3&)transf["Position"]).x += 0.001f; + //for (auto oneModel : m_World->allModels) + //{ + + //} + m_RenderQueueFactory->Update(m_World); //wireframe diff --git a/src/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h index 9f4ae8c7..887ad59b 100644 --- a/src/Tests/OctTreeTestGameClass.h +++ b/src/Tests/OctTreeTestGameClass.h @@ -30,6 +30,9 @@ private: GUI::Frame* m_FrameStack; HardcodedTestWorld* m_World; RenderQueueFactory* m_RenderQueueFactory; + + int frameCounter = 0; + glm::vec3 minPos = glm::vec3(-0.2f, 0.2f, 0.3f); }; #endif diff --git a/src/Tests/OctTreeTestGameMain.cpp b/src/Tests/OctTreeTestGameMain.cpp index ab13e930..9266754e 100644 --- a/src/Tests/OctTreeTestGameMain.cpp +++ b/src/Tests/OctTreeTestGameMain.cpp @@ -16,9 +16,9 @@ using boost::unit_test_framework::test_case; //#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) //#define new DEBUG_CLIENTBLOCK -BOOST_AUTO_TEST_SUITE(collisionTests) +BOOST_AUTO_TEST_SUITE(cTest) -BOOST_AUTO_TEST_CASE(collisionTest) +BOOST_AUTO_TEST_CASE(cTest) { //memleak int* globalLeak = new int[5]; @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(collisionTest) //_CrtDumpMemoryLeaks(); } -BOOST_AUTO_TEST_CASE(collisionTest2) +BOOST_AUTO_TEST_CASE(cTest2) { //fixed seed srand(2); diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index 4ce0c587..1e785994 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -8,6 +8,7 @@ //octTree //#include +#include //last! #define private public #include @@ -15,14 +16,20 @@ class HardcodedTestWorld : public World { public: + struct LinkOctTreeAndModel { + EntityID entId; + }; EntityID OctTreeEntityIdSaved; + //std::vector allModels; + //ComponentWrapper moveModel; + //OctTree* someOctTreePointer; //constructor HardcodedTestWorld() : World() { registerTestComponents(); - createTestEntities(); + //createTestEntities(); } private: @@ -54,142 +61,58 @@ private: RegisterComponent(f); } - void createTestEntities() + void createTestEntities(AABB anotherBox) { 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 someAABB = AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); + OctTree someOctTree = OctTree(someAABB, 2); + //add a box + //auto anotherBox = AABB(glm::vec3(-0.2f, 0.2f, 0.3f), glm::vec3(0.1f, 0.4f, 0.6f)); + //note: have to delete the box in the tree first, since were trying to move the box + someOctTree.ClearBoxes(); + someOctTree.AddBox(anotherBox); - auto someOctTree = OctTree(someAABB, 2); + //the main box first + AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, someOctTree.m_ContainingBoxes.size()); - //auto min1 = someOctTree.m_Children[i]->m_Box.MinCorner(); - //auto max1 = someOctTree.m_Children[i]->m_Box.MaxCorner(); + //draw anotherbox + AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, 0); - float boxDrawFactor = 1.00f; - 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*2.0f; - - ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox2.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)*halfSizeFactor*boxDrawFactor*2.0f; - - ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox2.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 + //draw the octTree for (size_t j = 0; j < 8; j++) { + AddBoxModel(someOctTree.m_Children[j]->m_Box.Center(), + someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j]->m_ContainingBoxes.size()); + auto someChild = someOctTree.m_Children[j]; for (size_t i = 0; i < 8; i++) { - auto cen1 = someChild->m_Children[i]->m_Box.Center(); - halfSizeFactor = someChild->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)*halfSizeFactor*boxDrawFactor*2.0f; - - ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox2.obj"; - model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - //OctTreeEntityIdSaved = entityDummyScene; + AddBoxModel(someChild->m_Children[i]->m_Box.Center(), + someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i]->m_ContainingBoxes.size()); } - } - - } + }//end CreateEnt + void AddBoxModel(const glm::vec3 ¢er, const float &halfSize, const int &contBoxes) { + World& world = *this; + EntityID entityDummyScene = world.CreateEntity(); + + ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform"); + transform["Position"] = center; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f; + ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); + model["Resource"] = "Models/Core/UnitBox2.obj"; + model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + if (contBoxes != 0) + model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + + //extra + //allModels.push_back(model); } }; \ No newline at end of file From 0e6353dd7912710d55f66e2969c9c356b5684bf6 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 9 Dec 2015 13:37:02 +0100 Subject: [PATCH 040/185] Fixed bug where closing glwindow as client crashed. Server bug is still present. --- include/Engine/Network/Client.h | 5 ++- src/Engine/Network/Client.cpp | 14 ++++--- src/Engine/Network/Server.cpp | 66 +++++++++++++++++---------------- src/Game/Game.cpp | 5 ++- 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 2e03f981..0ddc03dc 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -23,7 +23,6 @@ public: ~Client(); void Start(World* world, EventBroker* eventBroker); void Close(); - private: // Threaded void ReadFromServer(); @@ -50,12 +49,14 @@ private: World* m_World; int m_PlayerID = -1; glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; - //std::string m_PlayerNames[MAXCONNECTIONS]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; std::clock_t m_StartPingTime; double m_DurationOfPingTime; std::string m_PlayerName; bool m_ThreadIsRunning = true; + // Use to check if we should send disconnect message + // if game is turned of by closing window. + bool m_WasStarted = false; // Events EventBroker* m_EventBroker; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 5efa796e..17bcde7e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -18,10 +18,11 @@ Client::~Client() void Client::Start(World* world, EventBroker* eventBroker) { // Subscribe to events - m_EventBroker = eventBroker; + m_WasStarted = true; + m_EventBroker = eventBroker; m_World = world; m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); - m_EventBroker->Subscribe(m_EKeyDown); + m_EventBroker->Subscribe(m_EKeyDown); std::cout << "Please enter you name: "; std::cin >> m_PlayerName; while (m_PlayerName.size() > 7) { @@ -30,15 +31,16 @@ void Client::Start(World* world, EventBroker* eventBroker) } m_Socket.connect(m_ReceiverEndpoint); std::cout << "I am client. BIP BOP\n"; - ReadFromServer(); } void Client::Close() { - Disconnect(); - m_ThreadIsRunning = false; - m_Socket.close(); + if (m_WasStarted) { + Disconnect(); + m_ThreadIsRunning = false; + m_EventBroker->Unsubscribe(m_EKeyDown); + } } void Client::ReadFromServer() diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 2e95c0f6..3dece632 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -28,36 +28,11 @@ void Server::Start(World* world) void Server::DisplayLoop() { - int lengthOfMessage = -1; - std::clock_t previousePingMessage = std::clock(); - std::clock_t previousSnapshotMessage = std::clock(); - std::clock_t timOutTimer = std::clock(); - int intervallMs = 1000; - int snapshotInterval = 50; - int timeToCheckTimeOutTime = 100; - char* data; + for (;;) { - std::clock_t currentTime = std::clock(); - // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - SendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - CheckForTimeOuts(); - timOutTimer = currentTime; - } + } } @@ -65,6 +40,14 @@ void Server::ReadFromClients() { char readBuf[1024] = { 0 }; int bytesRead = 0; + // time for previouse message + std::clock_t previousePingMessage = std::clock(); + std::clock_t previousSnapshotMessage = std::clock(); + std::clock_t timOutTimer = std::clock(); + // How offen we send messages (milliseconds) + int intervallMs = 1000; + int snapshotInterval = 50; + int timeToCheckTimeOutTime = 100; for (;;) { if (m_Socket.available()) { @@ -77,6 +60,26 @@ void Server::ReadFromClients() std::cout << "Read from client crashed: " << err.what(); //} } + + std::clock_t currentTime = std::clock(); + // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + SendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + CheckForTimeOuts(); + timOutTimer = currentTime; + } } } } @@ -299,24 +302,24 @@ void Server::ParseEvent(char * data, size_t length) unsigned int entityId = m_PlayerDefinitions[i].EntityID; if ("+Forward" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.z -= 0.5f; + temp.z -= 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } if ("-Forward" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.z += 0.5f; + temp.z += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } if ("+Right" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.x += 0.5f; + temp.x += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } if ("-Right" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.x -= 0.5f; + temp.x -= 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } } @@ -340,6 +343,7 @@ void Server::ParseConnect(char * data, size_t length) transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; + model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = std::string(data); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d21e64ea..4b928b15 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -41,15 +41,16 @@ Game::Game(int argc, char* argv[]) // TEMP: Invoke network boost::thread workerThread(&Game::NetworkFunction, this); - m_LastTime = glfwGetTime(); } Game::~Game() { + // Call before to ensure that thread closes correctly. + m_Client.Close(); + delete m_FrameStack; delete m_EventBroker; - m_Client.Close(); } void Game::Tick() From 14bcb7ea0db5d54a76653d907692af1e8749aa67 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 9 Dec 2015 13:52:17 +0100 Subject: [PATCH 041/185] Added Update call in Game to test OctTree by using collision. --- include/Engine/Core/OctTree.h | 10 +++++++ include/Game/Game.h | 3 +++ include/Game/HardcodedTestWorld.h | 36 ++++++++++++++++++++++++++ src/Engine/Core/OctTree.cpp | 43 +++++++++++++++++++++++++++++++ src/Game/Game.cpp | 9 +++++++ 5 files changed, 101 insertions(+) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 911375d5..e5d5a83a 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -4,6 +4,8 @@ #include "Core/AABB.h" struct Ray; +class World; +class Camera; class OctTree { @@ -23,6 +25,9 @@ public: OctTree(const OctTree&& other) = delete; OctTree& operator= (const OctTree& other) = delete; + //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? + void Update(float dt, World* world, Camera* cam); + void AddDynamicObject(const AABB& box); void AddStaticObject(const AABB& box); @@ -47,6 +52,11 @@ private: std::vector m_DynamicObjects; AABB m_Box; + bool m_UpdatedOnce; + unsigned int m_BoxID; + glm::vec3 m_PrevPos; + glm::quat m_PrevOri; + inline bool hasChildren() const; int childIndexContainingPoint(const glm::vec3& point) const; std::vector childIndicesContainingBox(const AABB& box) const; diff --git a/include/Game/Game.h b/include/Game/Game.h index cd16a3dd..8667b8c8 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -10,6 +10,8 @@ #include "Core/World.h" #include "Rendering/RenderQueueFactory.h" +class OctTree; + class Game { public: @@ -28,6 +30,7 @@ private: GUI::Frame* m_FrameStack; World* m_World; RenderQueueFactory* m_RenderQueueFactory; + OctTree* m_OctTree; }; #endif diff --git a/include/Game/HardcodedTestWorld.h b/include/Game/HardcodedTestWorld.h index f183330f..5f7cc5f6 100644 --- a/include/Game/HardcodedTestWorld.h +++ b/include/Game/HardcodedTestWorld.h @@ -42,6 +42,11 @@ private: f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f)); f.AddProperty("Visible", true); RegisterComponent(f); + + f = ComponentWrapperFactory("Collision"); + f.AddProperty("BoxCenter", glm::vec3(0.f, 0.f, 0.f)); + f.AddProperty("BoxSize", glm::vec3(1.f, 1.f, 1.f)); + RegisterComponent(f); } void createTestEntities() @@ -103,6 +108,37 @@ private: ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); model["Resource"] = "Models/DummyScene.obj"; } + { + EntityID entityCollisionBox = world.CreateEntity(); + ComponentWrapper transform = world.AttachComponent(entityCollisionBox, "Transform"); + transform["Position"] = glm::vec3(0.f, 2.f, 0.f); + ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + + ComponentWrapper collision = world.AttachComponent(entityCollisionBox, "Collision"); + glm::vec3 pos = transform["Position"]; + glm::vec3 scale = transform["Scale"]; + glm::quat ori = transform["Orientation"]; + Model* modelRes = ResourceManager::Load(model["Resource"]); + + //WTODO: This only works for objects that never moves/scales/rotates since modelMatrix don't change. + //For dynamic objects, should save a collision box in modelspace and transform box with modelMatrix per collision check. + glm::mat4 modelMatrix = modelRes->m_Matrix * glm::translate(glm::mat4(), pos) * glm::toMat4(ori) * glm::scale(scale); + + glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); + glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); + for (const auto& v : modelRes->m_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); + } + collision["BoxCenter"] = 0.5f * (maxi + mini); + collision["BoxSize"] = maxi - mini; + } diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 66355580..82c1b554 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -4,6 +4,8 @@ #include "Core/OctTree.h" #include "Core/Collision.h" +#include "Core/World.h" +#include "Rendering/Camera.h" namespace { @@ -27,6 +29,7 @@ OctTree::OctTree() OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) : m_Box(octTreeBounds) + , m_UpdatedOnce(false) { if (subDivisions == 0) { for (OctTree*& c : m_Children) { @@ -80,6 +83,46 @@ OctTree::~OctTree() } } +void OctTree::Update(float dt, World* world, Camera* cam) +{ + AABB aabb; + for (ComponentWrapper& c : world->GetComponents("Collision")) { + aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); + AddStaticObject(aabb); + } + const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); + const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); + const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + + if (!m_UpdatedOnce) { + m_BoxID = world->CreateEntity(); + ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); + transform["Scale"] = boxSize; + ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + m_UpdatedOnce = true; + } + + AABB box; + auto boxPos = cam->Position() + 1.2f*cam->Forward(); + box.CreateFromCenter(boxPos, boxSize); + ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); + transform["Position"] = boxPos; + ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); + //if (BoxCollides(box, AABB())) { + if (Collision::AABBVsAABB(box, aabb)) { + cam->SetPosition(m_PrevPos); + cam->SetOrientation(m_PrevOri); + model["Color"] = greenCol; + } else { + model["Color"] = redCol; + } + + m_PrevPos = cam->Position(); + m_PrevOri = cam->Orientation(); + ClearObjects(); +} + bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const { if (hasChildren()) { diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 416b054e..03e71dce 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,6 @@ #include "Game.h" #include "HardcodedTestWorld.h" +#include "Core/OctTree.h" Game::Game(int argc, char* argv[]) { @@ -38,6 +39,10 @@ Game::Game(int argc, char* argv[]) // Create a TEST WORLD m_World = new HardcodedTestWorld(); + //WTODO: Current worldsize is temp. + glm::vec3 worldSize = glm::vec3(50, 50, 50); + m_OctTree = new OctTree(AABB(-0.5f*worldSize, 0.5f*worldSize), 2); + m_LastTime = glfwGetTime(); } @@ -45,6 +50,7 @@ Game::~Game() { delete m_FrameStack; delete m_EventBroker; + delete m_OctTree; } void Game::Tick() @@ -56,6 +62,9 @@ void Game::Tick() m_EventBroker->Swap(); m_InputManager->Update(dt); m_Renderer->Update(dt); + + m_OctTree->Update(dt, m_World, m_Renderer->Camera()); + m_EventBroker->Swap(); m_RenderQueueFactory->Update(m_World); From 8949db5456161fbc7a8814757b06c6a8a9c9e611 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 9 Dec 2015 13:56:59 +0100 Subject: [PATCH 042/185] Little more work with OctTreeTest --- src/Tests/OctTreeTest.cpp | 9 ++- src/Tests/OctTreeTestGameMain.cpp | 83 ----------------------- src/Tests/OctTreeTestHardCodedTestWorld.h | 14 ++-- 3 files changed, 11 insertions(+), 95 deletions(-) diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index fee2932f..962db3d4 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(octTreeTest) BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); //simple OctTree constructor check - auto someOctTree = OctTree(someAABB, 5); + OctTree someOctTree(someAABB, 5); BOOST_CHECK(someOctTree.m_Children[0] != nullptr); //TODO: a check so it split the tree properly @@ -40,14 +40,13 @@ BOOST_AUTO_TEST_CASE(octTreeTest) //advanced AddBox check //add a boxcontainer - which crosses the mid-split auto someAABB2 = AABB(glm::vec3(0.45f, 0.45f, 0.45f), glm::vec3(0.55f, 0.55f, 0.55f)); - someOctTree.AddBox(someAABB2); + someOctTree.AddDynamicObject(someAABB2); //clear the boxcontainer //need to check so it added the box properly - - someOctTree.ClearBoxes(); + someOctTree.ClearDynamicObjects(); //add a boxcontainer - someOctTree.AddBox(someAABB2); + someOctTree.AddDynamicObject(someAABB2); //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure diff --git a/src/Tests/OctTreeTestGameMain.cpp b/src/Tests/OctTreeTestGameMain.cpp index 9266754e..5dd23cf2 100644 --- a/src/Tests/OctTreeTestGameMain.cpp +++ b/src/Tests/OctTreeTestGameMain.cpp @@ -17,88 +17,5 @@ using boost::unit_test_framework::test_case; //#define new DEBUG_CLIENTBLOCK BOOST_AUTO_TEST_SUITE(cTest) - -BOOST_AUTO_TEST_CASE(cTest) -{ - //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(cTest2) -{ - //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() diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index 1e785994..dbdbcb45 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -29,7 +29,7 @@ public: : World() { registerTestComponents(); - //createTestEntities(); + createTestEntities(AABB(glm::vec3(-0.2f, 0.2f, 0.3f), glm::vec3(0.1f, 0.4f, 0.6f))); } private: @@ -68,15 +68,15 @@ private: //add octTree { auto someAABB = AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); - OctTree someOctTree = OctTree(someAABB, 2); + OctTree someOctTree(someAABB, 2); //add a box //auto anotherBox = AABB(glm::vec3(-0.2f, 0.2f, 0.3f), glm::vec3(0.1f, 0.4f, 0.6f)); //note: have to delete the box in the tree first, since were trying to move the box - someOctTree.ClearBoxes(); - someOctTree.AddBox(anotherBox); + someOctTree.ClearDynamicObjects(); + someOctTree.AddDynamicObject(anotherBox); //the main box first - AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, someOctTree.m_ContainingBoxes.size()); + AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, someOctTree.m_DynamicObjects.size()); //draw anotherbox AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, 0); @@ -85,14 +85,14 @@ private: for (size_t j = 0; j < 8; j++) { AddBoxModel(someOctTree.m_Children[j]->m_Box.Center(), - someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j]->m_ContainingBoxes.size()); + someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j]->m_DynamicObjects.size()); auto someChild = someOctTree.m_Children[j]; for (size_t i = 0; i < 8; i++) { AddBoxModel(someChild->m_Children[i]->m_Box.Center(), - someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i]->m_ContainingBoxes.size()); + someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i]->m_DynamicObjects.size()); } } } From 0807a7d0ae4763ce54c04649f0aeb72268d77679 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 9 Dec 2015 14:43:43 +0100 Subject: [PATCH 043/185] Fixed the bug where starting a server made the program crash on closing. Fixed some memory leaks in Client.cpp. --- include/Engine/Network/Server.h | 6 ++++-- src/Engine/Network/Client.cpp | 3 +++ src/Engine/Network/Server.cpp | 21 +++++++++++---------- src/Game/Game.cpp | 1 + 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 752edc6f..381759d7 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -19,6 +19,7 @@ public: Server(); ~Server(); void Start(World* m_world); + void Close(); private: // udp stuff @@ -30,15 +31,16 @@ private: std::clock_t m_StartPingTime; std::clock_t m_StopTimes[8]; // Game logic - World* m_World; - + // Close logic + bool m_ThreadIsRunning = true; // Threaded void DisplayLoop(); void ReadFromClients(); void InputLoop(); + int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char * data); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 0e13fb4c..df418e06 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -44,6 +44,7 @@ void Client::Close() Disconnect(); m_ThreadIsRunning = false; m_EventBroker->Unsubscribe(m_EKeyDown); + m_EventBroker->Unsubscribe(m_EKeyUp); } } @@ -78,6 +79,7 @@ void Client::SendToServer() dataPackage, len), m_ReceiverEndpoint, 0); + delete[] dataPackage; } if (m_NextSnapshot.inputRight != "") { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled @@ -86,6 +88,7 @@ void Client::SendToServer() dataPackage, len), m_ReceiverEndpoint, 0); + delete[] dataPackage; } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 3dece632..344054f6 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -26,14 +26,14 @@ void Server::Start(World* world) threads.join_all(); } +void Server::Close() +{ + m_ThreadIsRunning = false; +} + void Server::DisplayLoop() { - - for (;;) { - - - } } void Server::ReadFromClients() @@ -49,8 +49,11 @@ void Server::ReadFromClients() int snapshotInterval = 50; int timeToCheckTimeOutTime = 100; - for (;;) { - if (m_Socket.available()) { + while(m_ThreadIsRunning) { + // m_ThreadIsRunning might be unnecessary but the + // program crashed if it executed m_Socket.available() + // when closing the program. + if (m_ThreadIsRunning && m_Socket.available()) { try { bytesRead = Receive(readBuf, INPUTSIZE); ParseMessageType(readBuf, bytesRead); @@ -89,7 +92,7 @@ void Server::InputLoop() char inputBuffer[INPUTSIZE] = { 0 }; std::string inputMessage; - for (;;) { + while (m_ThreadIsRunning) { std::cin.getline(inputBuffer, INPUTSIZE); inputMessage = (std::string)inputBuffer; @@ -283,8 +286,6 @@ void Server::Disconnect(int i) m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].Name = ""; - - } void Server::ParseEvent(char * data, size_t length) diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index c40aa10a..5722eaf2 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -49,6 +49,7 @@ Game::~Game() { // Call before to ensure that thread closes correctly. m_Client.Close(); + m_Server.Close(); delete m_FrameStack; delete m_EventBroker; From e580540143b7827795f113f8aaaf54bef38ac114 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 9 Dec 2015 17:16:11 +0100 Subject: [PATCH 044/185] Made some optimizations in OctTree and added a unit test for BoxesInSameRegion. --- include/Engine/Core/OctTree.h | 9 +++--- src/Engine/Core/OctTree.cpp | 55 ++++++++++++++++++++++------------- src/Tests/OctTreeTest.cpp | 20 +++++++++++++ 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index e5d5a83a..27fbcba7 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -25,9 +25,6 @@ public: OctTree(const OctTree&& other) = delete; OctTree& operator= (const OctTree& other) = delete; - //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? - void Update(float dt, World* world, Camera* cam); - void AddDynamicObject(const AABB& box); void AddStaticObject(const AABB& box); @@ -36,10 +33,13 @@ public: void ClearObjects(); void ClearDynamicObjects(); + //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? + void Update(float dt, World* world, Camera* cam); //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. //On collision with a box, that box is written to [outBoxIntersected]. + //Note: More efficient than calling BoxesInSameRegion from outside and testing there. bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const; private: @@ -47,11 +47,10 @@ private: //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; - + bool m_UpdatedOnce; unsigned int m_BoxID; glm::vec3 m_PrevPos; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 82c1b554..5fab6f04 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -21,6 +21,16 @@ bool isFirstLower(const ChildInfo& first, const ChildInfo& second) return first.Distance < second.Distance; } +bool isSameBoxProbably(const AABB& first, const AABB& second) +{ + const float EPS = 0.0001f; + const auto& ma = first.MaxCorner(); + const auto& mi = first.MinCorner(); + return (std::abs(ma.x - mi.x) < EPS) && + (std::abs(ma.z - mi.z) < EPS) && + (std::abs(ma.y - mi.y) < EPS); +} + } OctTree::OctTree() @@ -131,16 +141,18 @@ bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const return true; } } else { - 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; - } + for (const auto& obj : m_StaticObjects) { + if (Collision::AABBVsAABB(boxToTest, obj)) { + outBoxIntersected = obj; + return true; + } + } + for (const auto& obj : m_DynamicObjects) { + //If there is a collision and it is not testing against itself. + if (!isSameBoxProbably(boxToTest, obj) && + Collision::AABBVsAABB(boxToTest, obj)) { + outBoxIntersected = obj; + return true; } } } @@ -170,17 +182,18 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const //Check against boxes in the node. float minDist = INFINITY; bool intersected = false; - 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; - } + for (const auto& obj : m_StaticObjects) { + float dist; + if (Collision::RayVsAABB(ray, obj, dist)) { + minDist = std::min(dist, minDist); + intersected = true; + } + } + for (const auto& obj : m_DynamicObjects) { + float dist; + if (Collision::RayVsAABB(ray, obj, dist)) { + minDist = std::min(dist, minDist); + intersected = true; } } diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 5392e63c..47036485 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -16,5 +16,25 @@ BOOST_AUTO_TEST_CASE(octTreeTest2) } +BOOST_AUTO_TEST_CASE(octSameRegionTest) +{ + glm::vec3 mini = glm::vec3(-1, -1, -1); + glm::vec3 maxi = glm::vec3(1, 1, 1); + OctTree tree(AABB(mini, maxi), 2); + AABB firstQuadrant(mini, 0.8f*mini); + tree.AddStaticObject(firstQuadrant); + AABB testBox(0.9f*mini, 0.8f*mini); + std::vector region; + 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.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); +} + BOOST_AUTO_TEST_SUITE_END() From 4de613814b1fe31239e17d3ef074690d61138409 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 9 Dec 2015 17:43:36 +0100 Subject: [PATCH 045/185] WIP Packet loss identification. Put packetID in message --- include/Engine/Network/Client.h | 5 ++++ include/Engine/Network/NetworkDefinitions.h | 1 + include/Engine/Network/Server.h | 5 ++++ include/Game/Game.h | 3 +-- src/Engine/Network/Client.cpp | 26 ++++++++++++++++++--- src/Engine/Network/Server.cpp | 12 ++++++++++ src/Game/Game.cpp | 6 +++-- 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 5b2070d6..3485736b 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -42,12 +42,17 @@ private: void ParseServerPing(); void ParseSnapshot(char* data, size_t length); void CreateNewPlayer(int i); + void IdentifyPacketLoss(); // udp stuff boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; + // Packet loss logic + unsigned int m_PacketID = 0; + unsigned int m_PreviousPacketID = 0; + World* m_World; int m_PlayerID = -1; glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index e9da132f..b9d36226 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -7,6 +7,7 @@ #define BOARDSIZE 16 #define MAXCONNECTIONS 8 #define INPUTSIZE 128 +#define PACKETMODULUS 1000 // How many packets before the number resets typedef boost::shared_ptr socket_ptr; typedef boost::shared_ptr string_ptr; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 381759d7..3b476d2a 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -32,6 +32,11 @@ private: std::clock_t m_StopTimes[8]; // Game logic World* m_World; + // Packet loss logic + unsigned int m_PacketCounter = 0; + unsigned int m_PacketID = 0; + const unsigned int m_PacketModolus = 1000; + // Close logic bool m_ThreadIsRunning = true; // Threaded diff --git a/include/Game/Game.h b/include/Game/Game.h index 2763b4dd..8ec4a6d8 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -36,8 +36,7 @@ private: RenderQueueFactory* m_RenderQueueFactory; // Network variables boost::thread m_NetworkThread; - Server m_Server; - Client m_Client; + // Network methods void NetworkFunction(); // Network events diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index df418e06..5e9b1fb3 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -7,6 +7,8 @@ Client::Client() : m_Socket(m_IOService) { // Set up network stream m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + m_NextSnapshot.inputForward = ""; + m_NextSnapshot.inputRight = ""; } Client::~Client() @@ -72,7 +74,7 @@ void Client::ReadFromServer() void Client::SendToServer() { - if (m_NextSnapshot.inputForward != "") { + if (m_NextSnapshot.inputForward != "" && m_NextSnapshot.inputForward[0] != '\0') { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputForward, dataPackage); m_Socket.send_to(boost::asio::buffer( @@ -81,7 +83,7 @@ void Client::SendToServer() m_ReceiverEndpoint, 0); delete[] dataPackage; } - if (m_NextSnapshot.inputRight != "") { + if (m_NextSnapshot.inputRight != "" && m_NextSnapshot.inputRight[0] != '\0') { char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputRight, dataPackage); m_Socket.send_to(boost::asio::buffer( @@ -98,6 +100,12 @@ void Client::ParseMessageType(char* data, size_t length) memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + // Read packet ID + m_PreviousPacketID = m_PacketID; + memcpy(&m_PacketID, data, sizeof(int)); + MoveMessageHead(data, length, sizeof(int)); + IdentifyPacketLoss(); + switch (static_cast(messageType)) { case MessageType::Connect: ParseConnect(data, length); @@ -323,4 +331,16 @@ void Client::CreateNewPlayer(int i) ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; -} \ No newline at end of file +} + +void Client::IdentifyPacketLoss() +{ + // if no packets lost, difference should be equal to 1 + int difference = m_PacketID - m_PreviousPacketID; + if (difference != 1) { + for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) + { + LOG_INFO("Packet %i was lost...", i); + } + } +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 344054f6..235b26ec 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -162,10 +162,15 @@ int Server::CreateMessage(MessageType type, std::string message, char * data) // Message type memcpy(data + offset, &type, sizeof(int)); offset += sizeof(int); + // Packet ID + m_PacketID = m_PacketCounter % 10; + memcpy(data + offset, &m_PacketID, sizeof(int)); + offset += sizeof(int); // Message, add one extra byte for null terminator memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); offset += (lengthOfMessage + 1) * sizeof(char); + m_PacketCounter++; return offset; } @@ -273,6 +278,9 @@ int Server::CreateHeader(MessageType type, char * data) int offset = 0; memcpy(data, &messageType, sizeof(int)); offset += sizeof(int); + m_PacketID = m_PacketCounter % 10; + memcpy(data + offset, &m_PacketID, sizeof(int)); + offset += sizeof(int); return offset; } @@ -361,6 +369,10 @@ void Server::ParseConnect(char * data, size_t length) offset += sizeof(int); memcpy(temp + offset, &i, sizeof(int)); + memcpy(temp, &m_PacketID, sizeof(int)); + offset += sizeof(int); + m_PacketCounter++; + m_Socket.send_to( boost::asio::buffer(temp, sizeof(int) * 2), m_PlayerDefinitions[i].Endpoint, diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 5722eaf2..affaaa66 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -48,8 +48,8 @@ Game::Game(int argc, char* argv[]) Game::~Game() { // Call before to ensure that thread closes correctly. - m_Client.Close(); - m_Server.Close(); + //m_Client.Close(); + //m_Server.Close(); delete m_FrameStack; delete m_EventBroker; @@ -84,9 +84,11 @@ void Game::NetworkFunction() std::cout << "Start client or server? (c/s)" << std::endl; std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { + Client m_Client; m_Client.Start(m_World, m_EventBroker); } if (inputMessage == "s" || inputMessage == "S") { + Server m_Server; m_Server.Start(m_World); } } \ No newline at end of file From 663aca26419773c200fd63f7dd3352afd3e56a38 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 9 Dec 2015 17:50:30 +0100 Subject: [PATCH 046/185] Moved client and server from header. Fixed so user are able to start a server and client on the same computer. Starting 2 servers on the same computer will probably still crash the newest server (Don't do it). --- include/Game/Game.h | 2 -- src/Engine/Network/Client.cpp | 19 ++++++++++++++----- src/Game/Game.cpp | 6 ++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/Game/Game.h b/include/Game/Game.h index 2763b4dd..fd4068da 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -36,8 +36,6 @@ private: RenderQueueFactory* m_RenderQueueFactory; // Network variables boost::thread m_NetworkThread; - Server m_Server; - Client m_Client; // Network methods void NetworkFunction(); // Network events diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index df418e06..24085352 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -206,11 +206,20 @@ void Client::ParseSnapshot(char* data, size_t length) int Client::Receive(char* data, size_t length) { - int bytesReceived = m_Socket.receive_from(boost - ::asio::buffer((void*)data, length), - m_ReceiverEndpoint, - 0); - return bytesReceived; + + try { + int bytesReceived = m_Socket.receive_from(boost + ::asio::buffer((void*)data, length), + m_ReceiverEndpoint, + 0); + return bytesReceived; + } catch (const std::exception& err) { + // To not spam "socket closed messages" + //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { + std::cout << "Read from client crashed: " << err.what(); + //} + } + return 0; } int Client::CreateMessage(MessageType type, std::string message, char* data) diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 5722eaf2..12a3a711 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -48,8 +48,8 @@ Game::Game(int argc, char* argv[]) Game::~Game() { // Call before to ensure that thread closes correctly. - m_Client.Close(); - m_Server.Close(); + //m_Client.Close(); + //m_Server.Close(); delete m_FrameStack; delete m_EventBroker; @@ -84,9 +84,11 @@ void Game::NetworkFunction() std::cout << "Start client or server? (c/s)" << std::endl; std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { + Client m_Client; m_Client.Start(m_World, m_EventBroker); } if (inputMessage == "s" || inputMessage == "S") { + Server m_Server; m_Server.Start(m_World); } } \ No newline at end of file From bc8a922b77f39259e4312c242a0325ceaa7a1787 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 9 Dec 2015 17:57:32 +0100 Subject: [PATCH 047/185] Merging octTreeTests a bit --- src/Tests/OctTreeTest.cpp | 18 +--- src/Tests/OctTreeTestGameClass.cpp | 101 ++++++++++++++++++---- src/Tests/OctTreeTestGameClass.h | 15 +++- src/Tests/OctTreeTestHardCodedTestWorld.h | 68 +++++++++------ 4 files changed, 142 insertions(+), 60 deletions(-) diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 962db3d4..b0b5c25d 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -32,33 +32,17 @@ BOOST_AUTO_TEST_CASE(octTreeTest) //simple OctTree constructor check OctTree someOctTree(someAABB, 5); BOOST_CHECK(someOctTree.m_Children[0] != nullptr); - //TODO: a check so it split the tree properly - - - - - //advanced AddBox check - //add a boxcontainer - which crosses the mid-split - auto someAABB2 = AABB(glm::vec3(0.45f, 0.45f, 0.45f), glm::vec3(0.55f, 0.55f, 0.55f)); - someOctTree.AddDynamicObject(someAABB2); - //clear the boxcontainer - //need to check so it added the box properly - - someOctTree.ClearDynamicObjects(); - //add a boxcontainer - someOctTree.AddDynamicObject(someAABB2); - //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure } BOOST_AUTO_TEST_CASE(octTreeTest2) { + //octtree ritningen osv Game game(0, nullptr); while (game.Running()) { game.Tick(); } - } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 918782ec..e79f645b 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -1,6 +1,6 @@ #include "OctTreeTestGameClass.h" -Game::Game(int argc, char* argv[]) +Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worldSize), 2) { ResourceManager::RegisterType("ConfigFile"); ResourceManager::RegisterType("Model"); @@ -57,31 +57,100 @@ void Game::Tick() m_Renderer->Update(dt); m_EventBroker->Swap(); - //movement - minPos.x += 0.001f; - //frameCounter++; - //if (frameCounter > 50) { - // m_World->createTestEntities(AABB(minPos, glm::vec3(0.1f, 0.4f, 0.6f))); - // frameCounter = 0; - //} - //auto transf = m_World->GetComponent(m_World->OctTreeEntityIdSaved, "Transform"); - //((glm::vec3&)transf["Position"]).x += 0.001f; +#define TEST2 +#ifdef TEST1 + //add/move the trigger box + auto pos = m_Renderer->Camera()->Forward() + m_Renderer->Camera()->Position(); + AABB boxi; + boxi.CreateFromCenter(pos, maxPos - minPos); + frameCounter++; + if (frameCounter > 50) { + m_World->someOctTree.ClearDynamicObjects(); + m_World->someOctTree.AddDynamicObject(boxi); + frameCounter = 0; + } + ComponentWrapper transform = m_World->GetComponent(m_World->anotherBoxTransformId, "Transform"); + transform["Position"] = boxi.Center(); - //for (auto oneModel : m_World->allModels) - //{ + //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! + std::vector boxIndex; + boxIndex = m_World->someOctTree.childIndicesContainingBox(boxi); - //} + for (auto& oneLinkedObject : m_World->linkOM) + { + ComponentWrapper model = m_World->GetComponent(oneLinkedObject.entId, "Model"); + model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + if (oneLinkedObject.child->m_DynamicObjects.size() != 0) { + model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + } + //next check if the childIndicesContainingBox method returns the correct boxes + //REQUIRED: childIndicesContainingBox must be public to test this! + for each (auto someBoxIndex in boxIndex) + { + glm::vec3 pos = m_World->someOctTree.m_Children[someBoxIndex]->m_Box.Center(); + 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) { + model["Color"] = glm::vec4(0.0f, 1.0f, 0.0f, 1.0f); + + } + } + } m_RenderQueueFactory->Update(m_World); //wireframe glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif +#ifdef TEST2 + + //only add 1 for now... + //grey box + AABB aabb; + aabb.CreateFromCenter(glm::vec3(0.f, 2.f, 0.f), glm::vec3(1.f, 1.f, 1.f)); + + const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); + const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); + const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + + if (!m_UpdatedOnce) { + someOctTree.AddStaticObject(aabb); + m_BoxID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_BoxID, "Transform"); + transform["Scale"] = boxSize; + ComponentWrapper model = m_World->AttachComponent(m_BoxID, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + m_UpdatedOnce = true; + m_World->createTestEntitiesTest2(); + } + + //red box + AABB redBox; + auto boxPos = m_Renderer->Camera()->Position() + 1.2f*m_Renderer->Camera()->Forward(); + redBox.CreateFromCenter(boxPos, boxSize); + ComponentWrapper transform = m_World->GetComponent(m_BoxID, "Transform"); + transform["Position"] = boxPos; + ComponentWrapper model = m_World->GetComponent(m_BoxID, "Model"); + if (someOctTree.BoxCollides(redBox, AABB())) { + //if (Collision::AABBVsAABB(redBox, aabb)) { + m_Renderer->Camera()->SetPosition(m_PrevPos); + m_Renderer->Camera()->SetOrientation(m_PrevOri); + model["Color"] = greenCol; + } + else { + model["Color"] = redCol; + } + + m_PrevPos = m_Renderer->Camera()->Position(); + m_PrevOri = m_Renderer->Camera()->Orientation(); + someOctTree.ClearObjects(); + + m_RenderQueueFactory->Update(m_World); +#endif m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - m_EventBroker->Swap(); m_EventBroker->Clear(); diff --git a/src/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h index 887ad59b..8ca34510 100644 --- a/src/Tests/OctTreeTestGameClass.h +++ b/src/Tests/OctTreeTestGameClass.h @@ -11,6 +11,7 @@ #include "Rendering/RenderQueueFactory.h" #include "OctTreeTestHardCodedTestWorld.h" +#include "Core\Collision.h" class Game { @@ -31,8 +32,20 @@ private: HardcodedTestWorld* m_World; RenderQueueFactory* m_RenderQueueFactory; + //Test1 int frameCounter = 0; - glm::vec3 minPos = glm::vec3(-0.2f, 0.2f, 0.3f); + glm::vec3 minPos = glm::vec3(0.1f, 0.1f, 0.1f); + glm::vec3 maxPos = glm::vec3(0.2f, 0.2f, 0.2f); + + //Test2 + bool m_UpdatedOnce = false; + unsigned int m_BoxID; + glm::vec3 m_PrevPos; + glm::quat m_PrevOri; + + glm::vec3 worldSize = glm::vec3(50, 50, 50); + OctTree someOctTree; + }; #endif diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index dbdbcb45..ff7b56cc 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -5,9 +5,6 @@ #include "Core/World.h" #include "Core/Util/Any.h" -//octTree -//#include - #include //last! #define private public @@ -18,18 +15,26 @@ class HardcodedTestWorld : public World public: struct LinkOctTreeAndModel { EntityID entId; + OctTree* child; + glm::vec3 posxyz; + LinkOctTreeAndModel(EntityID eId, OctTree* ch, glm::vec3 pos) + { + entId = eId; + child = ch; + posxyz = pos; + } }; - EntityID OctTreeEntityIdSaved; - //std::vector allModels; - //ComponentWrapper moveModel; - //OctTree* someOctTreePointer; + EntityID anotherBoxTransformId; + std::vector linkOM; + OctTree someOctTree; //constructor HardcodedTestWorld() : World() + , someOctTree(AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)), 2) { registerTestComponents(); - createTestEntities(AABB(glm::vec3(-0.2f, 0.2f, 0.3f), glm::vec3(0.1f, 0.4f, 0.6f))); + //createTestEntities(); } private: @@ -61,58 +66,69 @@ private: RegisterComponent(f); } - void createTestEntities(AABB anotherBox) + void createTestEntities() { World& world = *this; - + EntityID tempId; //add octTree { + //copy of mainbox auto someAABB = AABB(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); - OctTree someOctTree(someAABB, 2); - //add a box - //auto anotherBox = AABB(glm::vec3(-0.2f, 0.2f, 0.3f), glm::vec3(0.1f, 0.4f, 0.6f)); + + //draw main box first + AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, &someOctTree, tempId); + + //add anotherbox in octTree + auto anotherBox = AABB(glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.2f, 0.2f, 0.2f)); //note: have to delete the box in the tree first, since were trying to move the box - someOctTree.ClearDynamicObjects(); someOctTree.AddDynamicObject(anotherBox); - //the main box first - AddBoxModel(someAABB.Center(), someAABB.HalfSize().x, someOctTree.m_DynamicObjects.size()); - - //draw anotherbox - AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, 0); + //draw anotherbox and save it in anotherBoxTransformId + AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, &someOctTree, anotherBoxTransformId); //draw the octTree for (size_t j = 0; j < 8; j++) { AddBoxModel(someOctTree.m_Children[j]->m_Box.Center(), - someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j]->m_DynamicObjects.size()); + someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j], tempId); auto someChild = someOctTree.m_Children[j]; for (size_t i = 0; i < 8; i++) { AddBoxModel(someChild->m_Children[i]->m_Box.Center(), - someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i]->m_DynamicObjects.size()); + someChild->m_Children[i]->m_Box.HalfSize().x, someChild->m_Children[i], tempId); } } } }//end CreateEnt - void AddBoxModel(const glm::vec3 ¢er, const float &halfSize, const int &contBoxes) { + void AddBoxModel(const glm::vec3 ¢er, const float &halfSize, OctTree* child, EntityID &outEntityId) { World& world = *this; EntityID entityDummyScene = world.CreateEntity(); - + outEntityId = entityDummyScene; ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform"); transform["Position"] = center; - transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f*0.97f; ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox2.obj"; + model["Resource"] = "Models/Core/UnitBox.obj"; model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - if (contBoxes != 0) + if (child->m_DynamicObjects.size() != 0) model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + linkOM.emplace_back(entityDummyScene, child, center); //extra //allModels.push_back(model); } + void createTestEntitiesTest2() + { + World& world = *this; + + EntityID entityCollisionBox = world.CreateEntity(); + ComponentWrapper transform = world.AttachComponent(entityCollisionBox, "Transform"); + transform["Position"] = glm::vec3(0.f, 2.f, 0.f); + ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + } }; \ No newline at end of file From c60e96883662d244d99b894f718cd9b6b6f6d9ab Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 10 Dec 2015 11:03:40 +0100 Subject: [PATCH 048/185] Removed a boxclear in the end of the test2 method --- include/Engine/Core/OctTree.h | 1 + src/Engine/Core/OctTree.cpp | 4 ++-- src/Tests/OctTreeTestGameClass.cpp | 24 ++++++++++++++++++----- src/Tests/OctTreeTestHardCodedTestWorld.h | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index e5d5a83a..7379b202 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -58,6 +58,7 @@ private: glm::quat m_PrevOri; inline bool hasChildren() const; +public: int childIndexContainingPoint(const glm::vec3& point) const; std::vector childIndicesContainingBox(const AABB& box) const; }; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 82c1b554..582e3acd 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -109,8 +109,8 @@ void OctTree::Update(float dt, World* world, Camera* cam) ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); transform["Position"] = boxPos; ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); - //if (BoxCollides(box, AABB())) { - if (Collision::AABBVsAABB(box, aabb)) { + if (BoxCollides(box, AABB())) { + //if (Collision::AABBVsAABB(box, aabb)) { cam->SetPosition(m_PrevPos); cam->SetOrientation(m_PrevOri); model["Color"] = greenCol; diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index e79f645b..6b2e23bc 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -58,7 +58,13 @@ void Game::Tick() m_EventBroker->Swap(); #define TEST2 + //this draws the octTree and you can set the cube inside it and see what boxes in the tree that it belongs to #ifdef TEST1 + if (!m_UpdatedOnce) { + m_UpdatedOnce = true; + m_World->createTestEntitiesTest1(); + } + //add/move the trigger box auto pos = m_Renderer->Camera()->Forward() + m_Renderer->Camera()->Position(); AABB boxi; @@ -103,25 +109,32 @@ void Game::Tick() //wireframe glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); #endif + //this tests AABB vs AABB collision and AABB vs OctTree with AABB in it #ifdef TEST2 //only add 1 for now... //grey box - AABB aabb; - aabb.CreateFromCenter(glm::vec3(0.f, 2.f, 0.f), glm::vec3(1.f, 1.f, 1.f)); const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + AABB aabb; + aabb.CreateFromCenter(glm::vec3(0, 2.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); + if (m_UpdatedOnce) { + auto test = someOctTree.childIndicesContainingBox(aabb); + std::vector test2; + someOctTree.BoxesInSameRegion(aabb, test2); + } if (!m_UpdatedOnce) { + m_UpdatedOnce = true; someOctTree.AddStaticObject(aabb); + //create the "small red box" m_BoxID = m_World->CreateEntity(); ComponentWrapper transform = m_World->AttachComponent(m_BoxID, "Transform"); transform["Scale"] = boxSize; ComponentWrapper model = m_World->AttachComponent(m_BoxID, "Model"); model["Resource"] = "Models/Core/UnitBox.obj"; - m_UpdatedOnce = true; m_World->createTestEntitiesTest2(); } @@ -132,8 +145,10 @@ void Game::Tick() ComponentWrapper transform = m_World->GetComponent(m_BoxID, "Transform"); transform["Position"] = boxPos; ComponentWrapper model = m_World->GetComponent(m_BoxID, "Model"); + //this checks AABB vs an AABB in the octTree if (someOctTree.BoxCollides(redBox, AABB())) { - //if (Collision::AABBVsAABB(redBox, aabb)) { + //this checks AABB vs AABB + //if (Collision::AABBVsAABB(redBox, aabb)) { m_Renderer->Camera()->SetPosition(m_PrevPos); m_Renderer->Camera()->SetOrientation(m_PrevOri); model["Color"] = greenCol; @@ -144,7 +159,6 @@ void Game::Tick() m_PrevPos = m_Renderer->Camera()->Position(); m_PrevOri = m_Renderer->Camera()->Orientation(); - someOctTree.ClearObjects(); m_RenderQueueFactory->Update(m_World); #endif diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index ff7b56cc..a0762cce 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -66,7 +66,7 @@ private: RegisterComponent(f); } - void createTestEntities() + void createTestEntitiesTest1() { World& world = *this; EntityID tempId; From 9a8f5293afc0b546fd09cd28686f59bc0a22ab4c Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 10 Dec 2015 12:55:28 +0100 Subject: [PATCH 049/185] Can now Identify Packet Loss. Enumerated messages that loops around 0-1000. --- include/Engine/Network/NetworkDefinitions.h | 2 +- src/Engine/Network/Client.cpp | 12 ++-- src/Engine/Network/Server.cpp | 62 +++++++++++---------- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index b9d36226..4ad32e26 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -7,7 +7,7 @@ #define BOARDSIZE 16 #define MAXCONNECTIONS 8 #define INPUTSIZE 128 -#define PACKETMODULUS 1000 // How many packets before the number resets +#define PACKETMODULUS 1000 // How many packets to send before the number resets typedef boost::shared_ptr socket_ptr; typedef boost::shared_ptr string_ptr; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 5e9b1fb3..4f397b5b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,7 +6,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); m_NextSnapshot.inputForward = ""; m_NextSnapshot.inputRight = ""; } @@ -133,14 +133,15 @@ void Client::ParseMessageType(char* data, size_t length) void Client::ParseConnect(char* data, size_t len) { - memcpy(&m_PlayerID, data, sizeof(int)); - std::cout << "I am player: " << m_PlayerID << std::endl; + memcpy(&m_PacketID, data, sizeof(int)); + m_PreviousPacketID = m_PacketID; + std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } void Client::ParsePing() { m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - std::cout << "response time with ctime(ms): " << m_DurationOfPingTime << std::endl; + std::cout << m_PacketID << ": response time with ctime(ms): " << m_DurationOfPingTime << std::endl; } void Client::ParseServerPing() @@ -169,7 +170,7 @@ void Client::ParseEventMessage(char* data, size_t length) m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { - std::cout << "Event message: " << std::string(data) << std::endl; + std::cout << m_PacketID << ": Event message: " << std::string(data) << std::endl; } MoveMessageHead(data, length, std::string(data).size() + 1); @@ -177,6 +178,7 @@ void Client::ParseEventMessage(char* data, size_t length) void Client::ParseSnapshot(char* data, size_t length) { + std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 235b26ec..2dea57f5 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -53,6 +53,8 @@ void Server::ReadFromClients() // m_ThreadIsRunning might be unnecessary but the // program crashed if it executed m_Socket.available() // when closing the program. + + // If available message -> Socket.available() = true if (m_ThreadIsRunning && m_Socket.available()) { try { bytesRead = Receive(readBuf, INPUTSIZE); @@ -60,30 +62,29 @@ void Server::ReadFromClients() } catch (const std::exception& err) { // To not spam "socket closed messages" //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { - std::cout << "Read from client crashed: " << err.what(); + std::cout << m_PacketID << ": Read from client crashed: " << err.what(); //} } - - std::clock_t currentTime = std::clock(); - // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendSnapshot(); - previousSnapshotMessage = currentTime; - } - - // Send pings each - if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - SendPing(); - previousePingMessage = currentTime; - } - - // Time out logic - if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - CheckForTimeOuts(); - timOutTimer = currentTime; - } } + std::clock_t currentTime = std::clock(); + // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendSnapshot(); + previousSnapshotMessage = currentTime; + } + + // Send pings each + if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + SendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + CheckForTimeOuts(); + timOutTimer = currentTime; + } } } @@ -102,7 +103,7 @@ void Server::InputLoop() Broadcast(inputMessage); } catch (const std::exception& err) { - std::cout << "Read from WriteLoop crashed: " << err.what(); + std::cout << m_PacketID << ": Read from WriteLoop crashed: " << err.what(); } } if (inputMessage.find("exit") != std::string::npos) @@ -163,7 +164,7 @@ int Server::CreateMessage(MessageType type, std::string message, char * data) memcpy(data + offset, &type, sizeof(int)); offset += sizeof(int); // Packet ID - m_PacketID = m_PacketCounter % 10; + m_PacketID = m_PacketCounter % PACKETMODULUS; memcpy(data + offset, &m_PacketID, sizeof(int)); offset += sizeof(int); // Message, add one extra byte for null terminator @@ -182,7 +183,7 @@ void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) void Server::Broadcast(std::string message) { - std::cout << "Broadcast: " << message << std::endl; + std::cout << m_PacketID << ": Broadcast: " << message << std::endl; char* data = new char[128]; int offset = CreateMessage(MessageType::Event, message, data); for (int i = 0; i < MAXCONNECTIONS; i++) { @@ -238,7 +239,7 @@ void Server::SendPing() // Prints connected players ping for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) - std::cout << "Player " << i << "'s ping: " << 1000 * (m_StopTimes[i] - m_StartPingTime) + std::cout << m_PacketID << ": Player " << i << "'s ping: " << 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast(CLOCKS_PER_SEC) << std::endl; } @@ -278,9 +279,10 @@ int Server::CreateHeader(MessageType type, char * data) int offset = 0; memcpy(data, &messageType, sizeof(int)); offset += sizeof(int); - m_PacketID = m_PacketCounter % 10; + m_PacketID = m_PacketCounter % PACKETMODULUS; memcpy(data + offset, &m_PacketID, sizeof(int)); offset += sizeof(int); + m_PacketCounter++; return offset; } @@ -358,7 +360,7 @@ void Server::ParseConnect(char * data, size_t length) m_PlayerDefinitions[i].Name = std::string(data); m_StopTimes[i] = std::clock(); - std::cout << "Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << + std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; int offset = 0; @@ -379,7 +381,7 @@ void Server::ParseConnect(char * data, size_t length) 0); // Send notification that a player has connected - std::string str = "Player " + m_PlayerDefinitions[i].Name + " connected on: " + std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " + m_PlayerDefinitions[i].Endpoint.address().to_string(); Broadcast(str); // +1 is the null terminator @@ -392,7 +394,7 @@ void Server::ParseConnect(char * data, size_t length) void Server::ParseDisconnect() { - std::cout << "Parsing disconnect. \n"; + std::cout << m_PacketID << ":Parsing disconnect. \n"; for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { @@ -407,7 +409,7 @@ void Server::ParseClientPing() char* testMesssage = new char[128]; int testOffset = CreateMessage(MessageType::ClientPing, "Ping recieved", testMesssage); - std::cout << "Parsing ping." << std::endl; + std::cout << m_PacketID << ":Parsing ping." << std::endl; // Return ping m_Socket.send_to( boost::asio::buffer( From 7804d42feacfeaa21a1461ab85e41c982d671b15 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 10 Dec 2015 13:42:39 +0100 Subject: [PATCH 050/185] OctTree debug temporarily disabled because of the new master layout --- src/Engine/Core/OctTree.cpp | 66 ++++++++++++++++++------------------- src/Tests/WorldTest.cpp | 10 +++--- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 582e3acd..29230c74 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -85,42 +85,42 @@ OctTree::~OctTree() void OctTree::Update(float dt, World* world, Camera* cam) { - AABB aabb; - for (ComponentWrapper& c : world->GetComponents("Collision")) { - aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); - AddStaticObject(aabb); - } - const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); - const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); - const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + //AABB aabb; + //for (ComponentWrapper& c : world->GetComponents("Collision")) { + // aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); + // AddStaticObject(aabb); + //} + //const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); + //const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); + //const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); - if (!m_UpdatedOnce) { - m_BoxID = world->CreateEntity(); - ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); - transform["Scale"] = boxSize; - ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); - model["Resource"] = "Models/Core/UnitBox.obj"; - m_UpdatedOnce = true; - } + //if (!m_UpdatedOnce) { + // m_BoxID = world->CreateEntity(); + // ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); + // transform["Scale"] = boxSize; + // ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); + // model["Resource"] = "Models/Core/UnitBox.obj"; + // m_UpdatedOnce = true; + //} - AABB box; - auto boxPos = cam->Position() + 1.2f*cam->Forward(); - box.CreateFromCenter(boxPos, boxSize); - ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); - transform["Position"] = boxPos; - ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); - if (BoxCollides(box, AABB())) { - //if (Collision::AABBVsAABB(box, aabb)) { - cam->SetPosition(m_PrevPos); - cam->SetOrientation(m_PrevOri); - model["Color"] = greenCol; - } else { - model["Color"] = redCol; - } + //AABB box; + //auto boxPos = cam->Position() + 1.2f*cam->Forward(); + //box.CreateFromCenter(boxPos, boxSize); + //ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); + //transform["Position"] = boxPos; + //ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); + //if (BoxCollides(box, AABB())) { + ////if (Collision::AABBVsAABB(box, aabb)) { + // cam->SetPosition(m_PrevPos); + // cam->SetOrientation(m_PrevOri); + // model["Color"] = greenCol; + //} else { + // model["Color"] = redCol; + //} - m_PrevPos = cam->Position(); - m_PrevOri = cam->Orientation(); - ClearObjects(); + //m_PrevPos = cam->Position(); + //m_PrevOri = cam->Orientation(); + //ClearObjects(); } bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 4fd4ceed..0b1c243d 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -63,9 +63,9 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001)) } // Loop through them and check data - int i = 0; - for (auto& c : w.GetComponents("Test")) { - BOOST_TEST((int)c["TestInteger"] == i); - i++; - } + //int i = 0; + //for (auto& c : w.GetComponents("Test")) { + // BOOST_TEST((int)c["TestInteger"] == i); + // i++; + //} } From f377d9ba7045f6c0deef120df0cff88fca207caa Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 10 Dec 2015 14:14:36 +0100 Subject: [PATCH 051/185] Fixed client movement. --- include/Engine/Network/Client.h | 3 +- include/Engine/Network/NetworkDefinitions.h | 3 + include/Engine/Network/SnapshotDefinitions.h | 12 +- src/Engine/Network/Client.cpp | 412 ++++++++++--------- 4 files changed, 234 insertions(+), 196 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 5b2070d6..266fe719 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -27,7 +27,7 @@ public: void Close(); private: void ReadFromServer(); - void SendToServer(); + void SendSnapshotToServer(); int Receive(char* data, size_t length); int CreateMessage(MessageType type, std::string message, char* data); @@ -60,6 +60,7 @@ private: // Use to check if we should send disconnect message // if game is turned of by closing window. bool m_WasStarted = false; + IsWASDKeyDown m_IsWASDKeyDown; // Events EventBroker* m_EventBroker; diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index e9da132f..469fbcbc 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -7,9 +7,12 @@ #define BOARDSIZE 16 #define MAXCONNECTIONS 8 #define INPUTSIZE 128 +#define PLAYERSPEED 0.2f; typedef boost::shared_ptr socket_ptr; typedef boost::shared_ptr string_ptr; typedef boost::shared_ptr> messageQueue_ptr; + + #endif \ No newline at end of file diff --git a/include/Engine/Network/SnapshotDefinitions.h b/include/Engine/Network/SnapshotDefinitions.h index 7f9e4ce5..2b4ba948 100644 --- a/include/Engine/Network/SnapshotDefinitions.h +++ b/include/Engine/Network/SnapshotDefinitions.h @@ -4,9 +4,17 @@ struct SnapshotDefinitions { // "+Forward" is 8 characters * sizeof(char) = 8 - char* inputForward = new char[8]; + char* InputForward = new char[8]; // "+Right" is 6 characters * sizeof(char) = 6 - char* inputRight = new char[6]; + char* InputRight = new char[6]; +}; + +struct IsWASDKeyDown +{ + bool W = false; + bool A = false; + bool S = false; + bool D = false; }; #endif \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 24085352..423a04ee 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,8 +5,8 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + // Set up network stream + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); } Client::~Client() @@ -19,22 +19,22 @@ void Client::Start(World* world, EventBroker* eventBroker) { m_WasStarted = true; m_EventBroker = eventBroker; - m_World = world; - - // Subscribe to events - m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); + m_World = world; + + // Subscribe to events + m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EKeyDown); - m_EKeyUp = decltype(m_EKeyUp)(std::bind(&Client::OnKeyUp, this, std::placeholders::_1)); - m_EventBroker->Subscribe(m_EKeyUp); - - std::cout << "Please enter you name: "; - std::cin >> m_PlayerName; - while (m_PlayerName.size() > 7) { - std::cout << "Please enter you name(No longer than 7 characters): "; - std::cin >> m_PlayerName; - } - m_Socket.connect(m_ReceiverEndpoint); - std::cout << "I am client. BIP BOP\n"; + m_EKeyUp = decltype(m_EKeyUp)(std::bind(&Client::OnKeyUp, this, std::placeholders::_1)); + m_EventBroker->Subscribe(m_EKeyUp); + + std::cout << "Please enter you name: "; + std::cin >> m_PlayerName; + while (m_PlayerName.size() > 7) { + std::cout << "Please enter you name(No longer than 7 characters): "; + std::cin >> m_PlayerName; + } + m_Socket.connect(m_ReceiverEndpoint); + std::cout << "I am client. BIP BOP\n"; ReadFromServer(); } @@ -50,193 +50,205 @@ void Client::Close() void Client::ReadFromServer() { - int bytesRead = -1; - char readBuf[1024] = { 0 }; + int bytesRead = -1; + char readBuf[1024] = { 0 }; - int snapshotInterval = 33; - std::clock_t previousSnapshotMessage = std::clock(); + int snapshotInterval = 33; + std::clock_t previousSnapshotMessage = std::clock(); - while (m_ThreadIsRunning) { - if (m_Socket.available()) { - bytesRead = Receive(readBuf, INPUTSIZE); - ParseMessageType(readBuf, bytesRead); - } - std::clock_t currentTime = std::clock(); - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendToServer(); - previousSnapshotMessage = currentTime; - } - - } + while (m_ThreadIsRunning) { + if (m_Socket.available()) { + bytesRead = Receive(readBuf, INPUTSIZE); + ParseMessageType(readBuf, bytesRead); + } + std::clock_t currentTime = std::clock(); + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendSnapshotToServer(); + previousSnapshotMessage = currentTime; + } + + } } -void Client::SendToServer() +void Client::SendSnapshotToServer() { - if (m_NextSnapshot.inputForward != "") { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputForward, dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + // Reset previouse key state in snapshot. + m_NextSnapshot.InputRight = ""; + m_NextSnapshot.InputRight = ""; + // See if any movement keys are down + // We dont care if it's overwritten by later + // if statement. Watcha gonna do, right! + if (m_IsWASDKeyDown.W) { + m_NextSnapshot.InputRight = "+Forward"; + } + if (m_IsWASDKeyDown.A) { + m_NextSnapshot.InputRight = "-Right"; + } + if (m_IsWASDKeyDown.S) { + m_NextSnapshot.InputRight = "-Forward"; + } + if (m_IsWASDKeyDown.D) { + m_NextSnapshot.InputRight = "+Right"; + } + + if (m_NextSnapshot.InputForward != "") { + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int len = CreateMessage(MessageType::Event, m_NextSnapshot.InputForward, dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); delete[] dataPackage; - } - if (m_NextSnapshot.inputRight != "") { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputRight, dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); + } + if (m_NextSnapshot.InputRight != "") { + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + int len = CreateMessage(MessageType::Event, m_NextSnapshot.InputRight, dataPackage); + m_Socket.send_to(boost::asio::buffer( + dataPackage, + len), + m_ReceiverEndpoint, 0); delete[] dataPackage; - } + } } void Client::ParseMessageType(char* data, size_t length) { - int messageType = -1; - memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server - MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + int messageType = -1; + memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server + MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from - switch (static_cast(messageType)) { - case MessageType::Connect: - ParseConnect(data, length); - break; - case MessageType::ClientPing: - ParsePing(); - break; - case MessageType::ServerPing: - ParseServerPing(); - break; - case MessageType::Message: - break; - case MessageType::Snapshot: - ParseSnapshot(data, length); - break; - case MessageType::Disconnect: - break; - case MessageType::Event: - ParseEventMessage(data, length); - break; - default: - break; - } + switch (static_cast(messageType)) { + case MessageType::Connect: + ParseConnect(data, length); + break; + case MessageType::ClientPing: + ParsePing(); + break; + case MessageType::ServerPing: + ParseServerPing(); + break; + case MessageType::Message: + break; + case MessageType::Snapshot: + ParseSnapshot(data, length); + break; + case MessageType::Disconnect: + break; + case MessageType::Event: + ParseEventMessage(data, length); + break; + default: + break; + } } void Client::ParseConnect(char* data, size_t len) { - memcpy(&m_PlayerID, data, sizeof(int)); - std::cout << "I am player: " << m_PlayerID << std::endl; + memcpy(&m_PlayerID, data, sizeof(int)); + std::cout << "I am player: " << m_PlayerID << std::endl; } void Client::ParsePing() { - m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - std::cout << "response time with ctime(ms): " << m_DurationOfPingTime << std::endl; + m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + std::cout << "response time with ctime(ms): " << m_DurationOfPingTime << std::endl; } void Client::ParseServerPing() { - char* testMessage = new char[128]; - int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMessage); + char* testMessage = new char[128]; + int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMessage); - //std::cout << "Parsing ping." << std::endl; + //std::cout << "Parsing ping." << std::endl; - m_Socket.send_to(boost::asio::buffer( + m_Socket.send_to(boost::asio::buffer( testMessage, - testOffset), - m_ReceiverEndpoint, 0); + testOffset), + m_ReceiverEndpoint, 0); delete[] testMessage; } void Client::ParseEventMessage(char* data, size_t length) { - int Id = -1; - std::string command = std::string(data); - if (command.find("+Player") != std::string::npos) { - MoveMessageHead(data, length, command.size() + 1); - memcpy(&Id, data, sizeof(int)); - MoveMessageHead(data, length, sizeof(int)); - // Sett Player name - m_PlayerDefinitions[Id].Name = command.erase(0, 7); - } - else { - std::cout << "Event message: " << std::string(data) << std::endl; - } + int Id = -1; + std::string command = std::string(data); + if (command.find("+Player") != std::string::npos) { + MoveMessageHead(data, length, command.size() + 1); + memcpy(&Id, data, sizeof(int)); + MoveMessageHead(data, length, sizeof(int)); + // Sett Player name + m_PlayerDefinitions[Id].Name = command.erase(0, 7); + } else { + std::cout << "Event message: " << std::string(data) << std::endl; + } - MoveMessageHead(data, length, std::string(data).size() + 1); + MoveMessageHead(data, length, std::string(data).size() + 1); } void Client::ParseSnapshot(char* data, size_t length) { - std::string tempName; - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - // We're checking for empty name for now. This might not be the best way, - // but it is to avoid sending redundant data. + std::string tempName; + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + // We're checking for empty name for now. This might not be the best way, + // but it is to avoid sending redundant data. - // Read position data - glm::vec3 playerPos; - memcpy(&playerPos.x, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - memcpy(&playerPos.y, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - memcpy(&playerPos.z, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - - tempName = std::string(data); - // +1 for null terminator - MoveMessageHead(data, length, tempName.size() + 1); - // Apply the position data read to the player entity - // New player connected on the server side - if (m_PlayerDefinitions[i].Name == "" && tempName != "") { - CreateNewPlayer(i); - } - else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { - // Someone disconnected - // TODO: Insert code here - } - else if (m_PlayerDefinitions[i].Name == "" && tempName == "") { - // Not a connected player - break; - } - m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; - m_PlayerDefinitions[i].Name = tempName; - } + // Read position data + glm::vec3 playerPos; + memcpy(&playerPos.x, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + memcpy(&playerPos.y, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + memcpy(&playerPos.z, data, sizeof(float)); + MoveMessageHead(data, length, sizeof(float)); + + tempName = std::string(data); + // +1 for null terminator + MoveMessageHead(data, length, tempName.size() + 1); + // Apply the position data read to the player entity + // New player connected on the server side + if (m_PlayerDefinitions[i].Name == "" && tempName != "") { + CreateNewPlayer(i); + } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { + // Someone disconnected + // TODO: Insert code here + } else if (m_PlayerDefinitions[i].Name == "" && tempName == "") { + // Not a connected player + break; + } + m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + m_PlayerDefinitions[i].Name = tempName; + } } int Client::Receive(char* data, size_t length) { + boost::system::error_code error; - try { - int bytesReceived = m_Socket.receive_from(boost - ::asio::buffer((void*)data, length), - m_ReceiverEndpoint, - 0); - return bytesReceived; - } catch (const std::exception& err) { - // To not spam "socket closed messages" - //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { - std::cout << "Read from client crashed: " << err.what(); - //} - } - return 0; + int bytesReceived = m_Socket.receive_from(boost + ::asio::buffer((void*)data, length), + m_ReceiverEndpoint, + 0, error); + + std::cout << "ReadFromServer crashed: " << error.message(); + + return bytesReceived; } int Client::CreateMessage(MessageType type, std::string message, char* data) { - int lengthOfMessage = 0; - int messageType = static_cast(type); - lengthOfMessage = message.size(); + int lengthOfMessage = 0; + int messageType = static_cast(type); + lengthOfMessage = message.size(); - int offset = 0; - // Message type - memcpy(data + offset, &messageType, sizeof(int)); - offset += sizeof(int); - // Message, add one extra byte for null terminator - memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); - offset += (lengthOfMessage + 1) * sizeof(char); + int offset = 0; + // Message type + memcpy(data + offset, &messageType, sizeof(int)); + offset += sizeof(int); + // Message, add one extra byte for null terminator + memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); + offset += (lengthOfMessage + 1) * sizeof(char); - return offset; + return offset; } void Client::Connect() @@ -263,7 +275,7 @@ void Client::Disconnect() } void Client::Ping() -{ +{ char* dataPackage = new char[INPUTSIZE]; if (GetAsyncKeyState('P')) { // Maybe use previous key here int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); @@ -279,57 +291,71 @@ void Client::Ping() void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) { - data += stepSize; - length -= stepSize; + data += stepSize; + length -= stepSize; } bool Client::OnKeyDown(const Events::KeyDown& event) { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - if (event.KeyCode == GLFW_KEY_W) { - m_NextSnapshot.inputForward = "+Forward"; - } - if (event.KeyCode == GLFW_KEY_A) { - m_NextSnapshot.inputRight = "-Right"; - } - if (event.KeyCode == GLFW_KEY_S) { - m_NextSnapshot.inputForward = "-Forward"; - } - if (event.KeyCode == GLFW_KEY_D) { - m_NextSnapshot.inputRight = "+Right"; - } + char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled + if (event.KeyCode == GLFW_KEY_W) { + m_IsWASDKeyDown.W = true; + //m_NextSnapshot.inputForward = "+Forward"; + } + if (event.KeyCode == GLFW_KEY_A) { + m_IsWASDKeyDown.A = true; + //m_NextSnapshot.inputRight = "-Right"; + } + if (event.KeyCode == GLFW_KEY_S) { + m_IsWASDKeyDown.S = true; + //m_NextSnapshot.inputForward = "-Forward"; + } + if (event.KeyCode == GLFW_KEY_D) { + m_IsWASDKeyDown.D = true; + //m_NextSnapshot.inputRight = "+Right"; + } - if (event.KeyCode == GLFW_KEY_V) { - Disconnect(); - } - if (event.KeyCode == GLFW_KEY_C) { - Connect(); - } + if (event.KeyCode == GLFW_KEY_V) { + Disconnect(); + } + if (event.KeyCode == GLFW_KEY_C) { + Connect(); + } if (event.KeyCode == GLFW_KEY_P) { Ping(); } - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; - return true; + memset(dataPackage, 0, INPUTSIZE); + delete[] dataPackage; + return true; } bool Client::OnKeyUp(const Events::KeyUp & e) { - if (e.KeyCode == GLFW_KEY_W || e.KeyCode == GLFW_KEY_S) { - m_NextSnapshot.inputForward = ""; - return true; - } - if (e.KeyCode == GLFW_KEY_A || e.KeyCode == GLFW_KEY_D) { - m_NextSnapshot.inputRight = ""; - return true; - } - return false; + if (e.KeyCode == GLFW_KEY_W) { + m_IsWASDKeyDown.W = false; + //m_NextSnapshot.inputForward = ""; + return true; + } + if (e.KeyCode == GLFW_KEY_A){ + m_IsWASDKeyDown.A = false; + return true; + } + if (e.KeyCode == GLFW_KEY_S){ + m_IsWASDKeyDown.S = false; + return true; + } + if (e.KeyCode == GLFW_KEY_D) { + m_IsWASDKeyDown.D = false; + //m_NextSnapshot.inputRight = ""; + return true; + } + return false; } void Client::CreateNewPlayer(int i) { - m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; + m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; } \ No newline at end of file From 0d8f7acb7e229507e5c924c85eb59a8978232f6f Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 10 Dec 2015 16:04:55 +0100 Subject: [PATCH 052/185] OctTree doesn't check the same object multiple times if it exists in multiple places in the tree. --- include/Engine/Core/OctTree.h | 80 +++++++++--- include/Game/HardcodedTestWorld.h | 5 +- src/Engine/Core/OctTree.cpp | 201 +++++++++++++++++++++++------- 3 files changed, 222 insertions(+), 64 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 27fbcba7..2a3b87b2 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -13,7 +13,21 @@ public: struct Output { float CollideDistance; - }; + }; + struct ContainedObject + { + ContainedObject() + : Box(AABB()) + , Checked(false) + {} + ContainedObject(AABB box) + : Box(box) + , Checked(false) + {} + AABB Box; + bool Checked; + }; + OctTree(); ~OctTree(); //For the root OctTree, [octTreeBounds] should be a box containing the entire level. @@ -24,41 +38,71 @@ public: OctTree(const OctTree& other) = delete; OctTree(const OctTree&& other) = delete; OctTree& operator= (const OctTree& other) = delete; - + //Add a dynamic object (one that moves around) into the tree. void AddDynamicObject(const AABB& box); + //Add a static object (that does not move) into the tree. void AddStaticObject(const AABB& box); - - void BoxesInSameRegion(const AABB& box, std::vector& outBoxes) const; - + //Get the boxes that are in the same area as the input [box], the boxes are put in [outBoxes]. + void BoxesInSameRegion(const AABB& box, std::vector& outBoxes); + //Empty the tree of all objects, static and dynamic. void ClearObjects(); + //Empty the tree of all dynamic objects. Static objects remain in the tree. void ClearDynamicObjects(); //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? void Update(float dt, World* world, Camera* cam); //Returns true if the ray collides with something in the tree. Result is written to [data]. - bool RayCollides(const Ray& ray, Output& data) const; + bool RayCollides(const Ray& ray, Output& data); //Returns true if the box collides with something in the tree. //On collision with a box, that box is written to [outBoxIntersected]. //Note: More efficient than calling BoxesInSameRegion from outside and testing there. - bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const; + bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected); private: - OctTree* m_Children[8]; - //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. - std::vector m_StaticObjects; - std::vector m_DynamicObjects; - AABB m_Box; - + struct OctChild; + OctChild* m_Root; + std::vector m_StaticObjects; + std::vector m_DynamicObjects; + bool m_UpdatedOnce; unsigned int m_BoxID; glm::vec3 m_PrevPos; glm::quat m_PrevOri; - inline bool hasChildren() const; - int childIndexContainingPoint(const glm::vec3& point) const; - std::vector childIndicesContainingBox(const AABB& box) const; + void falsifyObjectChecks(); + + struct OctChild + { + ~OctChild(); + OctChild(const AABB& octTreeBounds, + int subDivisions, + std::vector& staticObjects, + std::vector& dynamicObjects); + OctChild(const OctChild& other) = delete; + OctChild(const OctChild&& other) = delete; + OctChild& operator= (const OctChild& 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(); + bool RayCollides(const Ray& ray, Output& data) const; + bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const; + + OctChild* m_Children[8]; + //Indices into the lists in OctTree. + std::vector m_StaticObjIndices; + std::vector m_DynamicObjIndices; + AABB m_Box; + //Reference to the lists in OctTree. + std::vector& m_StaticObjectsRef; + std::vector& m_DynamicObjectsRef; + + inline bool hasChildren() const; + int childIndexContainingPoint(const glm::vec3& point) const; + std::vector childIndicesContainingBox(const AABB& box) const; + }; }; + #endif \ No newline at end of file diff --git a/include/Game/HardcodedTestWorld.h b/include/Game/HardcodedTestWorld.h index 5f7cc5f6..dd132971 100644 --- a/include/Game/HardcodedTestWorld.h +++ b/include/Game/HardcodedTestWorld.h @@ -108,12 +108,15 @@ private: ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); model["Resource"] = "Models/DummyScene.obj"; } + for (int i = 0; i < 16; ++i) { EntityID entityCollisionBox = world.CreateEntity(); ComponentWrapper transform = world.AttachComponent(entityCollisionBox, "Transform"); - transform["Position"] = glm::vec3(0.f, 2.f, 0.f); + transform["Position"] = glm::vec3(rand()%11-5, rand() % 11 - 5, rand() % 11 - 5); ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model"); model["Resource"] = "Models/Core/UnitBox.obj"; + float sc = 0.20f; + transform["Scale"] = glm::vec3(sc, sc, sc); ComponentWrapper collision = world.AttachComponent(entityCollisionBox, "Collision"); glm::vec3 pos = transform["Position"]; diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 5fab6f04..63eba63e 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -38,11 +38,79 @@ OctTree::OctTree() {} OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) - : m_Box(octTreeBounds) + : m_Root(new OctChild(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects)) , m_UpdatedOnce(false) +{} + +OctTree::~OctTree() +{ + delete m_Root; +} + +void OctTree::AddDynamicObject(const AABB& box) +{ + m_Root->AddDynamicObject(box); + m_DynamicObjects.push_back(box); +} + +void OctTree::AddStaticObject(const AABB& box) +{ + m_Root->AddStaticObject(box); + m_StaticObjects.push_back(box); +} + +void OctTree::BoxesInSameRegion(const AABB& box, std::vector& outBoxes) +{ + falsifyObjectChecks(); + m_Root->BoxesInSameRegion(box, outBoxes); +} + +void OctTree::ClearObjects() +{ + m_StaticObjects.clear(); + m_DynamicObjects.clear(); + m_Root->ClearObjects(); +} + +void OctTree::ClearDynamicObjects() +{ + m_DynamicObjects.clear(); + m_Root->ClearDynamicObjects(); +} + +bool OctTree::RayCollides(const Ray& ray, Output& data) +{ + falsifyObjectChecks(); + data.CollideDistance = -1; + return m_Root->RayCollides(ray, data); +} + +bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) +{ + falsifyObjectChecks(); + return m_Root->BoxCollides(boxToTest, outBoxIntersected); +} + +void OctTree::falsifyObjectChecks() +{ + for (auto& obj : m_StaticObjects) { + obj.Checked = false; + } + for (auto& obj : m_DynamicObjects) { + obj.Checked = false; + } +} + +OctTree::OctChild::OctChild(const AABB& octTreeBounds, + int subDivisions, + std::vector& staticObjects, + std::vector& dynamicObjects) + : m_Box(octTreeBounds) + , m_StaticObjectsRef(staticObjects) + , m_DynamicObjectsRef(dynamicObjects) { if (subDivisions == 0) { - for (OctTree*& c : m_Children) { + for (OctChild*& c : m_Children) { c = nullptr; } } else { @@ -78,14 +146,14 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) minPos.z = parentMin.z; maxPos.z = parentCenter.z; } - m_Children[i] = new OctTree(AABB(minPos, maxPos), subDivisions); + m_Children[i] = new OctChild(AABB(minPos, maxPos), subDivisions, m_StaticObjectsRef, m_DynamicObjectsRef); } } } -OctTree::~OctTree() +OctTree::OctChild::~OctChild() { - for (OctTree*& c : m_Children) { + for (OctChild*& c : m_Children) { if (c != nullptr) { delete c; c = nullptr; @@ -95,19 +163,22 @@ OctTree::~OctTree() void OctTree::Update(float dt, World* world, Camera* cam) { - AABB aabb; for (ComponentWrapper& c : world->GetComponents("Collision")) { + AABB aabb; aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); - AddStaticObject(aabb); + AddDynamicObject(aabb); } const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); - const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + const glm::vec4 blueCol = glm::vec4(0.1f, 0.05f, 0.95f, 1); + const glm::vec4 cyanCol = glm::vec4(0.1f, 0.9f, 0.85f, 1); + const glm::vec3 boxSize = 0.05f*glm::vec3(1.0f, 1.0f, 1.0f); if (!m_UpdatedOnce) { m_BoxID = world->CreateEntity(); ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); transform["Scale"] = boxSize; + ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); model["Resource"] = "Models/Core/UnitBox.obj"; m_UpdatedOnce = true; @@ -119,21 +190,24 @@ void OctTree::Update(float dt, World* world, Camera* cam) ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); transform["Position"] = boxPos; ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); - //if (BoxCollides(box, AABB())) { - if (Collision::AABBVsAABB(box, aabb)) { + bool collBox = BoxCollides(box, AABB()); + if (collBox) { cam->SetPosition(m_PrevPos); cam->SetOrientation(m_PrevOri); - model["Color"] = greenCol; + bool collRay = RayCollides({ cam->Position(), cam->Forward() }, Output()); + model["Color"] = collRay ? cyanCol : greenCol; + } else if (RayCollides({ cam->Position(), cam->Forward() }, Output())) { + model["Color"] = blueCol; } else { model["Color"] = redCol; } m_PrevPos = cam->Position(); m_PrevOri = cam->Orientation(); - ClearObjects(); + ClearDynamicObjects(); } -bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const +bool OctTree::OctChild::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const { if (hasChildren()) { for (int i : childIndicesContainingBox(boxToTest)) { @@ -141,25 +215,32 @@ bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const return true; } } else { - for (const auto& obj : m_StaticObjects) { - if (Collision::AABBVsAABB(boxToTest, obj)) { - outBoxIntersected = obj; - return true; + for (int i : m_StaticObjIndices) { + if (!m_StaticObjectsRef[i].Checked) { + const AABB& objBox = m_StaticObjectsRef[i].Box; + if (Collision::AABBVsAABB(boxToTest, objBox)) { + outBoxIntersected = objBox; + return true; + } + m_StaticObjectsRef[i].Checked = true; } } - for (const auto& obj : m_DynamicObjects) { - //If there is a collision and it is not testing against itself. - if (!isSameBoxProbably(boxToTest, obj) && - Collision::AABBVsAABB(boxToTest, obj)) { - outBoxIntersected = obj; - return true; + for (int i : m_DynamicObjIndices) { + if (!m_DynamicObjectsRef[i].Checked) { + const AABB& objBox = m_DynamicObjectsRef[i].Box; + if (!isSameBoxProbably(boxToTest, objBox) && + Collision::AABBVsAABB(boxToTest, objBox)) { + outBoxIntersected = objBox; + return true; + } + m_DynamicObjectsRef[i].Checked = true; } } } return false; } -bool OctTree::RayCollides(const Ray& ray, Output& data) const +bool OctTree::OctChild::RayCollides(const Ray& ray, Output& data) const { //If the node AABB is missed, everything it contains is missed. if (Collision::RayAABBIntr(ray, m_Box)) { @@ -182,19 +263,25 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const //Check against boxes in the node. float minDist = INFINITY; bool intersected = false; - for (const auto& obj : m_StaticObjects) { + for (int i : m_StaticObjIndices) { float dist; - if (Collision::RayVsAABB(ray, obj, dist)) { + //If we haven't tested against this object before, and the ray hits. + if (!m_StaticObjectsRef[i].Checked && + Collision::RayVsAABB(ray, m_StaticObjectsRef[i].Box, dist)) { minDist = std::min(dist, minDist); intersected = true; } + m_StaticObjectsRef[i].Checked = true; } - for (const auto& obj : m_DynamicObjects) { + for (int i : m_DynamicObjIndices) { float dist; - if (Collision::RayVsAABB(ray, obj, dist)) { + //If we haven't tested against this object before, and the ray hits. + if (!m_DynamicObjectsRef[i].Checked && + Collision::RayVsAABB(ray, m_DynamicObjectsRef[i].Box, dist)) { minDist = std::min(dist, minDist); intersected = true; } + m_DynamicObjectsRef[i].Checked = true; } data.CollideDistance = minDist; @@ -205,60 +292,84 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const } -void OctTree::AddDynamicObject(const AABB& box) +void OctTree::OctChild::AddDynamicObject(const AABB& box) { if (hasChildren()) { for (auto i : childIndicesContainingBox(box)) { m_Children[i]->AddDynamicObject(box); } } else { - m_DynamicObjects.push_back(box); + //Since it hasn't been added yet to the real object list, the index is after the last =size. + m_DynamicObjIndices.push_back(m_DynamicObjectsRef.size()); } } -void OctTree::AddStaticObject(const AABB& box) +void OctTree::OctChild::AddStaticObject(const AABB& box) { if (hasChildren()) { for (auto i : childIndicesContainingBox(box)) { m_Children[i]->AddStaticObject(box); } } else { - m_StaticObjects.push_back(box); + //Since it hasn't been added yet to the real object list, the index is after the last =size. + m_StaticObjIndices.push_back(m_StaticObjectsRef.size()); } } -void OctTree::BoxesInSameRegion(const AABB& box, std::vector& outBoxes) const +void OctTree::OctChild::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()); + int startIndex = outBoxes.size(); + int numDuplicates = 0; + outBoxes.resize(outBoxes.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size()); + for (size_t i = 0; i < m_StaticObjIndices.size(); ++i){ + ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]]; + if (obj.Checked) { + ++numDuplicates; + } else { + obj.Checked = true; + outBoxes[startIndex + i - numDuplicates] = obj.Box; + } + } + for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) { + ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]]; + if (obj.Checked) { + ++numDuplicates; + } else { + obj.Checked = true; + outBoxes[startIndex + i - numDuplicates] = obj.Box; + } + } + for (size_t i = 0; i < numDuplicates; ++i) { + outBoxes.pop_back(); + } } } -void OctTree::ClearObjects() +void OctTree::OctChild::ClearObjects() { if (hasChildren()) { - for (OctTree*& c : m_Children) { + for (OctChild*& c : m_Children) { c->ClearObjects(); } } else { - m_DynamicObjects.clear(); - m_StaticObjects.clear(); + m_DynamicObjIndices.clear(); + m_StaticObjIndices.clear(); } } -void OctTree::ClearDynamicObjects() +void OctTree::OctChild::ClearDynamicObjects() { if (hasChildren()) { - for (OctTree*& c : m_Children) { + for (OctChild*& c : m_Children) { c->ClearObjects(); } } else { - m_DynamicObjects.clear(); + m_DynamicObjIndices.clear(); } } @@ -274,13 +385,13 @@ void OctTree::ClearDynamicObjects() // x : - - - - + + + + // y : - - + + - - + + // z : - + - + - + - + -int OctTree::childIndexContainingPoint(const glm::vec3& point) const +int OctTree::OctChild::childIndexContainingPoint(const glm::vec3& point) const { const glm::vec3& c = m_Box.Center(); return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); } -std::vector OctTree::childIndicesContainingBox(const AABB& box) const +std::vector OctTree::OctChild::childIndicesContainingBox(const AABB& box) const { int minInd = childIndexContainingPoint(box.MinCorner()); int maxInd = childIndexContainingPoint(box.MaxCorner()); @@ -318,7 +429,7 @@ std::vector OctTree::childIndicesContainingBox(const AABB& box) const } } -inline bool OctTree::hasChildren() const +inline bool OctTree::OctChild::hasChildren() const { return m_Children[0] != nullptr; } \ No newline at end of file From de044dabd3701101682cab8335f60f6fe40b2664 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 10 Dec 2015 16:55:28 +0100 Subject: [PATCH 053/185] Added ConfigFileTests! --- src/Tests/ConfigFileTest.cpp | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/Tests/ConfigFileTest.cpp diff --git a/src/Tests/ConfigFileTest.cpp b/src/Tests/ConfigFileTest.cpp new file mode 100644 index 00000000..f20de79b --- /dev/null +++ b/src/Tests/ConfigFileTest.cpp @@ -0,0 +1,55 @@ +#include +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include //srand + +//#define private public +#include "Engine\Core\ConfigFile.h" + +BOOST_AUTO_TEST_SUITE(confTest) + +BOOST_AUTO_TEST_CASE(configFileTest) +{ + //note: this ConfigFileclass currently has memleaks! + + ResourceManager::RegisterType("ConfigFile"); + auto m_Config = ResourceManager::Load("ConfigTest.ini"); + + //bägge måste vara av samma typ, T typen är string + //http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html + //"Note that we construct the path to the value by separating the individual keys with dots" + + //get from tree tests + auto getSomething = m_Config->Get("Test.Test1", 0); + BOOST_CHECK(getSomething == 423); + + auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string("")); + BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\""); + + //set/get tests + m_Config->Set("Test.4321", 123); + auto getSomething3 = m_Config->Get("Test.4321", 0); + BOOST_CHECK(getSomething3 == 123); + + m_Config->Set("3_2_1_0_5", "t454j54hj5k32"); + auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string("")); + BOOST_CHECK(getSomething4 == "t454j54hj5k32"); + + //***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values! + auto m_Config2 = ResourceManager::Load("ConfigTestNotExists.ini"); + + //set value/savetodisk/load/checkvalue... + m_Config->SaveToDisk(); + m_Config->Set("Test.4321", 145); + m_Config->SaveToDisk(); + auto m_Config3 = ResourceManager::Load("ConfigTest.ini"); + auto getSomething5 = m_Config->Get("Test.4321", 0); + BOOST_CHECK(getSomething5 == 145); + + //reload,onchildreload unimplemented + +} + +BOOST_AUTO_TEST_SUITE_END() + From 58952725e91dad639250ebf70d4ccab47cb64646 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 10 Dec 2015 17:07:18 +0100 Subject: [PATCH 054/185] Added class Package to help refactor the code. The code got easier to read. --- include/Engine/Network/Client.h | 1 + include/Engine/Network/NetworkDefinitions.h | 2 + include/Engine/Network/Package.h | 32 ++++++ include/Engine/Network/Server.h | 4 +- src/Engine/Network/Client.cpp | 89 +++++---------- src/Engine/Network/Package.cpp | 24 ++++ src/Engine/Network/Server.cpp | 115 +++++++++----------- 7 files changed, 138 insertions(+), 129 deletions(-) create mode 100644 include/Engine/Network/Package.h create mode 100644 src/Engine/Network/Package.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 3485736b..26f4489d 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -30,6 +30,7 @@ private: void SendToServer(); int Receive(char* data, size_t length); + void Send(Package& message); int CreateMessage(MessageType type, std::string message, char* data); void Connect(); void Disconnect(); diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index 4ad32e26..8b2ebadf 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -3,6 +3,8 @@ #include #include +#include "Network/Package.h" + #define BOARDSIZE 16 #define MAXCONNECTIONS 8 diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h new file mode 100644 index 00000000..949fc05b --- /dev/null +++ b/include/Engine/Network/Package.h @@ -0,0 +1,32 @@ +#ifndef Package_h__ +#define Package_h__ + +#include +#include "Network/MessageType.h" + +// Defines the +class Package +{ +public: + // arg1: Type of message (Connect, Disconnect...) + // arg2: PackageID for identifying packet loss. + Package(MessageType type); + ~Package(); + // Add primitive types like int, float, char... + template + void AddPrimitive(T val) + { + memcpy(m_Data + m_Offset, &val, sizeof(T)); + m_Offset += sizeof(T); + } + void AddString(std::string str); + + int Size() { return m_Offset; }; + char* Data() { return m_Data; }; + +private: + char* m_Data = new char[128]; + int m_Offset = 0; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 3b476d2a..2826684d 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -47,10 +47,12 @@ private: int Receive(char* data, size_t length); + void Send(Package& package, int playerID); + void Send(Package& package); int CreateMessage(MessageType type, std::string message, char * data); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); void Broadcast(std::string message); - void Broadcast(char* data, size_t length); + void Broadcast(Package& package); void SendSnapshot(); void SendPing(); void CheckForTimeOuts(); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 4f397b5b..73b8b823 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -75,22 +75,14 @@ void Client::ReadFromServer() void Client::SendToServer() { if (m_NextSnapshot.inputForward != "" && m_NextSnapshot.inputForward[0] != '\0') { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputForward, dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - delete[] dataPackage; + Package message(MessageType::Event); + message.AddString(m_NextSnapshot.inputForward); + Send(message); } if (m_NextSnapshot.inputRight != "" && m_NextSnapshot.inputRight[0] != '\0') { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int len = CreateMessage(MessageType::Event, m_NextSnapshot.inputRight, dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - delete[] dataPackage; + Package message(MessageType::Event); + message.AddString(m_NextSnapshot.inputRight); + Send(message); } } @@ -146,16 +138,9 @@ void Client::ParsePing() void Client::ParseServerPing() { - char* testMessage = new char[128]; - int testOffset = CreateMessage(MessageType::ServerPing, "Ping recieved", testMessage); - - //std::cout << "Parsing ping." << std::endl; - - m_Socket.send_to(boost::asio::buffer( - testMessage, - testOffset), - m_ReceiverEndpoint, 0); - delete[] testMessage; + Package message(MessageType::ServerPing); + message.AddString("Ping recieved"); + Send(message); } void Client::ParseEventMessage(char* data, size_t length) @@ -223,59 +208,35 @@ int Client::Receive(char* data, size_t length) return bytesReceived; } -int Client::CreateMessage(MessageType type, std::string message, char* data) +void Client::Send(Package& package) { - int lengthOfMessage = 0; - int messageType = static_cast(type); - lengthOfMessage = message.size(); - - int offset = 0; - // Message type - memcpy(data + offset, &messageType, sizeof(int)); - offset += sizeof(int); - // Message, add one extra byte for null terminator - memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); - offset += (lengthOfMessage + 1) * sizeof(char); - - return offset; + m_Socket.send_to(boost::asio::buffer( + package.Data(), + package.Size()), + m_ReceiverEndpoint, 0); } void Client::Connect() { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int length = CreateMessage(MessageType::Connect, m_PlayerName, dataPackage); - m_StartPingTime = std::clock(); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - length), - m_ReceiverEndpoint, 0); - delete[] dataPackage; + Package message(MessageType::Connect); + message.AddString(m_PlayerName); + m_StartPingTime = std::clock(); + Send(message); } void Client::Disconnect() { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled - int len = CreateMessage(MessageType::Disconnect, "+Disconnect", dataPackage); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - len), - m_ReceiverEndpoint, 0); - delete[] dataPackage; + Package message(MessageType::Connect); + message.AddString("+Disconnect"); + Send(message); } void Client::Ping() { - char* dataPackage = new char[INPUTSIZE]; - if (GetAsyncKeyState('P')) { // Maybe use previous key here - int length = CreateMessage(MessageType::ClientPing, "Ping", dataPackage); - m_StartPingTime = std::clock(); - m_Socket.send_to(boost::asio::buffer( - dataPackage, - length), - m_ReceiverEndpoint, 0); - } - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; + Package message(MessageType::Connect); + message.AddString("Ping"); + m_StartPingTime = std::clock(); + Send(message); } void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp new file mode 100644 index 00000000..eb363aac --- /dev/null +++ b/src/Engine/Network/Package.cpp @@ -0,0 +1,24 @@ +#include "Network/Package.h" + +Package::Package(MessageType type) +{ + // Create message header + // Add message type + int messageType = static_cast(type); + memcpy(m_Data, &messageType, sizeof(int)); + m_Offset += sizeof(int); +} + +Package::~Package() +{ + delete[] m_Data; +} + + + +void Package::AddString(std::string str) +{ + // Message, add one extra byte for null terminator + memcpy(m_Data + m_Offset, str.data(), (str.size() + 1) * sizeof(char)); + m_Offset += (str.size() + 1) * sizeof(char); +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 2dea57f5..fe851ede 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -154,6 +154,24 @@ int Server::Receive(char * data, size_t length) return length; } +void Server::Send(Package& message, int playerID) +{ + m_Socket.send_to( + boost::asio::buffer(message.Data(), message.Size()), + m_PlayerDefinitions[playerID].Endpoint, + 0); +} + +void Server::Send(Package & package) +{ + m_Socket.send_to( + boost::asio::buffer( + package.Data(), + package.Size()), + m_ReceiverEndpoint, + 0); +} + int Server::CreateMessage(MessageType type, std::string message, char * data) { int lengthOfMessage = 0; @@ -183,55 +201,42 @@ void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) void Server::Broadcast(std::string message) { - std::cout << m_PacketID << ": Broadcast: " << message << std::endl; - char* data = new char[128]; - int offset = CreateMessage(MessageType::Event, message, data); + Package package(MessageType::Event); + package.AddPrimitive(12); // Input PackageID here + package.AddString(message); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - m_Socket.send_to( - boost::asio::buffer(data, offset), - m_PlayerDefinitions[i].Endpoint, - 0); + Send(package, i); } } - delete[] data; } -void Server::Broadcast(char * data, size_t length) +void Server::Broadcast(Package& package) { for (int i = 0; i < MAXCONNECTIONS; ++i) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - m_Socket.send_to( - boost::asio::buffer(data, length), - m_PlayerDefinitions[i].Endpoint, - 0); + Send(package, i); } } } void Server::SendSnapshot() { - char* data = new char[INPUTSIZE]; - int offset = CreateHeader(MessageType::Snapshot, data); + Package package(MessageType::Snapshot); + package.AddPrimitive(12); // Input PackageID here for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].EntityID == -1) { continue; } // Pack player pos into data package glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; - memcpy(data + offset, &playerPos.x, sizeof(float)); - offset += sizeof(float); - memcpy(data + offset, &playerPos.y, sizeof(float)); - offset += sizeof(float); - memcpy(data + offset, &playerPos.z, sizeof(float)); - offset += sizeof(float); - // +1 for null terminator - // Pack player name into data package - memcpy(data + offset, m_PlayerDefinitions[i].Name.data(), m_PlayerDefinitions[i].Name.size() + 1); - offset += (m_PlayerDefinitions[i].Name.size() + 1) * sizeof(char); + package.AddPrimitive(playerPos.x); + package.AddPrimitive(playerPos.y); + package.AddPrimitive(playerPos.z); + + package.AddString(m_PlayerDefinitions[i].Name); } - Broadcast(data, offset); - delete[] data; + Broadcast(package); } void Server::SendPing() @@ -244,14 +249,13 @@ void Server::SendPing() } // Create ping message - char* data = new char[128]; - int len = CreateMessage(MessageType::ServerPing, "Ping from server", data); - // Time message + Package package(MessageType::ServerPing); + package.AddPrimitive(12); // Input PackageID here + package.AddString("Ping from server"); + // Time message m_StartPingTime = std::clock(); // Send message - Broadcast(data, len); - delete[] data; - + Broadcast(package); } void Server::CheckForTimeOuts() @@ -358,35 +362,23 @@ void Server::ParseConnect(char * data, size_t length) m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = std::string(data); + // +1 is the null terminator + MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); m_StopTimes[i] = std::clock(); std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; - int offset = 0; - char* temp = new char[sizeof(int) * 2]; - int messagType = 0; - - memcpy(temp, &messagType, sizeof(int)); - offset += sizeof(int); - memcpy(temp + offset, &i, sizeof(int)); - - memcpy(temp, &m_PacketID, sizeof(int)); - offset += sizeof(int); - m_PacketCounter++; - - m_Socket.send_to( - boost::asio::buffer(temp, sizeof(int) * 2), - m_PlayerDefinitions[i].Endpoint, - 0); + Package package(MessageType::Connect); + package.AddPrimitive(12); // Input PackageID here + package.AddPrimitive(i); // Player ID + + Send(package, i); // Send notification that a player has connected std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " + m_PlayerDefinitions[i].Endpoint.address().to_string(); Broadcast(str); - // +1 is the null terminator - MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); - delete[] temp; break; } } @@ -406,18 +398,12 @@ void Server::ParseDisconnect() void Server::ParseClientPing() { - char* testMesssage = new char[128]; - int testOffset = CreateMessage(MessageType::ClientPing, "Ping recieved", testMesssage); - - std::cout << m_PacketID << ":Parsing ping." << std::endl; - // Return ping - m_Socket.send_to( - boost::asio::buffer( - testMesssage, - testOffset), - m_ReceiverEndpoint, - 0); - delete[] testMesssage; + std::cout << m_PacketID << ":Parsing ping." << std::endl; + // Return ping + Package package(MessageType::ClientPing); + package.AddPrimitive(12); // Insert packet ID here + package.AddString("Ping received"); + Send(package); } void Server::ParseServerPing() @@ -430,6 +416,7 @@ void Server::ParseServerPing() } } +// NOT USED void Server::ParseSnapshot(char * data, size_t length) { // Does no logic. Returns snapshot if client request one From c651face4c60815ccb823ea3f24904f82530a67b Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 10 Dec 2015 17:20:47 +0100 Subject: [PATCH 055/185] ConfigFile now has tests covering the whole class --- src/Tests/ConfigFileTest.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tests/ConfigFileTest.cpp b/src/Tests/ConfigFileTest.cpp index f20de79b..558a208d 100644 --- a/src/Tests/ConfigFileTest.cpp +++ b/src/Tests/ConfigFileTest.cpp @@ -47,8 +47,11 @@ BOOST_AUTO_TEST_CASE(configFileTest) auto getSomething5 = m_Config->Get("Test.4321", 0); BOOST_CHECK(getSomething5 == 145); - //reload,onchildreload unimplemented + //***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini" + //***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": + auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); + //reload,onchildreload unimplemented } BOOST_AUTO_TEST_SUITE_END() From d8b1f4e514cb90d9fcef78e0378d65331f9487f4 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 10 Dec 2015 17:46:17 +0100 Subject: [PATCH 056/185] ConfigFileTest attempt to explore the memleaks further --- src/Tests/ConfigFileTest.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Tests/ConfigFileTest.cpp b/src/Tests/ConfigFileTest.cpp index 558a208d..dfcfa527 100644 --- a/src/Tests/ConfigFileTest.cpp +++ b/src/Tests/ConfigFileTest.cpp @@ -7,6 +7,11 @@ using boost::unit_test_framework::test_case; //#define private public #include "Engine\Core\ConfigFile.h" +#define _CRTDBG_MAP_ALLOC +#include +#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) +#define new DEBUG_CLIENTBLOCK + BOOST_AUTO_TEST_SUITE(confTest) BOOST_AUTO_TEST_CASE(configFileTest) @@ -51,7 +56,13 @@ BOOST_AUTO_TEST_CASE(configFileTest) //***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); + //test to try to fix memleaks - failed, probably something else + //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); + //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestNotExists.ini")); + //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); + //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestFailed.ini")); //reload,onchildreload unimplemented + _CrtDumpMemoryLeaks(); } BOOST_AUTO_TEST_SUITE_END() From 37f9ab232223a9aefa31c720d07f0dfd07740246 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 10 Dec 2015 17:53:33 +0100 Subject: [PATCH 057/185] Quick fix for unit test compilation. --- src/Tests/WorldTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 4fd4ceed..8d92a328 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001)) // Loop through them and check data int i = 0; - for (auto& c : w.GetComponents("Test")) { + for (auto& c : *w.GetComponents("Test")) { BOOST_TEST((int)c["TestInteger"] == i); i++; } From 4195baa5dca6a31eca4d83ce7df6a9cfc7eba022 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 10 Dec 2015 17:57:09 +0100 Subject: [PATCH 058/185] ContainedObject in OctTree made private. --- include/Engine/Core/OctTree.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index 2a3b87b2..a3715480 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -14,19 +14,6 @@ public: { float CollideDistance; }; - struct ContainedObject - { - ContainedObject() - : Box(AABB()) - , Checked(false) - {} - ContainedObject(AABB box) - : Box(box) - , Checked(false) - {} - AABB Box; - bool Checked; - }; OctTree(); ~OctTree(); @@ -59,7 +46,20 @@ public: bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected); private: - struct OctChild; + struct OctChild; //Fwd declaration; + struct ContainedObject + { + ContainedObject() + : Box(AABB()) + , Checked(false) + {} + ContainedObject(AABB box) + : Box(box) + , Checked(false) + {} + AABB Box; + bool Checked; + }; OctChild* m_Root; std::vector m_StaticObjects; std::vector m_DynamicObjects; From 01d7388f915004e74647f030e8833ed68b661378 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 11 Dec 2015 11:55:23 +0100 Subject: [PATCH 059/185] Reactored the package loss logic. Server cannot handle multiple clients yet. Fixed WorldTest code by adding astrix. --- include/Engine/Network/Client.h | 3 +- include/Engine/Network/NetworkDefinitions.h | 1 - include/Engine/Network/Package.h | 32 ++++----- include/Engine/Network/Server.h | 17 ++--- src/Engine/Network/Client.cpp | 36 ++++------ src/Engine/Network/Package.cpp | 10 +-- src/Engine/Network/Server.cpp | 73 +++++++-------------- src/Tests/WorldTest.cpp | 2 +- 8 files changed, 70 insertions(+), 104 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 51d66fc8..8e54aabb 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -51,8 +51,9 @@ private: boost::asio::ip::udp::socket m_Socket; // Packet loss logic - unsigned int m_PacketID = 0; + unsigned int m_PacketID = 0; unsigned int m_PreviousPacketID = 0; + unsigned int m_SendPacketID = 0; World* m_World; int m_PlayerID = -1; diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index 88eab7cf..be76671e 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -9,7 +9,6 @@ #define BOARDSIZE 16 #define MAXCONNECTIONS 8 #define INPUTSIZE 128 -#define PACKETMODULUS 1000 // How many packets to send before the number resets #define PLAYERSPEED 0.2f; typedef boost::shared_ptr socket_ptr; diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h index 949fc05b..63409bf0 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Package.h @@ -8,25 +8,25 @@ class Package { public: - // arg1: Type of message (Connect, Disconnect...) - // arg2: PackageID for identifying packet loss. - Package(MessageType type); - ~Package(); - // Add primitive types like int, float, char... - template - void AddPrimitive(T val) - { - memcpy(m_Data + m_Offset, &val, sizeof(T)); - m_Offset += sizeof(T); - } - void AddString(std::string str); + // arg1: Type of message (Connect, Disconnect...) + // arg2: PackageID for identifying packet loss. + Package(MessageType type, unsigned int& packageID); + ~Package(); + // Add primitive types like int, float, char... + template + void AddPrimitive(T val) + { + memcpy(m_Data + m_Offset, &val, sizeof(T)); + m_Offset += sizeof(T); + } + void AddString(std::string str); - int Size() { return m_Offset; }; - char* Data() { return m_Data; }; + int Size() { return m_Offset; }; + char* Data() { return m_Data; }; private: - char* m_Data = new char[128]; - int m_Offset = 0; + char* m_Data = new char[128]; + int m_Offset = 0; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 2826684d..259f47c4 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -32,11 +32,10 @@ private: std::clock_t m_StopTimes[8]; // Game logic World* m_World; - // Packet loss logic - unsigned int m_PacketCounter = 0; - unsigned int m_PacketID = 0; - const unsigned int m_PacketModolus = 1000; - + // Packet loss logic + unsigned int m_PacketID; + unsigned int m_PreviousPacketID; + unsigned int m_SendPacketID; // Close logic bool m_ThreadIsRunning = true; // Threaded @@ -45,18 +44,15 @@ private: void InputLoop(); - int Receive(char* data, size_t length); - void Send(Package& package, int playerID); - void Send(Package& package); - int CreateMessage(MessageType type, std::string message, char * data); + void Send(Package& package, int playerID); + void Send(Package& package); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); void Broadcast(std::string message); void Broadcast(Package& package); void SendSnapshot(); void SendPing(); void CheckForTimeOuts(); - int CreateHeader(MessageType type, char* data); void Disconnect(int i); void ParseMessageType(char* data, size_t length); void ParseEvent(char* data, size_t length); @@ -65,6 +61,7 @@ private: void ParseClientPing(); void ParseServerPing(); void ParseSnapshot(char* data, size_t length); + void IdentifyPacketLoss(); }; #endif diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index f9d20377..c80a6d56 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,7 +6,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } @@ -68,14 +68,13 @@ void Client::ReadFromServer() SendSnapshotToServer(); previousSnapshotMessage = currentTime; } - } } void Client::SendSnapshotToServer() { // Reset previouse key state in snapshot. - Package message(MessageType::Event); + Package message(MessageType::Event, m_SendPacketID); message.AddString(m_NextSnapshot.InputForward); Send(message); m_NextSnapshot.InputRight = ""; @@ -97,12 +96,12 @@ void Client::SendSnapshotToServer() } if (m_NextSnapshot.InputForward != "") { - Package message(MessageType::Event); + Package message(MessageType::Event, m_SendPacketID); message.AddString(m_NextSnapshot.InputForward); Send(message); } if (m_NextSnapshot.InputRight != "") { - Package message(MessageType::Event); + Package message(MessageType::Event, m_SendPacketID); message.AddString(m_NextSnapshot.InputRight); Send(message); } @@ -115,8 +114,8 @@ void Client::ParseMessageType(char* data, size_t length) MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from // Read packet ID - m_PreviousPacketID = m_PacketID; - memcpy(&m_PacketID, data, sizeof(int)); + m_PreviousPacketID = m_PacketID; // Set previous packet id + memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id MoveMessageHead(data, length, sizeof(int)); IdentifyPacketLoss(); @@ -160,7 +159,7 @@ void Client::ParsePing() void Client::ParseServerPing() { - Package message(MessageType::ServerPing); + Package message(MessageType::ServerPing, m_SendPacketID); message.AddString("Ping recieved"); Send(message); //std::cout << "Parsing ping." << std::endl; @@ -228,8 +227,10 @@ int Client::Receive(char* data, size_t length) m_ReceiverEndpoint, 0, error); - std::cout << "ReadFromServer crashed: " << error.message(); - + if (error) { + std::cout << "ReadFromServer crashed: " << error.message(); + } + return bytesReceived; } @@ -243,7 +244,7 @@ void Client::Send(Package& package) void Client::Connect() { - Package message(MessageType::Connect); + Package message(MessageType::Connect, m_SendPacketID); message.AddString(m_PlayerName); m_StartPingTime = std::clock(); Send(message); @@ -251,14 +252,14 @@ void Client::Connect() void Client::Disconnect() { - Package message(MessageType::Connect); + Package message(MessageType::Connect, m_SendPacketID); message.AddString("+Disconnect"); Send(message); } void Client::Ping() { - Package message(MessageType::Connect); + Package message(MessageType::Connect, m_SendPacketID); message.AddString("Ping"); m_StartPingTime = std::clock(); Send(message); @@ -272,22 +273,17 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) bool Client::OnKeyDown(const Events::KeyDown& event) { - char* dataPackage = new char[INPUTSIZE]; // The package that will be sent to the server, when filled if (event.KeyCode == GLFW_KEY_W) { m_IsWASDKeyDown.W = true; - //m_NextSnapshot.inputForward = "+Forward"; } if (event.KeyCode == GLFW_KEY_A) { m_IsWASDKeyDown.A = true; - //m_NextSnapshot.inputRight = "-Right"; } if (event.KeyCode == GLFW_KEY_S) { m_IsWASDKeyDown.S = true; - //m_NextSnapshot.inputForward = "-Forward"; } if (event.KeyCode == GLFW_KEY_D) { m_IsWASDKeyDown.D = true; - //m_NextSnapshot.inputRight = "+Right"; } if (event.KeyCode == GLFW_KEY_V) { @@ -299,8 +295,6 @@ bool Client::OnKeyDown(const Events::KeyDown& event) if (event.KeyCode == GLFW_KEY_P) { Ping(); } - memset(dataPackage, 0, INPUTSIZE); - delete[] dataPackage; return true; } @@ -308,7 +302,6 @@ bool Client::OnKeyUp(const Events::KeyUp & e) { if (e.KeyCode == GLFW_KEY_W) { m_IsWASDKeyDown.W = false; - //m_NextSnapshot.inputForward = ""; return true; } if (e.KeyCode == GLFW_KEY_A){ @@ -321,7 +314,6 @@ bool Client::OnKeyUp(const Events::KeyUp & e) } if (e.KeyCode == GLFW_KEY_D) { m_IsWASDKeyDown.D = false; - //m_NextSnapshot.inputRight = ""; return true; } return false; diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index eb363aac..665d15ce 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -1,12 +1,14 @@ #include "Network/Package.h" -Package::Package(MessageType type) +Package::Package(MessageType type,unsigned int& packageID) { // Create message header // Add message type int messageType = static_cast(type); - memcpy(m_Data, &messageType, sizeof(int)); - m_Offset += sizeof(int); + Package::AddPrimitive(messageType); + packageID = packageID % 1000; // Packet id modulos + Package::AddPrimitive(packageID); + packageID++; } Package::~Package() @@ -14,8 +16,6 @@ Package::~Package() delete[] m_Data; } - - void Package::AddString(std::string str) { // Message, add one extra byte for null terminator diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index fe851ede..494eaaf2 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -119,12 +119,18 @@ void Server::ParseMessageType(char * data, size_t length) memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id + MoveMessageHead(data, length, sizeof(int)); + IdentifyPacketLoss(); + switch (static_cast(messageType)) { case MessageType::Connect: ParseConnect(data, length); break; case MessageType::ClientPing: - ParseClientPing(); + //ParseClientPing(); break; case MessageType::ServerPing: ParseServerPing(); @@ -172,27 +178,6 @@ void Server::Send(Package & package) 0); } -int Server::CreateMessage(MessageType type, std::string message, char * data) -{ - int lengthOfMessage = 0; - int offset = 0; - - lengthOfMessage = message.size(); - // Message type - memcpy(data + offset, &type, sizeof(int)); - offset += sizeof(int); - // Packet ID - m_PacketID = m_PacketCounter % PACKETMODULUS; - memcpy(data + offset, &m_PacketID, sizeof(int)); - offset += sizeof(int); - // Message, add one extra byte for null terminator - memcpy(data + offset, message.data(), (lengthOfMessage + 1) * sizeof(char)); - offset += (lengthOfMessage + 1) * sizeof(char); - - m_PacketCounter++; - return offset; -} - void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) { data += stepSize; @@ -201,8 +186,7 @@ void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) void Server::Broadcast(std::string message) { - Package package(MessageType::Event); - package.AddPrimitive(12); // Input PackageID here + Package package(MessageType::Event, m_SendPacketID); package.AddString(message); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { @@ -222,8 +206,7 @@ void Server::Broadcast(Package& package) void Server::SendSnapshot() { - Package package(MessageType::Snapshot); - package.AddPrimitive(12); // Input PackageID here + Package package(MessageType::Snapshot, m_SendPacketID); for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].EntityID == -1) { continue; @@ -249,8 +232,7 @@ void Server::SendPing() } // Create ping message - Package package(MessageType::ServerPing); - package.AddPrimitive(12); // Input PackageID here + Package package(MessageType::ServerPing, m_SendPacketID); package.AddString("Ping from server"); // Time message m_StartPingTime = std::clock(); @@ -277,20 +259,6 @@ void Server::CheckForTimeOuts() } } -int Server::CreateHeader(MessageType type, char * data) -{ - int messageType = static_cast(type); - int offset = 0; - memcpy(data, &messageType, sizeof(int)); - offset += sizeof(int); - m_PacketID = m_PacketCounter % PACKETMODULUS; - memcpy(data + offset, &m_PacketID, sizeof(int)); - offset += sizeof(int); - m_PacketCounter++; - - return offset; -} - void Server::Disconnect(int i) { Broadcast("A player disconnected"); @@ -369,8 +337,7 @@ void Server::ParseConnect(char * data, size_t length) std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; - Package package(MessageType::Connect); - package.AddPrimitive(12); // Input PackageID here + Package package(MessageType::Connect, m_SendPacketID); package.AddPrimitive(i); // Player ID Send(package, i); @@ -400,10 +367,9 @@ void Server::ParseClientPing() { std::cout << m_PacketID << ":Parsing ping." << std::endl; // Return ping - Package package(MessageType::ClientPing); - package.AddPrimitive(12); // Insert packet ID here + Package package(MessageType::ClientPing, m_SendPacketID); package.AddString("Ping received"); - Send(package); + Send(package); // This dosen't work for multiple users } void Server::ParseServerPing() @@ -429,4 +395,15 @@ void Server::ParseSnapshot(char * data, size_t length) 0); } } -} \ No newline at end of file +} + +void Server::IdentifyPacketLoss() +{ + // if no packets lost, difference should be equal to 1 + int difference = m_PacketID - m_PreviousPacketID; + if (difference != 1) { + for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) { + LOG_INFO("Packet %i was lost...", i); + } + } +} diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 4fd4ceed..8d92a328 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001)) // Loop through them and check data int i = 0; - for (auto& c : w.GetComponents("Test")) { + for (auto& c : *w.GetComponents("Test")) { BOOST_TEST((int)c["TestInteger"] == i); i++; } From 350038057d5273b16f016fc4df7a684516a87124 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 11 Dec 2015 13:51:07 +0100 Subject: [PATCH 060/185] Misc OctTreeTest changes --- src/Engine/Core/OctTree.cpp | 2 +- src/Tests/OctTreeTest.cpp | 4 +- src/Tests/OctTreeTestGameClass.cpp | 10 ++--- src/Tests/OctTreeTestHardCodedTestWorld.h | 49 +++++++++++------------ 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 63eba63e..aae9762a 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -163,7 +163,7 @@ OctTree::OctChild::~OctChild() void OctTree::Update(float dt, World* world, Camera* cam) { - for (ComponentWrapper& c : world->GetComponents("Collision")) { + for (ComponentWrapper& c : *world->GetComponents("Collision")) { AABB aabb; aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); AddDynamicObject(aabb); diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 23a09fcd..71d41cad 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -30,8 +30,8 @@ BOOST_AUTO_TEST_CASE(octTreeTest) BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); //simple OctTree constructor check - OctTree someOctTree(someAABB, 5); - BOOST_CHECK(someOctTree.m_Children[0] != nullptr); + //OctTree someOctTree(someAABB, 5); + //BOOST_CHECK(someOctTree.m_Children[0] != nullptr); //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure } diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 6b2e23bc..735d3ee8 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -57,7 +57,7 @@ void Game::Tick() m_Renderer->Update(dt); m_EventBroker->Swap(); -#define TEST2 +#define TEST1 //this draws the octTree and you can set the cube inside it and see what boxes in the tree that it belongs to #ifdef TEST1 if (!m_UpdatedOnce) { @@ -81,13 +81,13 @@ void Game::Tick() //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! std::vector boxIndex; - boxIndex = m_World->someOctTree.childIndicesContainingBox(boxi); + boxIndex = m_World->someOctTree.m_Root->childIndicesContainingBox(boxi); for (auto& oneLinkedObject : m_World->linkOM) { ComponentWrapper model = m_World->GetComponent(oneLinkedObject.entId, "Model"); model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); - if (oneLinkedObject.child->m_DynamicObjects.size() != 0) { + if (oneLinkedObject.child->m_DynamicObjIndices.size() != 0) { model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); } @@ -95,7 +95,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_Children[someBoxIndex]->m_Box.Center(); + glm::vec3 pos = m_World->someOctTree.m_Root->m_Children[someBoxIndex]->m_Box.Center(); 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) { @@ -122,7 +122,7 @@ void Game::Tick() aabb.CreateFromCenter(glm::vec3(0, 2.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f)); if (m_UpdatedOnce) { - auto test = someOctTree.childIndicesContainingBox(aabb); + //auto test = someOctTree.childIndicesContainingBox(aabb); std::vector test2; someOctTree.BoxesInSameRegion(aabb, test2); } diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index a0762cce..46b1e00b 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -15,9 +15,9 @@ class HardcodedTestWorld : public World public: struct LinkOctTreeAndModel { EntityID entId; - OctTree* child; + OctTree::OctChild* child; glm::vec3 posxyz; - LinkOctTreeAndModel(EntityID eId, OctTree* ch, glm::vec3 pos) + LinkOctTreeAndModel(EntityID eId, OctTree::OctChild* ch, glm::vec3 pos) { entId = eId; child = ch; @@ -76,7 +76,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, tempId); + AddBoxModel(someAABB.Center(), 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)); @@ -84,15 +84,15 @@ private: someOctTree.AddDynamicObject(anotherBox); //draw anotherbox and save it in anotherBoxTransformId - AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, &someOctTree, anotherBoxTransformId); + AddBoxModel(anotherBox.Center(), anotherBox.HalfSize().x, someOctTree.m_Root, anotherBoxTransformId); //draw the octTree for (size_t j = 0; j < 8; j++) { - AddBoxModel(someOctTree.m_Children[j]->m_Box.Center(), - someOctTree.m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Children[j], tempId); + AddBoxModel(someOctTree.m_Root->m_Children[j]->m_Box.Center(), + someOctTree.m_Root->m_Children[j]->m_Box.HalfSize().x, someOctTree.m_Root->m_Children[j], tempId); - auto someChild = someOctTree.m_Children[j]; + auto someChild = someOctTree.m_Root->m_Children[j]; for (size_t i = 0; i < 8; i++) { @@ -103,24 +103,6 @@ private: } }//end CreateEnt - void AddBoxModel(const glm::vec3 ¢er, const float &halfSize, OctTree* child, EntityID &outEntityId) { - World& world = *this; - - EntityID entityDummyScene = world.CreateEntity(); - outEntityId = entityDummyScene; - ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform"); - transform["Position"] = center; - transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f*0.97f; - ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); - model["Resource"] = "Models/Core/UnitBox.obj"; - model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); - if (child->m_DynamicObjects.size() != 0) - model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); - - linkOM.emplace_back(entityDummyScene, child, center); - //extra - //allModels.push_back(model); - } void createTestEntitiesTest2() { World& world = *this; @@ -131,4 +113,21 @@ private: ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model"); model["Resource"] = "Models/Core/UnitBox.obj"; } + + void AddBoxModel(const glm::vec3 ¢er, const float &halfSize, OctTree::OctChild* child, EntityID &outEntityId) { + World& world = *this; + + EntityID entityDummyScene = world.CreateEntity(); + outEntityId = entityDummyScene; + ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform"); + transform["Position"] = center; + transform["Scale"] = glm::vec3(1.0f, 1.0f, 1.0f)*halfSize*2.0f*0.97f; + ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + model["Color"] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + if (child->m_DynamicObjIndices.size() != 0) + model["Color"] = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + + linkOM.emplace_back(entityDummyScene, child, center); + } }; \ No newline at end of file From 81034420a9cb9502bc24cc06f95f0ff2f69e940e Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 11 Dec 2015 16:04:30 +0100 Subject: [PATCH 061/185] Put back old version of OctTree for testing, made unit tests. Tests shows the old version checks for collisions etc. faster, new version adds objects into tree faster, and doesn't give duplicated results. --- src/Engine/Core/OctTree.cpp | 2 +- src/Tests/OctTreeTest.cpp | 135 ++++++++++++++- src/Tests/OldOctTree.cpp | 328 ++++++++++++++++++++++++++++++++++++ src/Tests/OldOctTree.h | 69 ++++++++ 4 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 src/Tests/OldOctTree.cpp create mode 100644 src/Tests/OldOctTree.h diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 63eba63e..aae9762a 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -163,7 +163,7 @@ OctTree::OctChild::~OctChild() void OctTree::Update(float dt, World* world, Camera* cam) { - for (ComponentWrapper& c : world->GetComponents("Collision")) { + for (ComponentWrapper& c : *world->GetComponents("Collision")) { AABB aabb; aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); AddDynamicObject(aabb); diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 47036485..d9ba2e86 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -2,7 +2,9 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include //srand -#include +#include "Engine/Core/OctTree.h" +#include "Engine/Core/Ray.h" +#include "OldOctTree.h" BOOST_AUTO_TEST_SUITE(octTreeTests) @@ -36,5 +38,136 @@ BOOST_AUTO_TEST_CASE(octSameRegionTest) BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().z, firstQuadrant.HalfSize().z, 0.00001f); } +const int LEVEL_BOUNDS = 500; +const int MAXSIZE = 50; +const int BOXES = 400; +const int NUM_DYNAMICS = 0; +const int NUM_STATICS = BOXES - NUM_DYNAMICS; +const int SEED = 6548; +const int TEST_FRAMES = 1; //300 +const int NUM_FUNCTION_LOOPS = 1; //25 +const int TESTS = 1; //10 + +template +void RegionTest(Tree& tree) +{ + AABB aabb; + aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS), + glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE)); + std::vector outVec; + tree.BoxesInSameRegion(aabb, outVec); +} + +template +void RayTest(Tree& tree) +{ + Tree::Output data; + glm::vec3 rayStart = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); + glm::vec3 rayEnd = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); + tree.RayCollides({ rayStart , glm::normalize(rayEnd - rayStart) }, data); +} + +template +void BoxTest(Tree& tree) +{ + AABB outBox; + AABB aabb; + aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS), + glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE)); + tree.BoxCollides(aabb, outBox); +} + +template +void NopTest(Tree& tree) +{ + +} + +template +void TestLoop(TestFunction xTest) +{ + srand(SEED); + glm::vec3 mini = glm::vec3(0, 0, 0); + glm::vec3 maxi = glm::vec3(LEVEL_BOUNDS, LEVEL_BOUNDS, LEVEL_BOUNDS); + Tree tree(AABB(mini, maxi), 3); + AABB aabb; + glm::vec3 center; + glm::vec3 size; + for (int t = 0; t < TESTS; ++t) { + for (int i = 0; i < NUM_STATICS; ++i) { + center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); + size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE); + aabb.CreateFromCenter(center, size); + tree.AddStaticObject(aabb); + } + for (int fr = 0; fr < TEST_FRAMES; ++fr) { + for (int i = 0; i < NUM_DYNAMICS; ++i) { + center = glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS); + size = glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE); + aabb.CreateFromCenter(center, size); + tree.AddDynamicObject(aabb); + } + + for (int fl = 0; fl < NUM_FUNCTION_LOOPS; ++fl) { + xTest(tree); + } + + tree.ClearDynamicObjects(); + } + tree.ClearObjects(); + } + int asda = 0; + asda = 123; + BOOST_CHECK(asda == 123); +} + +BOOST_AUTO_TEST_CASE(octRegionPerfTestWithDuplicates) +{ + TestLoop(RegionTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octRegionPerfTestNoDuplicates) +{ + TestLoop(RegionTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octBoxPerfTestWithDuplicates) +{ + TestLoop(BoxTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octBoxPerfTestNoDuplicates) +{ + TestLoop(BoxTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octRayPerfTestWithDuplicates) +{ + TestLoop(RayTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octRayPerfTestNoDuplicates) +{ + TestLoop(RayTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octNopPerfTestWithDuplicates) +{ + TestLoop(NopTest); + BOOST_CHECK(true); +} + +BOOST_AUTO_TEST_CASE(octNopPerfTestNoDuplicates) +{ + TestLoop(NopTest); + BOOST_CHECK(true); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/Tests/OldOctTree.cpp b/src/Tests/OldOctTree.cpp new file mode 100644 index 00000000..72decd4d --- /dev/null +++ b/src/Tests/OldOctTree.cpp @@ -0,0 +1,328 @@ +#include +#include +#include + +#include "OldOctTree.h" +#include "Core/Collision.h" +#include "Core/World.h" +#include "Rendering/Camera.h" + +namespace Old +{ + +namespace +{ +//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 isSameBoxProbably(const AABB& first, const AABB& second) +{ + const float EPS = 0.0001f; + const auto& ma = first.MaxCorner(); + const auto& mi = first.MinCorner(); + return (std::abs(ma.x - mi.x) < EPS) && + (std::abs(ma.z - mi.z) < EPS) && + (std::abs(ma.y - mi.y) < EPS); +} + +} + +OctTree::OctTree() + : OctTree(AABB(), 0) +{} + +OctTree::OctTree(const AABB& octTreeBounds, int subDivisions) + : m_Box(octTreeBounds) + , m_UpdatedOnce(false) +{ + if (subDivisions == 0) { + for (OctTree*& c : m_Children) { + c = nullptr; + } + } else { + --subDivisions; + 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 { + 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 { + minPos.y = parentMin.y; + maxPos.y = parentCenter.y; + } + //If child is 1,3,5,7 + if (bits.test(0)) { + minPos.z = parentCenter.z; + maxPos.z = parentMax.z; + } else { + minPos.z = parentMin.z; + maxPos.z = parentCenter.z; + } + m_Children[i] = new OctTree(AABB(minPos, maxPos), subDivisions); + } + } +} + +OctTree::~OctTree() +{ + for (OctTree*& c : m_Children) { + if (c != nullptr) { + delete c; + c = nullptr; + } + } +} + +void OctTree::Update(float dt, World* world, Camera* cam) +{ + AABB aabb; + for (ComponentWrapper& c : *world->GetComponents("Collision")) { + aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); + AddStaticObject(aabb); + } + const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); + const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); + const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f); + + if (!m_UpdatedOnce) { + m_BoxID = world->CreateEntity(); + ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); + transform["Scale"] = boxSize; + ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); + model["Resource"] = "Models/Core/UnitBox.obj"; + m_UpdatedOnce = true; + } + + AABB box; + auto boxPos = cam->Position() + 1.2f*cam->Forward(); + box.CreateFromCenter(boxPos, boxSize); + ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); + transform["Position"] = boxPos; + ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); + //if (BoxCollides(box, AABB())) { + if (Collision::AABBVsAABB(box, aabb)) { + cam->SetPosition(m_PrevPos); + cam->SetOrientation(m_PrevOri); + model["Color"] = greenCol; + } else { + model["Color"] = redCol; + } + + m_PrevPos = cam->Position(); + m_PrevOri = cam->Orientation(); + ClearObjects(); +} + +bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const +{ + if (hasChildren()) { + for (int i : childIndicesContainingBox(boxToTest)) { + if (m_Children[i]->BoxCollides(boxToTest, outBoxIntersected)) + return true; + } + } else { + for (const auto& obj : m_StaticObjects) { + if (Collision::AABBVsAABB(boxToTest, obj)) { + outBoxIntersected = obj; + return true; + } + } + for (const auto& obj : m_DynamicObjects) { + //If there is a collision and it is not testing against itself. + if (!isSameBoxProbably(boxToTest, obj) && + Collision::AABBVsAABB(boxToTest, obj)) { + outBoxIntersected = obj; + return true; + } + } + } + return false; +} + +bool OctTree::RayCollides(const Ray& ray, Output& data) const +{ + //If the node AABB is missed, everything it contains is missed. + if (Collision::RayAABBIntr(ray, m_Box)) { + //If the ray shoots the tree, and it is a parent to 8 children :o + if (hasChildren()) { + //Sort children according to their distance from the ray origin. + 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()) }); + } + 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. + for (const ChildInfo& info : childInfos) { + if (m_Children[info.Index]->RayCollides(ray, data)) { + return true; + } + } + } else { + //Check against boxes in the node. + float minDist = INFINITY; + bool intersected = false; + for (const auto& obj : m_StaticObjects) { + float dist; + if (Collision::RayVsAABB(ray, obj, dist)) { + minDist = std::min(dist, minDist); + intersected = true; + } + } + for (const auto& obj : m_DynamicObjects) { + float dist; + if (Collision::RayVsAABB(ray, obj, dist)) { + minDist = std::min(dist, minDist); + intersected = true; + } + } + + data.CollideDistance = minDist; + return intersected; + } + } + return false; +} + + +void OctTree::AddDynamicObject(const AABB& box) +{ + if (hasChildren()) { + for (auto i : childIndicesContainingBox(box)) { + m_Children[i]->AddDynamicObject(box); + } + } else { + m_DynamicObjects.push_back(box); + } +} + +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->ClearObjects(); + } + } else { + m_DynamicObjects.clear(); + m_StaticObjects.clear(); + } +} + +void OctTree::ClearDynamicObjects() +{ + if (hasChildren()) { + for (OctTree*& c : m_Children) { + c->ClearObjects(); + } + } else { + m_DynamicObjects.clear(); + } +} + +//: 3 7 +//: +//: 2 6 +//: | +//: 1 5 \ y +//: z +//: 0 4 0 x--> +// +// child: 0 1 2 3 4 5 6 7 +// x : - - - - + + + + +// y : - - + + - - + + +// z : - + - + - + - + +int OctTree::childIndexContainingPoint(const glm::vec3& point) const +{ + const glm::vec3& c = m_Box.Center(); + return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z); +} + +std::vector OctTree::childIndicesContainingBox(const AABB& box) const +{ + int minInd = childIndexContainingPoint(box.MinCorner()); + int maxInd = childIndexContainingPoint(box.MaxCorner()); + //Because of the predictable ordering of the child indices, + //the number of bits set when xor:ing the indices will determine the number of children containing the box. + std::bitset<3> bits(minInd ^ maxInd); + switch (bits.count()) { + //Box contained completely in one child. + case 0: + return{ minInd }; + //Two children. + case 1: + return{ minInd, maxInd }; + //Four children. + case 2: + { + std::vector ret; + //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(); + //At this point the bits necessarily have exactly one bit set. + for (int c = 0; c < 8; ++c) { + //If the child index have the same bit set as the bits, add box to it. + if (bits.to_ulong() & c) { + ret.push_back(c); + } + } + return ret; + } + case 3: //Eight children. + return{ 0,1,2,3,4,5,6,7 }; + default: + return std::vector(); + } +} + +inline bool OctTree::hasChildren() const +{ + return m_Children[0] != nullptr; +} +} \ No newline at end of file diff --git a/src/Tests/OldOctTree.h b/src/Tests/OldOctTree.h new file mode 100644 index 00000000..2e37b739 --- /dev/null +++ b/src/Tests/OldOctTree.h @@ -0,0 +1,69 @@ +#ifndef OldOctTree_h__ +#define OldOctTree_h__ + +#include "Core/AABB.h" + +struct Ray; +class World; +class Camera; + +namespace Old +{ + +class OctTree +{ +public: + struct Output + { + float CollideDistance; + }; + OctTree(); + ~OctTree(); + //For the root OctTree, [octTreeBounds] should be a box containing the entire level. + OctTree(const AABB& octTreeBounds, int subDivisions); + + //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(); + + //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? + void Update(float dt, World* world, Camera* cam); + //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. + //On collision with a box, that box is written to [outBoxIntersected]. + //Note: More efficient than calling BoxesInSameRegion from outside and testing there. + bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const; + +private: + OctTree* m_Children[8]; + //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. + std::vector m_StaticObjects; + std::vector m_DynamicObjects; + AABB m_Box; + + bool m_UpdatedOnce; + unsigned int m_BoxID; + glm::vec3 m_PrevPos; + glm::quat m_PrevOri; + + inline bool hasChildren() const; + int childIndexContainingPoint(const glm::vec3& point) const; + std::vector childIndicesContainingBox(const AABB& box) const; +}; + +} + +#endif \ No newline at end of file From b3bb0e543f666f31c1021efe063d477e3d29243f Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 11 Dec 2015 16:17:23 +0100 Subject: [PATCH 062/185] Added EventBroker Test from the other project --- include/Engine/Core/InputController.h | 3 +- src/Engine/Core/EventBroker.cpp | 2 +- src/Tests/EventFixture.h | 54 +++++++++++++++++++++++++++ src/Tests/EventTest.cpp | 19 ++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/Tests/EventFixture.h create mode 100644 src/Tests/EventTest.cpp diff --git a/include/Engine/Core/InputController.h b/include/Engine/Core/InputController.h index b91fb448..919d0e6e 100644 --- a/include/Engine/Core/InputController.h +++ b/include/Engine/Core/InputController.h @@ -17,7 +17,8 @@ public: virtual void Initialize() { - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand); + EVENT_SUBSCRIBE_MEMBER( + _EInputCommand, &InputController::OnCommand); EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &InputController::OnMouseMove); } diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index 76c243e8..c12f915f 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -1,4 +1,4 @@ -#include "Core/EventBroker.h" +#include "Core\EventBroker.h" BaseEventRelay::~BaseEventRelay() { diff --git a/src/Tests/EventFixture.h b/src/Tests/EventFixture.h new file mode 100644 index 00000000..42258932 --- /dev/null +++ b/src/Tests/EventFixture.h @@ -0,0 +1,54 @@ +#ifndef EVENTFIXTURE_H +#define EVENTFIXTURE_H + +#include +#include "Core\EventBroker.h" + +template +struct EventFixture +{ + EventFixture() + { + this->ventBroker = new EventBroker(); + m_EEventType = decltype(m_EEventType)(std::bind(&EventFixture::OnEvent, this, std::placeholders::_1)); + this->ventBroker->Subscribe(m_EEventType); + Run(); + Check(); + } + ~EventFixture() + { + this->ventBroker->Unsubscribe(m_EEventType); + delete this->ventBroker; + } + + EventBroker* ventBroker = nullptr; + EventRelay m_EEventType; + bool m_EventRecieved = false; + EventType Before; + EventType After; + + bool OnEvent(const EventType& event) + { + m_EventRecieved = true; + After = event; + + return true; + } + + void Run() + { + // Publish the event + this->ventBroker->Publish(Before); + // Clear to swap buffers + this->ventBroker->Swap(); + // Process the event + this->ventBroker->template Process(); + } + + void Check() + { + BOOST_CHECK(m_EventRecieved); + } +}; + +#endif \ No newline at end of file diff --git a/src/Tests/EventTest.cpp b/src/Tests/EventTest.cpp new file mode 100644 index 00000000..4a030055 --- /dev/null +++ b/src/Tests/EventTest.cpp @@ -0,0 +1,19 @@ +#include +#include "EventFixture.h" + +struct ETestEvent : public Event +{ + int Int = 5; + float Float = 1.33333f; + double Double = 1.33333; + std::string String = "Hello World"; +}; + +BOOST_AUTO_TEST_CASE(EventBrokerTest) +{ + EventFixture f; + BOOST_CHECK(f.Before.Int == f.After.Int); + BOOST_CHECK_CLOSE(f.Before.Float, f.After.Float, 0.00001f); + BOOST_CHECK_CLOSE(f.Before.Double, f.After.Double, 0.00001f); + BOOST_CHECK(f.Before.String == f.After.String); +} \ No newline at end of file From 36ae451ea62c2f9067794e7f431dcdc59a55da31 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 11 Dec 2015 16:22:14 +0100 Subject: [PATCH 063/185] Indentation --- src/Engine/Network/Client.cpp | 103 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index c80a6d56..f3840caf 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,9 +6,9 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); - m_NextSnapshot.InputForward = ""; - m_NextSnapshot.InputRight = ""; + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_NextSnapshot.InputForward = ""; + m_NextSnapshot.InputRight = ""; } Client::~Client() @@ -74,9 +74,9 @@ void Client::ReadFromServer() void Client::SendSnapshotToServer() { // Reset previouse key state in snapshot. - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputForward); - Send(message); + Package message(MessageType::Event, m_SendPacketID); + message.AddString(m_NextSnapshot.InputForward); + Send(message); m_NextSnapshot.InputRight = ""; m_NextSnapshot.InputRight = ""; // See if any movement keys are down @@ -96,14 +96,14 @@ void Client::SendSnapshotToServer() } if (m_NextSnapshot.InputForward != "") { - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputForward); - Send(message); + Package message(MessageType::Event, m_SendPacketID); + message.AddString(m_NextSnapshot.InputForward); + Send(message); } if (m_NextSnapshot.InputRight != "") { - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputRight); - Send(message); + Package message(MessageType::Event, m_SendPacketID); + message.AddString(m_NextSnapshot.InputRight); + Send(message); } } @@ -113,11 +113,11 @@ void Client::ParseMessageType(char* data, size_t length) memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from - // Read packet ID - m_PreviousPacketID = m_PacketID; // Set previous packet id - memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id - MoveMessageHead(data, length, sizeof(int)); - IdentifyPacketLoss(); + // Read packet ID + m_PreviousPacketID = m_PacketID; // Set previous packet id + memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id + MoveMessageHead(data, length, sizeof(int)); + IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: @@ -146,22 +146,22 @@ void Client::ParseMessageType(char* data, size_t length) void Client::ParseConnect(char* data, size_t len) { - memcpy(&m_PacketID, data, sizeof(int)); - m_PreviousPacketID = m_PacketID; - std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; + memcpy(&m_PacketID, data, sizeof(int)); + m_PreviousPacketID = m_PacketID; + std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } void Client::ParsePing() { m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - std::cout << m_PacketID << ": response time with ctime(ms): " << m_DurationOfPingTime << std::endl; + std::cout << m_PacketID << ": response time with ctime(ms): " << m_DurationOfPingTime << std::endl; } void Client::ParseServerPing() { - Package message(MessageType::ServerPing, m_SendPacketID); - message.AddString("Ping recieved"); - Send(message); + Package message(MessageType::ServerPing, m_SendPacketID); + message.AddString("Ping recieved"); + Send(message); //std::cout << "Parsing ping." << std::endl; } @@ -176,7 +176,7 @@ void Client::ParseEventMessage(char* data, size_t length) // Sett Player name m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { - std::cout << m_PacketID << ": Event message: " << std::string(data) << std::endl; + std::cout << m_PacketID << ": Event message: " << std::string(data) << std::endl; } MoveMessageHead(data, length, std::string(data).size() + 1); @@ -184,7 +184,7 @@ void Client::ParseEventMessage(char* data, size_t length) void Client::ParseSnapshot(char* data, size_t length) { - std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; + std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, @@ -226,7 +226,7 @@ int Client::Receive(char* data, size_t length) ::asio::buffer((void*)data, length), m_ReceiverEndpoint, 0, error); - + if (error) { std::cout << "ReadFromServer crashed: " << error.message(); } @@ -236,33 +236,33 @@ int Client::Receive(char* data, size_t length) void Client::Send(Package& package) { - m_Socket.send_to(boost::asio::buffer( - package.Data(), - package.Size()), - m_ReceiverEndpoint, 0); + m_Socket.send_to(boost::asio::buffer( + package.Data(), + package.Size()), + m_ReceiverEndpoint, 0); } void Client::Connect() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString(m_PlayerName); - m_StartPingTime = std::clock(); - Send(message); + Package message(MessageType::Connect, m_SendPacketID); + message.AddString(m_PlayerName); + m_StartPingTime = std::clock(); + Send(message); } void Client::Disconnect() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString("+Disconnect"); - Send(message); + Package message(MessageType::Connect, m_SendPacketID); + message.AddString("+Disconnect"); + Send(message); } void Client::Ping() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString("Ping"); - m_StartPingTime = std::clock(); - Send(message); + Package message(MessageType::Connect, m_SendPacketID); + message.AddString("Ping"); + m_StartPingTime = std::clock(); + Send(message); } void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) @@ -304,11 +304,11 @@ bool Client::OnKeyUp(const Events::KeyUp & e) m_IsWASDKeyDown.W = false; return true; } - if (e.KeyCode == GLFW_KEY_A){ + if (e.KeyCode == GLFW_KEY_A) { m_IsWASDKeyDown.A = false; return true; } - if (e.KeyCode == GLFW_KEY_S){ + if (e.KeyCode == GLFW_KEY_S) { m_IsWASDKeyDown.S = false; return true; } @@ -329,12 +329,11 @@ void Client::CreateNewPlayer(int i) void Client::IdentifyPacketLoss() { - // if no packets lost, difference should be equal to 1 - int difference = m_PacketID - m_PreviousPacketID; - if (difference != 1) { - for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) - { - LOG_INFO("Packet %i was lost...", i); - } - } + // if no packets lost, difference should be equal to 1 + int difference = m_PacketID - m_PreviousPacketID; + if (difference != 1) { + for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) { + LOG_INFO("Packet %i was lost...", i); + } + } } From 9a7d77f29d400a405c885ab1ce16183f97ee6a56 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 11 Dec 2015 16:44:49 +0100 Subject: [PATCH 064/185] Removed notes in OldOctTree. --- src/Tests/OldOctTree.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Tests/OldOctTree.h b/src/Tests/OldOctTree.h index 2e37b739..316b9545 100644 --- a/src/Tests/OldOctTree.h +++ b/src/Tests/OldOctTree.h @@ -36,7 +36,7 @@ public: void ClearObjects(); void ClearDynamicObjects(); - //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? + //Collision test function. void Update(float dt, World* world, Camera* cam); //Returns true if the ray collides with something in the tree. Result is written to [data]. bool RayCollides(const Ray& ray, Output& data) const; @@ -47,9 +47,6 @@ public: private: OctTree* m_Children[8]; - //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. std::vector m_StaticObjects; std::vector m_DynamicObjects; AABB m_Box; From 55aad493ff5d009740e0d2013028b3b805ac4630 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 11 Dec 2015 16:45:38 +0100 Subject: [PATCH 065/185] Fixed warnings in OctTree. Cleaned unit tests. --- src/Engine/Core/OctTree.cpp | 6 +++--- src/Tests/OctTreeTest.cpp | 9 +++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index aae9762a..e41a1692 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -300,7 +300,7 @@ void OctTree::OctChild::AddDynamicObject(const AABB& box) } } else { //Since it hasn't been added yet to the real object list, the index is after the last =size. - m_DynamicObjIndices.push_back(m_DynamicObjectsRef.size()); + m_DynamicObjIndices.push_back((int)m_DynamicObjectsRef.size()); } } @@ -312,7 +312,7 @@ void OctTree::OctChild::AddStaticObject(const AABB& box) } } else { //Since it hasn't been added yet to the real object list, the index is after the last =size. - m_StaticObjIndices.push_back(m_StaticObjectsRef.size()); + m_StaticObjIndices.push_back((int)m_StaticObjectsRef.size()); } } @@ -323,7 +323,7 @@ void OctTree::OctChild::BoxesInSameRegion(const AABB& box, std::vector& ou m_Children[i]->BoxesInSameRegion(box, outBoxes); } } else { - int startIndex = outBoxes.size(); + size_t startIndex = outBoxes.size(); int numDuplicates = 0; outBoxes.resize(outBoxes.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size()); for (size_t i = 0; i < m_StaticObjIndices.size(); ++i){ diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index d9ba2e86..efd2d109 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -44,9 +44,9 @@ const int BOXES = 400; const int NUM_DYNAMICS = 0; const int NUM_STATICS = BOXES - NUM_DYNAMICS; const int SEED = 6548; -const int TEST_FRAMES = 1; //300 -const int NUM_FUNCTION_LOOPS = 1; //25 -const int TESTS = 1; //10 +const int TEST_FRAMES = 300; +const int NUM_FUNCTION_LOOPS = 25; +const int TESTS = 0; //10 template void RegionTest(Tree& tree) @@ -116,9 +116,6 @@ void TestLoop(TestFunction xTest) } tree.ClearObjects(); } - int asda = 0; - asda = 123; - BOOST_CHECK(asda == 123); } BOOST_AUTO_TEST_CASE(octRegionPerfTestWithDuplicates) From 11e37ca8981258dd6ae4eee58f738f6ebe06f63a Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 14 Dec 2015 10:42:45 +0100 Subject: [PATCH 066/185] Added functions to test ray vs triangle- and model-intersections. --- include/Engine/Core/Collision.h | 28 +++++++++++- src/Engine/Core/Collision.cpp | 77 ++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/Engine/Core/Collision.h b/include/Engine/Core/Collision.h index b23b33cc..87f521bd 100644 --- a/include/Engine/Core/Collision.h +++ b/include/Engine/Core/Collision.h @@ -1,17 +1,43 @@ #ifndef Collision_h__ #define Collision_h__ +#include + #include "Core/Ray.h" #include "Core/AABB.h" +#include "Engine/Rendering/RawModel.h" namespace Collision { - +//Return true if the ray hits the box. bool RayAABBIntr(const Ray& ray, const AABB& box); bool RayVsAABB(const Ray& ray, const AABB& box); +//Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance]. bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); +//Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected. +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices); +//Return true if the ray hits any of the triangles in the model. +//Also returns the position of the intersection point. Will loop through all the whole model indices. +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + glm::vec3& outHitPosition); +//Return true if the ray hits any of the triangles in the model. +//Also returns the distance from the ray origin to the closest +//intersection point, and the barycentric u,v-coordinates. Will loop through all the whole model indices. +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + float& outDistance, + float& outUCoord, + float& outVCoord); + +//Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); + } #endif \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index 07e37085..dee567e0 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -1,6 +1,7 @@ +#include + #include "Core/Collision.h" #include "Engine/GLM.h" -#include namespace Collision { @@ -74,4 +75,76 @@ bool AABBVsAABB(const AABB& a, const AABB& b) return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); } -} \ No newline at end of file +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices) +{ + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction, e2); + float DetInv = 1.0f / glm::dot(e1, DxE2); + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction, MxE1) * DetInv; + if (u < 0 && v < 0 && 1 < u + v) { + continue; + } + //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. + if (0 <= glm::dot(e2, MxE1) * DetInv) { + return true; + } + } + return false; +} + +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + float& outDistance, + float& outUCoord, + float& outVCoord) +{ + outDistance = INFINITY; + bool hit = false; + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction, e2); + float DetInv = 1.0f / glm::dot(e1, DxE2); + float dist = glm::dot(e2, MxE1) * DetInv; + if (dist >= outDistance) { + continue; + } + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction, MxE1) * DetInv; + //If u and v are positive, u+v <= 1, dist is positive, and less than closest. + if (0 <= u && 0 <= v && u + v <= 1 && 0 <= dist) { + outDistance = dist; + outUCoord = u; + outVCoord = v; + hit = true; + } + } + return hit; +} + +bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + glm::vec3& outHitPosition) +{ + float u; + float v; + float dist; + bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); + outHitPosition = ray.Origin + dist * ray.Direction; + return hit; +} + +} From 5f5cab11714d0ff258ee4e98feeb922a0cf79903 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 10:55:49 +0100 Subject: [PATCH 067/185] Added Tests for ResourceManager --- src/Tests/ResourceManagerTest.cpp | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/Tests/ResourceManagerTest.cpp diff --git a/src/Tests/ResourceManagerTest.cpp b/src/Tests/ResourceManagerTest.cpp new file mode 100644 index 00000000..e05d8563 --- /dev/null +++ b/src/Tests/ResourceManagerTest.cpp @@ -0,0 +1,56 @@ +#include + +#include "Core/World.h" + +//#define private public +#include "Core/ResourceManager.h" + +#include "Core/ConfigFile.h" + +#include "Rendering/Renderer.h" +#include "Core/EntityXMLFile.h" +#include "Engine\Rendering\Texture.h" + +//#include "Core/EventBroker.h" +//#include "Core/InputManager.h" +//#include "GUI/Frame.h" +//#include "Rendering/RenderQueueFactory.h" +//#include "Core/EKeyDown.h" +//#include "Core/SystemPipeline.h" +//#include "RaptorCopterSystem.h" + + +BOOST_AUTO_TEST_SUITE(resourceManagerTests) + +BOOST_AUTO_TEST_CASE(resourceManagerTest) +{ + World m_World; + + //private static metoder/variabler + + //ugly private->public hack doesnt work, tons of link errors. hence cant test it properly + //its not my job to implement testfunctions for unittests in the class either + + //craptests ahead: + ResourceManager::RegisterType("ConfigFile"); + BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); + auto m_Config = ResourceManager::Load("Config.ini"); + BOOST_CHECK(ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); + ResourceManager::Release("ConfigFile", "Config.ini"); + BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); + + //configfile without register + //check so output says "EE failed to load: type not registered..." + auto m_ScreenQuadNoRegister = ResourceManager::Load("Models/Core/ScreenQuad.obj"); + BOOST_CHECK(!ResourceManager::IsResourceLoaded("Model", "Models/Core/ScreenQuad.obj")); + + //there is no error feedback to check if you try to release the wrong resources - hence that cant be tested either + + //registertype (bind with function) + //m_CompilerTypenameToResourceType = global... + //m_FactoryFunctions = global... + //BOOST_CHECK(ResourceManager::m_CompilerTypenameToResourceType.size() != 0); + //BOOST_CHECK(ResourceManager::m_FactoryFunctions.size() != 0); +} + +BOOST_AUTO_TEST_SUITE_END() From bf08ffe392144c0508e92f02edd2f8d5a6418cf9 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 11:02:23 +0100 Subject: [PATCH 068/185] Added InputManagerTest --- src/Tests/InputManagerTest.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/Tests/InputManagerTest.cpp diff --git a/src/Tests/InputManagerTest.cpp b/src/Tests/InputManagerTest.cpp new file mode 100644 index 00000000..5b447c2b --- /dev/null +++ b/src/Tests/InputManagerTest.cpp @@ -0,0 +1,12 @@ +#include + +#include "Engine\Core\InputManager.h" + +BOOST_AUTO_TEST_SUITE(inputManagerTests) + +BOOST_AUTO_TEST_CASE(inputManagerTest) +{ + //already tested eventbroker so inputManager is indirectly already tested +} + +BOOST_AUTO_TEST_SUITE_END() From 5fce7490a9d547e37d673d78f1c714ea5e6dc718 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 11:57:18 +0100 Subject: [PATCH 069/185] MergeFix OctTree williambranch and andersbranch --- src/Tests/OctTreeTest.cpp | 45 ++----------------- src/Tests/OctTreeTestAnders.cpp | 53 +++++++++++++++++++++++ src/Tests/OctTreeTestGameClass.h | 1 + src/Tests/OctTreeTestHardCodedTestWorld.h | 1 + 4 files changed, 58 insertions(+), 42 deletions(-) create mode 100644 src/Tests/OctTreeTestAnders.cpp diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index 68aa4c7a..0206ce50 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -2,51 +2,12 @@ using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; #include //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 -//#include "Engine/Core/OctTree.h" + +#include "Engine/Core/OctTree.h" #include "Engine/Core/Ray.h" #include "OldOctTree.h" -//friend class and refactoringIntoNewClass is some extra work and needs to be updated when the original class is updated, and can contain bugs that -//isnt in the original class -//Reflection-inspection seems to be only available for C# -//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 -BOOST_AUTO_TEST_SUITE(octTreeTests) - -BOOST_AUTO_TEST_CASE(octTreeTest) -{ - //white box testing - //http://softwaretestingfundamentals.com/differences-between-black-box-testing-and-white-box-testing/ - //http://technologyconversations.com/2013/12/11/black-box-vs-white-box-testing/ - - //simple AABB constructor check - 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); - BOOST_CHECK(someAABB.MinCorner() == minCorner); - BOOST_CHECK(someAABB.MaxCorner() == maxCorner); - BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); - - //simple OctTree constructor check - //OctTree someOctTree(someAABB, 5); - //BOOST_CHECK(someOctTree.m_Children[0] != nullptr); - - //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure -} - -BOOST_AUTO_TEST_CASE(octTreeTest2) -{ - //octtree ritningen osv - Game game(0, nullptr); - while (game.Running()) { - game.Tick(); - } -} +BOOST_AUTO_TEST_SUITE(octTreeTestsW) BOOST_AUTO_TEST_CASE(octSameRegionTest) { diff --git a/src/Tests/OctTreeTestAnders.cpp b/src/Tests/OctTreeTestAnders.cpp new file mode 100644 index 00000000..12a122ea --- /dev/null +++ b/src/Tests/OctTreeTestAnders.cpp @@ -0,0 +1,53 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; +#include //srand + +//#define private public//HACK! Needed for white box testing +//#include "Engine/Core/OctTree.h" +//#include "OldOctTree.h" +//friend class and refactoringIntoNewClass is some extra work and needs to be updated when the original class is updated, and can contain bugs that +//isnt in the original class +//Reflection-inspection seems to be only available for C# +//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 + +#include "OctTreeTestGameClass.h" + +#define private public//HACK! Needed for white box testing +#include +//else we would have to "open up" the octTree class more with get/sets, public methods, etc. which is not good encapsulation-wise + +BOOST_AUTO_TEST_SUITE(octTreeTestsA) + +BOOST_AUTO_TEST_CASE(octTreeTest) +{ + //white box testing + //http://softwaretestingfundamentals.com/differences-between-black-box-testing-and-white-box-testing/ + //http://technologyconversations.com/2013/12/11/black-box-vs-white-box-testing/ + + //simple AABB constructor check + 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); + BOOST_CHECK(someAABB.MinCorner() == minCorner); + BOOST_CHECK(someAABB.MaxCorner() == maxCorner); + BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); + + //simple OctTree constructor check + //OctTree someOctTree(someAABB, 5); + //BOOST_CHECK(someOctTree.m_Children[0] != nullptr); + + //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure +} + +BOOST_AUTO_TEST_CASE(octTreeTest2) +{ + //octtree ritningen osv + Game game(0, nullptr); + while (game.Running()) { + game.Tick(); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h index 8ca34510..38aaab66 100644 --- a/src/Tests/OctTreeTestGameClass.h +++ b/src/Tests/OctTreeTestGameClass.h @@ -13,6 +13,7 @@ #include "OctTreeTestHardCodedTestWorld.h" #include "Core\Collision.h" + class Game { public: diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h index 46b1e00b..512716df 100644 --- a/src/Tests/OctTreeTestHardCodedTestWorld.h +++ b/src/Tests/OctTreeTestHardCodedTestWorld.h @@ -7,6 +7,7 @@ #include //last! +//#include "OldOctTree.h" #define private public #include From 63db236dfac94b45a65edbd35d102bfadde48203 Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 14 Dec 2015 16:35:43 +0100 Subject: [PATCH 070/185] Fixed bug which made the player not able to move diagonally. Fixed a bug were m_PlayerID was not set for the client when connecting. --- include/Engine/Network/SnapshotDefinitions.h | 4 +- src/Engine/Network/Client.cpp | 16 +-- src/Engine/Network/Server.cpp | 140 +++++++++---------- 3 files changed, 79 insertions(+), 81 deletions(-) diff --git a/include/Engine/Network/SnapshotDefinitions.h b/include/Engine/Network/SnapshotDefinitions.h index 2b4ba948..9fe8beca 100644 --- a/include/Engine/Network/SnapshotDefinitions.h +++ b/include/Engine/Network/SnapshotDefinitions.h @@ -4,9 +4,9 @@ struct SnapshotDefinitions { // "+Forward" is 8 characters * sizeof(char) = 8 - char* InputForward = new char[8]; + std::string InputForward; // "+Right" is 6 characters * sizeof(char) = 6 - char* InputRight = new char[6]; + std::string InputRight; }; struct IsWASDKeyDown diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index c80a6d56..b393a2c2 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -77,19 +77,19 @@ void Client::SendSnapshotToServer() Package message(MessageType::Event, m_SendPacketID); message.AddString(m_NextSnapshot.InputForward); Send(message); - m_NextSnapshot.InputRight = ""; + m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; // See if any movement keys are down // We dont care if it's overwritten by later // if statement. Watcha gonna do, right! if (m_IsWASDKeyDown.W) { - m_NextSnapshot.InputRight = "+Forward"; + m_NextSnapshot.InputForward = "+Forward"; } if (m_IsWASDKeyDown.A) { m_NextSnapshot.InputRight = "-Right"; } if (m_IsWASDKeyDown.S) { - m_NextSnapshot.InputRight = "-Forward"; + m_NextSnapshot.InputForward = "-Forward"; } if (m_IsWASDKeyDown.D) { m_NextSnapshot.InputRight = "+Right"; @@ -148,6 +148,9 @@ void Client::ParseConnect(char* data, size_t len) { memcpy(&m_PacketID, data, sizeof(int)); m_PreviousPacketID = m_PacketID; + MoveMessageHead(data, len, sizeof(int)); + memcpy(&m_PlayerID, data, sizeof(int)); + MoveMessageHead(data, len, sizeof(int)); std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } @@ -184,7 +187,7 @@ void Client::ParseEventMessage(char* data, size_t length) void Client::ParseSnapshot(char* data, size_t length) { - std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; + //std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, @@ -332,9 +335,6 @@ void Client::IdentifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) - { - LOG_INFO("Packet %i was lost...", i); - } + LOG_INFO("%i Packet(s) were lost...", difference); } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 494eaaf2..92eb28f6 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -1,12 +1,10 @@ #include "Network/Server.h" Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 13)) -{ -} +{ } Server::~Server() -{ -} +{ } void Server::Start(World* world) @@ -27,7 +25,7 @@ void Server::Start(World* world) } void Server::Close() -{ +{ m_ThreadIsRunning = false; } @@ -49,12 +47,12 @@ void Server::ReadFromClients() int snapshotInterval = 50; int timeToCheckTimeOutTime = 100; - while(m_ThreadIsRunning) { + while (m_ThreadIsRunning) { // m_ThreadIsRunning might be unnecessary but the // program crashed if it executed m_Socket.available() // when closing the program. - // If available message -> Socket.available() = true + // If available message -> Socket.available() = true if (m_ThreadIsRunning && m_Socket.available()) { try { bytesRead = Receive(readBuf, INPUTSIZE); @@ -66,25 +64,25 @@ void Server::ReadFromClients() //} } } - std::clock_t currentTime = std::clock(); - // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendSnapshot(); - previousSnapshotMessage = currentTime; - } + std::clock_t currentTime = std::clock(); + // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + SendSnapshot(); + previousSnapshotMessage = currentTime; + } - // Send pings each - if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - SendPing(); - previousePingMessage = currentTime; - } + // Send pings each + if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + SendPing(); + previousePingMessage = currentTime; + } - // Time out logic - if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - CheckForTimeOuts(); - timOutTimer = currentTime; - } + // Time out logic + if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + CheckForTimeOuts(); + timOutTimer = currentTime; + } } } @@ -162,20 +160,20 @@ int Server::Receive(char * data, size_t length) void Server::Send(Package& message, int playerID) { - m_Socket.send_to( - boost::asio::buffer(message.Data(), message.Size()), - m_PlayerDefinitions[playerID].Endpoint, - 0); + m_Socket.send_to( + boost::asio::buffer(message.Data(), message.Size()), + m_PlayerDefinitions[playerID].Endpoint, + 0); } void Server::Send(Package & package) { - m_Socket.send_to( - boost::asio::buffer( - package.Data(), - package.Size()), - m_ReceiverEndpoint, - 0); + m_Socket.send_to( + boost::asio::buffer( + package.Data(), + package.Size()), + m_ReceiverEndpoint, + 0); } void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) @@ -186,11 +184,11 @@ void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) void Server::Broadcast(std::string message) { - Package package(MessageType::Event, m_SendPacketID); - package.AddString(message); + Package package(MessageType::Event, m_SendPacketID); + package.AddString(message); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - Send(package, i); + Send(package, i); } } } @@ -199,27 +197,27 @@ void Server::Broadcast(Package& package) { for (int i = 0; i < MAXCONNECTIONS; ++i) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - Send(package, i); + Send(package, i); } } } void Server::SendSnapshot() { - Package package(MessageType::Snapshot, m_SendPacketID); - for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].EntityID == -1) { - continue; - } - // Pack player pos into data package - glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; - package.AddPrimitive(playerPos.x); - package.AddPrimitive(playerPos.y); - package.AddPrimitive(playerPos.z); + Package package(MessageType::Snapshot, m_SendPacketID); + for (size_t i = 0; i < MAXCONNECTIONS; i++) { + if (m_PlayerDefinitions[i].EntityID == -1) { + continue; + } + // Pack player pos into data package + glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + package.AddPrimitive(playerPos.x); + package.AddPrimitive(playerPos.y); + package.AddPrimitive(playerPos.z); - package.AddString(m_PlayerDefinitions[i].Name); + package.AddString(m_PlayerDefinitions[i].Name); } - Broadcast(package); + Broadcast(package); } void Server::SendPing() @@ -232,9 +230,9 @@ void Server::SendPing() } // Create ping message - Package package(MessageType::ServerPing, m_SendPacketID); - package.AddString("Ping from server"); - // Time message + Package package(MessageType::ServerPing, m_SendPacketID); + package.AddString("Ping from server"); + // Time message m_StartPingTime = std::clock(); // Send message Broadcast(package); @@ -264,9 +262,9 @@ void Server::Disconnect(int i) Broadcast("A player disconnected"); std::cout << "Player " << i << " disconnected/Timed out" << std::endl; - // Remove enteties and stuff + // Remove enteties and stuff m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); - m_PlayerDefinitions[i].EntityID = -1; + m_PlayerDefinitions[i].EntityID = -1; m_PlayerDefinitions[i].Name = ""; } @@ -293,13 +291,13 @@ void Server::ParseEvent(char * data, size_t length) temp.z += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } - + if ("+Right" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.x += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } - + if ("-Right" == std::string(data)) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.x -= 0.1f; @@ -310,7 +308,7 @@ void Server::ParseEvent(char * data, size_t length) void Server::ParseConnect(char * data, size_t length) { std::cout << "Parsing connection." << std::endl; - + // Check if player is already connected for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { return; @@ -319,7 +317,7 @@ void Server::ParseConnect(char * data, size_t length) for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { - + m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); @@ -330,20 +328,20 @@ void Server::ParseConnect(char * data, size_t length) m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = std::string(data); - // +1 is the null terminator - MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); + // +1 is the null terminator + MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); m_StopTimes[i] = std::clock(); std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; - Package package(MessageType::Connect, m_SendPacketID); - package.AddPrimitive(i); // Player ID - - Send(package, i); + Package package(MessageType::Connect, m_SendPacketID); + package.AddPrimitive(i); // Player ID + + Send(package, i); // Send notification that a player has connected - std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " + std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " + m_PlayerDefinitions[i].Endpoint.address().to_string(); Broadcast(str); break; @@ -365,11 +363,11 @@ void Server::ParseDisconnect() void Server::ParseClientPing() { - std::cout << m_PacketID << ":Parsing ping." << std::endl; - // Return ping - Package package(MessageType::ClientPing, m_SendPacketID); - package.AddString("Ping received"); - Send(package); // This dosen't work for multiple users + std::cout << m_PacketID << ":Parsing ping." << std::endl; + // Return ping + Package package(MessageType::ClientPing, m_SendPacketID); + package.AddString("Ping received"); + Send(package); // This dosen't work for multiple users } void Server::ParseServerPing() From e52052b4313c728a5c3d2176ff1edbead1f11adf Mon Sep 17 00:00:00 2001 From: Jocke Date: Mon, 14 Dec 2015 16:50:16 +0100 Subject: [PATCH 071/185] IdentifyPacketLoss() crashed when multiple users connected which also crashed the server. The function is not needed for now as the server logic is not implemented. --- src/Engine/Network/Server.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 92eb28f6..fe9454fd 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -121,7 +121,7 @@ void Server::ParseMessageType(char * data, size_t length) m_PreviousPacketID = m_PacketID; // Set previous packet id memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id MoveMessageHead(data, length, sizeof(int)); - IdentifyPacketLoss(); + //IdentifyPacketLoss(); // crashed when it started to spam! switch (static_cast(messageType)) { case MessageType::Connect: @@ -400,8 +400,6 @@ void Server::IdentifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - for (int i = m_PreviousPacketID + 1; i < m_PacketID; i++) { - LOG_INFO("Packet %i was lost...", i); - } + LOG_INFO("%i Packet(s) were lost...", difference); } } From bac0a1de26a05914d7d9c38a533b3fbbef028d18 Mon Sep 17 00:00:00 2001 From: stiffly Date: Mon, 14 Dec 2015 16:55:23 +0100 Subject: [PATCH 072/185] Removed annoying cube --- resources/Schema/Entities/Test.xml | 4 ++-- src/Engine/Network/Client.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 4b8fb132..1aa59961 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -31,7 +31,7 @@ - + diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index d145cbbf..8c8ae5fd 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,7 +6,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } From 7f8e78c8cdeedcfb794b75b4cba3b00f583941ea Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 17:04:35 +0100 Subject: [PATCH 073/185] RayVsModel tests in progress --- src/Engine/Core/Collision.cpp | 13 +++-- src/Tests/CMakeLists.txt | 1 + src/Tests/CollisionTest.cpp | 95 ++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index dee567e0..44875aa4 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -86,10 +86,14 @@ bool RayVsModel(const Ray& ray, glm::vec3 m = ray.Origin - v0; glm::vec3 MxE1 = glm::cross(m, e1); glm::vec3 DxE2 = glm::cross(ray.Direction, e2); - float DetInv = 1.0f / glm::dot(e1, DxE2); + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } + DetInv = 1.0f / DetInv; float u = glm::dot(m, DxE2) * DetInv; float v = glm::dot(ray.Direction, MxE1) * DetInv; - if (u < 0 && v < 0 && 1 < u + v) { + if (u < 0 || v < 0 || 1 < u + v) { continue; } //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. @@ -116,7 +120,10 @@ bool RayVsModel(const Ray& ray, glm::vec3 m = ray.Origin - v0; glm::vec3 MxE1 = glm::cross(m, e1); glm::vec3 DxE2 = glm::cross(ray.Direction, e2); - float DetInv = 1.0f / glm::dot(e1, DxE2); + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } float dist = glm::dot(e2, MxE1) * DetInv; if (dist >= outDistance) { continue; diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt index 697dea29..a3f95a37 100644 --- a/src/Tests/CMakeLists.txt +++ b/src/Tests/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories( ) file(GLOB SOURCE_FILES + "*.h" "*.cpp" ) diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index eef24e61..497812a3 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -3,11 +3,18 @@ #include using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; -#include +#include "Engine\Core\Collision.h" #include "Engine/Core/AABB.h" #include "Engine/Core/Ray.h" #include //srand #include "Engine/Core/OctTree.h" +//vs model +#include + +//ray vs model +#include "Engine\Core\ResourceManager.h" +#include "Engine\Rendering\Model.h" +#include "Engine\Core\Ray.h" //vs memleaks //#define _CRTDBG_MAP_ALLOC @@ -87,6 +94,92 @@ BOOST_AUTO_TEST_CASE(collisionTest2) BOOST_CHECK(test >= 0); } +BOOST_AUTO_TEST_CASE(rayVsModelTest) +{ + //simple test + + Ray ray; + ray.Origin = glm::vec3(-50, 0, 0); + //ray.Direction = glm::vec3(-1, 0, 0); + ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + //inte model, det kräver renderar grejs tydligen + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); + BOOST_CHECK(unitBox != nullptr); + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(hit); + ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(!hit); +} + +BOOST_AUTO_TEST_CASE(rayVsModelTest2) +{ + //advanced test, based on ray vs AABB + srand(7676762); + Ray ray; + AABB someAABB; + glm::vec3 minPos; + glm::vec3 maxPos; + bool z; + int test = 0; + minPos = glm::vec3(-0.5f, -0.5f, -0.5f); + maxPos = glm::vec3(0.5f, 0.5f, 0.5f); + someAABB = AABB(minPos, maxPos); + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); + BOOST_CHECK(unitBox != nullptr); + + 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; + ray.Origin /= 100; + ray.Origin = glm::vec3(-2, 0, 0); + ray.Direction /= 100; + ray.Direction = glm::normalize(ray.Direction); + + z = Collision::RayVsAABB(ray, someAABB); + if (z) { + //hit + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + if (!hit) { + hit = hit; + glm::vec3 outtttttttt; + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + } + else { + hit = hit; + } + BOOST_CHECK(hit); + } + // + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + if (hit) { + //hit + z = Collision::RayVsAABB(ray, someAABB); + if (!z) { + z = z; + z = Collision::RayVsAABB(ray, someAABB); + glm::vec3 outtttttttt; + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + } + else { + z = z; + } + BOOST_CHECK(hit); + } + + } +} + + BOOST_AUTO_TEST_CASE(octTest) { glm::vec3 mini = glm::vec3(-1, -1, -1); From 59095c2ce50b85f864d57eedb38d0a5da0224cde Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 14 Dec 2015 17:08:00 +0100 Subject: [PATCH 074/185] Started on CollisionSystem and TriggerSystem. Moved collision code to Collision folder. --- .../Engine/{Core => Collision}/Collision.h | 0 include/Engine/Collision/CollisionSystem.h | 30 ++++++++++++++ include/Engine/Collision/ETrigger.h | 39 +++++++++++++++++++ include/Engine/Collision/TriggerSystem.h | 23 +++++++++++ resources/Schema/Components.xsd | 2 + resources/Schema/Components/AABB.xml | 4 ++ resources/Schema/Components/AABB.xsd | 14 +++++++ resources/Schema/Components/Trigger.xml | 2 + resources/Schema/Components/Trigger.xsd | 8 ++++ src/Engine/{Core => Collision}/Collision.cpp | 0 src/Engine/Collision/CollisionSystem.cpp | 16 ++++++++ src/Engine/Collision/TriggerSystem.cpp | 22 +++++++++++ src/Game/Game.cpp | 4 +- 13 files changed, 162 insertions(+), 2 deletions(-) rename include/Engine/{Core => Collision}/Collision.h (100%) create mode 100644 include/Engine/Collision/CollisionSystem.h create mode 100644 include/Engine/Collision/ETrigger.h create mode 100644 include/Engine/Collision/TriggerSystem.h create mode 100644 resources/Schema/Components/AABB.xml create mode 100644 resources/Schema/Components/AABB.xsd create mode 100644 resources/Schema/Components/Trigger.xml create mode 100644 resources/Schema/Components/Trigger.xsd rename src/Engine/{Core => Collision}/Collision.cpp (100%) create mode 100644 src/Engine/Collision/CollisionSystem.cpp create mode 100644 src/Engine/Collision/TriggerSystem.cpp diff --git a/include/Engine/Core/Collision.h b/include/Engine/Collision/Collision.h similarity index 100% rename from include/Engine/Core/Collision.h rename to include/Engine/Collision/Collision.h diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h new file mode 100644 index 00000000..1aecfacc --- /dev/null +++ b/include/Engine/Collision/CollisionSystem.h @@ -0,0 +1,30 @@ +#ifndef CollisionSystem_h__ +#define CollisionSystem_h__ + +#include +#include + +#include "Common.h" +#include "Core/System.h" +#include "Core/EventBroker.h" +#include "Core/EKeyUp.h" + +class CollisionSystem : public System +{ +public: + CollisionSystem(EventBroker* eventBroker) + : System(eventBroker, "AABB") + { + //TODO: Debug stuff, remove later. + EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); + } + + virtual void Update(World* world, ComponentWrapper& collision, double dt) override; + +private: + + EventRelay m_EKeyUp; + bool OnKeyUp(const Events::KeyUp &event); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Collision/ETrigger.h b/include/Engine/Collision/ETrigger.h new file mode 100644 index 00000000..aaa5ef06 --- /dev/null +++ b/include/Engine/Collision/ETrigger.h @@ -0,0 +1,39 @@ +#ifndef Events_TriggerEnter_h__ +#define Events_TriggerEnter_h__ + +#include "../Core/EventBroker.h" +#include "../Core/Entity.h" + +namespace Events +{ + +/** Thrown once, when an entity is completely inside a trigger. */ +struct TriggerTouch : Event +{ + /** The id of the entity that touches the trigger. */ + EntityID Entity; + /** The id of the trigger entity. */ + EntityID Trigger; +}; + +/** Thrown once, when an entity has completely left a trigger. */ +struct TriggerLeave : Event +{ + /** The id of the entity that left the trigger. */ + EntityID Entity; + /** The id of the trigger entity. */ + EntityID Trigger; +}; + +/** Thrown when an entity is completely inside a trigger. */ +struct TriggerEnter : Event +{ + /** The id of the entity that entered the trigger. */ + EntityID Entity; + /** The id of the trigger entity. */ + EntityID Trigger; +}; + +} + +#endif diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h new file mode 100644 index 00000000..94084ee3 --- /dev/null +++ b/include/Engine/Collision/TriggerSystem.h @@ -0,0 +1,23 @@ +#ifndef PlayerSystem_h__ +#define PlayerSystem_h__ + +#include + +#include "Core/System.h" +#include "Core/EventBroker.h" +#include "ETrigger.h" + +class TriggerSystem : public System +{ +public: + TriggerSystem(EventBroker* eventBroker) + : System(eventBroker, "Trigger") + {} + + virtual void Update(World* world, ComponentWrapper& collision, double dt) override; + +private: + +}; + +#endif \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 12fb870e..fd04fd39 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -6,4 +6,6 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/AABB.xml b/resources/Schema/Components/AABB.xml new file mode 100644 index 00000000..341d1d0d --- /dev/null +++ b/resources/Schema/Components/AABB.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AABB.xsd b/resources/Schema/Components/AABB.xsd new file mode 100644 index 00000000..8fac860e --- /dev/null +++ b/resources/Schema/Components/AABB.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Trigger.xml b/resources/Schema/Components/Trigger.xml new file mode 100644 index 00000000..4c8aad58 --- /dev/null +++ b/resources/Schema/Components/Trigger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/Trigger.xsd b/resources/Schema/Components/Trigger.xsd new file mode 100644 index 00000000..a8bc8865 --- /dev/null +++ b/resources/Schema/Components/Trigger.xsd @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Collision/Collision.cpp similarity index 100% rename from src/Engine/Core/Collision.cpp rename to src/Engine/Collision/Collision.cpp diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp new file mode 100644 index 00000000..d1657361 --- /dev/null +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -0,0 +1,16 @@ +#include "Collision/CollisionSystem.h" + + +void CollisionSystem::Update(World * world, ComponentWrapper & collision, double dt) +{ + m_EventBroker->Process(); + (glm::vec3&)collision["Center"] = (glm::vec3)world->GetComponent(collision.EntityID, "Transform")["Position"]; +} + +bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) +{ + if (event.KeyCode == GLFW_KEY_Z) { + + } + return false; +} diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp new file mode 100644 index 00000000..4b6c0de4 --- /dev/null +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -0,0 +1,22 @@ +#include "Collision/TriggerSystem.h" +#include "Core/AABB.h" + +void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) +{ + auto players = world->GetComponents("Player"); + if (players == nullptr) { + return; + } + //WTODO: Assumes box exists. + ComponentWrapper& cBox = world->GetComponent(trigger.EntityID, "AABB"); + AABB aabb; + aabb.CreateFromCenter(cBox["BoxCenter"], cBox["BoxSize"]); + for (auto& c : *players) { + + Events::TriggerEnter e; + e.Trigger = trigger.EntityID; + e.Entity = 41; + m_EventBroker->Publish(e); + } +} + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index fa12bbc6..1070d2fa 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,4 +1,5 @@ #include "Game.h" +#include "Collision/TriggerSystem.h" Game::Game(int argc, char* argv[]) { @@ -46,8 +47,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline = new SystemPipeline(m_EventBroker); m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - - + m_SystemPipeline->AddSystem(); m_LastTime = glfwGetTime(); From 7c714d1f985f80be5696be6802469757b8b4fe29 Mon Sep 17 00:00:00 2001 From: Tleety Date: Mon, 14 Dec 2015 17:35:01 +0100 Subject: [PATCH 075/185] Changed some error handling in the RenderState class. --- src/Engine/Rendering/RenderState.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Engine/Rendering/RenderState.cpp b/src/Engine/Rendering/RenderState.cpp index 87f4a30d..2d183b32 100644 --- a/src/Engine/Rendering/RenderState.cpp +++ b/src/Engine/Rendering/RenderState.cpp @@ -9,7 +9,7 @@ bool RenderState::Enable(GLenum GLEnable) { if(glIsEnabled(GLEnable)) { - LOG_WARNING("Trying to enable somthing that is already enabled."); + //LOG_WARNING("Trying to enable somthing that is already enabled."); return false; } m_Enables.push_back(GLEnable); @@ -25,17 +25,11 @@ bool RenderState::CullFace(GLenum GLCullFace) { if(!glIsEnabled(GL_CULL_FACE)) { - LOG_ERROR("Setting GL_CULL_FACE without enabling it."); - return false; + //LOG_ERROR("Setting GL_CULL_FACE without enabling it."); + Enable(GL_CULL_FACE); } - GLint a; - glGetIntegerv(GL_CULL_FACE_MODE, &a); - if(a != GL_BACK) - { - //LOG_INFO("Setting Cullface to back, unessesary since this is already default."); - glCullFace(GLCullFace); - } + glCullFace(GLCullFace); if (GLERROR("RenderState::CullFace")) { return false; From ae7d4b90979bf901160da16bfce4cdea3fa0aa16 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 14 Dec 2015 17:35:39 +0100 Subject: [PATCH 076/185] Put Collision folder in CMakeLists.txt and altered paths. --- include/Engine/Collision/TriggerSystem.h | 7 ++++--- src/Engine/CMakeLists.txt | 7 +++++++ src/Engine/Collision/Collision.cpp | 2 +- src/Engine/Core/OctTree.cpp | 2 +- src/Tests/CollisionTest.cpp | 2 +- src/Tests/OctTreeTestGameClass.cpp | 2 +- src/Tests/OctTreeTestGameClass.h | 2 +- src/Tests/OctTreeTestGameMain.cpp | 2 +- src/Tests/OldOctTree.cpp | 2 +- 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index 94084ee3..a7b2122f 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -1,7 +1,8 @@ -#ifndef PlayerSystem_h__ -#define PlayerSystem_h__ +#ifndef TriggerSystem_h__ +#define TriggerSystem_h__ #include +#include #include "Core/System.h" #include "Core/EventBroker.h" @@ -17,7 +18,7 @@ public: virtual void Update(World* world, ComponentWrapper& collision, double dt) override; private: - + std::unordered_map> m_EntitiesInTrigger; }; #endif \ No newline at end of file diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index de24b9cf..915cdee2 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -70,6 +70,12 @@ file(GLOB SOURCE_FILES_GUI ) source_group(GUI FILES ${SOURCE_FILES_GUI}) +file(GLOB SOURCE_FILES_Collision + "${INCLUDE_PATH}/Collision/*.h" + "Collision/*.cpp" +) +source_group(Collision FILES ${SOURCE_FILES_Collision}) + set(SOURCE_FILES ${SOURCE_FILES_Core} ${SOURCE_FILES_Core_Util} @@ -78,6 +84,7 @@ set(SOURCE_FILES ${SOURCE_FILES_GUI} ${SOURCE_FILES_Rendering} ${SOURCE_FILES_Rendering_Util} + ${SOURCE_FILES_Collision} ) set(LIBRARIES diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 44875aa4..f8dfedcb 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -1,6 +1,6 @@ #include -#include "Core/Collision.h" +#include "Collision/Collision.h" #include "Engine/GLM.h" namespace Collision diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index e41a1692..b5fed86b 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -3,7 +3,7 @@ #include #include "Core/OctTree.h" -#include "Core/Collision.h" +#include "Collision/Collision.h" #include "Core/World.h" #include "Rendering/Camera.h" diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 497812a3..21b2ef20 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -3,7 +3,7 @@ #include using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; -#include "Engine\Core\Collision.h" +#include "Engine/Collision/Collision.h" #include "Engine/Core/AABB.h" #include "Engine/Core/Ray.h" #include //srand diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 735d3ee8..1a7deb3f 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -15,7 +15,7 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl m_RenderQueueFactory = new RenderQueueFactory(); // Create the renderer - m_Renderer = new Renderer(); + m_Renderer = new Renderer(m_EventBroker); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); m_Renderer->SetResolution(Rectangle( diff --git a/src/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h index 38aaab66..985d34d4 100644 --- a/src/Tests/OctTreeTestGameClass.h +++ b/src/Tests/OctTreeTestGameClass.h @@ -11,7 +11,7 @@ #include "Rendering/RenderQueueFactory.h" #include "OctTreeTestHardCodedTestWorld.h" -#include "Core\Collision.h" +#include "Collision/Collision.h" class Game diff --git a/src/Tests/OctTreeTestGameMain.cpp b/src/Tests/OctTreeTestGameMain.cpp index 5dd23cf2..43789cea 100644 --- a/src/Tests/OctTreeTestGameMain.cpp +++ b/src/Tests/OctTreeTestGameMain.cpp @@ -3,7 +3,7 @@ #include using boost::unit_test_framework::test_suite; using boost::unit_test_framework::test_case; -#include +#include "Engine/Collision/Collision.h" #include "Engine/Core/AABB.h" #include "Engine/Core/Ray.h" #include //srand diff --git a/src/Tests/OldOctTree.cpp b/src/Tests/OldOctTree.cpp index 72decd4d..4aabf9ed 100644 --- a/src/Tests/OldOctTree.cpp +++ b/src/Tests/OldOctTree.cpp @@ -3,7 +3,7 @@ #include #include "OldOctTree.h" -#include "Core/Collision.h" +#include "Collision/Collision.h" #include "Core/World.h" #include "Rendering/Camera.h" From 948f6d5de74d967f931fee04b737989930268b57 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 17:53:11 +0100 Subject: [PATCH 077/185] RayVsModel & RayVsAABB comparison continued --- src/Engine/Core/Collision.cpp | 3 ++- src/Tests/CollisionTest.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index 44875aa4..f5381c08 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -119,11 +119,12 @@ bool RayVsModel(const Ray& ray, glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 glm::vec3 m = ray.Origin - v0; glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction, e2); + glm::vec3 DxE2 = glm::cross(ray.Direction, e2);//pVec float DetInv = glm::dot(e1, DxE2); if (std::abs(DetInv) < FLT_EPSILON) { continue; } + DetInv = 1.0f / DetInv; float dist = glm::dot(e2, MxE1) * DetInv; if (dist >= outDistance) { continue; diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 497812a3..3395d505 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -127,7 +127,8 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) maxPos = glm::vec3(0.5f, 0.5f, 0.5f); someAABB = AABB(minPos, maxPos); ResourceManager::RegisterType("RawModel"); - auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); + //auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); + auto unitBox = ResourceManager::Load("Models/Core/UnitCube.obj"); BOOST_CHECK(unitBox != nullptr); for (size_t i = 0; i < 1000000; i++) From 8e431c8edd2f0c04b45a1a53940d0201356b1ba6 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 15 Dec 2015 11:07:09 +0100 Subject: [PATCH 078/185] RayVsModel && RayVsAABB tests added and working. Also adjusted RayVsModel,RayVsAABB with deltas when values are very close to each other (floatingprecision problems) --- src/Engine/Core/Collision.cpp | 287 +++++++++++++++++----------------- src/Tests/CollisionTest.cpp | 86 +++++++++- 2 files changed, 225 insertions(+), 148 deletions(-) diff --git a/src/Engine/Core/Collision.cpp b/src/Engine/Core/Collision.cpp index f5381c08..151a7a28 100644 --- a/src/Engine/Core/Collision.cpp +++ b/src/Engine/Core/Collision.cpp @@ -6,153 +6,160 @@ namespace Collision { -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 half = box.HalfSize(); - - if (abs(c.x) > v.x + half.x) { - return false; - } - if (abs(c.y) > v.y + half.y) { - return false; - } - if (abs(c.z) > v.z + half.z) { - return false; - } + //note: this one hasnt been delta adjusted like RayVsAABB has + 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 half = box.HalfSize(); - if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) { - return false; - } - if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) { - return false; - } - return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); -} - -bool RayVsAABB(const Ray& ray, const AABB& box) -{ - float dummy; - return RayVsAABB(ray, box, dummy); -} - -bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) -{ - glm::vec3 invdir = 1.0f / ray.Direction; - - float t1 = (box.MinCorner().x - ray.Origin.x)*invdir.x; - float t2 = (box.MaxCorner().x - ray.Origin.x)*invdir.x; - float t3 = (box.MinCorner().y - ray.Origin.y)*invdir.y; - float t4 = (box.MaxCorner().y - ray.Origin.y)*invdir.y; - float t5 = (box.MinCorner().z - ray.Origin.z)*invdir.z; - float t6 = (box.MaxCorner().z - ray.Origin.z)*invdir.z; - - float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); - float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); - - if (tmax < 0 || tmin > tmax) - return false; - - outDistance = (tmin > 0) ? tmin : tmax; - return true; -} - -bool AABBVsAABB(const AABB& a, const AABB& b) -{ - const glm::vec3& aCenter = a.Center(); - const glm::vec3& bCenter = b.Center(); - 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. - if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) { - return false; - } - if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) { - return false; - } - return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); -} - -bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices) -{ - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction, e2); - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; + if (abs(c.x) > v.x + half.x) { + return false; } - DetInv = 1.0f / DetInv; - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction, MxE1) * DetInv; - if (u < 0 || v < 0 || 1 < u + v) { - continue; + if (abs(c.y) > v.y + half.y) { + return false; } - //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. - if (0 <= glm::dot(e2, MxE1) * DetInv) { - return true; + if (abs(c.z) > v.z + half.z) { + return false; } + + if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) { + return false; + } + if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) { + return false; + } + return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x); } - return false; -} -bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices, - float& outDistance, - float& outUCoord, - float& outVCoord) -{ - outDistance = INFINITY; - bool hit = false; - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction, e2);//pVec - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; - } - DetInv = 1.0f / DetInv; - float dist = glm::dot(e2, MxE1) * DetInv; - if (dist >= outDistance) { - continue; - } - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction, MxE1) * DetInv; - //If u and v are positive, u+v <= 1, dist is positive, and less than closest. - if (0 <= u && 0 <= v && u + v <= 1 && 0 <= dist) { - outDistance = dist; - outUCoord = u; - outVCoord = v; - hit = true; - } + bool RayVsAABB(const Ray& ray, const AABB& box) + { + float dummy; + return RayVsAABB(ray, box, dummy); } - return hit; -} -bool RayVsModel(const Ray& ray, - const std::vector& modelVertices, - const std::vector& modelIndices, - glm::vec3& outHitPosition) -{ - float u; - float v; - float dist; - bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); - outHitPosition = ray.Origin + dist * ray.Direction; - return hit; -} + bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) + { + glm::vec3 invdir = 1.0f / ray.Direction; + + float t1 = (box.MinCorner().x - ray.Origin.x)*invdir.x; + float t2 = (box.MaxCorner().x - ray.Origin.x)*invdir.x; + float t3 = (box.MinCorner().y - ray.Origin.y)*invdir.y; + float t4 = (box.MaxCorner().y - ray.Origin.y)*invdir.y; + float t5 = (box.MinCorner().z - ray.Origin.z)*invdir.z; + float t6 = (box.MaxCorner().z - ray.Origin.z)*invdir.z; + + float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); + float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); + + //if (tmax < 0 || tmin > tmax) + //if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly + //greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax + if (tmax < 0 || tmin>(tmax + 0.0001f)) + return false; + + outDistance = (tmin > 0) ? tmin : tmax; + return true; + } + + bool AABBVsAABB(const AABB& a, const AABB& b) + { + const glm::vec3& aCenter = a.Center(); + const glm::vec3& bCenter = b.Center(); + 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. + if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) { + return false; + } + if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) { + return false; + } + return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); + } + + bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices) + { + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction, e2); + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } + DetInv = 1.0f / DetInv; + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction, MxE1) * DetInv; + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { + continue; + } + //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. + if (0 <= glm::dot(e2, MxE1) * DetInv) { + return true; + } + } + return false; + } + + bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + float& outDistance, + float& outUCoord, + float& outVCoord) + { + outDistance = INFINITY; + bool hit = false; + for (int i = 0; i < modelIndices.size(); ++i) { + glm::vec3 v0 = modelVertices[modelIndices[i]].Position; + glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 + glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 + glm::vec3 m = ray.Origin - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction, e2);//pVec + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + continue; + } + DetInv = 1.0f / DetInv; + float dist = glm::dot(e2, MxE1) * DetInv; + if (dist >= outDistance) { + continue; + } + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction, MxE1) * DetInv; + + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + //If u and v are positive, u+v <= 1, dist is positive, and less than closest. + if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) { + outDistance = dist; + outUCoord = u; + outVCoord = v; + hit = true; + } + } + return hit; + } + + bool RayVsModel(const Ray& ray, + const std::vector& modelVertices, + const std::vector& modelIndices, + glm::vec3& outHitPosition) + { + float u; + float v; + float dist; + bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); + outHitPosition = ray.Origin + dist * ray.Direction; + return hit; + } } diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 3395d505..d5f7e0ed 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -96,13 +96,12 @@ BOOST_AUTO_TEST_CASE(collisionTest2) BOOST_AUTO_TEST_CASE(rayVsModelTest) { - //simple test + //simple box test Ray ray; ray.Origin = glm::vec3(-50, 0, 0); - //ray.Direction = glm::vec3(-1, 0, 0); ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); - //inte model, det kräver renderar grejs tydligen + //using a rawmodel here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); BOOST_CHECK(unitBox != nullptr); @@ -115,19 +114,24 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest) BOOST_AUTO_TEST_CASE(rayVsModelTest2) { - //advanced test, based on ray vs AABB - srand(7676762); + //advanced test, this will check so rayVSAABB and rayVsModel(with boxmodel) gives the same result (hit/miss) + //testing with different seeds +// srand(7676762); +// srand(7676462); +// srand(7462); + srand(72); Ray ray; AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; bool z; int test = 0; + //min/max is the same as the rawmodels boundaries ofcourse minPos = glm::vec3(-0.5f, -0.5f, -0.5f); maxPos = glm::vec3(0.5f, 0.5f, 0.5f); someAABB = AABB(minPos, maxPos); + //using a rawmodel here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); - //auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); auto unitBox = ResourceManager::Load("Models/Core/UnitCube.obj"); BOOST_CHECK(unitBox != nullptr); @@ -142,6 +146,9 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) ray.Origin /= 100; ray.Origin = glm::vec3(-2, 0, 0); ray.Direction /= 100; + //if we normalize the ray.direction when its 0,0,0 then we get nan,nan,nan - thus we have this check to prevent that + if (ray.Direction.x < 0.0001f && ray.Direction.y < 0.0001f && ray.Direction.z < 0.0001f) + continue; ray.Direction = glm::normalize(ray.Direction); z = Collision::RayVsAABB(ray, someAABB); @@ -149,7 +156,7 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) //hit bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); if (!hit) { - hit = hit; + //if rayvsaabb hit but rayvvmodel didnt hit, we get to here glm::vec3 outtttttttt; hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); @@ -159,13 +166,21 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) } BOOST_CHECK(hit); } + ////breakpoint test + //if (!z) { + // z = z; + //} // bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + ////breakpoint test + //if (!hit) { + // hit = hit; + //} if (hit) { //hit z = Collision::RayVsAABB(ray, someAABB); if (!z) { - z = z; + //if rayvsmodel hit but rayvsaabb didnt hit then we get to here z = Collision::RayVsAABB(ray, someAABB); glm::vec3 outtttttttt; hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); @@ -180,7 +195,62 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) } } +BOOST_AUTO_TEST_CASE(rayVsModelTest3) +{ + //simple test + Ray ray; + ray.Origin = glm::vec3(-50, 0, 0); + //ray.Direction = glm::vec3(-1, 0, 0); + ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + //using a rawmodel here, else we have to init the renderingsystem + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load("Models/Core/UnitSphere.obj"); + BOOST_CHECK(unitBox != nullptr); + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(hit); + ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(!hit); +} + +BOOST_AUTO_TEST_CASE(rayVsModelTest4) +{ + //simple test + + Ray ray; + ray.Origin = glm::vec3(-50, 0, 0); + //ray.Direction = glm::vec3(-1, 0, 0); + ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + //using a rawmodel here, else we have to init the renderingsystem + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load("Models/Core/UnitCylinder.obj"); + BOOST_CHECK(unitBox != nullptr); + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(hit); + ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(!hit); +} + +BOOST_AUTO_TEST_CASE(rayVsModelTest5) +{ + //simple test + + Ray ray; + ray.Origin = glm::vec3(-50, 0, 0); + //ray.Direction = glm::vec3(-1, 0, 0); + ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + //using a rawmodel here, else we have to init the renderingsystem + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load("Models/Core/UnitRaptor.obj"); + BOOST_CHECK(unitBox != nullptr); + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(hit); + ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(!hit); +} BOOST_AUTO_TEST_CASE(octTest) { glm::vec3 mini = glm::vec3(-1, -1, -1); From b698a0d36f1e2ae2761be4e5a7fdfb2891011399 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 11:21:46 +0100 Subject: [PATCH 079/185] WIP Adding models now crashes. Threading Added a create player event that currently is not used. --- include/Engine/Network/Client.h | 3 + include/Engine/Network/PlayerDefinition.h | 2 +- include/Engine/Network/Server.h | 5 +- include/Game/ECreatePlayer.h | 19 ++++++ include/Game/PlayerSystem.h | 6 ++ resources/Schema/Components/Player.xml | 4 ++ resources/Schema/Components/Player.xsd | 4 ++ src/Engine/Network/Client.cpp | 44 ++++++++++--- src/Engine/Network/Server.cpp | 77 ++++++++++++----------- src/Game/Game.cpp | 5 +- src/Game/PlayerSystem.cpp | 58 +++++++++++------ 11 files changed, 161 insertions(+), 66 deletions(-) create mode 100644 include/Game/ECreatePlayer.h diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 8e54aabb..52459d82 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -16,6 +16,7 @@ #include "Core/EventBroker.h" #include "Core/EKeyDown.h" #include "Core/EKeyUp.h" +#include "Input/EInputCommand.h" class Client @@ -75,6 +76,8 @@ private: bool OnKeyDown(const Events::KeyDown &e); EventRelay m_EKeyUp; bool OnKeyUp(const Events::KeyUp &e); + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand &e); }; #endif diff --git a/include/Engine/Network/PlayerDefinition.h b/include/Engine/Network/PlayerDefinition.h index dbacda95..b35ff463 100644 --- a/include/Engine/Network/PlayerDefinition.h +++ b/include/Engine/Network/PlayerDefinition.h @@ -3,7 +3,7 @@ #include struct PlayerDefinition { - int EntityID = -1; + unsigned int EntityID = -1; std::string Name = ""; boost::asio::ip::udp::endpoint Endpoint; }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 259f47c4..3d77e0d1 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -12,13 +12,15 @@ #include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Core/World.h" +#include "Core/EventBroker.h" +#include "Game/ECreatePlayer.h" class Server { public: Server(); ~Server(); - void Start(World* m_world); + void Start(World* m_world, EventBroker *eventBroker); void Close(); private: @@ -32,6 +34,7 @@ private: std::clock_t m_StopTimes[8]; // Game logic World* m_World; + EventBroker* m_EventBroker; // Packet loss logic unsigned int m_PacketID; unsigned int m_PreviousPacketID; diff --git a/include/Game/ECreatePlayer.h b/include/Game/ECreatePlayer.h new file mode 100644 index 00000000..bbfd3c6d --- /dev/null +++ b/include/Game/ECreatePlayer.h @@ -0,0 +1,19 @@ +#ifndef Events_CreatePlayer_h__ +#define Events_CreatePlayer_h__ + +#include "Core/EventBroker.h" +#include "Core/World.h" + +namespace Events +{ + +struct CreatePlayer : Event +{ + unsigned int entityID; + std::string modelPath; + World* world; +}; + +} + +#endif diff --git a/include/Game/PlayerSystem.h b/include/Game/PlayerSystem.h index 18752ac6..b5147e1d 100644 --- a/include/Game/PlayerSystem.h +++ b/include/Game/PlayerSystem.h @@ -9,6 +9,7 @@ #include "Core/EventBroker.h" #include "Core/EKeyDown.h" #include "Core/EKeyUp.h" +#include "ECreatePlayer.h" struct KeyInput { @@ -26,6 +27,7 @@ public: { EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown); EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp); + EVENT_SUBSCRIBE_MEMBER(m_ECreatePlayer, &PlayerSystem::OnCreatePlayer); } virtual void Update(World* world, ComponentWrapper& player, double dt) override; @@ -34,11 +36,15 @@ private: float m_Speed = 5; glm::vec3 m_Direction; KeyInput input; + bool ShouldCreatePlayer = false; + void CreatePlayer(World * world, unsigned int& entityID); EventRelay m_EKeyDown; bool OnKeyDown(const Events::KeyDown &event); EventRelay m_EKeyUp; bool OnKeyUp(const Events::KeyUp &event); + EventRelay m_ECreatePlayer; + bool OnCreatePlayer(const Events::CreatePlayer &event); }; #endif \ No newline at end of file diff --git a/resources/Schema/Components/Player.xml b/resources/Schema/Components/Player.xml index 91a3bb4e..190f2ed0 100644 --- a/resources/Schema/Components/Player.xml +++ b/resources/Schema/Components/Player.xml @@ -1,3 +1,7 @@ + false + false + false + false \ No newline at end of file diff --git a/resources/Schema/Components/Player.xsd b/resources/Schema/Components/Player.xsd index 78c5866b..76a6a8fb 100644 --- a/resources/Schema/Components/Player.xsd +++ b/resources/Schema/Components/Player.xsd @@ -7,6 +7,10 @@ + + + + diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 8c8ae5fd..e4b3bc1b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -28,7 +28,8 @@ void Client::Start(World* world, EventBroker* eventBroker) m_EventBroker->Subscribe(m_EKeyDown); m_EKeyUp = decltype(m_EKeyUp)(std::bind(&Client::OnKeyUp, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EKeyUp); - + m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); + m_EventBroker->Subscribe(m_EInputCommand); std::cout << "Please enter you name: "; std::cin >> m_PlayerName; while (m_PlayerName.size() > 7) { @@ -74,9 +75,9 @@ void Client::ReadFromServer() void Client::SendSnapshotToServer() { // Reset previouse key state in snapshot. - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputForward); - Send(message); + //Package message(MessageType::Event, m_SendPacketID); + //message.AddString(m_NextSnapshot.InputForward); + //Send(message); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; // See if any movement keys are down @@ -208,7 +209,7 @@ void Client::ParseSnapshot(char* data, size_t length) // Apply the position data read to the player entity // New player connected on the server side if (m_PlayerDefinitions[i].Name == "" && tempName != "") { - CreateNewPlayer(i); + //CreateNewPlayer(i); } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { // Someone disconnected // TODO: Insert code here @@ -216,7 +217,7 @@ void Client::ParseSnapshot(char* data, size_t length) // Not a connected player break; } - m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + //m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; m_PlayerDefinitions[i].Name = tempName; } } @@ -322,6 +323,35 @@ bool Client::OnKeyUp(const Events::KeyUp & e) return false; } +bool Client::OnInputCommand(const Events::InputCommand & e) +{ + if (e.Command == "Forward") { + if (e.Value > 0) { + m_IsWASDKeyDown.W = true; + } + else if (e.Value < 0) { + m_IsWASDKeyDown.S = true; + } else { + m_IsWASDKeyDown.W = false; + m_IsWASDKeyDown.S = false; + } + } + if (e.Command == "Right") { + if (e.Value > 0) { + m_IsWASDKeyDown.D = true; + } else if (e.Value < 0) { + m_IsWASDKeyDown.A = true; + } else { + m_IsWASDKeyDown.A = false; + m_IsWASDKeyDown.D = false; + } + } + if (e.Command == "Sprint") { // Temp connect + Connect(); + } + return false; +} + void Client::CreateNewPlayer(int i) { m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); @@ -335,6 +365,6 @@ void Client::IdentifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - LOG_INFO("%i Packet(s) were lost...", difference); + LOG_INFO("%i Packet(s) were lost...", difference); } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index fe9454fd..0bd13dfe 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -7,9 +7,10 @@ Server::~Server() { } -void Server::Start(World* world) +void Server::Start(World* world, EventBroker* eventBroker) { m_World = world; + m_EventBroker = eventBroker; for (size_t i = 0; i < MAXCONNECTIONS; i++) { m_StopTimes[i] = std::clock(); } @@ -42,7 +43,7 @@ void Server::ReadFromClients() std::clock_t previousePingMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock(); std::clock_t timOutTimer = std::clock(); - // How offen we send messages (milliseconds) + // How often we send messages (milliseconds) int intervallMs = 1000; int snapshotInterval = 50; int timeToCheckTimeOutTime = 100; @@ -63,6 +64,7 @@ void Server::ReadFromClients() std::cout << m_PacketID << ": Read from client crashed: " << err.what(); //} } + } std::clock_t currentTime = std::clock(); // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); @@ -121,7 +123,7 @@ void Server::ParseMessageType(char * data, size_t length) m_PreviousPacketID = m_PacketID; // Set previous packet id memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id MoveMessageHead(data, length, sizeof(int)); - //IdentifyPacketLoss(); // crashed when it started to spam! + //IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: @@ -210,7 +212,8 @@ void Server::SendSnapshot() continue; } // Pack player pos into data package - glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + //glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + glm::vec3 playerPos = glm::vec3(1.0f); package.AddPrimitive(playerPos.x); package.AddPrimitive(playerPos.y); package.AddPrimitive(playerPos.z); @@ -241,7 +244,6 @@ void Server::SendPing() void Server::CheckForTimeOuts() { int timeOutTimeMs = 5000; - int tempStartPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); @@ -276,33 +278,33 @@ void Server::ParseEvent(char * data, size_t length) break; } } - // If no player matches the ip return. + // If no player matches the address return. if (i >= 8) return; - unsigned int entityId = m_PlayerDefinitions[i].EntityID; - if ("+Forward" == std::string(data)) { - glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.z -= 0.1f; - m_World->GetComponent(entityId, "Transform")["Position"] = temp; - } - if ("-Forward" == std::string(data)) { - glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.z += 0.1f; - m_World->GetComponent(entityId, "Transform")["Position"] = temp; - } + //unsigned int entityId = m_PlayerDefinitions[i].EntityID; + //if ("+Forward" == std::string(data)) { + // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + // temp.z -= 0.1f; + // m_World->GetComponent(entityId, "Transform")["Position"] = temp; + //} + //if ("-Forward" == std::string(data)) { + // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + // temp.z += 0.1f; + // m_World->GetComponent(entityId, "Transform")["Position"] = temp; + //} - if ("+Right" == std::string(data)) { - glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.x += 0.1f; - m_World->GetComponent(entityId, "Transform")["Position"] = temp; - } + //if ("+Right" == std::string(data)) { + // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + // temp.x += 0.1f; + // m_World->GetComponent(entityId, "Transform")["Position"] = temp; + //} - if ("-Right" == std::string(data)) { - glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - temp.x -= 0.1f; - m_World->GetComponent(entityId, "Transform")["Position"] = temp; - } + //if ("-Right" == std::string(data)) { + // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; + // temp.x -= 0.1f; + // m_World->GetComponent(entityId, "Transform")["Position"] = temp; + //} } void Server::ParseConnect(char * data, size_t length) @@ -317,15 +319,20 @@ void Server::ParseConnect(char * data, size_t length) for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { + + //Events::CreatePlayer e; + //e.entityID = (m_PlayerDefinitions[i].EntityID); + //e.modelPath = "Models/Core/UnitSphere.obj"; + //e.world = m_World; + //m_EventBroker->Publish(e); - - m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); - transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; - model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - + //int entityID = m_World->CreateEntity(); + //ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); + //transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + //ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); + //model["Resource"] = "Models/Core/UnitSphere.obj";//modelPath; // You fix this :) + //model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = std::string(data); // +1 is the null terminator diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 94c18bfe..efc9e7c4 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -53,9 +53,6 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - - - // Invoke network if(m_Config->Get("Networking.StartNetwork", false) == true) boost::thread workerThread(&Game::NetworkFunction, this); @@ -144,6 +141,6 @@ void Game::NetworkFunction() } if (inputMessage == "s" || inputMessage == "S") { Server m_Server; - m_Server.Start(m_World); + m_Server.Start(m_World, m_EventBroker); } } \ No newline at end of file diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 736ea105..d48c02c1 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -3,24 +3,40 @@ void PlayerSystem::Update(World * world, ComponentWrapper & player, double dt) { - if (input.Forward) { - m_Direction.z = -1; - } else if (input.Back) { - m_Direction.z = 1; - } else { - m_Direction.z = 0; - } - if (input.Left) { - m_Direction.x = -1; - } else if (input.Right) { - m_Direction.x = 1; - } else { - m_Direction.x = 0; - } - m_EventBroker->Process(); - ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); - (glm::vec3&)player["Velocity"] = m_Speed * float(dt) * m_Direction; - (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; + //if (player["Forward"]) { + // ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; + //} + //if (player["Left"]) { + // ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt) * -1; + //} + //if (player["Back"]) { + // ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt); + //} + //if (player["Right"]) { + // ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); + //} + //ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); + //(glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; + + //m_EventBroker->Process(); + + //// TODO Jag tror inte vi kan göra det vi vill i updaten. + //// om man lägger till parametrar och tar bort overriden så blir det kanske inte så kul? + //// aja, lycka till! + //if (ShouldCreatePlayer) { + // int entityID = world->CreateEntity(); + // ComponentWrapper transform = world->AttachComponent(entityID, "Transform"); + // transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + // ComponentWrapper model = world->AttachComponent(entityID, "Model"); + // model["Resource"] = "Models/Core/UnitSphere.obj";//modelPath; // You fix this :) + // model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + // ShouldCreatePlayer = false; + //} +} + +void PlayerSystem::CreatePlayer(World * world, unsigned int& entityID) +{ + } bool PlayerSystem::OnKeyDown(const Events::KeyDown & event) @@ -56,3 +72,9 @@ bool PlayerSystem::OnKeyUp(const Events::KeyUp & event) } return false; } + +bool PlayerSystem::OnCreatePlayer(const Events::CreatePlayer & event) +{ + ShouldCreatePlayer = true; + return false; +} From 1910ab705b90a964364e522b9739b9fd47aa25a1 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 15 Dec 2015 13:48:14 +0100 Subject: [PATCH 080/185] AndersTest misc small mergefixes --- include/Engine/Core/InputController.h | 2 +- src/Engine/Core/ConfigFile.cpp | 3 +++ src/Tests/OctTreeTestGameClass.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/Engine/Core/InputController.h b/include/Engine/Core/InputController.h index 513ff70a..0cad346f 100644 --- a/include/Engine/Core/InputController.h +++ b/include/Engine/Core/InputController.h @@ -18,7 +18,7 @@ public: virtual void Initialize() { EVENT_SUBSCRIBE_MEMBER( - _EInputCommand, &InputController::OnCommand); + m_EInputCommand, &InputController::OnCommand); } virtual bool OnCommand(const Events::InputCommand& e) { return false; } diff --git a/src/Engine/Core/ConfigFile.cpp b/src/Engine/Core/ConfigFile.cpp index 00ab4993..fbb03b14 100644 --- a/src/Engine/Core/ConfigFile.cpp +++ b/src/Engine/Core/ConfigFile.cpp @@ -27,6 +27,9 @@ ConfigFile::ConfigFile(std::string path) for (auto& topLevelNode : m_PTreeOverrides) { auto& mergedTopLevelNode = m_PTreeMerged.find(topLevelNode.first); for (auto& childOverrideNode : topLevelNode.second) { + //auto ttt = mergedTopLevelNode->second; + //auto ttt2 = childOverrideNode.first; + //auto ttt3 = childOverrideNode.second; mergedTopLevelNode->second.put_child(childOverrideNode.first, childOverrideNode.second); } } diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 6b2e23bc..cb9ba9d6 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -15,7 +15,7 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl m_RenderQueueFactory = new RenderQueueFactory(); // Create the renderer - m_Renderer = new Renderer(); + m_Renderer = new Renderer(m_EventBroker); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); m_Renderer->SetResolution(Rectangle( From 454ed0032b45e391fd3803ec3b6dee682db77e36 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 15 Dec 2015 14:01:49 +0100 Subject: [PATCH 081/185] Refactored some RayVsModel tests --- src/Tests/CollisionTest.cpp | 77 ++++++++++--------------------------- 1 file changed, 21 insertions(+), 56 deletions(-) diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index eb048a79..82e2e800 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -10,6 +10,7 @@ using boost::unit_test_framework::test_case; #include "Engine/Core/OctTree.h" //vs model #include +#include //ray vs model #include "Engine\Core\ResourceManager.h" @@ -23,6 +24,22 @@ using boost::unit_test_framework::test_case; //#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) //#define new DEBUG_CLIENTBLOCK +void RayTest(std::string fileName) { + //simple box test + Ray ray; + ray.Origin = glm::vec3(-50, 0, 0); + ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + //using a rawmodel here, else we have to init the renderingsystem + ResourceManager::RegisterType("RawModel"); + auto unitBox = ResourceManager::Load(fileName); + BOOST_CHECK(unitBox != nullptr); + bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(hit); + ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + BOOST_CHECK(!hit); +} + BOOST_AUTO_TEST_SUITE(collisionTests) BOOST_AUTO_TEST_CASE(collisionTest) @@ -97,19 +114,7 @@ BOOST_AUTO_TEST_CASE(collisionTest2) BOOST_AUTO_TEST_CASE(rayVsModelTest) { //simple box test - - Ray ray; - ray.Origin = glm::vec3(-50, 0, 0); - ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); - //using a rawmodel here, else we have to init the renderingsystem - ResourceManager::RegisterType("RawModel"); - auto unitBox = ResourceManager::Load("Models/Core/UnitBox.obj"); - BOOST_CHECK(unitBox != nullptr); - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(hit); - ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(!hit); + RayTest("Models/Core/UnitBox.obj"); } BOOST_AUTO_TEST_CASE(rayVsModelTest2) @@ -194,62 +199,22 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) } } - BOOST_AUTO_TEST_CASE(rayVsModelTest3) { //simple test - - Ray ray; - ray.Origin = glm::vec3(-50, 0, 0); - //ray.Direction = glm::vec3(-1, 0, 0); - ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); - //using a rawmodel here, else we have to init the renderingsystem - ResourceManager::RegisterType("RawModel"); - auto unitBox = ResourceManager::Load("Models/Core/UnitSphere.obj"); - BOOST_CHECK(unitBox != nullptr); - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(hit); - ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(!hit); + RayTest("Models/Core/UnitSphere.obj"); } BOOST_AUTO_TEST_CASE(rayVsModelTest4) { //simple test - - Ray ray; - ray.Origin = glm::vec3(-50, 0, 0); - //ray.Direction = glm::vec3(-1, 0, 0); - ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); - //using a rawmodel here, else we have to init the renderingsystem - ResourceManager::RegisterType("RawModel"); - auto unitBox = ResourceManager::Load("Models/Core/UnitCylinder.obj"); - BOOST_CHECK(unitBox != nullptr); - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(hit); - ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(!hit); + RayTest("Models/Core/UnitCylinder.obj"); } BOOST_AUTO_TEST_CASE(rayVsModelTest5) { //simple test - - Ray ray; - ray.Origin = glm::vec3(-50, 0, 0); - //ray.Direction = glm::vec3(-1, 0, 0); - ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); - //using a rawmodel here, else we have to init the renderingsystem - ResourceManager::RegisterType("RawModel"); - auto unitBox = ResourceManager::Load("Models/Core/UnitRaptor.obj"); - BOOST_CHECK(unitBox != nullptr); - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(hit); - ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); - BOOST_CHECK(!hit); + RayTest("Models/Core/UnitRaptor.obj"); } BOOST_AUTO_TEST_CASE(octTest) { From 170610bcb1c1b24b031beca0935087135a436b88 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 15 Dec 2015 14:49:52 +0100 Subject: [PATCH 082/185] Added a TriggerSystem, seems to work as intended. --- include/Engine/Collision/Collision.h | 1 + include/Engine/Collision/ETrigger.h | 2 +- include/Engine/Collision/TriggerSystem.h | 18 +++- include/Game/PlayerSystem.h | 10 ++ resources/Schema/Entities/Test.xml | 6 +- src/Engine/Collision/Collision.cpp | 14 +++ src/Engine/Collision/TriggerSystem.cpp | 121 +++++++++++++++++++++-- src/Engine/Core/OctTree.cpp | 12 +-- src/Game/PlayerSystem.cpp | 18 ++++ 9 files changed, 178 insertions(+), 24 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 87f521bd..8b1f96b2 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -37,6 +37,7 @@ bool RayVsModel(const Ray& ray, //Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); +bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f); } diff --git a/include/Engine/Collision/ETrigger.h b/include/Engine/Collision/ETrigger.h index aaa5ef06..8852ee8c 100644 --- a/include/Engine/Collision/ETrigger.h +++ b/include/Engine/Collision/ETrigger.h @@ -25,7 +25,7 @@ struct TriggerLeave : Event EntityID Trigger; }; -/** Thrown when an entity is completely inside a trigger. */ +/** Thrown once, when an entity is completely inside a trigger. */ struct TriggerEnter : Event { /** The id of the entity that entered the trigger. */ diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index a7b2122f..59718018 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -8,6 +8,8 @@ #include "Core/EventBroker.h" #include "ETrigger.h" +class AABB; + class TriggerSystem : public System { public: @@ -18,7 +20,21 @@ public: virtual void Update(World* world, ComponentWrapper& collision, double dt) override; private: - std::unordered_map> m_EntitiesInTrigger; + std::unordered_map> m_EntitiesTouchingTrigger; + std::unordered_map> m_EntitiesCompletelyInTrigger; + + bool getEntityBox(World* world, EntityID id, AABB& outBox); + //True if leave event was thrown. + bool throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId); + void attachAABBComponentFromModel(World* world, EntityID id); + template + void publish(EntityID pId, EntityID tId) + { + Event e; + e.Trigger = tId; + e.Entity = pId; + m_EventBroker->Publish(e); + } }; #endif \ No newline at end of file diff --git a/include/Game/PlayerSystem.h b/include/Game/PlayerSystem.h index 18752ac6..de2a27a6 100644 --- a/include/Game/PlayerSystem.h +++ b/include/Game/PlayerSystem.h @@ -9,6 +9,7 @@ #include "Core/EventBroker.h" #include "Core/EKeyDown.h" #include "Core/EKeyUp.h" +#include "Collision/ETrigger.h" struct KeyInput { @@ -26,6 +27,9 @@ public: { EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown); EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp); + EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch); + EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter); + EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave); } virtual void Update(World* world, ComponentWrapper& player, double dt) override; @@ -39,6 +43,12 @@ private: bool OnKeyDown(const Events::KeyDown &event); EventRelay m_EKeyUp; bool OnKeyUp(const Events::KeyUp &event); + EventRelay m_EEnter; + bool OnEnter(const Events::TriggerEnter &event); + EventRelay m_ETouch; + bool PlayerSystem::OnTouch(const Events::TriggerTouch &event); + EventRelay m_ELeave; + bool PlayerSystem::OnLeave(const Events::TriggerLeave &event); }; #endif \ No newline at end of file diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 78494ce1..ef194ad0 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -14,11 +14,13 @@ - + Models/ScaleWidget.obj + + @@ -42,6 +44,8 @@ Models/Core/UnitCube.obj + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index f8dfedcb..baf599c0 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -154,4 +154,18 @@ bool RayVsModel(const Ray& ray, return hit; } +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& mi2 = second.MinCorner(); + return (std::abs(ma1.x - ma2.x) < epsilon) && + (std::abs(mi1.x - mi2.x) < epsilon) && + (std::abs(ma1.z - ma2.z) < epsilon) && + (std::abs(mi1.z - mi2.z) < epsilon) && + (std::abs(ma1.y - ma2.y) < epsilon) && + (std::abs(mi1.y - mi2.y) < epsilon); +} + } diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 4b6c0de4..38a8fac4 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -1,22 +1,123 @@ #include "Collision/TriggerSystem.h" +#include "Collision/Collision.h" #include "Core/AABB.h" +#include "Rendering/Model.h" void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) { + //Currently only players can trigger things. auto players = world->GetComponents("Player"); if (players == nullptr) { return; } - //WTODO: Assumes box exists. - ComponentWrapper& cBox = world->GetComponent(trigger.EntityID, "AABB"); - AABB aabb; - aabb.CreateFromCenter(cBox["BoxCenter"], cBox["BoxSize"]); - for (auto& c : *players) { - - Events::TriggerEnter e; - e.Trigger = trigger.EntityID; - e.Entity = 41; - m_EventBroker->Publish(e); + EntityID tId = trigger.EntityID; + AABB triggerBox; + //The trigger *should* have a bounding box, or something, to test against so it can be triggered. + if (!getEntityBox(world, tId, triggerBox)) { + return; + } + for (auto& pc : *players) { + EntityID pId = pc.EntityID; + AABB playerBox; + //The player can't trigger anything without an AABB. + if (!getEntityBox(world, pId, playerBox)) { + continue; + } + if (!Collision::AABBVsAABB(triggerBox, playerBox)) { + //Entity is not touching the trigger, + //Throw event if it was previously. + if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) { + continue; + } + //This only occurs if the entity was completely inside the trigger one frame, + //then completely outside the trigger, e.g. when dying and respawning. + throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId); + } else { + //Entity is at least touching the trigger. + AABB completelyInsideBox; + completelyInsideBox.CreateFromCenter(triggerBox.Center(), triggerBox.Size() - playerBox.Size()); + if (Collision::AABBVsAABB(completelyInsideBox, playerBox)) { + //Entity is completely inside the trigger. + //If it was only touching before, it is erased. + m_EntitiesTouchingTrigger[tId].erase(pId); + std::unordered_set& completeSet = m_EntitiesCompletelyInTrigger[tId]; + if (completeSet.count(pId) == 0) { + //If it wasn't completely in the trigger, throw Enter and add to the set. + completeSet.insert(pId); + publish(pId, tId); + } + } else { + //Entity is only touching the trigger. + std::unordered_set& touchSet = m_EntitiesTouchingTrigger[tId]; + std::unordered_set& completeSet = m_EntitiesCompletelyInTrigger[tId]; + const auto& it = completeSet.find(pId); + //If it was completely inside before. + if (it != completeSet.end()) { + completeSet.erase(it); + touchSet.insert(pId); + //If it was completely outside before. + } else if (touchSet.count(pId) == 0) { + publish(pId, tId); + touchSet.insert(pId); + } + //Else, it was touching the trigger last frame too and nothing is done. + } + } } } +bool TriggerSystem::getEntityBox(World* world, EntityID id, AABB& outBox) +{ + //TODO: Improve checking if component exists. Remove try + bool retry; + do { + retry = false; + try { + ComponentWrapper& cBox = world->GetComponent(id, "AABB"); + outBox.CreateFromCenter(cBox["BoxCenter"], cBox["BoxSize"]); + } catch (std::out_of_range e) { + retry = true; + attachAABBComponentFromModel(world, id); + } + } while (retry); + return true; +} + +bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId) +{ + const auto& it = triggerSet.find(pId); + if (it != triggerSet.end()) { + //If it was in the trigger, but not anymore, throw leaveEvent and erase from the set. + triggerSet.erase(it); + publish(pId, tId); + return true; + } + return false; +} + +void TriggerSystem::attachAABBComponentFromModel(World* world, EntityID id) +{ + ComponentWrapper model = world->GetComponent(id, "Model"); + ComponentWrapper transform = world->GetComponent(id, "Transform"); + ComponentWrapper collision = world->AttachComponent(id, "AABB"); + Model* modelRes = ResourceManager::Load(model["Resource"]); + + glm::mat4 modelMatrix = modelRes->m_Matrix * + glm::translate(glm::mat4(), (glm::vec3)transform["Position"]) * + glm::toMat4((glm::quat)transform["Orientation"]) * + glm::scale((glm::vec3)transform["Scale"]); + + glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); + glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); + for (const auto& v : modelRes->m_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); + } + collision["BoxCenter"] = 0.5f * (maxi + mini); + collision["BoxSize"] = maxi - mini; +} diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index b5fed86b..8c262faf 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -21,16 +21,6 @@ bool isFirstLower(const ChildInfo& first, const ChildInfo& second) return first.Distance < second.Distance; } -bool isSameBoxProbably(const AABB& first, const AABB& second) -{ - const float EPS = 0.0001f; - const auto& ma = first.MaxCorner(); - const auto& mi = first.MinCorner(); - return (std::abs(ma.x - mi.x) < EPS) && - (std::abs(ma.z - mi.z) < EPS) && - (std::abs(ma.y - mi.y) < EPS); -} - } OctTree::OctTree() @@ -228,7 +218,7 @@ bool OctTree::OctChild::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersect for (int i : m_DynamicObjIndices) { if (!m_DynamicObjectsRef[i].Checked) { const AABB& objBox = m_DynamicObjectsRef[i].Box; - if (!isSameBoxProbably(boxToTest, objBox) && + if (!Collision::IsSameBoxProbably(boxToTest, objBox) && Collision::AABBVsAABB(boxToTest, objBox)) { outBoxIntersected = objBox; return true; diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 736ea105..4f86a2de 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -56,3 +56,21 @@ bool PlayerSystem::OnKeyUp(const Events::KeyUp & event) } return false; } + +bool PlayerSystem::OnTouch(const Events::TriggerTouch &event) +{ + LOG_INFO("Player %i touched widget (entity %i).", event.Entity, event.Trigger); + return false; +} + +bool PlayerSystem::OnEnter(const Events::TriggerEnter &event) +{ + LOG_INFO("Player %i entered widget (entity %i).", event.Entity, event.Trigger); + return false; +} + +bool PlayerSystem::OnLeave(const Events::TriggerLeave &event) +{ + LOG_INFO("Player %i left widget (entity %i).", event.Entity, event.Trigger); + return false; +} \ No newline at end of file From 478c69231580c0760a04825bfc606c091e9a41c1 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 14:53:56 +0100 Subject: [PATCH 083/185] Refactoring. Client and server has Update Loop that runs before any game logic each frame. --- include/Engine/Network/Client.h | 4 ++ include/Engine/Network/Server.h | 3 + include/Game/Game.h | 3 + src/Engine/Network/Client.cpp | 18 +++++- src/Engine/Network/Server.cpp | 66 ++++++++++----------- src/Engine/Rendering/RenderQueueFactory.cpp | 16 +++-- src/Game/Game.cpp | 7 ++- src/Game/PlayerSystem.cpp | 28 ++++----- 8 files changed, 88 insertions(+), 57 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 52459d82..0cca0db5 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -25,6 +25,7 @@ public: Client(); ~Client(); void Start(World* world, EventBroker* eventBroker); + void Update(); void Close(); private: void ReadFromServer(); @@ -56,6 +57,9 @@ private: unsigned int m_PreviousPacketID = 0; unsigned int m_SendPacketID = 0; + // Game Logic + std::vector m_PlayersToCreate; + World* m_World; int m_PlayerID = -1; glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 3d77e0d1..610116d4 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -21,6 +21,7 @@ public: Server(); ~Server(); void Start(World* m_world, EventBroker *eventBroker); + void Update(); void Close(); private: @@ -35,6 +36,8 @@ private: // Game logic World* m_World; EventBroker* m_EventBroker; + // size = players to create, stores playerID + std::vector m_PlayersToCreate; // Packet loss logic unsigned int m_PacketID; unsigned int m_PreviousPacketID; diff --git a/include/Game/Game.h b/include/Game/Game.h index a3400679..2ff1d770 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -50,6 +50,9 @@ private: // Network methods void NetworkFunction(); + Client m_Client; + Server m_Server; + bool m_IsClient = false; EventRelay m_EInputCommand; bool debugOnInputCommand(const Events::InputCommand& e); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index e4b3bc1b..2dfdc59d 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -41,6 +41,17 @@ void Client::Start(World* world, EventBroker* eventBroker) ReadFromServer(); } +void Client::Update() +{ + while (m_PlayersToCreate.size() > 0) { + unsigned int i = m_PlayersToCreate.size() - 1; + m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + } +} + void Client::Close() { if (m_WasStarted) { @@ -210,6 +221,7 @@ void Client::ParseSnapshot(char* data, size_t length) // New player connected on the server side if (m_PlayerDefinitions[i].Name == "" && tempName != "") { //CreateNewPlayer(i); + m_PlayersToCreate.push_back(i); } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { // Someone disconnected // TODO: Insert code here @@ -217,8 +229,10 @@ void Client::ParseSnapshot(char* data, size_t length) // Not a connected player break; } - //m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; - m_PlayerDefinitions[i].Name = tempName; + if (m_PlayerDefinitions[i].EntityID != -1) { + m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + m_PlayerDefinitions[i].Name = tempName; + } } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 0bd13dfe..77eba2ae 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -25,6 +25,20 @@ void Server::Start(World* world, EventBroker* eventBroker) threads.join_all(); } +void Server::Update() +{ + while (m_PlayersToCreate.size() > 0) { + int i = m_PlayersToCreate.size() - 1; + m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); + transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + m_PlayersToCreate.pop_back(); + } +} + void Server::Close() { m_ThreadIsRunning = false; @@ -124,7 +138,6 @@ void Server::ParseMessageType(char * data, size_t length) memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id MoveMessageHead(data, length, sizeof(int)); //IdentifyPacketLoss(); - switch (static_cast(messageType)) { case MessageType::Connect: ParseConnect(data, length); @@ -211,9 +224,10 @@ void Server::SendSnapshot() if (m_PlayerDefinitions[i].EntityID == -1) { continue; } + // Pack player pos into data package - //glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; - glm::vec3 playerPos = glm::vec3(1.0f); + glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + //glm::vec3 playerPos = glm::vec3(1.0f); package.AddPrimitive(playerPos.x); package.AddPrimitive(playerPos.y); package.AddPrimitive(playerPos.z); @@ -282,29 +296,19 @@ void Server::ParseEvent(char * data, size_t length) if (i >= 8) return; - //unsigned int entityId = m_PlayerDefinitions[i].EntityID; - //if ("+Forward" == std::string(data)) { - // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - // temp.z -= 0.1f; - // m_World->GetComponent(entityId, "Transform")["Position"] = temp; - //} - //if ("-Forward" == std::string(data)) { - // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - // temp.z += 0.1f; - // m_World->GetComponent(entityId, "Transform")["Position"] = temp; - //} - - //if ("+Right" == std::string(data)) { - // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - // temp.x += 0.1f; - // m_World->GetComponent(entityId, "Transform")["Position"] = temp; - //} - - //if ("-Right" == std::string(data)) { - // glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; - // temp.x -= 0.1f; - // m_World->GetComponent(entityId, "Transform")["Position"] = temp; - //} + unsigned int entityId = m_PlayerDefinitions[i].EntityID; + if ("+Forward" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Forward"] = true; + } + if ("-Forward" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Back"] = true; + } + if ("+Right" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Right"] = true; + } + if ("-Right" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Left"] = true; + } } void Server::ParseConnect(char * data, size_t length) @@ -326,13 +330,9 @@ void Server::ParseConnect(char * data, size_t length) //e.world = m_World; //m_EventBroker->Publish(e); - //int entityID = m_World->CreateEntity(); - //ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); - //transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - //ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); - //model["Resource"] = "Models/Core/UnitSphere.obj";//modelPath; // You fix this :) - //model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - + // Create new player + m_PlayersToCreate.push_back(i); + m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = std::string(data); // +1 is the null terminator diff --git a/src/Engine/Rendering/RenderQueueFactory.cpp b/src/Engine/Rendering/RenderQueueFactory.cpp index 8d5bb420..747e68b1 100644 --- a/src/Engine/Rendering/RenderQueueFactory.cpp +++ b/src/Engine/Rendering/RenderQueueFactory.cpp @@ -46,9 +46,11 @@ glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity) glm::quat orientation; do { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation; - entity = world->GetParent(entity); + if (world->HasComponent(entity, "Transform")) { + ComponentWrapper transform = world->GetComponent(entity, "Transform"); + orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation; + entity = world->GetParent(entity); + } } while (entity != 0); return orientation; @@ -59,9 +61,11 @@ glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity) glm::vec3 scale(1.f); do { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - scale *= (glm::vec3)transform["Scale"]; - entity = world->GetParent(entity); + if (world->HasComponent(entity, "Transform")) { + ComponentWrapper transform = world->GetComponent(entity, "Transform"); + scale *= (glm::vec3)transform["Scale"]; + entity = world->GetParent(entity); + } } while (entity != 0); return scale; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 5ad730ab..a242f64d 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -89,6 +89,9 @@ void Game::Tick() m_InputProxy->Process(); m_EventBroker->Swap(); + // Update network + m_IsClient ? m_Client.Update() : m_Server.Update(); + // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); debugTick(dt); @@ -135,11 +138,11 @@ void Game::NetworkFunction() std::cout << "Start client or server? (c/s)" << std::endl; std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { - Client m_Client; + m_IsClient = true; m_Client.Start(m_World, m_EventBroker); } if (inputMessage == "s" || inputMessage == "S") { - Server m_Server; + m_IsClient = false; m_Server.Start(m_World, m_EventBroker); } } \ No newline at end of file diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index adfcba9b..6be82702 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -2,20 +2,20 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) { - //if (player["Forward"]) { - // ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; - //} - //if (player["Left"]) { - // ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt) * -1; - //} - //if (player["Back"]) { - // ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt); - //} - //if (player["Right"]) { - // ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); - //} - //ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); - //(glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; + if (player["Forward"]) { + ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; + } + if (player["Left"]) { + ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt) * -1; + } + if (player["Back"]) { + ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt); + } + if (player["Right"]) { + ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); + } + ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); + (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; //m_EventBroker->Process(); From e940c1d60483913fa616b541bc482291ce705d08 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 15 Dec 2015 14:55:56 +0100 Subject: [PATCH 084/185] WIP --- include/Engine/Network/Client.h | 8 +++---- include/Engine/Network/Package.h | 19 ++++++++++++++++ include/Engine/Network/Server.h | 8 +++---- src/Engine/Network/Client.cpp | 27 ++++++++++------------- src/Engine/Network/Package.cpp | 36 +++++++++++++++++++++++------- src/Engine/Network/Server.cpp | 38 +++++++++++++++----------------- 6 files changed, 85 insertions(+), 51 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 8e54aabb..37f524b8 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -36,12 +36,12 @@ private: void Disconnect(); void Ping(); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void ParseMessageType(char* data, size_t length); - void ParseEventMessage(char* data, size_t length); - void ParseConnect(char* data, size_t length); + void ParseMessageType(Package& package); + void ParseEventMessage(Package& package); + void ParseConnect(Package& package); void ParsePing(); void ParseServerPing(); - void ParseSnapshot(char* data, size_t length); + void ParseSnapshot(Package& package); void CreateNewPlayer(int i); void IdentifyPacketLoss(); diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h index 63409bf0..49118b6e 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Package.h @@ -3,6 +3,7 @@ #include #include "Network/MessageType.h" +#include "Core/Util/Logging.h" // Defines the class Package @@ -11,6 +12,8 @@ public: // arg1: Type of message (Connect, Disconnect...) // arg2: PackageID for identifying packet loss. Package(MessageType type, unsigned int& packageID); + // Used to create package from already existing data buffer. + Package(char* data, int sizeOfPackage); ~Package(); // Add primitive types like int, float, char... template @@ -19,13 +22,29 @@ public: memcpy(m_Data + m_Offset, &val, sizeof(T)); m_Offset += sizeof(T); } + // Pops the first element as if it was a primitive. + template + T PopFrontPrimitive() + { + if (m_Offset < m_ReturnDataOffset + sizeof(T)) { + LOG_WARNING("Package PopFrontPrimitive(): You are trying to remove more than what exists in this package!"); + return -1; + } + T returnValue; + memcpy(&returnValue, m_Data + m_ReturnDataOffset, sizeof(T)); + m_ReturnDataOffset += sizeof(T); + return returnValue; + } void AddString(std::string str); + // Pops the first element as if it was a string. + std::string PopFrontString(); int Size() { return m_Offset; }; char* Data() { return m_Data; }; private: char* m_Data = new char[128]; + unsigned int m_ReturnDataOffset = 0; int m_Offset = 0; }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 259f47c4..1af3d3f6 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -54,13 +54,13 @@ private: void SendPing(); void CheckForTimeOuts(); void Disconnect(int i); - void ParseMessageType(char* data, size_t length); - void ParseEvent(char* data, size_t length); - void ParseConnect(char* data, size_t length); + void ParseMessageType(Package& package); + void ParseEvent(Package& package); + void ParseConnect(Package& package); void ParseDisconnect(); void ParseClientPing(); void ParseServerPing(); - void ParseSnapshot(char* data, size_t length); + void ParseSnapshot(Package& package); void IdentifyPacketLoss(); }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 8c8ae5fd..f2eebd09 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,7 +6,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } @@ -61,7 +61,8 @@ void Client::ReadFromServer() while (m_ThreadIsRunning) { if (m_Socket.available()) { bytesRead = Receive(readBuf, INPUTSIZE); - ParseMessageType(readBuf, bytesRead); + Package package(readBuf,bytesRead); + ParseMessageType(package); } std::clock_t currentTime = std::clock(); if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { @@ -107,21 +108,17 @@ void Client::SendSnapshotToServer() } } -void Client::ParseMessageType(char* data, size_t length) +void Client::ParseMessageType(Package& package) { - int messageType = -1; - memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server - MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from - + int messageType = package.PopFrontPrimitive(); // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id - memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id - MoveMessageHead(data, length, sizeof(int)); + m_PacketID = package.PopFrontPrimitive(); //Read new packet id IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: - ParseConnect(data, length); + ParseConnect(package); break; case MessageType::ClientPing: ParsePing(); @@ -132,19 +129,19 @@ void Client::ParseMessageType(char* data, size_t length) case MessageType::Message: break; case MessageType::Snapshot: - ParseSnapshot(data, length); + ParseSnapshot(package); break; case MessageType::Disconnect: break; case MessageType::Event: - ParseEventMessage(data, length); + ParseEventMessage(package); break; default: break; } } -void Client::ParseConnect(char* data, size_t len) +void Client::ParseConnect(Package& package) { memcpy(&m_PacketID, data, sizeof(int)); m_PreviousPacketID = m_PacketID; @@ -168,7 +165,7 @@ void Client::ParseServerPing() //std::cout << "Parsing ping." << std::endl; } -void Client::ParseEventMessage(char* data, size_t length) +void Client::ParseEventMessage(Package& package) { int Id = -1; std::string command = std::string(data); @@ -187,7 +184,7 @@ void Client::ParseEventMessage(char* data, size_t length) void Client::ParseSnapshot(char* data, size_t length) { - std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; + //std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index 665d15ce..f25d0e5a 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -1,24 +1,44 @@ #include "Network/Package.h" -Package::Package(MessageType type,unsigned int& packageID) +Package::Package(MessageType type, unsigned int& packageID) { - // Create message header - // Add message type - int messageType = static_cast(type); + // Create message header + // Add message type + int messageType = static_cast(type); Package::AddPrimitive(messageType); packageID = packageID % 1000; // Packet id modulos Package::AddPrimitive(packageID); packageID++; } + +Package::Package(char* data, int sizeOfPackage) +{ + // Create message + memcpy(m_Data, data, sizeOfPackage); + m_Offset = sizeOfPackage; +} + Package::~Package() { - delete[] m_Data; + delete[] m_Data; } void Package::AddString(std::string str) { - // Message, add one extra byte for null terminator - memcpy(m_Data + m_Offset, str.data(), (str.size() + 1) * sizeof(char)); - m_Offset += (str.size() + 1) * sizeof(char); + // Message, add one extra byte for null terminator + memcpy(m_Data + m_Offset, str.data(), (str.size() + 1) * sizeof(char)); + m_Offset += (str.size() + 1) * sizeof(char); +} + +std::string Package::PopFrontString() +{ + std::string returnValue(m_Data + m_ReturnDataOffset); + if (m_Offset < m_ReturnDataOffset + returnValue.size()){ + LOG_WARNING("Package PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); + return "PopFrontString Failed"; + } + + m_ReturnDataOffset += returnValue.size(); + return returnValue; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index fe9454fd..7ede2ce8 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -56,7 +56,8 @@ void Server::ReadFromClients() if (m_ThreadIsRunning && m_Socket.available()) { try { bytesRead = Receive(readBuf, INPUTSIZE); - ParseMessageType(readBuf, bytesRead); + Package package(readBuf, bytesRead); + ParseMessageType(package); } catch (const std::exception& err) { // To not spam "socket closed messages" //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { @@ -111,21 +112,18 @@ void Server::InputLoop() } } -void Server::ParseMessageType(char * data, size_t length) +void Server::ParseMessageType(Package& package) { - int messageType = -1; - memcpy(&messageType, data, sizeof(int)); // Read what type off message was sent from server - MoveMessageHead(data, length, sizeof(int)); // Move the message head to know where to read from + int messageType = package.PopFrontPrimitive(); // Read what type off message was sent from server // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id - memcpy(&m_PacketID, data, sizeof(int)); //Read new packet id - MoveMessageHead(data, length, sizeof(int)); + m_PacketID = package.PopFrontPrimitive(); //Read new packet id //IdentifyPacketLoss(); // crashed when it started to spam! switch (static_cast(messageType)) { case MessageType::Connect: - ParseConnect(data, length); + ParseConnect(package); break; case MessageType::ClientPing: //ParseClientPing(); @@ -136,13 +134,13 @@ void Server::ParseMessageType(char * data, size_t length) case MessageType::Message: break; case MessageType::Snapshot: - ParseSnapshot(data, length); + ParseSnapshot(package); break; case MessageType::Disconnect: ParseDisconnect(); break; case MessageType::Event: - ParseEvent(data, length); + ParseEvent(package); break; default: break; @@ -268,7 +266,7 @@ void Server::Disconnect(int i) m_PlayerDefinitions[i].Name = ""; } -void Server::ParseEvent(char * data, size_t length) +void Server::ParseEvent(Package& package) { size_t i; for (i = 0; i < MAXCONNECTIONS; i++) { @@ -281,31 +279,32 @@ void Server::ParseEvent(char * data, size_t length) return; unsigned int entityId = m_PlayerDefinitions[i].EntityID; - if ("+Forward" == std::string(data)) { + std::string eventString = package.PopFrontString(); + if ("+Forward" == eventString) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.z -= 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } - if ("-Forward" == std::string(data)) { + if ("-Forward" == eventString) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.z += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } - if ("+Right" == std::string(data)) { + if ("+Right" == eventString) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.x += 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } - if ("-Right" == std::string(data)) { + if ("-Right" == eventString) { glm::vec3 temp = m_World->GetComponent(entityId, "Transform")["Position"]; temp.x -= 0.1f; m_World->GetComponent(entityId, "Transform")["Position"] = temp; } } -void Server::ParseConnect(char * data, size_t length) +void Server::ParseConnect(Package& package) { std::cout << "Parsing connection." << std::endl; // Check if player is already connected @@ -327,9 +326,8 @@ void Server::ParseConnect(char * data, size_t length) model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; - m_PlayerDefinitions[i].Name = std::string(data); - // +1 is the null terminator - MoveMessageHead(data, length, m_PlayerDefinitions[i].Name.size() + 1); + m_PlayerDefinitions[i].Name = package.PopFrontString(); + m_StopTimes[i] = std::clock(); std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << @@ -381,7 +379,7 @@ void Server::ParseServerPing() } // NOT USED -void Server::ParseSnapshot(char * data, size_t length) +void Server::ParseSnapshot(Package& package) { // Does no logic. Returns snapshot if client request one // The snapshot is not a real snapshot tho... From 1e370bac1337ce7db71e647adc6f1e0c255ee468 Mon Sep 17 00:00:00 2001 From: Tleety Date: Tue, 15 Dec 2015 15:28:37 +0100 Subject: [PATCH 085/185] ForwardPlus base debug commit. --- include/Engine/Rendering/Renderer.h | 2 + resources/Shaders/ForwardPlus.frag.glsl | 124 ++++++++++++++++++++++ resources/Shaders/ForwardPlus.vert.glsl | 34 +++++++ resources/Shaders/cullLights.comp.glsl | 130 ++++++++++++++++++++++-- src/Engine/Rendering/DrawScenePass.cpp | 6 +- src/Engine/Rendering/Renderer.cpp | 92 +++++++++++++---- 6 files changed, 359 insertions(+), 29 deletions(-) create mode 100644 resources/Shaders/ForwardPlus.frag.glsl create mode 100644 resources/Shaders/ForwardPlus.vert.glsl diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 886c98ca..59bf3d45 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -69,6 +69,7 @@ private: //----------------------Forward+-----------------------// void CalculateFrustum(); void CullLights(); + void DrawForwardPlus(RenderQueueCollection& rq); //Frustum struct Plane { glm::vec3 Normal; @@ -116,6 +117,7 @@ private: ShaderProgram* m_DrawScreenQuadProgram; ShaderProgram* m_CalculateFrustumProgram; ShaderProgram* m_LightCullProgram; + ShaderProgram* m_ForwardPlusProgram; }; diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl new file mode 100644 index 00000000..1f49102e --- /dev/null +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -0,0 +1,124 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec4 Color; + +uniform sampler2D texture0; + + +struct PointLight { + vec4 Position; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + float Padding; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + PointLight List[]; +} PointLights; + +struct LightGrid { + int Amount; + int Start; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + int LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; +}Input; + +out vec4 fragmentColor; + +vec4 scene_ambient = vec4(0.6,0.6,0.6,1); + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist) { + return 1.0 - smoothstep(radius * 1.0, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + + +void main() +{ + vec4 texel = texture2D(texture0, Input.TextureCoordinate); + vec4 position = V * M * vec4(Input.Position, 1.0); + vec4 normal = V * vec4(Input.Normal, 0.0); + vec4 viewVec = normalize(-position); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/16); + tilePos.y = int(gl_FragCoord.y/16); + + LightResult totalLighting; + totalLighting.Diffuse = scene_ambient; + + //for(int i = 0; i < 3; i++) + for(int i = LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start; i < LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount; i++) + { + int l = LightIndex[i]; + + LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal); + + totalLighting.Diffuse += result.Diffuse; + totalLighting.Specular += result.Specular; + } + + fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; + //fragmentColor = texel * Input.DiffuseColor * Color; + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) + { + fragmentColor = vec4(0.5, 0, 0, 0); + } else { + //fragmentColor = vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start/3600, 0, 0, 1); + } + +} + + diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl new file mode 100644 index 00000000..20ab9051 --- /dev/null +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -0,0 +1,34 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 DiffuseVertexColor; +layout(location = 6) in vec4 SpecularVertexColor; +layout(location = 7) in vec4 BoneIndices1; +layout(location = 8) in vec4 BoneIndices2; +layout(location = 9) in vec4 BoneWeights1; +layout(location = 10) in vec4 BoneWeights2; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; +}Output; + +void main() +{ + gl_Position = P*V*M * vec4(Position, 1.0); + + Output.Position = Position; + Output.TextureCoordinate = TextureCoords; + Output.Normal = Normal; + Output.DiffuseColor = DiffuseVertexColor; +} \ No newline at end of file diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index e9fa9a95..ffa69d0e 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -1,16 +1,19 @@ #version 430 -//in uvec3 gl_NumWorkGroups; -//in uvec3 gl_WorkGroupID; -//in uvec3 gl_LocalInvocationID; -//in uvec3 gl_GlobalInvocationID; -//in uint gl_LocalInvocationIndex; +//in uvec3 gl_NumWorkGroups; //contains the number of workgroups that have been dispatched to a compute shader +//in uvec3 gl_WorkGroupID; //contains the index of the workgroup currently being operated on by a compute shader +//in uvec3 gl_LocalInvocationID; //contains the index of work item currently being operated on by a compute shader +//in uvec3 gl_GlobalInvocationID; //contains the global index of work item currently being operated on by a compute shader +//in uint gl_LocalInvocationIndex; //contains the local linear index of work item currently being operated on by a compute shader #define NUM_LIGHTS 3 -#define MAX_LIGHTS_PER_TILE 200 +#define MAX_LIGHTS_PER_TILE 1024 #define NUM_TILES 3600 +#define TILE_SIZE 16 + +uniform mat4 V; struct Plane { vec3 Normal; @@ -25,11 +28,124 @@ layout (std430, binding = 0) buffer FrustumBuffer Frustum Data[3600]; } Frustums; +struct PointLight { + vec4 Position; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + float Padding; +}; +layout (std430, binding = 1) buffer LightBuffer +{ + PointLight List[]; +} PointLights; + +struct LightGrid { + int Amount; + int Start; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 3) buffer LightOffsetBuffer +{ + int LightOffset[]; +}; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + int LightIndex[]; +}; + +shared int GroupLightCount; +shared int GroupLightIndexStartOffset; +shared int GroupLightIndex[MAX_LIGHTS_PER_TILE]; +shared Frustum GroupFrustum; +uint GroupIndex; + +bool SphereInsidePlane(vec3 center, float radius, Plane plane) +{ + return dot(plane.Normal, center) - plane.d < -radius; +} + +bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/) +{ + bool result = true; + + //Check depth here + //if ( sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar ) + //{ + // result = false; + //} + + for (int i =0; i < 4 && result; i++) + { + if(SphereInsidePlane(center, radius, frustum.Planes[i])) + { + result = false; + } + } + return result; +} + +void AppendLight(uint li) +{ + uint index; + index = atomicAdd(GroupLightCount, 1); + if( index < MAX_LIGHTS_PER_TILE ) + { + GroupLightIndex[index] = int(li); + } +} layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main () { - if(1 == 1) { + GroupIndex = gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.y; + if(gl_LocalInvocationIndex == 0) + { + GroupLightCount = 0; + + GroupFrustum = Frustums.Data[GroupIndex]; + } + + memoryBarrierShared(); + barrier(); + + for(uint i = gl_LocalInvocationIndex; i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) + { + PointLight light = PointLights.List[i]; + + //if pointlight + //Pos i view antagligen + if(SphereInsideFrustrum(vec3(V * light.Position), light.Radius, GroupFrustum)) + { + //TODO: Fix transparent and opaque list, and depth test. + AppendLight( i ); + } + + + //if conelight + + //if directional + + } + + memoryBarrierShared(); + barrier(); + + if(gl_LocalInvocationIndex == 0) + { + GroupLightIndexStartOffset = atomicAdd(LightOffset[0], GroupLightCount); + LightGrid g; + g.Start = GroupLightIndexStartOffset; + g.Amount = GroupLightCount; + LightGrids.Data[GroupIndex]; } } \ No newline at end of file diff --git a/src/Engine/Rendering/DrawScenePass.cpp b/src/Engine/Rendering/DrawScenePass.cpp index 559a0f58..34fc6d12 100644 --- a/src/Engine/Rendering/DrawScenePass.cpp +++ b/src/Engine/Rendering/DrawScenePass.cpp @@ -28,9 +28,10 @@ void DrawScenePass::InitializeShaderPrograms() void DrawScenePass::Draw(RenderQueueCollection& rq) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); - GLERROR("Renderer::Draw PickingPass"); + GLERROR("DrawScenePass::Draw: Pre"); DrawScenePassState state; + m_BasicForwardProgram->Bind(); //TODO: Render: Add code for more jobs than modeljobs. @@ -39,7 +40,6 @@ void DrawScenePass::Draw(RenderQueueCollection& rq) if (modelJob) { GLuint ShaderHandle = m_BasicForwardProgram->GetHandle(); - m_BasicForwardProgram->Bind(); //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); @@ -62,5 +62,5 @@ void DrawScenePass::Draw(RenderQueueCollection& rq) continue; } } - GLERROR("DrawScene Error"); + GLERROR("DrawScenePass::Draw: End"); } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index f4897223..13b4b892 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -16,7 +16,7 @@ void Renderer::Initialize() InitializeShaders(); InitializeTextures(); InitializeSSBOs(); - //CalculateFrustum(); + CalculateFrustum(); m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); @@ -73,15 +73,21 @@ void Renderer::InitializeShaders() m_DrawScreenQuadProgram->Compile(); m_DrawScreenQuadProgram->Link(); - //m_CalculateFrustumProgram = ResourceManager::Load("#CalculateFrustumProgram"); - //m_CalculateFrustumProgram.AddShader(std::shared_ptr(new ComputeShader("Shaders/GridFrustum.comp.glsl"))); - //m_CalculateFrustumProgram.Compile(); - //m_CalculateFrustumProgram.Link(); + m_CalculateFrustumProgram = ResourceManager::Load("#CalculateFrustumProgram"); + m_CalculateFrustumProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/GridFrustum.comp.glsl"))); + m_CalculateFrustumProgram->Compile(); + m_CalculateFrustumProgram->Link(); - //m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); - //m_LightCullProgram.AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); - //m_LightCullProgram.Compile(); - //m_LightCullProgram.Link(); + m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); + m_LightCullProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); + m_LightCullProgram->Compile(); + m_LightCullProgram->Link(); + + m_ForwardPlusProgram = ResourceManager::Load("#ForwardPlusProgram"); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ForwardPlusProgram->Compile(); + m_ForwardPlusProgram->Link(); } void Renderer::InputUpdate(double dt) @@ -150,9 +156,10 @@ void Renderer::Draw(RenderQueueCollection& rq) { m_PickingPass->Draw(rq); //DrawScreenQuad(m_PickingPass->PickingTexture()); - //CullLights(); + CullLights(); - m_DrawScenePass->Draw(rq); + //m_DrawScenePass->Draw(rq); + DrawForwardPlus(rq); GLERROR("Renderer::Draw m_DrawScenePass->Draw"); glfwSwapBuffers(m_Window); } @@ -252,39 +259,86 @@ void Renderer::InitializeRenderPasses() void Renderer::CalculateFrustum() { - GLERROR("CalculateFrustum Error-1"); + GLERROR("CalculateFrustum Error: Pre"); + m_CalculateFrustumProgram->Bind(); - GLERROR("CalculateFrustum Error1"); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); - GLERROR("CalculateFrustum Error2"); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix())); - GLERROR("CalculateFrustum Error3"); glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height); - GLERROR("CalculateFrustum Error4"); glDispatchCompute(5, 3, 1); - GLERROR("CalculateFrustum Error5"); + GLERROR("CalculateFrustum Error: End"); } void Renderer::TEMPCreateLights() { for (int i = 0; i < NUM_LIGHTS; i++) { - m_PointLights[i].Position = glm::vec4(i, 0.f, 0.f, 0.f); + m_PointLights[i].Position = glm::vec4(5.f * (i-1), 0.f, 0.f, 1.f); m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); + m_PointLights[i].Radius = 10.f; } } void Renderer::CullLights() { + GLERROR("CullLights Error: Pre"); + m_LightCullProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1); - GLERROR("CullLights Error"); + + GLERROR("CullLights Error: End"); } +void Renderer::DrawForwardPlus(RenderQueueCollection& rq) +{ + GLERROR("Renderer::DrawForwardPlus: Pre"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glClearColor(200.f / 255, 0.f / 255, 200.f / 255, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_ForwardPlusProgram->Bind(); + GLuint ShaderHandle = m_ForwardPlusProgram->GetHandle(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + //TODO: Render: Add code for more jobs than modeljobs. + for (auto &job : rq.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); + + //TODO: Renderer: bättre textur felhantering samt fler texturer stöd + if (modelJob->DiffuseTexture != nullptr) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); + + continue; + } + } + GLERROR("Renderer::DrawForwardPlus: End"); +} + From 472a8db81a28ef3da07f0ce988b0ce7f4f8473ae Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 15:32:31 +0100 Subject: [PATCH 086/185] Various bug fixes. --- src/Engine/Network/Client.cpp | 14 ++++++++++---- src/Engine/Network/Server.cpp | 7 +++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 2dfdc59d..96f218e0 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -6,7 +6,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { // Set up network stream - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } @@ -45,10 +45,13 @@ void Client::Update() { while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; - m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = m_World->CreateEntity(); + unsigned int tempID = m_World->CreateEntity(); ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; + ComponentWrapper player = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Player"); + m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; + m_PlayersToCreate.pop_back(); } } @@ -215,12 +218,14 @@ void Client::ParseSnapshot(char* data, size_t length) MoveMessageHead(data, length, sizeof(float)); tempName = std::string(data); + // +1 for null terminator MoveMessageHead(data, length, tempName.size() + 1); // Apply the position data read to the player entity // New player connected on the server side if (m_PlayerDefinitions[i].Name == "" && tempName != "") { //CreateNewPlayer(i); + m_PlayerDefinitions[i].Name = tempName; m_PlayersToCreate.push_back(i); } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { // Someone disconnected @@ -230,8 +235,9 @@ void Client::ParseSnapshot(char* data, size_t length) break; } if (m_PlayerDefinitions[i].EntityID != -1) { - m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; - m_PlayerDefinitions[i].Name = tempName; + if (m_World->HasComponent(m_PlayerDefinitions[i].EntityID, "Player")) { + m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + } } } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 77eba2ae..e2e65d10 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -28,13 +28,15 @@ void Server::Start(World* world, EventBroker* eventBroker) void Server::Update() { while (m_PlayersToCreate.size() > 0) { - int i = m_PlayersToCreate.size() - 1; - m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = m_World->CreateEntity(); + unsigned int i = m_PlayersToCreate.size() - 1; + unsigned int tempID = m_World->CreateEntity(); ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + ComponentWrapper player = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Player"); + m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; m_PlayersToCreate.pop_back(); } } @@ -225,6 +227,7 @@ void Server::SendSnapshot() continue; } + // Pack player pos into data package glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; //glm::vec3 playerPos = glm::vec3(1.0f); From e2417be8c726043f94542d17552d9770af77226d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 15 Dec 2015 15:36:28 +0100 Subject: [PATCH 087/185] Very simple CollisionSystem made, 'Z','Y' to toggle on/off. --- include/Engine/Collision/CollisionSystem.h | 5 +-- resources/Schema/Entities/Test.xml | 7 ++-- src/Engine/Collision/CollisionSystem.cpp | 38 +++++++++++++++++++--- src/Game/Game.cpp | 2 ++ src/Game/PlayerSystem.cpp | 6 ++-- 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index 1aecfacc..e7a862f7 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -14,15 +14,16 @@ class CollisionSystem : public System public: CollisionSystem(EventBroker* eventBroker) : System(eventBroker, "AABB") + , zPress(false) { //TODO: Debug stuff, remove later. EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); } - virtual void Update(World* world, ComponentWrapper& collision, double dt) override; + virtual void Update(World* world, ComponentWrapper& cAABB, double dt) override; private: - + bool zPress; EventRelay m_EKeyUp; bool OnKeyUp(const Events::KeyUp &event); }; diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index ef194ad0..0233ff95 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -14,23 +14,24 @@ - + Models/ScaleWidget.obj - - + Models/RotationWidget.obj + + diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index d1657361..e1fcb0a2 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -1,16 +1,46 @@ +#include "Collision/Collision.h" #include "Collision/CollisionSystem.h" +#include "Core/AABB.h" - -void CollisionSystem::Update(World * world, ComponentWrapper & collision, double dt) +void CollisionSystem::Update(World * world, ComponentWrapper & cAABB, double dt) { + //cAABB is any entity that should be collideable. m_EventBroker->Process(); - (glm::vec3&)collision["Center"] = (glm::vec3)world->GetComponent(collision.EntityID, "Transform")["Position"]; + //Currently the box is translated according to the models Transform matrix, + //but not scaled (or rotated since it's AABB). This should be fine, if we don't + //want to shrink or scale up an collideable object after creation. + cAABB["BoxCenter"] = (glm::vec3)world->GetComponent(cAABB.EntityID, "Transform")["Position"]; + AABB thisBox; + thisBox.CreateFromCenter(cAABB["BoxCenter"], cAABB["BoxSize"]); + //Here c should be an object that moves, currently only players. + if (zPress) { + return; + } + for (auto& mover : *world->GetComponents("Player")) { + if (cAABB.EntityID == mover.EntityID) { + continue; + } + AABB otherBox; + ComponentWrapper& aabbComp = world->GetComponent(mover.EntityID, "AABB"); + otherBox.CreateFromCenter(aabbComp["BoxCenter"], aabbComp["BoxSize"]); + if (Collision::AABBVsAABB(thisBox, otherBox)) { + ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform"); + //TODO: Move entity to correct position on collision instead of this. Special treatment if both are movers. + glm::vec3 newPos = trans["Position"]; + float moveSpeed = 0.12f; + newPos += moveSpeed * glm::normalize(newPos - thisBox.Center()); + trans["Position"] = newPos; + aabbComp["BoxCenter"] = newPos; + } + } } bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) { if (event.KeyCode == GLFW_KEY_Z) { - + zPress = true; + } else if (event.KeyCode == GLFW_KEY_X) { + zPress = false; } return false; } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 1070d2fa..ee5a29b0 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,6 @@ #include "Game.h" #include "Collision/TriggerSystem.h" +#include "Collision/CollisionSystem.h" Game::Game(int argc, char* argv[]) { @@ -47,6 +48,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline = new SystemPipeline(m_EventBroker); m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); m_LastTime = glfwGetTime(); diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 4f86a2de..727ddea3 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -59,18 +59,18 @@ bool PlayerSystem::OnKeyUp(const Events::KeyUp & event) bool PlayerSystem::OnTouch(const Events::TriggerTouch &event) { - LOG_INFO("Player %i touched widget (entity %i).", event.Entity, event.Trigger); + LOG_INFO("Player entity %i touched widget (entity %i).", event.Entity, event.Trigger); return false; } bool PlayerSystem::OnEnter(const Events::TriggerEnter &event) { - LOG_INFO("Player %i entered widget (entity %i).", event.Entity, event.Trigger); + LOG_INFO("Player entity %i entered widget (entity %i).", event.Entity, event.Trigger); return false; } bool PlayerSystem::OnLeave(const Events::TriggerLeave &event) { - LOG_INFO("Player %i left widget (entity %i).", event.Entity, event.Trigger); + LOG_INFO("Player entity %i left widget (entity %i).", event.Entity, event.Trigger); return false; } \ No newline at end of file From 1431bd1a11a2eb9a9602c681dd1ccbbf83452219 Mon Sep 17 00:00:00 2001 From: Tleety Date: Tue, 15 Dec 2015 15:39:23 +0100 Subject: [PATCH 088/185] DebugChanges --- resources/Shaders/cullLights.comp.glsl | 10 +++++----- src/Engine/Rendering/Renderer.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index ffa69d0e..465e9225 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -67,7 +67,7 @@ shared int GroupLightCount; shared int GroupLightIndexStartOffset; shared int GroupLightIndex[MAX_LIGHTS_PER_TILE]; shared Frustum GroupFrustum; -uint GroupIndex; +int GroupIndex; bool SphereInsidePlane(vec3 center, float radius, Plane plane) { @@ -94,9 +94,9 @@ bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zN return result; } -void AppendLight(uint li) +void AppendLight(int li) { - uint index; + int index; index = atomicAdd(GroupLightCount, 1); if( index < MAX_LIGHTS_PER_TILE ) { @@ -107,7 +107,7 @@ void AppendLight(uint li) layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main () { - GroupIndex = gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.y; + GroupIndex = int(gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.y); if(gl_LocalInvocationIndex == 0) { GroupLightCount = 0; @@ -118,7 +118,7 @@ void main () memoryBarrierShared(); barrier(); - for(uint i = gl_LocalInvocationIndex; i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) + for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) { PointLight light = PointLights.List[i]; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 13b4b892..1bf5e1b4 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -283,6 +283,12 @@ void Renderer::TEMPCreateLights() void Renderer::CullLights() { GLERROR("CullLights Error: Pre"); + m_LightOffset = 0; + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); From 1669649186a507a5273f85695d4f28526e7ebcd3 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 16:24:09 +0100 Subject: [PATCH 089/185] Fixed bug with entityID. Also trying to fix movement WIP. --- src/Engine/Network/Client.cpp | 6 +++--- src/Engine/Network/Server.cpp | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 96f218e0..3d94ad15 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -46,10 +46,10 @@ void Client::Update() while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; unsigned int tempID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); + ComponentWrapper transform = m_World->AttachComponent(tempID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(tempID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; - ComponentWrapper player = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Player"); + ComponentWrapper player = m_World->AttachComponent(tempID, "Player"); m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; m_PlayersToCreate.pop_back(); } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index e2e65d10..3800b88e 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -30,12 +30,12 @@ void Server::Update() while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; unsigned int tempID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Transform"); + ComponentWrapper transform = m_World->AttachComponent(tempID, "Transform"); transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Model"); + ComponentWrapper model = m_World->AttachComponent(tempID, "Model"); model["Resource"] = "Models/Core/UnitSphere.obj"; model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - ComponentWrapper player = m_World->AttachComponent(m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID, "Player"); + ComponentWrapper player = m_World->AttachComponent(tempID, "Player"); m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; m_PlayersToCreate.pop_back(); } @@ -300,6 +300,11 @@ void Server::ParseEvent(char * data, size_t length) return; unsigned int entityId = m_PlayerDefinitions[i].EntityID; + m_World->GetComponent(entityId, "Player")["Forward"] = false; + m_World->GetComponent(entityId, "Player")["Left"] = false; + m_World->GetComponent(entityId, "Player")["Back"] = false; + m_World->GetComponent(entityId, "Player")["Right"] = false; + if ("+Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Forward"] = true; } From 889e0bb3d35987e0887ea8e6baad2330a71872f8 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 16:35:09 +0100 Subject: [PATCH 090/185] Cleaned up PlayerSystem. Sets velocity to 0 every frame. --- include/Game/PlayerSystem.h | 31 +------------------ src/Game/PlayerSystem.cpp | 62 ++----------------------------------- 2 files changed, 3 insertions(+), 90 deletions(-) diff --git a/include/Game/PlayerSystem.h b/include/Game/PlayerSystem.h index b722751c..aad6e3c5 100644 --- a/include/Game/PlayerSystem.h +++ b/include/Game/PlayerSystem.h @@ -6,45 +6,16 @@ #include "Common.h" #include "Core/System.h" -#include "Core/EventBroker.h" -#include "Core/EKeyDown.h" -#include "Core/EKeyUp.h" -#include "ECreatePlayer.h" - -struct KeyInput -{ - bool Forward = false; - bool Left = false; - bool Back = false; - bool Right = false; -}; class PlayerSystem : public PureSystem { public: PlayerSystem(EventBroker* eventBroker) : PureSystem(eventBroker, "Player") - { - EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown); - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp); - EVENT_SUBSCRIBE_MEMBER(m_ECreatePlayer, &PlayerSystem::OnCreatePlayer); - } - + { } virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override; - private: float m_Speed = 5; - glm::vec3 m_Direction; - KeyInput input; - bool ShouldCreatePlayer = false; - - void CreatePlayer(World * world, unsigned int& entityID); - EventRelay m_EKeyDown; - bool OnKeyDown(const Events::KeyDown &event); - EventRelay m_EKeyUp; - bool OnKeyUp(const Events::KeyUp &event); - EventRelay m_ECreatePlayer; - bool OnCreatePlayer(const Events::CreatePlayer &event); }; #endif \ No newline at end of file diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 6be82702..02e7ab22 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -2,6 +2,7 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) { + (glm::vec3)player["Velocity"] = glm::vec3(0.f); if (player["Forward"]) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; } @@ -14,66 +15,7 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, dou if (player["Right"]) { ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); } + ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; - - //m_EventBroker->Process(); - - //// TODO Jag tror inte vi kan göra det vi vill i updaten. - //// om man lägger till parametrar och tar bort overriden så blir det kanske inte så kul? - //// aja, lycka till! - //if (ShouldCreatePlayer) { - // int entityID = world->CreateEntity(); - // ComponentWrapper transform = world->AttachComponent(entityID, "Transform"); - // transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - // ComponentWrapper model = world->AttachComponent(entityID, "Model"); - // model["Resource"] = "Models/Core/UnitSphere.obj";//modelPath; // You fix this :) - // model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - // ShouldCreatePlayer = false; - //} -} - -void PlayerSystem::CreatePlayer(World * world, unsigned int& entityID) -{ - -} - -bool PlayerSystem::OnKeyDown(const Events::KeyDown & event) -{ - if (event.KeyCode == GLFW_KEY_W) { - input.Forward = true; - } - if (event.KeyCode == GLFW_KEY_A) { - input.Left = true; - } - if (event.KeyCode == GLFW_KEY_S) { - input.Back = true; - } - if (event.KeyCode == GLFW_KEY_D) { - input.Right = true; - } - return true; -} - -bool PlayerSystem::OnKeyUp(const Events::KeyUp & event) -{ - if (event.KeyCode == GLFW_KEY_W) { - input.Forward = false; - } - if (event.KeyCode == GLFW_KEY_A) { - input.Left = false; - } - if (event.KeyCode == GLFW_KEY_S) { - input.Back = false; - } - if (event.KeyCode == GLFW_KEY_D) { - input.Right = false; - } - return false; -} - -bool PlayerSystem::OnCreatePlayer(const Events::CreatePlayer & event) -{ - ShouldCreatePlayer = true; - return false; } From 9b348a7d973a74bf487b6fb868e6e3b20715d2b6 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 16:50:59 +0100 Subject: [PATCH 091/185] Updated movement code once again. --- src/Engine/Network/Client.cpp | 19 +++++++++++++------ src/Engine/Network/Server.cpp | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 3d94ad15..9022b8ac 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -111,14 +111,21 @@ void Client::SendSnapshotToServer() } if (m_NextSnapshot.InputForward != "") { - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputForward); - Send(message); + Package package(MessageType::Event, m_SendPacketID); + package.AddString(m_NextSnapshot.InputForward); + Send(package); + } else { + Package package(MessageType::Event, m_SendPacketID); + package.AddString("0Forward"); } if (m_NextSnapshot.InputRight != "") { - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputRight); - Send(message); + Package package(MessageType::Event, m_SendPacketID); + package.AddString(m_NextSnapshot.InputRight); + Send(package); + } else { + Package package(MessageType::Event, m_SendPacketID); + package.AddString("0Right"); + Send(package); } } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 3800b88e..46b803bf 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -26,7 +26,7 @@ void Server::Start(World* world, EventBroker* eventBroker) } void Server::Update() -{ +{ while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; unsigned int tempID = m_World->CreateEntity(); @@ -80,7 +80,7 @@ void Server::ReadFromClients() std::cout << m_PacketID << ": Read from client crashed: " << err.what(); //} } - + } std::clock_t currentTime = std::clock(); // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); @@ -300,22 +300,22 @@ void Server::ParseEvent(char * data, size_t length) return; unsigned int entityId = m_PlayerDefinitions[i].EntityID; - m_World->GetComponent(entityId, "Player")["Forward"] = false; - m_World->GetComponent(entityId, "Player")["Left"] = false; - m_World->GetComponent(entityId, "Player")["Back"] = false; - m_World->GetComponent(entityId, "Player")["Right"] = false; if ("+Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Forward"] = true; - } - if ("-Forward" == std::string(data)) { + } else if ("-Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Back"] = true; + } else if ("0Forward" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Forward"] = false; + m_World->GetComponent(entityId, "Player")["Back"] = false; } if ("+Right" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Right"] = true; - } - if ("-Right" == std::string(data)) { + } else if ("-Right" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Left"] = true; + } else if ("0Right" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Right"] = false; + m_World->GetComponent(entityId, "Player")["Left"] = false; } } @@ -331,7 +331,7 @@ void Server::ParseConnect(char * data, size_t length) for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { - + //Events::CreatePlayer e; //e.entityID = (m_PlayerDefinitions[i].EntityID); //e.modelPath = "Models/Core/UnitSphere.obj"; From 082b3fd3df2500cd656a8fe44a0eee3daea031ac Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 17:22:46 +0100 Subject: [PATCH 092/185] Removed old input events from client --- include/Engine/Network/Client.h | 4 --- src/Engine/Network/Client.cpp | 55 +-------------------------------- src/Engine/Network/Server.cpp | 4 +++ src/Game/PlayerSystem.cpp | 8 +++-- 4 files changed, 10 insertions(+), 61 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 0cca0db5..ec0123f6 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -76,10 +76,6 @@ private: // Events EventBroker* m_EventBroker; - EventRelay m_EKeyDown; - bool OnKeyDown(const Events::KeyDown &e); - EventRelay m_EKeyUp; - bool OnKeyUp(const Events::KeyUp &e); EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand &e); }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 9022b8ac..b4ec5b8c 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -24,10 +24,6 @@ void Client::Start(World* world, EventBroker* eventBroker) m_World = world; // Subscribe to events - m_EKeyDown = decltype(m_EKeyDown)(std::bind(&Client::OnKeyDown, this, std::placeholders::_1)); - m_EventBroker->Subscribe(m_EKeyDown); - m_EKeyUp = decltype(m_EKeyUp)(std::bind(&Client::OnKeyUp, this, std::placeholders::_1)); - m_EventBroker->Subscribe(m_EKeyUp); m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EInputCommand); std::cout << "Please enter you name: "; @@ -60,8 +56,7 @@ void Client::Close() if (m_WasStarted) { Disconnect(); m_ThreadIsRunning = false; - m_EventBroker->Unsubscribe(m_EKeyDown); - m_EventBroker->Unsubscribe(m_EKeyUp); + m_EventBroker->Unsubscribe(m_EInputCommand); } } @@ -302,54 +297,6 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) length -= stepSize; } -bool Client::OnKeyDown(const Events::KeyDown& event) -{ - if (event.KeyCode == GLFW_KEY_W) { - m_IsWASDKeyDown.W = true; - } - if (event.KeyCode == GLFW_KEY_A) { - m_IsWASDKeyDown.A = true; - } - if (event.KeyCode == GLFW_KEY_S) { - m_IsWASDKeyDown.S = true; - } - if (event.KeyCode == GLFW_KEY_D) { - m_IsWASDKeyDown.D = true; - } - - if (event.KeyCode == GLFW_KEY_V) { - Disconnect(); - } - if (event.KeyCode == GLFW_KEY_C) { - Connect(); - } - if (event.KeyCode == GLFW_KEY_P) { - Ping(); - } - return true; -} - -bool Client::OnKeyUp(const Events::KeyUp & e) -{ - if (e.KeyCode == GLFW_KEY_W) { - m_IsWASDKeyDown.W = false; - return true; - } - if (e.KeyCode == GLFW_KEY_A) { - m_IsWASDKeyDown.A = false; - return true; - } - if (e.KeyCode == GLFW_KEY_S) { - m_IsWASDKeyDown.S = false; - return true; - } - if (e.KeyCode == GLFW_KEY_D) { - m_IsWASDKeyDown.D = false; - return true; - } - return false; -} - bool Client::OnInputCommand(const Events::InputCommand & e) { if (e.Command == "Forward") { diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 46b803bf..cffb0d81 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -303,15 +303,19 @@ void Server::ParseEvent(char * data, size_t length) if ("+Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Forward"] = true; + m_World->GetComponent(entityId, "Player")["Back"] = false; } else if ("-Forward" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Forward"] = false; m_World->GetComponent(entityId, "Player")["Back"] = true; } else if ("0Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Forward"] = false; m_World->GetComponent(entityId, "Player")["Back"] = false; } if ("+Right" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Left"] = false; m_World->GetComponent(entityId, "Player")["Right"] = true; } else if ("-Right" == std::string(data)) { + m_World->GetComponent(entityId, "Player")["Right"] = false; m_World->GetComponent(entityId, "Player")["Left"] = true; } else if ("0Right" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Right"] = false; diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 02e7ab22..13c4096a 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -2,7 +2,7 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) { - (glm::vec3)player["Velocity"] = glm::vec3(0.f); + (glm::vec3)player["Velocity"] = glm::vec3(0.f, 0.f, 0.f); if (player["Forward"]) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; } @@ -16,6 +16,8 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, dou ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); } - ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); - (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; + if ((glm::vec3)player["Velocity"] != glm::vec3(0.f)) { + ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); + (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; + } } From 3f602c9d63162eef1b21e1b087a3b7a835117892 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 17:55:08 +0100 Subject: [PATCH 093/185] Test code --- src/Engine/Network/Client.cpp | 4 ++++ src/Engine/Network/Server.cpp | 1 + src/Game/PlayerSystem.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index b4ec5b8c..d573472b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -112,7 +112,11 @@ void Client::SendSnapshotToServer() } else { Package package(MessageType::Event, m_SendPacketID); package.AddString("0Forward"); + Send(package); } + + + if (m_NextSnapshot.InputRight != "") { Package package(MessageType::Event, m_SendPacketID); package.AddString(m_NextSnapshot.InputRight); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index cffb0d81..ac1ec43e 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -300,6 +300,7 @@ void Server::ParseEvent(char * data, size_t length) return; unsigned int entityId = m_PlayerDefinitions[i].EntityID; + std::string templalala = std::string(data); if ("+Forward" == std::string(data)) { m_World->GetComponent(entityId, "Player")["Forward"] = true; diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 13c4096a..6c7e8311 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -3,16 +3,16 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) { (glm::vec3)player["Velocity"] = glm::vec3(0.f, 0.f, 0.f); - if (player["Forward"]) { + if (static_cast(player["Forward"])== true) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; } - if (player["Left"]) { + if (static_cast(player["Left"]) == true) { ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt) * -1; } - if (player["Back"]) { + if (static_cast(player["Back"]) == true) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt); } - if (player["Right"]) { + if (static_cast(player["Right"]) == true) { ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); } From e74b2b68747c4c4438fb6ff0cd222313143768e4 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 16 Dec 2015 10:40:40 +0100 Subject: [PATCH 094/185] Made it easier for non network members to create packages and extract information from them by addin PopFrontString() and PopFrontPrimitive(). --- src/Engine/Network/Client.cpp | 51 ++++++++++++++-------------------- src/Engine/Network/Package.cpp | 4 +-- src/Engine/Network/Server.cpp | 6 ++-- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index f2eebd09..cac91f05 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -61,8 +61,10 @@ void Client::ReadFromServer() while (m_ThreadIsRunning) { if (m_Socket.available()) { bytesRead = Receive(readBuf, INPUTSIZE); - Package package(readBuf,bytesRead); - ParseMessageType(package); + if (bytesRead > 0) { + Package package(readBuf, bytesRead); + ParseMessageType(package); + } } std::clock_t currentTime = std::clock(); if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { @@ -75,9 +77,6 @@ void Client::ReadFromServer() void Client::SendSnapshotToServer() { // Reset previouse key state in snapshot. - Package message(MessageType::Event, m_SendPacketID); - message.AddString(m_NextSnapshot.InputForward); - Send(message); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; // See if any movement keys are down @@ -111,6 +110,8 @@ void Client::SendSnapshotToServer() void Client::ParseMessageType(Package& package) { int messageType = package.PopFrontPrimitive(); + if (messageType == -1) + return; // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = package.PopFrontPrimitive(); //Read new packet id @@ -143,11 +144,9 @@ void Client::ParseMessageType(Package& package) void Client::ParseConnect(Package& package) { - memcpy(&m_PacketID, data, sizeof(int)); + m_PacketID = package.PopFrontPrimitive(); m_PreviousPacketID = m_PacketID; - MoveMessageHead(data, len, sizeof(int)); - memcpy(&m_PlayerID, data, sizeof(int)); - MoveMessageHead(data, len, sizeof(int)); + m_PlayerID = package.PopFrontPrimitive(); std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } @@ -168,40 +167,25 @@ void Client::ParseServerPing() void Client::ParseEventMessage(Package& package) { int Id = -1; - std::string command = std::string(data); + std::string command = package.PopFrontString(); if (command.find("+Player") != std::string::npos) { - MoveMessageHead(data, length, command.size() + 1); - memcpy(&Id, data, sizeof(int)); - MoveMessageHead(data, length, sizeof(int)); + Id = package.PopFrontPrimitive(); // Sett Player name m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { - std::cout << m_PacketID << ": Event message: " << std::string(data) << std::endl; + std::cout << m_PacketID << ": Event message: " << command << std::endl; } - - MoveMessageHead(data, length, std::string(data).size() + 1); } -void Client::ParseSnapshot(char* data, size_t length) +void Client::ParseSnapshot(Package& package) { //std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, // but it is to avoid sending redundant data. - - // Read position data - glm::vec3 playerPos; - memcpy(&playerPos.x, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - memcpy(&playerPos.y, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - memcpy(&playerPos.z, data, sizeof(float)); - MoveMessageHead(data, length, sizeof(float)); - - tempName = std::string(data); - // +1 for null terminator - MoveMessageHead(data, length, tempName.size() + 1); + tempName = package.PopFrontString(); + // Apply the position data read to the player entity // New player connected on the server side if (m_PlayerDefinitions[i].Name == "" && tempName != "") { @@ -209,10 +193,17 @@ void Client::ParseSnapshot(char* data, size_t length) } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { // Someone disconnected // TODO: Insert code here + break; } else if (m_PlayerDefinitions[i].Name == "" && tempName == "") { // Not a connected player break; } + // Read position data + glm::vec3 playerPos; + playerPos.x = package.PopFrontPrimitive(); + playerPos.y = package.PopFrontPrimitive(); + playerPos.z = package.PopFrontPrimitive(); + // Move player to server position m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; m_PlayerDefinitions[i].Name = tempName; } diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index f25d0e5a..729276a3 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -38,7 +38,7 @@ std::string Package::PopFrontString() LOG_WARNING("Package PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); return "PopFrontString Failed"; } - - m_ReturnDataOffset += returnValue.size(); + // +1 for null terminator. + m_ReturnDataOffset += returnValue.size() + 1; return returnValue; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 7ede2ce8..969c257e 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -204,6 +204,10 @@ void Server::SendSnapshot() { Package package(MessageType::Snapshot, m_SendPacketID); for (size_t i = 0; i < MAXCONNECTIONS; i++) { + + // Send an empty name if there is no player connected on this position. + package.AddString(m_PlayerDefinitions[i].Name); + if (m_PlayerDefinitions[i].EntityID == -1) { continue; } @@ -212,8 +216,6 @@ void Server::SendSnapshot() package.AddPrimitive(playerPos.x); package.AddPrimitive(playerPos.y); package.AddPrimitive(playerPos.z); - - package.AddString(m_PlayerDefinitions[i].Name); } Broadcast(package); } From 99b76d7ae1780fdc3022ae097581e10fdfff1ec7 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 16 Dec 2015 12:19:43 +0100 Subject: [PATCH 095/185] Fixed returning address to temporary in functions. AABB also constructible from glm::vec4s. --- include/Engine/Core/AABB.h | 3 ++- include/Engine/Core/ComponentPool.h | 2 +- include/Engine/Core/MemoryPool.h | 2 +- src/Engine/Core/AABB.cpp | 4 ++++ src/Engine/Core/ComponentPool.cpp | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/Engine/Core/AABB.h b/include/Engine/Core/AABB.h index 0a0adafa..c8e05248 100644 --- a/include/Engine/Core/AABB.h +++ b/include/Engine/Core/AABB.h @@ -9,6 +9,7 @@ public: AABB() = default; //No checks are made. Values in minPos must be less than values in maxPos, i.e. min.x < max.x, etc. 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); virtual ~AABB(); @@ -16,7 +17,7 @@ public: 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& Size() const { return 2.0f * m_HalfSize; } + const glm::vec3 Size() const { return 2.0f * m_HalfSize; } const glm::vec3& HalfSize() const { return m_HalfSize; } private: glm::vec3 m_MinCorner; diff --git a/include/Engine/Core/ComponentPool.h b/include/Engine/Core/ComponentPool.h index 8dd8dc29..619aade8 100644 --- a/include/Engine/Core/ComponentPool.h +++ b/include/Engine/Core/ComponentPool.h @@ -20,7 +20,7 @@ public: ~ComponentPoolForwardIterator() = default; ComponentPoolForwardIterator& operator=(const ComponentPoolForwardIterator& other) = default; ComponentPoolForwardIterator& operator++(); - ComponentPoolForwardIterator& operator++(int); + ComponentPoolForwardIterator operator++(int); bool operator!=(const ComponentPoolForwardIterator& other) const; bool operator==(const ComponentPoolForwardIterator& other) const; ComponentWrapper operator*() const; diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index 034e6dc4..ff24ac80 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -253,7 +253,7 @@ public: } //Postfix increment i.e. iter++. Prefer pre-increment (++iter) for efficiency. - MemoryPoolForwardIterator& operator++(int) + MemoryPoolForwardIterator operator++(int) { MemoryPoolForwardIterator copyIter(*this); operator++(); diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index 9da2bdb0..05403022 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -7,6 +7,10 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) , m_HalfSize(0.5f * (maxPos - minPos)) {} +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) { m_Center = center; diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index ca9cc801..ce24c1f7 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -19,7 +19,7 @@ bool ComponentPoolForwardIterator::operator!=(const ComponentPoolForwardIterator return m_MemoryPoolIterator != other.m_MemoryPoolIterator; } -ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++(int) +ComponentPoolForwardIterator ComponentPoolForwardIterator::operator++(int) { ComponentPoolForwardIterator copyIter(*this); operator++(); From d10df6ae095b3589b2dc3b7d29b06d7320c04f2e Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 16 Dec 2015 12:22:15 +0100 Subject: [PATCH 096/185] TriggerSystem implemented and working. --- include/Engine/Collision/Collision.h | 8 ++++ include/Engine/Collision/TriggerSystem.h | 8 ++-- src/Engine/Collision/Collision.cpp | 57 ++++++++++++++++++++++++ src/Engine/Collision/TriggerSystem.cpp | 54 +++------------------- src/Game/PlayerSystem.cpp | 2 +- 5 files changed, 75 insertions(+), 54 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 8b1f96b2..1fcb910e 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -6,6 +6,10 @@ #include "Core/Ray.h" #include "Core/AABB.h" #include "Engine/Rendering/RawModel.h" +#include "Core/Entity.h" + +class World; +struct ComponentWrapper; namespace Collision { @@ -39,6 +43,10 @@ bool RayVsModel(const Ray& ray, bool AABBVsAABB(const AABB& a, const AABB& b); 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); + } #endif \ No newline at end of file diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index 59718018..7e6ef008 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -10,23 +10,21 @@ class AABB; -class TriggerSystem : public System +class TriggerSystem : public PureSystem { public: TriggerSystem(EventBroker* eventBroker) - : System(eventBroker, "Trigger") + : PureSystem(eventBroker, "Trigger") {} - virtual void Update(World* world, ComponentWrapper& collision, double dt) override; + virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override; private: std::unordered_map> m_EntitiesTouchingTrigger; std::unordered_map> m_EntitiesCompletelyInTrigger; - bool getEntityBox(World* world, EntityID id, AABB& outBox); //True if leave event was thrown. bool throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId); - void attachAABBComponentFromModel(World* world, EntityID id); template void publish(EntityID pId, EntityID tId) { diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 69bffa1a..500d59bc 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -2,6 +2,8 @@ #include "Collision/Collision.h" #include "Engine/GLM.h" +#include "Core/World.h" +#include "Rendering/Model.h" namespace Collision { @@ -176,4 +178,59 @@ bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilo (std::abs(mi1.y - mi2.y) < epsilon); } +void attachAABBComponentFromModel(World* world, EntityID id) +{ + ComponentWrapper model = world->GetComponent(id, "Model"); + ComponentWrapper collision = world->AttachComponent(id, "AABB"); + Model* modelRes = ResourceManager::Load(model["Resource"]); + + glm::mat4 modelMatrix = modelRes->m_Matrix; + + glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); + glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); + for (const auto& v : modelRes->m_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); + } + collision["BoxCenter"] = 0.5f * (maxi + mini); + collision["BoxSize"] = maxi - mini; +} + +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(); + + 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) +{ + if (!world->HasComponent(entity, "AABB")) { + if (forceBoxFromModel) { + attachAABBComponentFromModel(world, entity); + } else { + return false; + } + } + + ComponentWrapper& cBox = world->GetComponent(entity, "AABB"); + return GetEntityBox(world, cBox, outBox); +} + } diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 38a8fac4..09092461 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -3,7 +3,7 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) +void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& trigger, double dt) { //Currently only players can trigger things. auto players = world->GetComponents("Player"); @@ -13,14 +13,14 @@ void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) EntityID tId = trigger.EntityID; AABB triggerBox; //The trigger *should* have a bounding box, or something, to test against so it can be triggered. - if (!getEntityBox(world, tId, triggerBox)) { + if (!Collision::GetEntityBox(world, tId, triggerBox, true)) { return; } for (auto& pc : *players) { EntityID pId = pc.EntityID; AABB playerBox; //The player can't trigger anything without an AABB. - if (!getEntityBox(world, pId, playerBox)) { + if (!Collision::GetEntityBox(world, pId, playerBox, true)) { continue; } if (!Collision::AABBVsAABB(triggerBox, playerBox)) { @@ -35,8 +35,9 @@ void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) } else { //Entity is at least touching the trigger. AABB completelyInsideBox; - completelyInsideBox.CreateFromCenter(triggerBox.Center(), triggerBox.Size() - playerBox.Size()); - if (Collision::AABBVsAABB(completelyInsideBox, playerBox)) { + completelyInsideBox.CreateFromCenter(triggerBox.Center(), 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); @@ -66,23 +67,6 @@ void TriggerSystem::Update(World* world, ComponentWrapper& trigger, double dt) } } -bool TriggerSystem::getEntityBox(World* world, EntityID id, AABB& outBox) -{ - //TODO: Improve checking if component exists. Remove try - bool retry; - do { - retry = false; - try { - ComponentWrapper& cBox = world->GetComponent(id, "AABB"); - outBox.CreateFromCenter(cBox["BoxCenter"], cBox["BoxSize"]); - } catch (std::out_of_range e) { - retry = true; - attachAABBComponentFromModel(world, id); - } - } while (retry); - return true; -} - bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId) { const auto& it = triggerSet.find(pId); @@ -95,29 +79,3 @@ bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& trigg return false; } -void TriggerSystem::attachAABBComponentFromModel(World* world, EntityID id) -{ - ComponentWrapper model = world->GetComponent(id, "Model"); - ComponentWrapper transform = world->GetComponent(id, "Transform"); - ComponentWrapper collision = world->AttachComponent(id, "AABB"); - Model* modelRes = ResourceManager::Load(model["Resource"]); - - glm::mat4 modelMatrix = modelRes->m_Matrix * - glm::translate(glm::mat4(), (glm::vec3)transform["Position"]) * - glm::toMat4((glm::quat)transform["Orientation"]) * - glm::scale((glm::vec3)transform["Scale"]); - - glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); - glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); - for (const auto& v : modelRes->m_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); - } - collision["BoxCenter"] = 0.5f * (maxi + mini); - collision["BoxSize"] = maxi - mini; -} diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 41d5602c..9f7a14cf 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -16,7 +16,7 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, dou } else { m_Direction.x = 0; } - m_EventBroker->Process(); + ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform"); (glm::vec3&)player["Velocity"] = m_Speed * float(dt) * m_Direction; (glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"]; From cf0ff9bfe54e0971f0de9981a1aef920db411474 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 16 Dec 2015 12:23:08 +0100 Subject: [PATCH 097/185] Simple quickly made CollisionSystem. --- include/Engine/Collision/CollisionSystem.h | 6 +++--- src/Engine/Collision/CollisionSystem.cpp | 21 ++++++++------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index e7a862f7..254a2461 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -9,18 +9,18 @@ #include "Core/EventBroker.h" #include "Core/EKeyUp.h" -class CollisionSystem : public System +class CollisionSystem : public PureSystem { public: CollisionSystem(EventBroker* eventBroker) - : System(eventBroker, "AABB") + : PureSystem(eventBroker, "AABB") , zPress(false) { //TODO: Debug stuff, remove later. EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); } - virtual void Update(World* world, ComponentWrapper& cAABB, double dt) override; + virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override; private: bool zPress; diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index e1fcb0a2..ee5d4d29 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -2,16 +2,13 @@ #include "Collision/CollisionSystem.h" #include "Core/AABB.h" -void CollisionSystem::Update(World * world, ComponentWrapper & cAABB, double dt) +void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt) { //cAABB is any entity that should be collideable. - m_EventBroker->Process(); - //Currently the box is translated according to the models Transform matrix, - //but not scaled (or rotated since it's AABB). This should be fine, if we don't - //want to shrink or scale up an collideable object after creation. - cAABB["BoxCenter"] = (glm::vec3)world->GetComponent(cAABB.EntityID, "Transform")["Position"]; AABB thisBox; - thisBox.CreateFromCenter(cAABB["BoxCenter"], cAABB["BoxSize"]); + if (!Collision::GetEntityBox(world, cAABB, thisBox)) { + return; + } //Here c should be an object that moves, currently only players. if (zPress) { return; @@ -21,8 +18,9 @@ void CollisionSystem::Update(World * world, ComponentWrapper & cAABB, double dt) continue; } AABB otherBox; - ComponentWrapper& aabbComp = world->GetComponent(mover.EntityID, "AABB"); - otherBox.CreateFromCenter(aabbComp["BoxCenter"], aabbComp["BoxSize"]); + if (!Collision::GetEntityBox(world, mover.EntityID, otherBox)) { + continue; + } if (Collision::AABBVsAABB(thisBox, otherBox)) { ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform"); //TODO: Move entity to correct position on collision instead of this. Special treatment if both are movers. @@ -30,7 +28,6 @@ void CollisionSystem::Update(World * world, ComponentWrapper & cAABB, double dt) float moveSpeed = 0.12f; newPos += moveSpeed * glm::normalize(newPos - thisBox.Center()); trans["Position"] = newPos; - aabbComp["BoxCenter"] = newPos; } } } @@ -38,9 +35,7 @@ void CollisionSystem::Update(World * world, ComponentWrapper & cAABB, double dt) bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) { if (event.KeyCode == GLFW_KEY_Z) { - zPress = true; - } else if (event.KeyCode == GLFW_KEY_X) { - zPress = false; + zPress = !zPress; } return false; } From 5602b32507a6a3f35b7f7493c837476bde44088d Mon Sep 17 00:00:00 2001 From: viktorljung Date: Wed, 16 Dec 2015 13:36:38 +0100 Subject: [PATCH 098/185] Forward+ Fixes --- include/Engine/Rendering/Renderer.h | 22 +++++++------------ resources/Shaders/ForwardPlus.frag.glsl | 20 +++++++++++------- resources/Shaders/GridFrustum.comp.glsl | 9 ++++++-- resources/Shaders/cullLights.comp.glsl | 19 ++++++++++++----- src/Engine/Rendering/Renderer.cpp | 28 +++++++++++++------------ 5 files changed, 56 insertions(+), 42 deletions(-) diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 59bf3d45..63b41b32 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -18,14 +18,6 @@ #define NUM_LIGHTS 3 -enum lightType -{ - Point, - Spot, - Directional, - Area -}; - #include "../Core/EventBroker.h" #include "EPicking.h" @@ -94,22 +86,22 @@ private: PointLight m_PointLights[NUM_LIGHTS]; struct LightGrid { - int Amount; - int Start; + float Start; + float Amount; glm::vec2 Padding; }; LightGrid m_LightGrid[80*45]; int m_LightOffset = 0; - int m_LightIndex[80*45*200]; + float m_LightIndex[80*45*200]; //-------------------------SSBO------------------------// GLuint m_FrustumSSBO = 0; - GLuint m_LightSSBO = 1; - GLuint m_LightGridSSBO = 2; - GLuint m_LightOffsetSSBO = 3; - GLuint m_LightIndexSSBO = 4; + GLuint m_LightSSBO = 0; + GLuint m_LightGridSSBO = 0; + GLuint m_LightOffsetSSBO = 0; + GLuint m_LightIndexSSBO = 0; void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 1f49102e..e3a3f05c 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -23,8 +23,8 @@ layout (std430, binding = 1) buffer LightBuffer } PointLights; struct LightGrid { - int Amount; - int Start; + float Start; + float Amount; vec2 Padding; }; @@ -35,7 +35,7 @@ layout (std430, binding = 2) buffer LightGridBuffer layout (std430, binding = 4) buffer LightIndexBuffer { - int LightIndex[]; + float LightIndex[]; }; @@ -98,11 +98,14 @@ void main() LightResult totalLighting; totalLighting.Diffuse = scene_ambient; - + + + int start = int(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start); + int amount = int(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount); //for(int i = 0; i < 3; i++) - for(int i = LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start; i < LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount; i++) + for(int i = start; i < start + amount; i++) { - int l = LightIndex[i]; + int l = int(LightIndex[i]); LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal); @@ -111,12 +114,15 @@ void main() } fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; + //fragmentColor = texel * Input.DiffuseColor * Color; if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { fragmentColor = vec4(0.5, 0, 0, 0); } else { - //fragmentColor = vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start/3600, 0, 0, 1); + //fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1); + + } } diff --git a/resources/Shaders/GridFrustum.comp.glsl b/resources/Shaders/GridFrustum.comp.glsl index 27559370..523852d5 100644 --- a/resources/Shaders/GridFrustum.comp.glsl +++ b/resources/Shaders/GridFrustum.comp.glsl @@ -67,7 +67,12 @@ void main () - - Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f; + + if ( gl_GlobalInvocationID.x < ScreenDimensions.x / TILE_SIZE && gl_GlobalInvocationID.y < ScreenDimensions.y / TILE_SIZE ) { // innanför skärmen? + Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f; + + } + + } } \ No newline at end of file diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index 465e9225..012d72a7 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -43,8 +43,8 @@ layout (std430, binding = 1) buffer LightBuffer } PointLights; struct LightGrid { - int Amount; - int Start; + float Start; + float Amount; vec2 Padding; }; @@ -60,7 +60,7 @@ layout (std430, binding = 3) buffer LightOffsetBuffer layout (std430, binding = 4) buffer LightIndexBuffer { - int LightIndex[]; + float LightIndex[]; }; shared int GroupLightCount; @@ -107,7 +107,7 @@ void AppendLight(int li) layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main () { - GroupIndex = int(gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.y); + GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * 80)); if(gl_LocalInvocationIndex == 0) { GroupLightCount = 0; @@ -146,6 +146,15 @@ void main () LightGrid g; g.Start = GroupLightIndexStartOffset; g.Amount = GroupLightCount; - LightGrids.Data[GroupIndex]; + g.Padding = vec2(1111, 1111); + LightGrids.Data[GroupIndex] = g; + } + + memoryBarrierShared(); + barrier(); + + for (uint i = gl_LocalInvocationIndex; i < GroupLightCount; i += TILE_SIZE * TILE_SIZE ) + { + LightIndex[GroupLightIndexStartOffset + i] = GroupLightIndex[i]; } } \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 1bf5e1b4..b838bdbc 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -209,44 +209,35 @@ void Renderer::InitializeSSBOs() glGenBuffers(1, &m_FrustumSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_FrustumSSBO"); glGenBuffers(1, &m_LightSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightSSBO"); + glGenBuffers(1, &m_LightGridSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightGridSSBO"); glGenBuffers(1, &m_LightOffsetSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightOffsetSSBO"); glGenBuffers(1, &m_LightIndexSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightIndexSSBO"); } @@ -274,9 +265,9 @@ void Renderer::CalculateFrustum() void Renderer::TEMPCreateLights() { for (int i = 0; i < NUM_LIGHTS; i++) { - m_PointLights[i].Position = glm::vec4(5.f * (i-1), 0.f, 0.f, 1.f); + m_PointLights[i].Position = glm::vec4(5.f * (i-1), -1.5f, 0.f, 1.f); m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); - m_PointLights[i].Radius = 10.f; + m_PointLights[i].Radius = 2.f; } } @@ -287,7 +278,18 @@ void Renderer::CullLights() glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); From 50ccf962682048f4e69e3ca6ec6525ad549c7d55 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 16 Dec 2015 13:52:16 +0100 Subject: [PATCH 099/185] Movement code not buggy anymore. Also changed package to not allocate more data than needed. --- include/Engine/Network/Package.h | 4 ++-- src/Engine/Network/Package.cpp | 4 +++- src/Game/PlayerSystem.cpp | 10 +++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h index 49118b6e..a7b3c126 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Package.h @@ -13,7 +13,7 @@ public: // arg2: PackageID for identifying packet loss. Package(MessageType type, unsigned int& packageID); // Used to create package from already existing data buffer. - Package(char* data, int sizeOfPackage); + Package(char* data, const int sizeOfPackage); ~Package(); // Add primitive types like int, float, char... template @@ -43,7 +43,7 @@ public: char* Data() { return m_Data; }; private: - char* m_Data = new char[128]; + char* m_Data; unsigned int m_ReturnDataOffset = 0; int m_Offset = 0; }; diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index 729276a3..a30d3ee5 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -2,6 +2,7 @@ Package::Package(MessageType type, unsigned int& packageID) { + m_Data = new char[128]; // Create message header // Add message type int messageType = static_cast(type); @@ -12,9 +13,10 @@ Package::Package(MessageType type, unsigned int& packageID) } -Package::Package(char* data, int sizeOfPackage) +Package::Package(char* data, const int sizeOfPackage) { // Create message + m_Data = new char[sizeOfPackage]; memcpy(m_Data, data, sizeOfPackage); m_Offset = sizeOfPackage; } diff --git a/src/Game/PlayerSystem.cpp b/src/Game/PlayerSystem.cpp index 6c7e8311..f10dba28 100644 --- a/src/Game/PlayerSystem.cpp +++ b/src/Game/PlayerSystem.cpp @@ -2,17 +2,17 @@ void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) { - (glm::vec3)player["Velocity"] = glm::vec3(0.f, 0.f, 0.f); - if (static_cast(player["Forward"])== true) { + player["Velocity"] = glm::vec3(0.f, 0.f, 0.f); + if ((bool&)player["Forward"] == true) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt) * -1; } - if (static_cast(player["Left"]) == true) { + if ((bool&)player["Left"] == true) { ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt) * -1; } - if (static_cast(player["Back"]) == true) { + if ((bool&)player["Back"] == true) { ((glm::vec3&)player["Velocity"]).z = m_Speed * float(dt); } - if (static_cast(player["Right"]) == true) { + if ((bool&)player["Right"] == true) { ((glm::vec3&)player["Velocity"]).x = m_Speed * float(dt); } From 58a9d38e266344776aeda44fccbdb512b9aea4b9 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 16 Dec 2015 14:56:53 +0100 Subject: [PATCH 100/185] Added a class that client and server inherits from. Class and server now share the same pointer i game. You are now able to start a client and a server on the same computer. --- include/Engine/Network/Client.h | 4 ++-- include/Engine/Network/Network.h | 19 +++++++++++++++ include/Engine/Network/Server.h | 3 ++- include/Game/Game.h | 6 ++--- src/Engine/Network/Client.cpp | 2 +- src/Engine/Network/Network.cpp | 13 +++++++++++ src/Game/Game.cpp | 40 +++++++++++++++++++------------- 7 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 include/Engine/Network/Network.h create mode 100644 src/Engine/Network/Network.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 80958142..21f6ec61 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -17,9 +17,9 @@ #include "Core/EKeyDown.h" #include "Core/EKeyUp.h" #include "Input/EInputCommand.h" +#include "Network/Network.h" - -class Client +class Client : public Network { public: Client(); diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h new file mode 100644 index 00000000..e3b9c1ce --- /dev/null +++ b/include/Engine/Network/Network.h @@ -0,0 +1,19 @@ +#ifndef Network_h__ +#define Network_h__ + +#include "Core/World.h" +#include "Core/EventBroker.h" +#include "Network/Package.h" + +class Network +{ +public: + Network(); + ~Network(); + virtual void Start(World* m_world, EventBroker *eventBroker); + virtual void Update(); +protected: + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index a9ddceb0..fb49e707 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -14,8 +14,9 @@ #include "Core/World.h" #include "Core/EventBroker.h" #include "Game/ECreatePlayer.h" +#include "Network/Network.h" -class Server +class Server : public Network { public: Server(); diff --git a/include/Game/Game.h b/include/Game/Game.h index 2ff1d770..1b8f9bcf 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -21,6 +21,7 @@ // Network #include +#include "Network/Network.h" #include "Network/Server.h" #include "Network/Client.h" @@ -50,9 +51,8 @@ private: // Network methods void NetworkFunction(); - Client m_Client; - Server m_Server; - bool m_IsClient = false; + Network* m_ClientOrServer; + bool m_IsClientOrServer = false; EventRelay m_EInputCommand; bool debugOnInputCommand(const Events::InputCommand& e); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 01bc9cba..a4199b8e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,8 +5,8 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - // Set up network stream m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp new file mode 100644 index 00000000..51a93407 --- /dev/null +++ b/src/Engine/Network/Network.cpp @@ -0,0 +1,13 @@ +#include "Network/Network.h" + +Network::Network() +{ } + +Network::~Network() +{ } + +void Network::Start(World * m_world, EventBroker * eventBroker) +{ } + +void Network::Update() +{ } \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index a242f64d..6080b8f5 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -20,7 +20,7 @@ Game::Game(int argc, char* argv[]) m_Renderer = new Renderer(m_EventBroker); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); - m_Renderer->SetResolution(Rectangle::Rectangle( + m_Renderer->SetResolution(Rectangle::Rectangle( 0, 0, m_Config->Get("Video.Width", 1280), @@ -53,9 +53,9 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - // Invoke network - if(m_Config->Get("Networking.StartNetwork", false) == true) - boost::thread workerThread(&Game::NetworkFunction, this); + // Invoke network + if (m_Config->Get("Networking.StartNetwork", false) == true) + boost::thread workerThread(&Game::NetworkFunction, this); m_LastTime = glfwGetTime(); debugInitialize(); @@ -90,7 +90,9 @@ void Game::Tick() m_EventBroker->Swap(); // Update network - m_IsClient ? m_Client.Update() : m_Server.Update(); + if (m_IsClientOrServer) + m_ClientOrServer->Update(); + // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); @@ -133,16 +135,22 @@ void Game::debugTick(double dt) } void Game::NetworkFunction() -{ - std::string inputMessage; - std::cout << "Start client or server? (c/s)" << std::endl; - std::cin >> inputMessage; - if (inputMessage == "c" || inputMessage == "C") { - m_IsClient = true; - m_Client.Start(m_World, m_EventBroker); - } - if (inputMessage == "s" || inputMessage == "S") { - m_IsClient = false; - m_Server.Start(m_World, m_EventBroker); +{ + std::string inputMessage; + std::cout << "Start client or server? (c/s)" << std::endl; + std::cin >> inputMessage; + if (inputMessage == "c" || inputMessage == "C") { + m_IsClientOrServer = true; + m_ClientOrServer = new Client(); } + if (inputMessage == "s" || inputMessage == "S") { + m_IsClientOrServer = true; + m_ClientOrServer = new Server(); + } + m_ClientOrServer->Start(m_World, m_EventBroker); + // I don't think we are reaching this part of the code right now. + // When server or client is done set it to false. + m_IsClientOrServer = false; + // Destroy it! (with fire) + delete m_ClientOrServer; } \ No newline at end of file From 6da5fd1263a8c831fe3a87811412ee73d05f13b0 Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 16 Dec 2015 15:47:51 +0100 Subject: [PATCH 101/185] Restructured code and added bool to stop client from spamming Snapshots to a server when it wasn't connected to one. --- include/Engine/Network/Client.h | 52 ++++++++++++++++----------------- include/Engine/Network/Server.h | 2 +- src/Engine/Network/Client.cpp | 7 ++++- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 21f6ec61..00d05a94 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -27,57 +27,57 @@ public: void Start(World* world, EventBroker* eventBroker); void Update(); void Close(); -private: - void ReadFromServer(); - void SendSnapshotToServer(); - int Receive(char* data, size_t length); - void Send(Package& message); - int CreateMessage(MessageType type, std::string message, char* data); - void Connect(); - void Disconnect(); - void Ping(); - void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void ParseMessageType(Package& package); - void ParseEventMessage(Package& package); - void ParseConnect(Package& package); - void ParsePing(); - void ParseServerPing(); - void ParseSnapshot(Package& package); - void CreateNewPlayer(int i); - void IdentifyPacketLoss(); +private: // udp stuff boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; - + //Connection logic + bool m_IsConnected = false; // Packet loss logic unsigned int m_PacketID = 0; unsigned int m_PreviousPacketID = 0; unsigned int m_SendPacketID = 0; - // Game Logic + glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; + PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; std::vector m_PlayersToCreate; - - World* m_World; - int m_PlayerID = -1; - glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; - PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; SnapshotDefinitions m_NextSnapshot; std::clock_t m_StartPingTime; double m_DurationOfPingTime; std::string m_PlayerName; bool m_ThreadIsRunning = true; + int m_PlayerID = -1; + World* m_World; // Use to check if we should send disconnect message // if game is turned of by closing window. bool m_WasStarted = false; IsWASDKeyDown m_IsWASDKeyDown; - // Events EventBroker* m_EventBroker; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand &e); + + // Network functions + void ReadFromServer(); + void SendSnapshotToServer(); + int Receive(char* data, size_t length); + void Send(Package& message); + int CreateMessage(MessageType type, std::string message, char* data); + void Connect(); + void Disconnect(); + void Ping(); + void MoveMessageHead(char*& data, size_t& length, size_t stepSize); + void ParseMessageType(Package& package); + void ParseEventMessage(Package& package); + void ParseConnect(Package& package); + void ParsePing(); + void ParseServerPing(); + void ParseSnapshot(Package& package); + void CreateNewPlayer(int i); + void IdentifyPacketLoss(); }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index fb49e707..65a69bba 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -50,7 +50,7 @@ private: void ReadFromClients(); void InputLoop(); - + // Network functions int Receive(char* data, size_t length); void Send(Package& package, int playerID); void Send(Package& package); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index a4199b8e..b980bfde 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -56,6 +56,7 @@ void Client::Close() if (m_WasStarted) { Disconnect(); m_ThreadIsRunning = false; + m_IsConnected = false; m_EventBroker->Unsubscribe(m_EInputCommand); } } @@ -78,7 +79,9 @@ void Client::ReadFromServer() } std::clock_t currentTime = std::clock(); if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendSnapshotToServer(); + if (m_IsConnected) { + SendSnapshotToServer(); + } previousSnapshotMessage = currentTime; } } @@ -168,6 +171,7 @@ void Client::ParseConnect(Package& package) m_PacketID = package.PopFrontPrimitive(); m_PreviousPacketID = m_PacketID; m_PlayerID = package.PopFrontPrimitive(); + m_IsConnected = true; std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } @@ -267,6 +271,7 @@ void Client::Connect() void Client::Disconnect() { + m_IsConnected = false; Package message(MessageType::Connect, m_SendPacketID); message.AddString("+Disconnect"); Send(message); From 6d1cbd928ed2f84445d9390efdfcb992e0beb493 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 16 Dec 2015 16:34:27 +0100 Subject: [PATCH 102/185] Improved collision logic, still not perfect since it updates before PlayerSystem. --- include/Engine/Collision/Collision.h | 3 +++ src/Engine/Collision/Collision.cpp | 34 ++++++++++++++++++++++++ src/Engine/Collision/CollisionSystem.cpp | 17 ++++++------ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 1fcb910e..64bf2d2c 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -41,6 +41,9 @@ bool RayVsModel(const Ray& ray, //Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); +//Return true if the boxes are intersecting. +//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); 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]. diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 500d59bc..d9cf8a0e 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -81,6 +81,40 @@ namespace Collision return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1])); } + bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation) + { + minimumTranslation = glm::vec3(0, 0, 0); + const glm::vec3& aMax = a.MaxCorner(); + const glm::vec3& bMax = b.MaxCorner(); + const glm::vec3& aMin = a.MinCorner(); + const glm::vec3& bMin = b.MinCorner(); + const glm::vec3& bSize = b.Size(); + const glm::vec3& aSize = a.Size(); + float minOffset = INFINITY; + float off; + auto axisesIntersecting = glm::tvec3(false, false, false); + for (int i = 0; i < 3; ++i) { + off = bMax[i] - aMin[i]; + if (off > 0 && off < bSize[i] + aSize[i]) { + if (off < minOffset) { + minimumTranslation = glm::vec3(); + minimumTranslation[i] = minOffset = off; + } + axisesIntersecting[i] = true; + } + off = aMax[i] - bMin[i]; + if (off > 0 && off < bSize[i] + aSize[i]) { + if (off < minOffset) { + minOffset = off; + minimumTranslation = glm::vec3(); + minimumTranslation[i] = -off; + } + axisesIntersecting[i] = true; + } + } + return glm::all(axisesIntersecting); + } + bool RayVsModel(const Ray& ray, const std::vector& modelVertices, const std::vector& modelIndices) diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index ee5d4d29..dec33a20 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -4,15 +4,18 @@ void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt) { - //cAABB is any entity that should be collideable. + //TODO: Update CollisionSystem system after PlayerSystem. + + //Right now, cAABB is a component attached to any entity that should be collideable. AABB thisBox; if (!Collision::GetEntityBox(world, cAABB, thisBox)) { return; } - //Here c should be an object that moves, currently only players. + //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) { continue; @@ -21,13 +24,11 @@ void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, d if (!Collision::GetEntityBox(world, mover.EntityID, otherBox)) { continue; } - if (Collision::AABBVsAABB(thisBox, otherBox)) { + glm::vec3 resolveTranslation; + if (Collision::AABBVsAABB(otherBox, thisBox, resolveTranslation)) { ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform"); - //TODO: Move entity to correct position on collision instead of this. Special treatment if both are movers. - glm::vec3 newPos = trans["Position"]; - float moveSpeed = 0.12f; - newPos += moveSpeed * glm::normalize(newPos - thisBox.Center()); - trans["Position"] = newPos; + //TODO: Special treatment if both are movers. + trans["Position"] = (glm::vec3)trans["Position"] + resolveTranslation; } } } From 425f3ca3dd7bbb89ac4f65c88876f55e0f37701a Mon Sep 17 00:00:00 2001 From: Jocke Date: Wed, 16 Dec 2015 16:49:18 +0100 Subject: [PATCH 103/185] Fixed "trying to read more than package size" warnings. --- src/Engine/Network/Client.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index b980bfde..52037577 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -38,7 +38,7 @@ void Client::Start(World* world, EventBroker* eventBroker) } void Client::Update() -{ +{ while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; unsigned int tempID = m_World->CreateEntity(); @@ -117,7 +117,7 @@ void Client::SendSnapshotToServer() package.AddString("0Forward"); Send(package); } - + if (m_NextSnapshot.InputRight != "") { @@ -168,8 +168,6 @@ void Client::ParseMessageType(Package& package) void Client::ParseConnect(Package& package) { - m_PacketID = package.PopFrontPrimitive(); - m_PreviousPacketID = m_PacketID; m_PlayerID = package.PopFrontPrimitive(); m_IsConnected = true; std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; @@ -210,7 +208,7 @@ void Client::ParseSnapshot(Package& package) // We're checking for empty name for now. This might not be the best way, // but it is to avoid sending redundant data. tempName = package.PopFrontString(); - + // Apply the position data read to the player entity // New player connected on the server side @@ -225,13 +223,13 @@ void Client::ParseSnapshot(Package& package) // Not a connected player break; } - // Read position data - glm::vec3 playerPos; - playerPos.x = package.PopFrontPrimitive(); - playerPos.y = package.PopFrontPrimitive(); - playerPos.z = package.PopFrontPrimitive(); - // Move player to server position if (m_PlayerDefinitions[i].EntityID != -1) { + // Read position data + glm::vec3 playerPos; + playerPos.x = package.PopFrontPrimitive(); + playerPos.y = package.PopFrontPrimitive(); + playerPos.z = package.PopFrontPrimitive(); + // Move player to server position m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; } } @@ -296,8 +294,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e) if (e.Command == "Forward") { if (e.Value > 0) { m_IsWASDKeyDown.W = true; - } - else if (e.Value < 0) { + } else if (e.Value < 0) { m_IsWASDKeyDown.S = true; } else { m_IsWASDKeyDown.W = false; @@ -333,6 +330,6 @@ void Client::IdentifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - LOG_INFO("%i Packet(s) were lost...", difference); + LOG_INFO("%i Packet(s) were lost...", difference); } } From a23d69af9a884ef0839e09fc5827e882aeb4dee1 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 16 Dec 2015 17:08:55 +0100 Subject: [PATCH 104/185] Removed old relics from OctTree testing in OctTree. --- include/Engine/Core/OctTree.h | 8 ++---- src/Engine/Core/OctTree.cpp | 48 ----------------------------------- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index a3715480..c09ab63e 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -4,8 +4,6 @@ #include "Core/AABB.h" struct Ray; -class World; -class Camera; class OctTree { @@ -20,8 +18,8 @@ public: //For the root OctTree, [octTreeBounds] should be a box containing the entire level. OctTree(const AABB& octTreeBounds, int subDivisions); - //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. + //We cannot copy the OctTree as of now, because of the recursive dynamic allocation. + //Define these if the OctTree suddenly needs to be copied, think of the children OctChild* ptrs. OctTree(const OctTree& other) = delete; OctTree(const OctTree&& other) = delete; OctTree& operator= (const OctTree& other) = delete; @@ -36,8 +34,6 @@ public: //Empty the tree of all dynamic objects. Static objects remain in the tree. void ClearDynamicObjects(); - //Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system? - void Update(float dt, World* world, Camera* cam); //Returns true if the ray collides with something in the tree. Result is written to [data]. bool RayCollides(const Ray& ray, Output& data); //Returns true if the box collides with something in the tree. diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 8c262faf..31b32cec 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -4,8 +4,6 @@ #include "Core/OctTree.h" #include "Collision/Collision.h" -#include "Core/World.h" -#include "Rendering/Camera.h" namespace { @@ -151,52 +149,6 @@ OctTree::OctChild::~OctChild() } } -void OctTree::Update(float dt, World* world, Camera* cam) -{ - for (ComponentWrapper& c : *world->GetComponents("Collision")) { - AABB aabb; - aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]); - AddDynamicObject(aabb); - } - const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1); - const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1); - const glm::vec4 blueCol = glm::vec4(0.1f, 0.05f, 0.95f, 1); - const glm::vec4 cyanCol = glm::vec4(0.1f, 0.9f, 0.85f, 1); - const glm::vec3 boxSize = 0.05f*glm::vec3(1.0f, 1.0f, 1.0f); - - if (!m_UpdatedOnce) { - m_BoxID = world->CreateEntity(); - ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform"); - transform["Scale"] = boxSize; - - ComponentWrapper model = world->AttachComponent(m_BoxID, "Model"); - model["Resource"] = "Models/Core/UnitBox.obj"; - m_UpdatedOnce = true; - } - - AABB box; - auto boxPos = cam->Position() + 1.2f*cam->Forward(); - box.CreateFromCenter(boxPos, boxSize); - ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform"); - transform["Position"] = boxPos; - ComponentWrapper model = world->GetComponent(m_BoxID, "Model"); - bool collBox = BoxCollides(box, AABB()); - if (collBox) { - cam->SetPosition(m_PrevPos); - cam->SetOrientation(m_PrevOri); - bool collRay = RayCollides({ cam->Position(), cam->Forward() }, Output()); - model["Color"] = collRay ? cyanCol : greenCol; - } else if (RayCollides({ cam->Position(), cam->Forward() }, Output())) { - model["Color"] = blueCol; - } else { - model["Color"] = redCol; - } - - m_PrevPos = cam->Position(); - m_PrevOri = cam->Orientation(); - ClearDynamicObjects(); -} - bool OctTree::OctChild::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const { if (hasChildren()) { From 97a0d97b0b4141cd98aac16cd99b40e9696f3dd4 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 16 Dec 2015 17:56:44 +0100 Subject: [PATCH 105/185] Can now send transform components. --- include/Engine/Network/Package.h | 5 +++++ src/Engine/Network/Client.cpp | 19 +++++++++++-------- src/Engine/Network/Package.cpp | 16 ++++++++++++++++ src/Engine/Network/Server.cpp | 15 ++++++++------- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h index a7b3c126..9b45101d 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Package.h @@ -14,6 +14,7 @@ public: Package(MessageType type, unsigned int& packageID); // Used to create package from already existing data buffer. Package(char* data, const int sizeOfPackage); + ~Package(); // Add primitive types like int, float, char... template @@ -35,9 +36,13 @@ public: m_ReturnDataOffset += sizeof(T); return returnValue; } + // Add a string to the message void AddString(std::string str); + // Add data to the message + void AddData(char* data, int sizeOfData); // Pops the first element as if it was a string. std::string PopFrontString(); + char* PopData(int SizeOfData); int Size() { return m_Offset; }; char* Data() { return m_Data; }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index a4199b8e..9c16b6e9 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,7 +5,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; @@ -165,8 +165,6 @@ void Client::ParseMessageType(Package& package) void Client::ParseConnect(Package& package) { - m_PacketID = package.PopFrontPrimitive(); - m_PreviousPacketID = m_PacketID; m_PlayerID = package.PopFrontPrimitive(); std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; } @@ -222,13 +220,18 @@ void Client::ParseSnapshot(Package& package) break; } // Read position data - glm::vec3 playerPos; - playerPos.x = package.PopFrontPrimitive(); - playerPos.y = package.PopFrontPrimitive(); - playerPos.z = package.PopFrontPrimitive(); + //glm::vec3 playerPos; + //playerPos.x = package.PopFrontPrimitive(); + //playerPos.y = package.PopFrontPrimitive(); + //playerPos.z = package.PopFrontPrimitive(); + + + // Move player to server position if (m_PlayerDefinitions[i].EntityID != -1) { - m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + //m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; + int dataSize = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Info.Meta.Stride; + memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, package.PopData(dataSize), dataSize); } } } diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index a30d3ee5..43c28837 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -33,6 +33,15 @@ void Package::AddString(std::string str) m_Offset += (str.size() + 1) * sizeof(char); } +void Package::AddData(char * data, int sizeOfData) +{ + if (m_Offset + sizeOfData > 128) { + LOG_WARNING("Package::AddData(): Data size in package exceeded maximum package size.\n"); + } + memcpy(m_Data + m_Offset, data, sizeOfData); + m_Offset += sizeOfData; +} + std::string Package::PopFrontString() { std::string returnValue(m_Data + m_ReturnDataOffset); @@ -44,3 +53,10 @@ std::string Package::PopFrontString() m_ReturnDataOffset += returnValue.size() + 1; return returnValue; } + +char * Package::PopData(int SizeOfData) +{ + unsigned int oldReturnDataOffset = m_ReturnDataOffset; + m_ReturnDataOffset += SizeOfData; + return (m_Data + oldReturnDataOffset); +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 3d9d171a..d1d0c4c7 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -229,13 +229,14 @@ void Server::SendSnapshot() continue; } - - // Pack player pos into data package - glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; - //glm::vec3 playerPos = glm::vec3(1.0f); - package.AddPrimitive(playerPos.x); - package.AddPrimitive(playerPos.y); - package.AddPrimitive(playerPos.z); + //// Pack player pos into data package + //glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; + ////glm::vec3 playerPos = glm::vec3(1.0f); + //package.AddPrimitive(playerPos.x); + //package.AddPrimitive(playerPos.y); + //package.AddPrimitive(playerPos.z); + auto transform = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform"); + package.AddData(transform.Data, transform.Info.Meta.Stride); } Broadcast(package); } From 6a3c14540d1d75bc7f83d1bde2c2bdb62b67eed1 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 17 Dec 2015 10:38:13 +0100 Subject: [PATCH 106/185] fixes --- include/Engine/Rendering/Renderer.h | 2 + resources/Schema/Entities/Test.xml | 13 ++++-- resources/Shaders/ForwardPlus.frag.glsl | 13 +++--- resources/Shaders/GridFrustum.comp.glsl | 58 ++++++++++++------------- resources/Shaders/cullLights.comp.glsl | 15 ++----- src/Engine/Rendering/Renderer.cpp | 13 +----- 6 files changed, 51 insertions(+), 63 deletions(-) diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 63b41b32..fad41c5f 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -67,6 +67,7 @@ private: glm::vec3 Normal; float d; }; + struct Frustum { Plane Planes[4]; }; @@ -90,6 +91,7 @@ private: float Amount; glm::vec2 Padding; }; + LightGrid m_LightGrid[80*45]; int m_LightOffset = 0; diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 78494ce1..f8be48a7 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -5,11 +5,18 @@ - - Models/DummyScene.obj - + + + + + + + Models/Core/UnitPlane.obj + + + diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index e3a3f05c..685a8d22 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -7,6 +7,7 @@ uniform vec4 Color; uniform sampler2D texture0; +#define TILE_SIZE 16 struct PointLight { vec4 Position; @@ -48,7 +49,7 @@ in VertexData{ out vec4 fragmentColor; -vec4 scene_ambient = vec4(0.6,0.6,0.6,1); +vec4 scene_ambient = vec4(0.0,0.0,0.0,1); struct LightResult { vec4 Diffuse; @@ -98,10 +99,10 @@ void main() LightResult totalLighting; totalLighting.Diffuse = scene_ambient; + int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * 80)); - - int start = int(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Start); - int amount = int(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount); + int start = int(LightGrids.Data[currentTile].Start); + int amount = int(LightGrids.Data[currentTile].Amount); //for(int i = 0; i < 3; i++) for(int i = start; i < start + amount; i++) { @@ -114,11 +115,11 @@ void main() } fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; - + fragmentColor += vec4(LightGrids.Data[currentTile].Amount/3.0, 0, 0, 1); //fragmentColor = texel * Input.DiffuseColor * Color; if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { - fragmentColor = vec4(0.5, 0, 0, 0); + //fragmentColor = vec4(0.5, 0, 0, 0); } else { //fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1); diff --git a/resources/Shaders/GridFrustum.comp.glsl b/resources/Shaders/GridFrustum.comp.glsl index 523852d5..9e0f5a8e 100644 --- a/resources/Shaders/GridFrustum.comp.glsl +++ b/resources/Shaders/GridFrustum.comp.glsl @@ -16,7 +16,7 @@ struct Frustum { layout (std430, binding = 0) buffer FrustumBuffer { - Frustum Data[3600]; + Frustum Data[]; } Frustums; vec4 ConvertToView(vec4 ScreenCoords) @@ -43,36 +43,32 @@ Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 ) layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main () { - if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) { - //Top-Left = 0 | Top-Right = 1 - //Bottom-Left = 2 | Bottom-Right = 3 - vec4 ScreenCoords[4]; - ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1 - ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0); - ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); - ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); + //Top-Left = 0 | Top-Right = 1 + //Bottom-Left = 2 | Bottom-Right = 3 + vec4 ScreenCoords[4]; + ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); - vec3 ViewVectors[4]; - for(int i = 0; i < 4; i++) { - ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i])); - } - - vec3 EyePos = vec3(0,0,0); - - Frustum f; - f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); - f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); - f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); - f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); - - - - - if ( gl_GlobalInvocationID.x < ScreenDimensions.x / TILE_SIZE && gl_GlobalInvocationID.y < ScreenDimensions.y / TILE_SIZE ) { // innanför skärmen? - Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f; - - } - - + vec3 ViewVectors[4]; + for(int i = 0; i < 4; i++) { + ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i])); } + + vec3 EyePos = vec3(0,0,0); + + Frustum f; + f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); + f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); + f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); + f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); + + + + + if ( gl_GlobalInvocationID.x < ScreenDimensions.x / TILE_SIZE && gl_GlobalInvocationID.y < ScreenDimensions.y / TILE_SIZE ) { // inside the screen + Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f; + + } } \ No newline at end of file diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index 012d72a7..ecb0e8e6 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -25,7 +25,7 @@ struct Frustum { layout (std430, binding = 0) buffer FrustumBuffer { - Frustum Data[3600]; + Frustum Data[]; } Frustums; struct PointLight { @@ -111,11 +111,9 @@ void main () if(gl_LocalInvocationIndex == 0) { GroupLightCount = 0; - GroupFrustum = Frustums.Data[GroupIndex]; } - memoryBarrierShared(); barrier(); for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) @@ -124,7 +122,7 @@ void main () //if pointlight //Pos i view antagligen - if(SphereInsideFrustrum(vec3(V * light.Position), light.Radius, GroupFrustum)) + if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum)) { //TODO: Fix transparent and opaque list, and depth test. AppendLight( i ); @@ -137,20 +135,15 @@ void main () } - memoryBarrierShared(); barrier(); if(gl_LocalInvocationIndex == 0) { GroupLightIndexStartOffset = atomicAdd(LightOffset[0], GroupLightCount); - LightGrid g; - g.Start = GroupLightIndexStartOffset; - g.Amount = GroupLightCount; - g.Padding = vec2(1111, 1111); - LightGrids.Data[GroupIndex] = g; + LightGrids.Data[GroupIndex].Start = GroupLightIndexStartOffset; + LightGrids.Data[GroupIndex].Amount = GroupLightCount; } - memoryBarrierShared(); barrier(); for (uint i = gl_LocalInvocationIndex; i < GroupLightCount; i += TILE_SIZE * TILE_SIZE ) diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index b838bdbc..24e82cfd 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -265,7 +265,7 @@ void Renderer::CalculateFrustum() void Renderer::TEMPCreateLights() { for (int i = 0; i < NUM_LIGHTS; i++) { - m_PointLights[i].Position = glm::vec4(5.f * (i-1), -1.5f, 0.f, 1.f); + m_PointLights[i].Position = glm::vec4(5.f * (i-1), 1.f, 0.f, 1.f); m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); m_PointLights[i].Radius = 2.f; } @@ -280,17 +280,6 @@ void Renderer::CullLights() glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); From 4c29e071af1bfa04c1722179df77117e23d2db34 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 10:47:08 +0100 Subject: [PATCH 107/185] Cleaned code --- include/Engine/Network/Client.h | 73 ++++++++++++++++----------------- src/Engine/Network/Client.cpp | 17 ++++---- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 21f6ec61..415a8847 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -5,7 +5,6 @@ #include #include -#include // For input event #include "Network/MessageType.h" #include "Network/NetworkDefinitions.h" @@ -14,68 +13,66 @@ #include "Network/WinLeakCheck.h" #include "Core/World.h" #include "Core/EventBroker.h" -#include "Core/EKeyDown.h" -#include "Core/EKeyUp.h" #include "Input/EInputCommand.h" #include "Network/Network.h" class Client : public Network { public: - Client(); - ~Client(); - void Start(World* world, EventBroker* eventBroker); + Client(); + ~Client(); + void Start(World* world, EventBroker* eventBroker); void Update(); void Close(); private: - void ReadFromServer(); - void SendSnapshotToServer(); + void ReadFromServer(); + void SendSnapshotToServer(); - int Receive(char* data, size_t length); - void Send(Package& message); - int CreateMessage(MessageType type, std::string message, char* data); + int Receive(char* data, size_t length); + void Send(Package& message); void Connect(); void Disconnect(); void Ping(); - void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void ParseMessageType(Package& package); - void ParseEventMessage(Package& package); - void ParseConnect(Package& package); - void ParsePing(); - void ParseServerPing(); - void ParseSnapshot(Package& package); - void CreateNewPlayer(int i); - void IdentifyPacketLoss(); + void MoveMessageHead(char*& data, size_t& length, size_t stepSize); + void ParseMessageType(Package& package); + void ParseEventMessage(Package& package); + void ParseConnect(Package& package); + void ParsePing(); + void ParseServerPing(); + void ParseSnapshot(Package& package); + void CreateNewPlayer(int i); + void IdentifyPacketLoss(); - // udp stuff - boost::asio::ip::udp::endpoint m_ReceiverEndpoint; - boost::asio::io_service m_IOService; - boost::asio::ip::udp::socket m_Socket; + // UDP logic + boost::asio::ip::udp::endpoint m_ReceiverEndpoint; + boost::asio::io_service m_IOService; + boost::asio::ip::udp::socket m_Socket; - // Packet loss logic + // Packet loss logic unsigned int m_PacketID = 0; - unsigned int m_PreviousPacketID = 0; + unsigned int m_PreviousPacketID = 0; unsigned int m_SendPacketID = 0; - // Game Logic + // Game logic + World* m_World; std::vector m_PlayersToCreate; + glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; + std::string m_PlayerName; + int m_PlayerID = -1; + IsWASDKeyDown m_IsWASDKeyDown; - World* m_World; - int m_PlayerID = -1; - glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; - PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; - SnapshotDefinitions m_NextSnapshot; - std::clock_t m_StartPingTime; - double m_DurationOfPingTime; - std::string m_PlayerName; + // Network logic + PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; + SnapshotDefinitions m_NextSnapshot; bool m_ThreadIsRunning = true; + double m_DurationOfPingTime; + std::clock_t m_StartPingTime; // Use to check if we should send disconnect message // if game is turned of by closing window. bool m_WasStarted = false; - IsWASDKeyDown m_IsWASDKeyDown; - // Events - EventBroker* m_EventBroker; + // Events + EventBroker* m_EventBroker; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand &e); }; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 9c16b6e9..29b7ddde 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,7 +5,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; @@ -38,7 +38,7 @@ void Client::Start(World* world, EventBroker* eventBroker) } void Client::Update() -{ +{ while (m_PlayersToCreate.size() > 0) { unsigned int i = m_PlayersToCreate.size() - 1; unsigned int tempID = m_World->CreateEntity(); @@ -114,7 +114,7 @@ void Client::SendSnapshotToServer() package.AddString("0Forward"); Send(package); } - + if (m_NextSnapshot.InputRight != "") { @@ -204,7 +204,7 @@ void Client::ParseSnapshot(Package& package) // We're checking for empty name for now. This might not be the best way, // but it is to avoid sending redundant data. tempName = package.PopFrontString(); - + // Apply the position data read to the player entity // New player connected on the server side @@ -225,7 +225,7 @@ void Client::ParseSnapshot(Package& package) //playerPos.y = package.PopFrontPrimitive(); //playerPos.z = package.PopFrontPrimitive(); - + // Move player to server position if (m_PlayerDefinitions[i].EntityID != -1) { @@ -294,8 +294,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e) if (e.Command == "Forward") { if (e.Value > 0) { m_IsWASDKeyDown.W = true; - } - else if (e.Value < 0) { + } else if (e.Value < 0) { m_IsWASDKeyDown.S = true; } else { m_IsWASDKeyDown.W = false; @@ -312,7 +311,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e) m_IsWASDKeyDown.D = false; } } - if (e.Command == "Sprint") { // Temp connect + if (e.Command == "Sprint") { // Connect for now Connect(); } return false; @@ -331,6 +330,6 @@ void Client::IdentifyPacketLoss() // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; if (difference != 1) { - LOG_INFO("%i Packet(s) were lost...", difference); + LOG_INFO("%i Packet(s) were lost...", difference); } } From ba831f8a3c38c94d42ec9ab4814a837eb8acb8db Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 10:59:55 +0100 Subject: [PATCH 108/185] WIP Cleaning --- include/Engine/Network/Client.h | 1 - src/Engine/Network/Client.cpp | 33 ++++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 415a8847..025a1259 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -59,7 +59,6 @@ private: glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; std::string m_PlayerName; int m_PlayerID = -1; - IsWASDKeyDown m_IsWASDKeyDown; // Network logic PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 29b7ddde..c2c486ab 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,7 +5,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; @@ -89,19 +89,23 @@ void Client::SendSnapshotToServer() // Reset previouse key state in snapshot. m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; + + auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); + + // See if any movement keys are down // We dont care if it's overwritten by later // if statement. Watcha gonna do, right! - if (m_IsWASDKeyDown.W) { + if (player["Forward"]) { m_NextSnapshot.InputForward = "+Forward"; } - if (m_IsWASDKeyDown.A) { + if (player["Left"]) { m_NextSnapshot.InputRight = "-Right"; } - if (m_IsWASDKeyDown.S) { + if (player["Back"]) { m_NextSnapshot.InputForward = "-Forward"; } - if (m_IsWASDKeyDown.D) { + if (player["Right"]) { m_NextSnapshot.InputRight = "+Right"; } @@ -115,8 +119,6 @@ void Client::SendSnapshotToServer() Send(package); } - - if (m_NextSnapshot.InputRight != "") { Package package(MessageType::Event, m_SendPacketID); package.AddString(m_NextSnapshot.InputRight); @@ -291,24 +293,25 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) bool Client::OnInputCommand(const Events::InputCommand & e) { + ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); if (e.Command == "Forward") { if (e.Value > 0) { - m_IsWASDKeyDown.W = true; + (bool&)player["Forward"] = true; } else if (e.Value < 0) { - m_IsWASDKeyDown.S = true; + (bool&)player["Back"] = true; } else { - m_IsWASDKeyDown.W = false; - m_IsWASDKeyDown.S = false; + (bool&)player["Forward"] = false; + (bool&)player["Back"] = false; } } if (e.Command == "Right") { if (e.Value > 0) { - m_IsWASDKeyDown.D = true; + (bool&)player["Right"] = true; } else if (e.Value < 0) { - m_IsWASDKeyDown.A = true; + (bool&)player["Left"] = true; } else { - m_IsWASDKeyDown.A = false; - m_IsWASDKeyDown.D = false; + (bool&)player["Left"] = false; + (bool&)player["Right"] = false; } } if (e.Command == "Sprint") { // Connect for now From 4bb4e2951510528611c82a801e5cd52f9b02ae9a Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 13:23:15 +0100 Subject: [PATCH 109/185] More cleaning code --- include/Engine/Network/Client.h | 39 ++++++------ include/Engine/Network/Server.h | 16 +++-- src/Engine/Network/Client.cpp | 31 ++++----- src/Engine/Network/Server.cpp | 108 ++++++++------------------------ src/Game/Game.cpp | 2 +- 5 files changed, 68 insertions(+), 128 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index ce71b1b1..24b59b59 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -25,25 +25,6 @@ public: void Update(); void Close(); private: - void ReadFromServer(); - void SendSnapshotToServer(); - - int Receive(char* data, size_t length); - void Send(Package& message); - void Connect(); - void Disconnect(); - void Ping(); - void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void ParseMessageType(Package& package); - void ParseEventMessage(Package& package); - void ParseConnect(Package& package); - void ParsePing(); - void ParseServerPing(); - void ParseSnapshot(Package& package); - void CreateNewPlayer(int i); - void IdentifyPacketLoss(); - bool IsConnected(); - // UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; @@ -75,6 +56,26 @@ private: EventBroker* m_EventBroker; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand &e); + + void ReadFromServer(); + void SendSnapshotToServer(); + + int Receive(char* data, size_t length); + void Send(Package& message); + void Connect(); + void Disconnect(); + void Ping(); + void MoveMessageHead(char*& data, size_t& length, size_t stepSize); + void ParseMessageType(Package& package); + void ParseEventMessage(Package& package); + void ParseConnect(Package& package); + void ParsePing(); + void ParseServerPing(); + void ParseSnapshot(Package& package); + void CreateNewPlayer(int i); + void IdentifyPacketLoss(); + bool IsConnected(); + }; #endif diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 65a69bba..eb625b0d 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -4,8 +4,6 @@ #include #include -#include -#include #include #include "Network/MessageType.h" @@ -13,7 +11,6 @@ #include "Network/PlayerDefinition.h" #include "Core/World.h" #include "Core/EventBroker.h" -#include "Game/ECreatePlayer.h" #include "Network/Network.h" class Server : public Network @@ -26,32 +23,33 @@ public: void Close(); private: - // udp stuff + // UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; + //Timers std::clock_t m_StartPingTime; std::clock_t m_StopTimes[8]; + // Game logic World* m_World; EventBroker* m_EventBroker; - // size = players to create, stores playerID + // size = ammount of players to create, stores playerID's std::vector m_PlayersToCreate; + // Packet loss logic unsigned int m_PacketID; unsigned int m_PreviousPacketID; unsigned int m_SendPacketID; + // Close logic bool m_ThreadIsRunning = true; - // Threaded - void DisplayLoop(); - void ReadFromClients(); - void InputLoop(); // Network functions int Receive(char* data, size_t length); + void ReadFromClients(); void Send(Package& package, int playerID); void Send(Package& package); void MoveMessageHead(char*& data, size_t& length, size_t stepSize); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index dd0a02bb..bc727e49 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -26,14 +26,15 @@ void Client::Start(World* world, EventBroker* eventBroker) // Subscribe to events m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EInputCommand); - std::cout << "Please enter you name: "; + + LOG_INFO("Please enter your name: "); std::cin >> m_PlayerName; while (m_PlayerName.size() > 7) { - std::cout << "Please enter you name(No longer than 7 characters): "; + LOG_INFO("Please enter your name (No longer than 7 characters):"); std::cin >> m_PlayerName; } m_Socket.connect(m_ReceiverEndpoint); - std::cout << "I am client. BIP BOP\n"; + LOG_INFO("I am client. BIP BOP"); ReadFromServer(); } @@ -170,13 +171,13 @@ void Client::ParseMessageType(Package& package) void Client::ParseConnect(Package& package) { m_PlayerID = package.PopFrontPrimitive(); - std::cout << m_PacketID << ": I am player: " << m_PlayerID << std::endl; + LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); } void Client::ParsePing() { m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); - std::cout << m_PacketID << ": response time with ctime(ms): " << m_DurationOfPingTime << std::endl; + LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime); } void Client::ParseServerPing() @@ -184,7 +185,6 @@ void Client::ParseServerPing() Package message(MessageType::ServerPing, m_SendPacketID); message.AddString("Ping recieved"); Send(message); - //std::cout << "Parsing ping." << std::endl; } void Client::ParseEventMessage(Package& package) @@ -196,13 +196,12 @@ void Client::ParseEventMessage(Package& package) // Sett Player name m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { - std::cout << m_PacketID << ": Event message: " << command << std::endl; + LOG_INFO("%i: Event message: %s", m_PacketID, command); } } void Client::ParseSnapshot(Package& package) { - //std::cout << m_PacketID << ": Parsing incoming snapshot." << std::endl; std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, @@ -224,16 +223,8 @@ void Client::ParseSnapshot(Package& package) break; } if (m_PlayerDefinitions[i].EntityID != -1) { - // Read position data - //glm::vec3 playerPos; - //playerPos.x = package.PopFrontPrimitive(); - //playerPos.y = package.PopFrontPrimitive(); - //playerPos.z = package.PopFrontPrimitive(); - - // Move player to server position - //m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"] = playerPos; int dataSize = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Info.Meta.Stride; memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, package.PopData(dataSize), dataSize); } @@ -250,7 +241,7 @@ int Client::Receive(char* data, size_t length) 0, error); if (error) { - std::cout << "ReadFromServer crashed: " << error.message(); + LOG_ERROR("ReadFromServer: %s", error.message()); } return bytesReceived; @@ -295,13 +286,15 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) bool Client::OnInputCommand(const Events::InputCommand & e) { - if (m_PlayerID != -1) { + if (IsConnected()) { ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); if (e.Command == "Forward") { if (e.Value > 0) { (bool&)player["Forward"] = true; + (bool&)player["Back"] = false; } else if (e.Value < 0) { (bool&)player["Back"] = true; + (bool&)player["Forward"] = false; } else { (bool&)player["Forward"] = false; (bool&)player["Back"] = false; @@ -310,8 +303,10 @@ bool Client::OnInputCommand(const Events::InputCommand & e) if (e.Command == "Right") { if (e.Value > 0) { (bool&)player["Right"] = true; + (bool&)player["Left"] = false; } else if (e.Value < 0) { (bool&)player["Left"] = true; + (bool&)player["Right"] = false; } else { (bool&)player["Left"] = false; (bool&)player["Right"] = false; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index d1d0c4c7..e66c0680 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -14,15 +14,9 @@ void Server::Start(World* world, EventBroker* eventBroker) for (size_t i = 0; i < MAXCONNECTIONS; i++) { m_StopTimes[i] = std::clock(); } - boost::thread_group threads; + LOG_INFO("I am Server. BIP BOP\n"); - std::cout << "I am Server. BIP BOP\n"; - - threads.create_thread(boost::bind(&Server::DisplayLoop, this)); - threads.create_thread(boost::bind(&Server::ReadFromClients, this)); - threads.create_thread(boost::bind(&Server::InputLoop, this)); - - threads.join_all(); + ReadFromClients(); } void Server::Update() @@ -46,45 +40,35 @@ void Server::Close() m_ThreadIsRunning = false; } -void Server::DisplayLoop() -{ - -} - void Server::ReadFromClients() { - char readBuf[1024] = { 0 }; + char readBuffer[1024] = { 0 }; int bytesRead = 0; // time for previouse message std::clock_t previousePingMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock(); std::clock_t timOutTimer = std::clock(); // How often we send messages (milliseconds) - int intervallMs = 1000; + int intervalMs = 1000; int snapshotInterval = 50; - int timeToCheckTimeOutTime = 100; + int checkTimeOutInterval = 100; while (m_ThreadIsRunning) { // m_ThreadIsRunning might be unnecessary but the // program crashed if it executed m_Socket.available() // when closing the program. - // If available message -> Socket.available() = true if (m_ThreadIsRunning && m_Socket.available()) { try { - bytesRead = Receive(readBuf, INPUTSIZE); - Package package(readBuf, bytesRead); + bytesRead = Receive(readBuffer, INPUTSIZE); + Package package(readBuffer, bytesRead); ParseMessageType(package); } catch (const std::exception& err) { - // To not spam "socket closed messages" - //if (std::string(err.what()).find("forcefully closed") != std::string::npos) { - std::cout << m_PacketID << ": Read from client crashed: " << err.what(); - //} + LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } } std::clock_t currentTime = std::clock(); - // int tempTestRemovePlz = (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC); // Send snapshot if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { SendSnapshot(); @@ -92,44 +76,19 @@ void Server::ReadFromClients() } // Send pings each - if (intervallMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { SendPing(); previousePingMessage = currentTime; } // Time out logic - if (timeToCheckTimeOutTime < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { CheckForTimeOuts(); timOutTimer = currentTime; } } } -void Server::InputLoop() -{ - char inputBuffer[INPUTSIZE] = { 0 }; - std::string inputMessage; - - while (m_ThreadIsRunning) { - std::cin.getline(inputBuffer, INPUTSIZE); - inputMessage = (std::string)inputBuffer; - - if (!inputMessage.empty()) { - try { - // Broadcast message typed in console - Broadcast(inputMessage); - - } catch (const std::exception& err) { - std::cout << m_PacketID << ": Read from WriteLoop crashed: " << err.what(); - } - } - if (inputMessage.find("exit") != std::string::npos) - exit(1); - inputMessage.clear(); - memset(inputBuffer, 0, INPUTSIZE); - } -} - void Server::ParseMessageType(Package& package) { int messageType = package.PopFrontPrimitive(); // Read what type off message was sent from server @@ -137,7 +96,7 @@ void Server::ParseMessageType(Package& package) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = package.PopFrontPrimitive(); //Read new packet id - //IdentifyPacketLoss(); + IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: ParseConnect(package); @@ -221,22 +180,16 @@ void Server::SendSnapshot() { Package package(MessageType::Snapshot, m_SendPacketID); for (size_t i = 0; i < MAXCONNECTIONS; i++) { - + // Send an empty name if there is no player connected on this position. package.AddString(m_PlayerDefinitions[i].Name); if (m_PlayerDefinitions[i].EntityID == -1) { continue; } - - //// Pack player pos into data package - //glm::vec3 playerPos = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform")["Position"]; - ////glm::vec3 playerPos = glm::vec3(1.0f); - //package.AddPrimitive(playerPos.x); - //package.AddPrimitive(playerPos.y); - //package.AddPrimitive(playerPos.z); + // Pack transfrom component into data package auto transform = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform"); - package.AddData(transform.Data, transform.Info.Meta.Stride); + package.AddData(transform.Data, transform.Info.Meta.Stride); } Broadcast(package); } @@ -245,9 +198,10 @@ void Server::SendPing() { // Prints connected players ping for (size_t i = 0; i < MAXCONNECTIONS; i++) { - if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) - std::cout << m_PacketID << ": Player " << i << "'s ping: " << 1000 * (m_StopTimes[i] - m_StartPingTime) - / static_cast(CLOCKS_PER_SEC) << std::endl; + if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { + int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + LOG_INFO("%i: Player %i's ping: %i", m_PacketID, i, ping); + } } // Create ping message @@ -262,15 +216,15 @@ void Server::SendPing() void Server::CheckForTimeOuts() { int timeOutTimeMs = 5000; - int tempStartPing = 1000 * m_StartPingTime + int startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); for (size_t i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - int tempStopPing = 1000 * m_StopTimes[i] + int stopPing = 1000 * m_StopTimes[i] / static_cast(CLOCKS_PER_SEC); - if (tempStartPing > tempStopPing + timeOutTimeMs) { - std::cout << "player " << i << " timed out!" << std::endl; + if (startPing > stopPing + timeOutTimeMs) { + LOG_INFO("Player %i timed out!", i); Disconnect(i); } } @@ -280,7 +234,7 @@ void Server::CheckForTimeOuts() void Server::Disconnect(int i) { Broadcast("A player disconnected"); - std::cout << "Player " << i << " disconnected/Timed out" << std::endl; + LOG_INFO("Player %i disconnected/timed out", i); // Remove enteties and stuff m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint(); @@ -326,7 +280,7 @@ void Server::ParseEvent(Package& package) void Server::ParseConnect(Package& package) { - std::cout << "Parsing connection." << std::endl; + LOG_INFO("Parsing connections"); // Check if player is already connected for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { @@ -336,13 +290,6 @@ void Server::ParseConnect(Package& package) for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { - - //Events::CreatePlayer e; - //e.entityID = (m_PlayerDefinitions[i].EntityID); - //e.modelPath = "Models/Core/UnitSphere.obj"; - //e.world = m_World; - //m_EventBroker->Publish(e); - // Create new player m_PlayersToCreate.push_back(i); @@ -351,8 +298,7 @@ void Server::ParseConnect(Package& package) m_StopTimes[i] = std::clock(); - std::cout << m_PacketID << ": Player \"" << m_PlayerDefinitions[i].Name << "\" connected on IP: " << - m_PlayerDefinitions[i].Endpoint.address().to_string() << std::endl; + LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name, m_PlayerDefinitions[i].Endpoint.address().to_string()); Package package(MessageType::Connect, m_SendPacketID); package.AddPrimitive(i); // Player ID @@ -370,7 +316,7 @@ void Server::ParseConnect(Package& package) void Server::ParseDisconnect() { - std::cout << m_PacketID << ":Parsing disconnect. \n"; + LOG_INFO("%i: Parsing disconnect", m_PacketID); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { @@ -382,7 +328,7 @@ void Server::ParseDisconnect() void Server::ParseClientPing() { - std::cout << m_PacketID << ":Parsing ping." << std::endl; + LOG_INFO("%i: Parsing ping", m_PacketID); // Return ping Package package(MessageType::ClientPing, m_SendPacketID); package.AddString("Ping received"); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 6080b8f5..5f583f31 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -137,7 +137,7 @@ void Game::debugTick(double dt) void Game::NetworkFunction() { std::string inputMessage; - std::cout << "Start client or server? (c/s)" << std::endl; + LOG_INFO("Start client or server? (c/s)"); std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { m_IsClientOrServer = true; From 03d5f0dd674e486dfdbcbabced4f48875731285d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 13:31:54 +0100 Subject: [PATCH 110/185] Added an macro IF_DEBUG_IS(x) that executes if run in debug mode, AABB has a check so max and min corners are set properly in debug mode. --- include/Engine/Common.h | 3 ++- include/Engine/Core/Util/IfDebug.h | 17 +++++++++++++++++ src/Engine/Core/AABB.cpp | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 include/Engine/Core/Util/IfDebug.h diff --git a/include/Engine/Common.h b/include/Engine/Common.h index 2469a11d..ebdc90d0 100644 --- a/include/Engine/Common.h +++ b/include/Engine/Common.h @@ -4,4 +4,5 @@ #include #include -#include "Core/Util/Logging.h" \ No newline at end of file +#include "Core/Util/Logging.h" +#include "Core/Util/IfDebug.h" \ No newline at end of file diff --git a/include/Engine/Core/Util/IfDebug.h b/include/Engine/Core/Util/IfDebug.h new file mode 100644 index 00000000..159162c5 --- /dev/null +++ b/include/Engine/Core/Util/IfDebug.h @@ -0,0 +1,17 @@ +//Example: +//IF_DEBUG_IS(true) { +// //Stuff done only in debug mode. +//} +// +//IF_DEBUG_IS(false) { +// //Stuff done only in release mode. +//} else { +// //Stuff only in debug. +//} +#ifndef IF_DEBUG_IS +#ifndef DEBUG +#define IF_DEBUG_IS(c) if(c) +#else +#define IF_DEBUG_IS(c) if(!c) +#endif +#endif \ No newline at end of file diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index 05403022..b1da6b26 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -1,11 +1,24 @@ #include "Core/AABB.h" +#include "Common.h" AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) : m_MinCorner(minPos) , m_MaxCorner(maxPos) , m_Center(0.5f * (maxPos + minPos)) , m_HalfSize(0.5f * (maxPos - minPos)) -{} +{ + IF_DEBUG_IS(true) { + if (glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) { + LOG_WARNING("AABB maxCorner coordinates are not greater than minCorner"); + m_MaxCorner.x = glm::max(m_MaxCorner.x, m_MinCorner.x); + m_MinCorner.x = glm::min(m_MaxCorner.x, m_MinCorner.x); + m_MaxCorner.y = glm::max(m_MaxCorner.y, m_MinCorner.y); + m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y); + m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z); + m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z); + } + } +} AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos) : AABB(glm::vec3(minPos), glm::vec3(maxPos)) From 5160a45b446a9b30a85e35161e0442010b27fcfd Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 13:41:34 +0100 Subject: [PATCH 111/185] Made Ray into a class with checks so the direction will always be normalized. --- include/Engine/Collision/Collision.h | 4 +++ include/Engine/Core/OctTree.h | 2 +- include/Engine/Core/Ray.h | 25 +++++++++++-- src/Engine/Collision/Collision.cpp | 33 ++++++++--------- src/Engine/Core/OctTree.cpp | 2 +- src/Tests/CollisionTest.cpp | 53 ++++++++++------------------ src/Tests/OldOctTree.cpp | 2 +- src/Tests/OldOctTree.h | 2 +- 8 files changed, 66 insertions(+), 57 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 64bf2d2c..714cee3f 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -1,6 +1,10 @@ #ifndef Collision_h__ #define Collision_h__ +//NOTE: Collision.h needs to be #included before , +//because Collision #includes "RawModel.h", which has "Texture.h", which has "OpenGL.h" which must be #included first +//or you will get "fatal error C1189: #error: gl.h included before glew.h" + #include #include "Core/Ray.h" diff --git a/include/Engine/Core/OctTree.h b/include/Engine/Core/OctTree.h index c09ab63e..cdb21fbb 100644 --- a/include/Engine/Core/OctTree.h +++ b/include/Engine/Core/OctTree.h @@ -3,7 +3,7 @@ #include "Core/AABB.h" -struct Ray; +class Ray; class OctTree { diff --git a/include/Engine/Core/Ray.h b/include/Engine/Core/Ray.h index 64392cbc..2ed192a2 100644 --- a/include/Engine/Core/Ray.h +++ b/include/Engine/Core/Ray.h @@ -2,11 +2,30 @@ #define Ray_h__ #include "../GLM.h" +#include "Common.h" -struct Ray +class Ray { - glm::vec3 Origin; - glm::vec3 Direction; +public: + Ray(const glm::vec3& origin, const glm::vec3& dir) + : m_Origin(origin) + , m_Direction(glm::normalize(dir)) + { + IF_DEBUG_IS(true) { + if (glm::any(glm::isnan(m_Direction))) { + LOG_WARNING("Ray Direction was set to the zero-vector, expect unknown side effects and/or crashes."); + } + } + } + const glm::vec3& Origin() const { return m_Origin; } + const glm::vec3& Direction() const { return m_Direction; } + //Sets the ray origin at parameter. + void SetOrigin(const glm::vec3& origin) { m_Origin = origin; } + //Normalizes the parameter and sets direction to it. + void SetDirection(const glm::vec3& direction) { m_Direction = glm::normalize(direction); } +private: + glm::vec3 m_Origin; + glm::vec3 m_Direction; }; #endif // Ray_h__ diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d9cf8a0e..ec6c471c 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -11,9 +11,9 @@ namespace Collision //note: this one hasnt been delta adjusted like RayVsAABB has bool RayAABBIntr(const Ray& ray, const AABB& box) { - glm::vec3 w = 75.0f * ray.Direction; + 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.Center() + w; glm::vec3 half = box.HalfSize(); if (abs(c.x) > v.x + half.x) { @@ -43,14 +43,15 @@ namespace Collision bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance) { - glm::vec3 invdir = 1.0f / ray.Direction; + glm::vec3 invdir = 1.0f / ray.Direction(); + glm::vec3 origin = ray.Origin(); - float t1 = (box.MinCorner().x - ray.Origin.x)*invdir.x; - float t2 = (box.MaxCorner().x - ray.Origin.x)*invdir.x; - float t3 = (box.MinCorner().y - ray.Origin.y)*invdir.y; - float t4 = (box.MaxCorner().y - ray.Origin.y)*invdir.y; - float t5 = (box.MinCorner().z - ray.Origin.z)*invdir.z; - float t6 = (box.MaxCorner().z - ray.Origin.z)*invdir.z; + float t1 = (box.MinCorner().x - origin.x)*invdir.x; + float t2 = (box.MaxCorner().x - origin.x)*invdir.x; + float t3 = (box.MinCorner().y - origin.y)*invdir.y; + float t4 = (box.MaxCorner().y - origin.y)*invdir.y; + float t5 = (box.MinCorner().z - origin.z)*invdir.z; + float t6 = (box.MaxCorner().z - origin.z)*invdir.z; float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); @@ -123,16 +124,16 @@ namespace Collision glm::vec3 v0 = modelVertices[modelIndices[i]].Position; glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin - v0; + glm::vec3 m = ray.Origin() - v0; glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction, e2); + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2); float DetInv = glm::dot(e1, DxE2); if (std::abs(DetInv) < FLT_EPSILON) { continue; } DetInv = 1.0f / DetInv; float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction, MxE1) * DetInv; + float v = glm::dot(ray.Direction(), MxE1) * DetInv; //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { continue; @@ -158,9 +159,9 @@ namespace Collision glm::vec3 v0 = modelVertices[modelIndices[i]].Position; glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin - v0; + glm::vec3 m = ray.Origin() - v0; glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction, e2);//pVec + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec float DetInv = glm::dot(e1, DxE2); if (std::abs(DetInv) < FLT_EPSILON) { continue; @@ -171,7 +172,7 @@ namespace Collision continue; } float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction, MxE1) * DetInv; + float v = glm::dot(ray.Direction(), MxE1) * DetInv; //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem //If u and v are positive, u+v <= 1, dist is positive, and less than closest. @@ -194,7 +195,7 @@ namespace Collision float v; float dist; bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v); - outHitPosition = ray.Origin + dist * ray.Direction; + outHitPosition = ray.Origin() + dist * ray.Direction(); return hit; } diff --git a/src/Engine/Core/OctTree.cpp b/src/Engine/Core/OctTree.cpp index 31b32cec..c1d8c64e 100644 --- a/src/Engine/Core/OctTree.cpp +++ b/src/Engine/Core/OctTree.cpp @@ -192,7 +192,7 @@ bool OctTree::OctChild::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.Center()) }); } 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. diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 82e2e800..e6a29298 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -26,16 +26,14 @@ using boost::unit_test_framework::test_case; void RayTest(std::string fileName) { //simple box test - Ray ray; - ray.Origin = glm::vec3(-50, 0, 0); - ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); + Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0)); //using a rawmodel here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); - BOOST_CHECK(unitBox != nullptr); + BOOST_REQUIRE(unitBox != nullptr); bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); BOOST_CHECK(hit); - ray.Direction = glm::normalize(glm::vec3(-1, 0, 0)); + ray.SetDirection(glm::vec3(-1, 0, 0)); hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); BOOST_CHECK(!hit); } @@ -49,7 +47,6 @@ BOOST_AUTO_TEST_CASE(collisionTest) //fixed seed srand(2); - Ray ray; AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; @@ -57,12 +54,10 @@ BOOST_AUTO_TEST_CASE(collisionTest) 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; + Ray ray( + glm::vec3(rand() % 100, rand() % 100, rand() % 100), + glm::vec3(rand() % 100, rand() % 100, rand() % 100) + ); minPos.x = rand() % 100; minPos.y = rand() % 100; minPos.z = rand() % 100; @@ -83,7 +78,6 @@ BOOST_AUTO_TEST_CASE(collisionTest2) { //fixed seed srand(2); - Ray ray; AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; @@ -91,12 +85,10 @@ BOOST_AUTO_TEST_CASE(collisionTest2) 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; + Ray ray( + glm::vec3(rand() % 100, rand() % 100, rand() % 100), + glm::vec3(rand() % 100, rand() % 100, rand() % 100) + ); minPos.x = rand() % 100; minPos.y = rand() % 100; minPos.z = rand() % 100; @@ -114,7 +106,7 @@ BOOST_AUTO_TEST_CASE(collisionTest2) BOOST_AUTO_TEST_CASE(rayVsModelTest) { //simple box test - RayTest("Models/Core/UnitBox.obj"); + RayTest("Models/Core/UnitCube.obj"); } BOOST_AUTO_TEST_CASE(rayVsModelTest2) @@ -125,7 +117,6 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) // srand(7676462); // srand(7462); srand(72); - Ray ray; AABB someAABB; glm::vec3 minPos; glm::vec3 maxPos; @@ -142,19 +133,13 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) 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; - ray.Origin /= 100; - ray.Origin = glm::vec3(-2, 0, 0); - ray.Direction /= 100; + Ray ray( + glm::vec3(-2, 0, 0), + glm::vec3(rand() % 100, rand() % 100, rand() % 100) + ); //if we normalize the ray.direction when its 0,0,0 then we get nan,nan,nan - thus we have this check to prevent that - if (ray.Direction.x < 0.0001f && ray.Direction.y < 0.0001f && ray.Direction.z < 0.0001f) + if (glm::any(glm::isnan(ray.Direction()))) continue; - ray.Direction = glm::normalize(ray.Direction); z = Collision::RayVsAABB(ray, someAABB); if (z) { @@ -224,10 +209,10 @@ BOOST_AUTO_TEST_CASE(octTest) tree.AddDynamicObject(AABB(mini, -0.9f*maxi)); OctTree::Output data; glm::vec3 origin = 3.0f * mini; - bool rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data); + bool rayIntersected = tree.RayCollides(Ray(origin , mini - origin), data); BOOST_CHECK(rayIntersected); tree.ClearDynamicObjects(); - rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data); + rayIntersected = tree.RayCollides(Ray(origin, mini - origin), data); BOOST_CHECK(!rayIntersected); } diff --git a/src/Tests/OldOctTree.cpp b/src/Tests/OldOctTree.cpp index 4aabf9ed..d3738ee6 100644 --- a/src/Tests/OldOctTree.cpp +++ b/src/Tests/OldOctTree.cpp @@ -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.Center()) }); } 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. diff --git a/src/Tests/OldOctTree.h b/src/Tests/OldOctTree.h index 316b9545..3b0eefdc 100644 --- a/src/Tests/OldOctTree.h +++ b/src/Tests/OldOctTree.h @@ -3,7 +3,7 @@ #include "Core/AABB.h" -struct Ray; +class Ray; class World; class Camera; From 3e2ffdb85bae2742f75abc9ce857d195b408cc8b Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 13:48:35 +0100 Subject: [PATCH 112/185] Fixed comment on Trigger events. --- include/Engine/Collision/ETrigger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Engine/Collision/ETrigger.h b/include/Engine/Collision/ETrigger.h index 8852ee8c..687c73fa 100644 --- a/include/Engine/Collision/ETrigger.h +++ b/include/Engine/Collision/ETrigger.h @@ -7,7 +7,7 @@ namespace Events { -/** Thrown once, when an entity is completely inside a trigger. */ +/** Thrown once, when an entity is only touching a trigger. */ struct TriggerTouch : Event { /** The id of the entity that touches the trigger. */ @@ -25,7 +25,7 @@ struct TriggerLeave : Event EntityID Trigger; }; -/** Thrown once, when an entity is completely inside a trigger. */ +/** Thrown once, when an entity is completely contained inside a trigger. */ struct TriggerEnter : Event { /** The id of the entity that entered the trigger. */ From 0f0a1ceca7448090476967db602c286427d7d881 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 14:22:31 +0100 Subject: [PATCH 113/185] No more fake packet loss --- src/Engine/Network/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 056b914e..474634d1 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -141,7 +141,7 @@ void Client::ParseMessageType(Package& package) // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id m_PacketID = package.PopFrontPrimitive(); //Read new packet id - IdentifyPacketLoss(); + //IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: From 51a2da9cc099db3a8a4c4db71232d8479af3e2dc Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 14:28:17 +0100 Subject: [PATCH 114/185] Removed old Event that is not used --- include/Game/ECreatePlayer.h | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 include/Game/ECreatePlayer.h diff --git a/include/Game/ECreatePlayer.h b/include/Game/ECreatePlayer.h deleted file mode 100644 index bbfd3c6d..00000000 --- a/include/Game/ECreatePlayer.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef Events_CreatePlayer_h__ -#define Events_CreatePlayer_h__ - -#include "Core/EventBroker.h" -#include "Core/World.h" - -namespace Events -{ - -struct CreatePlayer : Event -{ - unsigned int entityID; - std::string modelPath; - World* world; -}; - -} - -#endif From 000adb198fe2147dfa674e97ef04604396481f91 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 14:36:36 +0100 Subject: [PATCH 115/185] Reset RenderQueueFactory.cpp to original state --- src/Engine/Rendering/RenderQueueFactory.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Engine/Rendering/RenderQueueFactory.cpp b/src/Engine/Rendering/RenderQueueFactory.cpp index 747e68b1..8d5bb420 100644 --- a/src/Engine/Rendering/RenderQueueFactory.cpp +++ b/src/Engine/Rendering/RenderQueueFactory.cpp @@ -46,11 +46,9 @@ glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity) glm::quat orientation; do { - if (world->HasComponent(entity, "Transform")) { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation; - entity = world->GetParent(entity); - } + ComponentWrapper transform = world->GetComponent(entity, "Transform"); + orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation; + entity = world->GetParent(entity); } while (entity != 0); return orientation; @@ -61,11 +59,9 @@ glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity) glm::vec3 scale(1.f); do { - if (world->HasComponent(entity, "Transform")) { - ComponentWrapper transform = world->GetComponent(entity, "Transform"); - scale *= (glm::vec3)transform["Scale"]; - entity = world->GetParent(entity); - } + ComponentWrapper transform = world->GetComponent(entity, "Transform"); + scale *= (glm::vec3)transform["Scale"]; + entity = world->GetParent(entity); } while (entity != 0); return scale; From 800065400541c4650dfbd0719d555d69f5bb2008 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 15:28:05 +0100 Subject: [PATCH 116/185] Model loading now fetches material opacity value properly --- src/Engine/Rendering/RawModel.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Engine/Rendering/RawModel.cpp b/src/Engine/Rendering/RawModel.cpp index 5aec7f22..95a75a15 100644 --- a/src/Engine/Rendering/RawModel.cpp +++ b/src/Engine/Rendering/RawModel.cpp @@ -76,13 +76,15 @@ RawModel::RawModel(std::string fileName) } // Material diffuse color - aiColor4D diffuse; + aiColor3D diffuse; material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); - desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a); + float opacity; + material->Get(AI_MATKEY_OPACITY, opacity); + desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity); // Material specular color - aiColor4D specular; + aiColor3D specular; material->Get(AI_MATKEY_COLOR_SPECULAR, specular); - desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, specular.a); + desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, 1.f); m_Vertices.push_back(desc); } From c1b9404e524138c47edf83b2965221b44642bc66 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:26:12 +0100 Subject: [PATCH 117/185] Created a FileDropped event for when a file is dropped onto the client by the OS --- include/Engine/Core/EFileDropped.h | 16 ++++++++++++++++ include/Engine/Core/InputManager.h | 3 +++ src/Engine/Core/InputManager.cpp | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 include/Engine/Core/EFileDropped.h diff --git a/include/Engine/Core/EFileDropped.h b/include/Engine/Core/EFileDropped.h new file mode 100644 index 00000000..1ad22a2f --- /dev/null +++ b/include/Engine/Core/EFileDropped.h @@ -0,0 +1,16 @@ +#ifndef EFileDropped_h__ +#define EFileDropped_h__ + +#include "EventBroker.h" + +namespace Events +{ + +struct FileDropped : Event +{ + std::string Path; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/InputManager.h b/include/Engine/Core/InputManager.h index 0d53169e..3b035dbe 100644 --- a/include/Engine/Core/InputManager.h +++ b/include/Engine/Core/InputManager.h @@ -16,6 +16,7 @@ #include "ELockMouse.h" #include "EGamepadAxis.h" #include "EGamepadButton.h" +#include "EFileDropped.h" class InputManager { @@ -71,6 +72,8 @@ private: static void GLFWCharCallback(GLFWwindow* window, unsigned int c); static std::vector> GLFWScrollCallbackQueue; static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset); + static std::vector GLFWDropCallbackQueue; + static void GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]); }; #endif diff --git a/src/Engine/Core/InputManager.cpp b/src/Engine/Core/InputManager.cpp index cb901cb8..50dcac7c 100644 --- a/src/Engine/Core/InputManager.cpp +++ b/src/Engine/Core/InputManager.cpp @@ -2,6 +2,7 @@ std::vector InputManager::GLFWCharCallbackQueue; std::vector> InputManager::GLFWScrollCallbackQueue; +std::vector InputManager::GLFWDropCallbackQueue; void InputManager::Initialize() { @@ -10,6 +11,7 @@ void InputManager::Initialize() //m_LastGamepadButtonState = std::array(); glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback); glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback); + glfwSetDropCallback(m_GLFWWindow, &InputManager::GLFWDropCallback); EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse); EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse); @@ -95,6 +97,14 @@ void InputManager::Update(double dt) } GLFWScrollCallbackQueue.clear(); + // File drop + for (auto& path : GLFWDropCallbackQueue) { + Events::FileDropped e; + e.Path = path; + m_EventBroker->Publish(e); + } + GLFWDropCallbackQueue.clear(); + // // Lock mouse while holding LMB // if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT]) // { @@ -229,6 +239,14 @@ void InputManager::GLFWScrollCallback(GLFWwindow* window, double xoffset, double GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset)); } + +void InputManager::GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]) +{ + for (int i = 0; i < count; i++) { + GLFWDropCallbackQueue.push_back(std::string(paths[i])); + } +} + bool InputManager::OnLockMouse(const Events::LockMouse &event) { m_MouseLocked = true; From cf6dde6c092955e135111486304716d22f9619d9 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:26:55 +0100 Subject: [PATCH 118/185] Boost dependency updated to version 1.60! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b04f8ed..7c5f2268 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,4 @@ Libraries that are too big to be bundled with the project. | Project | Version | License | Root folder environment variable (Windows) | | ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ | -| **[Boost](http://www.boost.org)** | 1.59.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT | +| **[Boost](http://www.boost.org)** | 1.60.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT | From a655f0bae5f428361f41ca5c8e4da689c537baba Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:28:31 +0100 Subject: [PATCH 119/185] Drag-and-drop asset picking and base work for showing component field tooltips in the editor --- assets | 2 +- include/Engine/Editor/EditorSystem.h | 5 ++++ src/Engine/Editor/EditorSystem.cpp | 42 +++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/assets b/assets index c5f67434..673d4a4e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c5f674349a915ab1a2b4da632d87a9832d1f6fab +Subproject commit 673d4a4e4c5a3f5bc9fedf82234e8f8751f63a44 diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 021a14ca..6709775d 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -1,5 +1,6 @@ #include #include +#include #include "../Core/System.h" #include "../Core/EMousePress.h" #include "../Core/EMouseRelease.h" @@ -8,6 +9,7 @@ #include "../Input/EInputCommand.h" #include "../Rendering/IRenderer.h" #include "../Rendering/EPicking.h" +#include "../Core/EFileDropped.h" #include "../Rendering/RenderQueueFactory.h" class EditorSystem : public ImpureSystem @@ -50,6 +52,7 @@ private: EntityID m_Selection = 0; EntityID m_LastSelection = 0; glm::vec3 m_Position; + std::string m_LastDroppedFile; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); @@ -61,6 +64,8 @@ private: bool OnMouseMove(const Events::MouseMove& e); EventRelay m_EPicking; bool OnPicking(const Events::Picking& e); + EventRelay m_EFileDropped; + bool OnFileDropped(const Events::FileDropped& e); void updateWidget(); void setWidgetMode(WidgetMode newMode); diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 2463aec6..32f5b162 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -19,6 +19,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer) EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease); EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove); EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking); + EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped); } void EditorSystem::Update(World* world, double dt) @@ -36,6 +37,11 @@ void EditorSystem::Update(World* world, double dt) updateWidget(); drawUI(world, dt); + + // Clear drop queue if it wasn't handled by any UI element + if (!m_LastDroppedFile.empty()) { + m_LastDroppedFile = ""; + } } bool EditorSystem::OnInputCommand(const Events::InputCommand& e) @@ -212,6 +218,12 @@ bool EditorSystem::OnPicking(const Events::Picking& e) return true; }; +bool EditorSystem::OnFileDropped(const Events::FileDropped& e) +{ + m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string(); + std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/'); + return true; +} void EditorSystem::updateWidget() { @@ -389,37 +401,53 @@ void EditorSystem::drawUI(World* world, double dt) const std::string& field = pair.first; const std::string& type = pair.second; + ImGui::PushID(field.c_str()); if (type == "Vector") { auto& val = component.Property(field); if (field == "Scale") { - ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); } else if (field == "Orientation") { glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); - if (ImGui::SliderFloat3(field.c_str(), glm::value_ptr(tempVal), 0.f, glm::two_pi())) { + if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { val = tempVal; } } else { - ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); } } else if (type == "Color") { auto& val = component.Property(field); - ImGui::ColorEdit4(field.c_str(), glm::value_ptr(val), true); + ImGui::ColorEdit4("", glm::value_ptr(val), true); } else if (type == "string") { std::string& val = component.Property(field); char tempString[1024]; memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); - if (ImGui::InputText(field.c_str(), tempString, sizeof(tempString))) { + if (ImGui::InputText("", tempString, sizeof(tempString))) { val = std::string(tempString); LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str()); } + // DROP STUFF + if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { + val = m_LastDroppedFile; + m_LastDroppedFile = ""; + } + } else if (type == "double") { float tempVal = static_cast(component.Property(field)); - if (ImGui::InputFloat(field.c_str(), &tempVal, 0.01f, 1.f)) { + if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { component.SetProperty(field, static_cast(tempVal)); } } else if (type == "bool") { auto& val = component.Property(field); - ImGui::Checkbox(field.c_str(), &val); + ImGui::Checkbox("", &val); + } else { + ImGui::TextDisabled(type.c_str()); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::Text(field.c_str()); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("field annotation goes here"); } } } From 00f6056f7c28631d1fdab1166e1d3850909464b6 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 14:16:08 +0100 Subject: [PATCH 120/185] Uniform scaling when dragging scaling widget origin --- src/Engine/Editor/EditorSystem.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 32f5b162..ed615a50 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -153,6 +153,13 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"]; glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"]; glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"]; + + if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) { + float movementLength = glm::length(movement); + float dot = glm::dot((glm::vec3)widgetOrientation, movement); + movement = glm::vec3(movementLength) * glm::sign(dot); + (glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement; + } if (m_WidgetCurrentAxis.x > 0) { scaleX.x += movement.x; } @@ -162,14 +169,19 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) if (m_WidgetCurrentAxis.z > 0) { scaleZ.z += movement.z; } - if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) { - float max = glm::max(scaleX.x, glm::max(scaleY.y, scaleZ.z)); - (glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(max); - } (glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement; } } + + /*LOG_DEBUG("DELTA %f", e.DeltaX); + if (e.X < 0) { + glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y); + } + if (e.X >= width) { + glfwSetCursorPos(m_Renderer->Window(), 0, e.Y); + }*/ + return true; } @@ -287,7 +299,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj"; if (m_Selection != 0) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection)); } } else if (newMode == WidgetMode::Rotate) { m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj"; From e9128efd136b928d6c20f17a04bfbdb77437d0f2 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 14:26:20 +0100 Subject: [PATCH 121/185] Translation widget planes --- include/Engine/Editor/EditorSystem.h | 3 +++ src/Engine/Editor/EditorSystem.cpp | 33 +++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 6709775d..779b7f97 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -43,8 +43,11 @@ private: EntityID m_Widget = 0; EntityID m_WidgetX = 0; + EntityID m_WidgetPlaneX = 0; EntityID m_WidgetY = 0; + EntityID m_WidgetPlaneY = 0; EntityID m_WidgetZ = 0; + EntityID m_WidgetPlaneZ = 0; EntityID m_WidgetOrigin = 0; glm::vec3 m_WidgetCurrentAxis; float m_WidgetPickingDepth = 0.f; diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index ed615a50..a43ca900 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -85,6 +85,9 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) return false; } + if (m_Selection == 0) { + return false; + } auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); glm::vec3 widgetOrientation = widgetTransform["Orientation"]; @@ -207,9 +210,9 @@ bool EditorSystem::OnPicking(const Events::Picking& e) EntityID parent = m_World->GetParent(entity); if (parent == m_Widget) { m_WidgetCurrentAxis = glm::vec3( - (entity == m_WidgetX) || (entity == m_WidgetOrigin), - (entity == m_WidgetY) || (entity == m_WidgetOrigin), - (entity == m_WidgetZ) || (entity == m_WidgetOrigin) + (entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ), + (entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ), + (entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY) ); m_WidgetPickingDepth = result.Depth; @@ -245,12 +248,24 @@ void EditorSystem::updateWidget() m_WidgetX = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetX, "Transform"); m_World->AttachComponent(m_WidgetX, "Model"); + m_WidgetPlaneX = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneX, "Transform"); + m_World->AttachComponent(m_WidgetPlaneX, "Model"); + m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj"; m_WidgetY = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetY, "Transform"); m_World->AttachComponent(m_WidgetY, "Model"); + m_WidgetPlaneY = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneY, "Transform"); + m_World->AttachComponent(m_WidgetPlaneY, "Model"); + m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj"; m_WidgetZ = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetZ, "Transform"); m_World->AttachComponent(m_WidgetZ, "Model"); + m_WidgetPlaneZ = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneZ, "Transform"); + m_World->AttachComponent(m_WidgetPlaneZ, "Model"); + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj"; m_WidgetOrigin = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetOrigin, "Transform"); m_World->AttachComponent(m_WidgetOrigin, "Model"); @@ -276,15 +291,24 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); widgetTransform["Orientation"] = glm::vec3(0.f); m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; if (newMode == WidgetMode::Translate) { m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj"; m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj"; m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj"; - m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; + // Temporarily disabled for local space until I can figure out what's wrong with the math + if (m_WidgetSpace != WidgetSpace::Local) { + m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true; + m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true; + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true; + } if (m_Selection != 0) { if (m_WidgetSpace == WidgetSpace::Local) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); @@ -305,7 +329,6 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj"; m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj"; m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj"; - m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; if (m_Selection != 0) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); if (m_WidgetSpace == WidgetSpace::Local) { From 0f59b863eedb9f154c01de26c5df8aecc1cb123d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 17:08:47 +0100 Subject: [PATCH 122/185] Renamed IF_DEBUG_IS to DEBUG_IF, slightly different behavior and added some safety checking for auto creating AABBs from models. --- include/Engine/Core/Ray.h | 2 +- include/Engine/Core/Util/IfDebug.h | 21 ++- .../Schema/Entities/CollisionTestLevel.xml | 122 ++++++++++++++++++ src/Engine/Collision/Collision.cpp | 9 +- src/Engine/Core/AABB.cpp | 18 ++- 5 files changed, 146 insertions(+), 26 deletions(-) create mode 100644 resources/Schema/Entities/CollisionTestLevel.xml diff --git a/include/Engine/Core/Ray.h b/include/Engine/Core/Ray.h index 2ed192a2..0fcef01e 100644 --- a/include/Engine/Core/Ray.h +++ b/include/Engine/Core/Ray.h @@ -11,7 +11,7 @@ public: : m_Origin(origin) , m_Direction(glm::normalize(dir)) { - IF_DEBUG_IS(true) { + DEBUG_IF(true) { if (glm::any(glm::isnan(m_Direction))) { LOG_WARNING("Ray Direction was set to the zero-vector, expect unknown side effects and/or crashes."); } diff --git a/include/Engine/Core/Util/IfDebug.h b/include/Engine/Core/Util/IfDebug.h index 159162c5..79cb3a4c 100644 --- a/include/Engine/Core/Util/IfDebug.h +++ b/include/Engine/Core/Util/IfDebug.h @@ -1,17 +1,12 @@ -//Example: -//IF_DEBUG_IS(true) { -// //Stuff done only in debug mode. -//} -// -//IF_DEBUG_IS(false) { -// //Stuff done only in release mode. -//} else { -// //Stuff only in debug. -//} -#ifndef IF_DEBUG_IS +// Example: +// DEBUG_IF(condition) { +// // This code is executed only in debug mode and if condition is true. +// } +// NOTE: condition statement is not executed at all in release mode. +#ifndef DEBUG_IF #ifndef DEBUG -#define IF_DEBUG_IS(c) if(c) +#define DEBUG_IF(c) if(c) #else -#define IF_DEBUG_IS(c) if(!c) +#define DEBUG_IF(c) if(false) #endif #endif \ No newline at end of file diff --git a/resources/Schema/Entities/CollisionTestLevel.xml b/resources/Schema/Entities/CollisionTestLevel.xml new file mode 100644 index 00000000..99842b88 --- /dev/null +++ b/resources/Schema/Entities/CollisionTestLevel.xml @@ -0,0 +1,122 @@ + + + + + + + + + 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 diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index ec6c471c..dd2adec8 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -213,8 +213,11 @@ bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilo (std::abs(mi1.y - mi2.y) < epsilon); } -void attachAABBComponentFromModel(World* world, EntityID id) +bool attachAABBComponentFromModel(World* world, EntityID id) { + if (!world->HasComponent(id, "Model")) { + return false; + } ComponentWrapper model = world->GetComponent(id, "Model"); ComponentWrapper collision = world->AttachComponent(id, "AABB"); Model* modelRes = ResourceManager::Load(model["Resource"]); @@ -234,6 +237,7 @@ void attachAABBComponentFromModel(World* world, EntityID id) } collision["BoxCenter"] = 0.5f * (maxi + mini); collision["BoxSize"] = maxi - mini; + return true; } bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox) @@ -258,7 +262,8 @@ bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFrom { if (!world->HasComponent(entity, "AABB")) { if (forceBoxFromModel) { - attachAABBComponentFromModel(world, entity); + if (!attachAABBComponentFromModel(world, entity)) + return false; } else { return false; } diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index b1da6b26..0df56229 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -7,16 +7,14 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) , m_Center(0.5f * (maxPos + minPos)) , m_HalfSize(0.5f * (maxPos - minPos)) { - IF_DEBUG_IS(true) { - if (glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) { - LOG_WARNING("AABB maxCorner coordinates are not greater than minCorner"); - m_MaxCorner.x = glm::max(m_MaxCorner.x, m_MinCorner.x); - m_MinCorner.x = glm::min(m_MaxCorner.x, m_MinCorner.x); - m_MaxCorner.y = glm::max(m_MaxCorner.y, m_MinCorner.y); - m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y); - m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z); - m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z); - } + DEBUG_IF(glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) { + LOG_WARNING("AABB maxCorner coordinates are not greater than minCorner"); + m_MaxCorner.x = glm::max(m_MaxCorner.x, m_MinCorner.x); + m_MinCorner.x = glm::min(m_MaxCorner.x, m_MinCorner.x); + m_MaxCorner.y = glm::max(m_MaxCorner.y, m_MinCorner.y); + m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y); + m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z); + m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z); } } From 076030a252e555d6966861d1722a83feeceb6a0c Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 17:28:43 +0100 Subject: [PATCH 123/185] Fixes, mostly name changes --- include/Engine/Network/Client.h | 41 +++--- include/Engine/Network/Network.h | 2 +- include/Engine/Network/NetworkDefinitions.h | 2 +- .../Engine/Network/{Package.h => Packet.h} | 30 ++-- include/Engine/Network/Server.h | 40 +++--- include/Game/Game.h | 2 +- resources/DefaultConfig.ini | 8 +- src/Engine/Input/InputProxy.cpp | 4 +- src/Engine/Network/Client.cpp | 130 +++++++++--------- .../Network/{Package.cpp => Packet.cpp} | 34 ++--- src/Engine/Network/Server.cpp | 122 ++++++++-------- src/Game/Game.cpp | 10 +- 12 files changed, 212 insertions(+), 213 deletions(-) rename include/Engine/Network/{Package.h => Packet.h} (61%) rename src/Engine/Network/{Package.cpp => Packet.cpp} (53%) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 24b59b59..1bf2f059 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -25,7 +25,7 @@ public: void Update(); void Close(); private: - // UDP logic + // Assio UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; @@ -52,30 +52,29 @@ private: // if game is turned of by closing window. bool m_WasStarted = false; + // Private member functions + void readFromServer(); + void sendSnapshotToServer(); + int receive(char* data, size_t length); + void send(Packet& packet); + void connect(); + void disconnect(); + void ping(); + void moveMessageHead(char*& data, size_t& length, size_t stepSize); + void parseMessageType(Packet& packet); + void parseEventMessage(Packet& packet); + void parseConnect(Packet& packet); + void parsePing(); + void parseServerPing(); + void parseSnapshot(Packet& packet); + void createNewPlayer(int i); + void identifyPacketLoss(); + bool isConnected(); + // Events EventBroker* m_EventBroker; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand &e); - - void ReadFromServer(); - void SendSnapshotToServer(); - - int Receive(char* data, size_t length); - void Send(Package& message); - void Connect(); - void Disconnect(); - void Ping(); - void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void ParseMessageType(Package& package); - void ParseEventMessage(Package& package); - void ParseConnect(Package& package); - void ParsePing(); - void ParseServerPing(); - void ParseSnapshot(Package& package); - void CreateNewPlayer(int i); - void IdentifyPacketLoss(); - bool IsConnected(); - }; #endif diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index e3b9c1ce..d6447a3c 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -3,7 +3,7 @@ #include "Core/World.h" #include "Core/EventBroker.h" -#include "Network/Package.h" +#include "Network/Packet.h" class Network { diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index be76671e..5a86c50d 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -3,7 +3,7 @@ #include #include -#include "Network/Package.h" +#include "Network/Packet.h" #define BOARDSIZE 16 diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Packet.h similarity index 61% rename from include/Engine/Network/Package.h rename to include/Engine/Network/Packet.h index 9b45101d..f39cacc9 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Packet.h @@ -1,34 +1,34 @@ -#ifndef Package_h__ -#define Package_h__ +#ifndef Packet_h__ +#define Packet_h__ #include #include "Network/MessageType.h" #include "Core/Util/Logging.h" // Defines the -class Package +class Packet { public: // arg1: Type of message (Connect, Disconnect...) - // arg2: PackageID for identifying packet loss. - Package(MessageType type, unsigned int& packageID); - // Used to create package from already existing data buffer. - Package(char* data, const int sizeOfPackage); + // arg2: PacketID for identifying packet loss. + Packet(MessageType type, unsigned int& packetID); + // Used to create packet from already existing data buffer. + Packet(char* data, const int sizeOfPacket); - ~Package(); + ~Packet(); // Add primitive types like int, float, char... template - void AddPrimitive(T val) + void WritePrimitive(T val) { memcpy(m_Data + m_Offset, &val, sizeof(T)); m_Offset += sizeof(T); } // Pops the first element as if it was a primitive. template - T PopFrontPrimitive() + T ReadPrimitive() { if (m_Offset < m_ReturnDataOffset + sizeof(T)) { - LOG_WARNING("Package PopFrontPrimitive(): You are trying to remove more than what exists in this package!"); + LOG_WARNING("Packaet PopFrontPrimitive(): You are trying to remove more than what exists in this packet!"); return -1; } T returnValue; @@ -37,12 +37,12 @@ public: return returnValue; } // Add a string to the message - void AddString(std::string str); + void WriteString(std::string str); // Add data to the message - void AddData(char* data, int sizeOfData); + void WriteData(char* data, int sizeOfData); // Pops the first element as if it was a string. - std::string PopFrontString(); - char* PopData(int SizeOfData); + std::string ReadString(); + char* ReadData(int SizeOfData); int Size() { return m_Offset; }; char* Data() { return m_Data; }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index eb625b0d..17ca7136 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -47,26 +47,26 @@ private: // Close logic bool m_ThreadIsRunning = true; - // Network functions - int Receive(char* data, size_t length); - void ReadFromClients(); - void Send(Package& package, int playerID); - void Send(Package& package); - void MoveMessageHead(char*& data, size_t& length, size_t stepSize); - void Broadcast(std::string message); - void Broadcast(Package& package); - void SendSnapshot(); - void SendPing(); - void CheckForTimeOuts(); - void Disconnect(int i); - void ParseMessageType(Package& package); - void ParseEvent(Package& package); - void ParseConnect(Package& package); - void ParseDisconnect(); - void ParseClientPing(); - void ParseServerPing(); - void ParseSnapshot(Package& package); - void IdentifyPacketLoss(); + // Private member functions + int receive(char* data, size_t length); + void readFromClients(); + void send(Packet& packet, int playerID); + void send(Packet& packet); + void moveMessageHead(char*& data, size_t& length, size_t stepSize); + void broadcast(std::string message); + void broadcast(Packet& packet); + void sendSnapshot(); + void sendPing(); + void checkForTimeOuts(); + void disconnect(int i); + void parseMessageType(Packet& packet); + void parseEvent(Packet& packet); + void parseConnect(Packet& packet); + void parseDisconnect(); + void parseClientPing(); + void parseServerPing(); + void parseSnapshot(Packet& packet); + void identifyPacketLoss(); }; #endif diff --git a/include/Game/Game.h b/include/Game/Game.h index 1b8f9bcf..33dc88a6 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -50,7 +50,7 @@ private: boost::thread m_NetworkThread; // Network methods - void NetworkFunction(); + void networkFunction(); Network* m_ClientOrServer; bool m_IsClientOrServer = false; diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index c44c8e07..9e4fb885 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -6,14 +6,12 @@ EditorEnabled=false [Video] - Fullscreen=false - VSYNC=false - Width=1280 - Height=720 FOV=45 [Networking] -StartNetwork=false \ No newline at end of file +StartNetwork=false +Address=0.0.0.0 +Port=0 \ No newline at end of file diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp index ad589df3..c3e4d669 100644 --- a/src/Engine/Input/InputProxy.cpp +++ b/src/Engine/Input/InputProxy.cpp @@ -62,7 +62,7 @@ void InputProxy::Process() e.Command = command; e.Value = currentValue; m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); m_LastCommandValues[command] = currentValue; } } @@ -78,7 +78,7 @@ void InputProxy::Process() } //e.Value = std::max(-1.f, std::min(e.Value, 1.f)); m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); } m_CommandQueue.clear(); } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 474634d1..ade0c00e 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -35,7 +35,7 @@ void Client::Start(World* world, EventBroker* eventBroker) } m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); - ReadFromServer(); + readFromServer(); } void Client::Update() @@ -55,13 +55,13 @@ void Client::Update() void Client::Close() { if (m_WasStarted) { - Disconnect(); + disconnect(); m_ThreadIsRunning = false; m_EventBroker->Unsubscribe(m_EInputCommand); } } -void Client::ReadFromServer() +void Client::readFromServer() { int bytesRead = -1; char readBuf[1024] = { 0 }; @@ -71,23 +71,23 @@ void Client::ReadFromServer() while (m_ThreadIsRunning) { if (m_Socket.available()) { - bytesRead = Receive(readBuf, INPUTSIZE); + bytesRead = receive(readBuf, INPUTSIZE); if (bytesRead > 0) { - Package package(readBuf, bytesRead); - ParseMessageType(package); + Packet packet(readBuf, bytesRead); + parseMessageType(packet); } } std::clock_t currentTime = std::clock(); if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - if (IsConnected()) { - SendSnapshotToServer(); + if (isConnected()) { + sendSnapshotToServer(); } previousSnapshotMessage = currentTime; } } } -void Client::SendSnapshotToServer() +void Client::sendSnapshotToServer() { // Reset previouse key state in snapshot. m_NextSnapshot.InputForward = ""; @@ -113,86 +113,86 @@ void Client::SendSnapshotToServer() } if (m_NextSnapshot.InputForward != "") { - Package package(MessageType::Event, m_SendPacketID); - package.AddString(m_NextSnapshot.InputForward); - Send(package); + Packet packet(MessageType::Event, m_SendPacketID); + packet.WriteString(m_NextSnapshot.InputForward); + send(packet); } else { - Package package(MessageType::Event, m_SendPacketID); - package.AddString("0Forward"); - Send(package); + Packet packet(MessageType::Event, m_SendPacketID); + packet.WriteString("0Forward"); + send(packet); } if (m_NextSnapshot.InputRight != "") { - Package package(MessageType::Event, m_SendPacketID); - package.AddString(m_NextSnapshot.InputRight); - Send(package); + Packet packet(MessageType::Event, m_SendPacketID); + packet.WriteString(m_NextSnapshot.InputRight); + send(packet); } else { - Package package(MessageType::Event, m_SendPacketID); - package.AddString("0Right"); - Send(package); + Packet packet(MessageType::Event, m_SendPacketID); + packet.WriteString("0Right"); + send(packet); } } -void Client::ParseMessageType(Package& package) +void Client::parseMessageType(Packet& packet) { - int messageType = package.PopFrontPrimitive(); + int messageType = packet.ReadPrimitive(); if (messageType == -1) return; // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id - m_PacketID = package.PopFrontPrimitive(); //Read new packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id //IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: - ParseConnect(package); + parseConnect(packet); break; case MessageType::ClientPing: - ParsePing(); + parsePing(); break; case MessageType::ServerPing: - ParseServerPing(); + parseServerPing(); break; case MessageType::Message: break; case MessageType::Snapshot: - ParseSnapshot(package); + parseSnapshot(packet); break; case MessageType::Disconnect: break; case MessageType::Event: - ParseEventMessage(package); + parseEventMessage(packet); break; default: break; } } -void Client::ParseConnect(Package& package) +void Client::parseConnect(Packet& packet) { - m_PlayerID = package.PopFrontPrimitive(); + m_PlayerID = packet.ReadPrimitive(); LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID); } -void Client::ParsePing() +void Client::parsePing() { m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime); } -void Client::ParseServerPing() +void Client::parseServerPing() { - Package message(MessageType::ServerPing, m_SendPacketID); - message.AddString("Ping recieved"); - Send(message); + Packet message(MessageType::ServerPing, m_SendPacketID); + message.WriteString("Ping recieved"); + send(message); } -void Client::ParseEventMessage(Package& package) +void Client::parseEventMessage(Packet& packet) { int Id = -1; - std::string command = package.PopFrontString(); + std::string command = packet.ReadString(); if (command.find("+Player") != std::string::npos) { - Id = package.PopFrontPrimitive(); + Id = packet.ReadPrimitive(); // Sett Player name m_PlayerDefinitions[Id].Name = command.erase(0, 7); } else { @@ -200,13 +200,13 @@ void Client::ParseEventMessage(Package& package) } } -void Client::ParseSnapshot(Package& package) +void Client::parseSnapshot(Packet& packet) { std::string tempName; for (size_t i = 0; i < MAXCONNECTIONS; i++) { // We're checking for empty name for now. This might not be the best way, // but it is to avoid sending redundant data. - tempName = package.PopFrontString(); + tempName = packet.ReadString(); // Apply the position data read to the player entity @@ -226,12 +226,12 @@ void Client::ParseSnapshot(Package& package) // Move player to server position int dataSize = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Info.Meta.Stride; - memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, package.PopData(dataSize), dataSize); + memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, packet.ReadData(dataSize), dataSize); } } } -int Client::Receive(char* data, size_t length) +int Client::receive(char* data, size_t length) { boost::system::error_code error; @@ -241,44 +241,44 @@ int Client::Receive(char* data, size_t length) 0, error); if (error) { - //LOG_ERROR("Receive: %s", error.message().c_str()); + //LOG_ERROR("receive: %s", error.message().c_str()); } return bytesReceived; } -void Client::Send(Package& package) +void Client::send(Packet& packet) { m_Socket.send_to(boost::asio::buffer( - package.Data(), - package.Size()), + packet.Data(), + packet.Size()), m_ReceiverEndpoint, 0); } -void Client::Connect() +void Client::connect() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString(m_PlayerName); + Packet message(MessageType::Connect, m_SendPacketID); + message.WriteString(m_PlayerName); m_StartPingTime = std::clock(); - Send(message); + send(message); } -void Client::Disconnect() +void Client::disconnect() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString("+Disconnect"); - Send(message); + Packet message(MessageType::Connect, m_SendPacketID); + message.WriteString("+Disconnect"); + send(message); } -void Client::Ping() +void Client::ping() { - Package message(MessageType::Connect, m_SendPacketID); - message.AddString("Ping"); + Packet message(MessageType::Connect, m_SendPacketID); + message.WriteString("Ping"); m_StartPingTime = std::clock(); - Send(message); + send(message); } -void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) +void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize) { data += stepSize; length -= stepSize; @@ -286,7 +286,7 @@ void Client::MoveMessageHead(char*& data, size_t& length, size_t stepSize) bool Client::OnInputCommand(const Events::InputCommand & e) { - if (IsConnected()) { + if (isConnected()) { ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player"); if (e.Command == "Forward") { if (e.Value > 0) { @@ -314,12 +314,12 @@ bool Client::OnInputCommand(const Events::InputCommand & e) } } if (e.Command == "ConnectToServer") { // Connect for now - Connect(); + connect(); } return false; } -void Client::CreateNewPlayer(int i) +void Client::createNewPlayer(int i) { m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); @@ -327,7 +327,7 @@ void Client::CreateNewPlayer(int i) model["Resource"] = "Models/Core/UnitSphere.obj"; } -void Client::IdentifyPacketLoss() +void Client::identifyPacketLoss() { // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; @@ -336,7 +336,7 @@ void Client::IdentifyPacketLoss() } } -bool Client::IsConnected() +bool Client::isConnected() { if (m_PlayerID != -1) { if (m_PlayerDefinitions[m_PlayerID].EntityID != -1) { diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Packet.cpp similarity index 53% rename from src/Engine/Network/Package.cpp rename to src/Engine/Network/Packet.cpp index 43c28837..84f4c440 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Packet.cpp @@ -1,52 +1,52 @@ -#include "Network/Package.h" +#include "Network/Packet.h" -Package::Package(MessageType type, unsigned int& packageID) +Packet::Packet(MessageType type, unsigned int& packetID) { m_Data = new char[128]; // Create message header // Add message type int messageType = static_cast(type); - Package::AddPrimitive(messageType); - packageID = packageID % 1000; // Packet id modulos - Package::AddPrimitive(packageID); - packageID++; + Packet::WritePrimitive(messageType); + packetID = packetID % 1000; // Packet id modulos + Packet::WritePrimitive(packetID); + packetID++; } -Package::Package(char* data, const int sizeOfPackage) +Packet::Packet(char* data, const int sizeOfPacket) { // Create message - m_Data = new char[sizeOfPackage]; - memcpy(m_Data, data, sizeOfPackage); - m_Offset = sizeOfPackage; + m_Data = new char[sizeOfPacket]; + memcpy(m_Data, data, sizeOfPacket); + m_Offset = sizeOfPacket; } -Package::~Package() +Packet::~Packet() { delete[] m_Data; } -void Package::AddString(std::string str) +void Packet::WriteString(std::string str) { // Message, add one extra byte for null terminator memcpy(m_Data + m_Offset, str.data(), (str.size() + 1) * sizeof(char)); m_Offset += (str.size() + 1) * sizeof(char); } -void Package::AddData(char * data, int sizeOfData) +void Packet::WriteData(char * data, int sizeOfData) { if (m_Offset + sizeOfData > 128) { - LOG_WARNING("Package::AddData(): Data size in package exceeded maximum package size.\n"); + LOG_WARNING("Packet::AddData(): Data size in packet exceeded maximum packet size.\n"); } memcpy(m_Data + m_Offset, data, sizeOfData); m_Offset += sizeOfData; } -std::string Package::PopFrontString() +std::string Packet::ReadString() { std::string returnValue(m_Data + m_ReturnDataOffset); if (m_Offset < m_ReturnDataOffset + returnValue.size()){ - LOG_WARNING("Package PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); + LOG_WARNING("packet PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); return "PopFrontString Failed"; } // +1 for null terminator. @@ -54,7 +54,7 @@ std::string Package::PopFrontString() return returnValue; } -char * Package::PopData(int SizeOfData) +char * Packet::ReadData(int SizeOfData) { unsigned int oldReturnDataOffset = m_ReturnDataOffset; m_ReturnDataOffset += SizeOfData; diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 2bf96528..cbe7a378 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -16,7 +16,7 @@ void Server::Start(World* world, EventBroker* eventBroker) } LOG_INFO("I am Server. BIP BOP\n"); - ReadFromClients(); + readFromClients(); } void Server::Update() @@ -40,7 +40,7 @@ void Server::Close() m_ThreadIsRunning = false; } -void Server::ReadFromClients() +void Server::readFromClients() { char readBuffer[1024] = { 0 }; int bytesRead = 0; @@ -60,9 +60,9 @@ void Server::ReadFromClients() if (m_ThreadIsRunning && m_Socket.available()) { try { - bytesRead = Receive(readBuffer, INPUTSIZE); - Package package(readBuffer, bytesRead); - ParseMessageType(package); + bytesRead = receive(readBuffer, INPUTSIZE); + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); } catch (const std::exception& err) { //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } @@ -71,59 +71,59 @@ void Server::ReadFromClients() std::clock_t currentTime = std::clock(); // Send snapshot if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - SendSnapshot(); + sendSnapshot(); previousSnapshotMessage = currentTime; } // Send pings each if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - SendPing(); + sendPing(); previousePingMessage = currentTime; } // Time out logic if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - CheckForTimeOuts(); + checkForTimeOuts(); timOutTimer = currentTime; } } } -void Server::ParseMessageType(Package& package) +void Server::parseMessageType(Packet& packet) { - int messageType = package.PopFrontPrimitive(); // Read what type off message was sent from server + int messageType = packet.ReadPrimitive(); // Read what type off message was sent from server // Read packet ID m_PreviousPacketID = m_PacketID; // Set previous packet id - m_PacketID = package.PopFrontPrimitive(); //Read new packet id + m_PacketID = packet.ReadPrimitive(); //Read new packet id //IdentifyPacketLoss(); switch (static_cast(messageType)) { case MessageType::Connect: - ParseConnect(package); + parseConnect(packet); break; case MessageType::ClientPing: - //ParseClientPing(); + //parseClientPing(); break; case MessageType::ServerPing: - ParseServerPing(); + parseServerPing(); break; case MessageType::Message: break; case MessageType::Snapshot: - ParseSnapshot(package); + parseSnapshot(packet); break; case MessageType::Disconnect: - ParseDisconnect(); + parseDisconnect(); break; case MessageType::Event: - ParseEvent(package); + parseEvent(packet); break; default: break; } } -int Server::Receive(char * data, size_t length) +int Server::receive(char * data, size_t length) { length = m_Socket.receive_from( boost::asio::buffer((void*)data @@ -132,69 +132,69 @@ int Server::Receive(char * data, size_t length) return length; } -void Server::Send(Package& message, int playerID) +void Server::send(Packet& packet, int playerID) { m_Socket.send_to( - boost::asio::buffer(message.Data(), message.Size()), + boost::asio::buffer(packet.Data(), packet.Size()), m_PlayerDefinitions[playerID].Endpoint, 0); } -void Server::Send(Package & package) +void Server::send(Packet & packet) { m_Socket.send_to( boost::asio::buffer( - package.Data(), - package.Size()), + packet.Data(), + packet.Size()), m_ReceiverEndpoint, 0); } -void Server::MoveMessageHead(char *& data, size_t & length, size_t stepSize) +void Server::moveMessageHead(char *& data, size_t & length, size_t stepSize) { data += stepSize; length -= stepSize; } -void Server::Broadcast(std::string message) +void Server::broadcast(std::string message) { - Package package(MessageType::Event, m_SendPacketID); - package.AddString(message); + Packet packet(MessageType::Event, m_SendPacketID); + packet.WriteString(message); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - Send(package, i); + send(packet, i); } } } -void Server::Broadcast(Package& package) +void Server::broadcast(Packet& packet) { for (int i = 0; i < MAXCONNECTIONS; ++i) { if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) { - Send(package, i); + send(packet, i); } } } -void Server::SendSnapshot() +void Server::sendSnapshot() { - Package package(MessageType::Snapshot, m_SendPacketID); + Packet packet(MessageType::Snapshot, m_SendPacketID); for (size_t i = 0; i < MAXCONNECTIONS; i++) { // Send an empty name if there is no player connected on this position. - package.AddString(m_PlayerDefinitions[i].Name); + packet.WriteString(m_PlayerDefinitions[i].Name); if (m_PlayerDefinitions[i].EntityID == -1) { continue; } - // Pack transfrom component into data package + // Pack transfrom component into data packet auto transform = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform"); - package.AddData(transform.Data, transform.Info.Meta.Stride); + packet.WriteData(transform.Data, transform.Info.Meta.Stride); } - Broadcast(package); + broadcast(packet); } -void Server::SendPing() +void Server::sendPing() { // Prints connected players ping for (size_t i = 0; i < MAXCONNECTIONS; i++) { @@ -205,15 +205,15 @@ void Server::SendPing() } // Create ping message - Package package(MessageType::ServerPing, m_SendPacketID); - package.AddString("Ping from server"); + Packet packet(MessageType::ServerPing, m_SendPacketID); + packet.WriteString("Ping from server"); // Time message m_StartPingTime = std::clock(); // Send message - Broadcast(package); + broadcast(packet); } -void Server::CheckForTimeOuts() +void Server::checkForTimeOuts() { int timeOutTimeMs = 5000; int startPing = 1000 * m_StartPingTime @@ -225,15 +225,15 @@ void Server::CheckForTimeOuts() / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + timeOutTimeMs) { LOG_INFO("Player %i timed out!", i); - Disconnect(i); + disconnect(i); } } } } -void Server::Disconnect(int i) +void Server::disconnect(int i) { - Broadcast("A player disconnected"); + broadcast("A player disconnected"); LOG_INFO("Player %i disconnected/timed out", i); // Remove enteties and stuff @@ -242,7 +242,7 @@ void Server::Disconnect(int i) m_PlayerDefinitions[i].Name = ""; } -void Server::ParseEvent(Package& package) +void Server::parseEvent(Packet& packet) { size_t i; for (i = 0; i < MAXCONNECTIONS; i++) { @@ -255,7 +255,7 @@ void Server::ParseEvent(Package& package) return; unsigned int entityId = m_PlayerDefinitions[i].EntityID; - std::string eventString = package.PopFrontString(); + std::string eventString = packet.ReadString(); if ("+Forward" == eventString) { m_World->GetComponent(entityId, "Player")["Forward"] = true; m_World->GetComponent(entityId, "Player")["Back"] = false; @@ -278,7 +278,7 @@ void Server::ParseEvent(Package& package) } } -void Server::ParseConnect(Package& package) +void Server::parseConnect(Packet& packet) { LOG_INFO("Parsing connections"); // Check if player is already connected @@ -294,48 +294,48 @@ void Server::ParseConnect(Package& package) m_PlayersToCreate.push_back(i); m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; - m_PlayerDefinitions[i].Name = package.PopFrontString(); + m_PlayerDefinitions[i].Name = packet.ReadString(); m_StopTimes[i] = std::clock(); LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name, m_PlayerDefinitions[i].Endpoint.address().to_string()); - Package package(MessageType::Connect, m_SendPacketID); - package.AddPrimitive(i); // Player ID + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WritePrimitive(i); // Player ID - Send(package, i); + send(packet, i); // Send notification that a player has connected std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: " + m_PlayerDefinitions[i].Endpoint.address().to_string(); - Broadcast(str); + broadcast(str); break; } } } -void Server::ParseDisconnect() +void Server::parseDisconnect() { LOG_INFO("%i: Parsing disconnect", m_PacketID); for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { - Disconnect(i); + disconnect(i); break; } } } -void Server::ParseClientPing() +void Server::parseClientPing() { LOG_INFO("%i: Parsing ping", m_PacketID); // Return ping - Package package(MessageType::ClientPing, m_SendPacketID); - package.AddString("Ping received"); - Send(package); // This dosen't work for multiple users + Packet packet(MessageType::ClientPing, m_SendPacketID); + packet.WriteString("Ping received"); + send(packet); // This dosen't work for multiple users } -void Server::ParseServerPing() +void Server::parseServerPing() { for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) { @@ -346,7 +346,7 @@ void Server::ParseServerPing() } // NOT USED -void Server::ParseSnapshot(Package& package) +void Server::parseSnapshot(Packet& packet) { // Does no logic. Returns snapshot if client request one // The snapshot is not a real snapshot tho... @@ -360,7 +360,7 @@ void Server::ParseSnapshot(Package& package) } } -void Server::IdentifyPacketLoss() +void Server::identifyPacketLoss() { // if no packets lost, difference should be equal to 1 int difference = m_PacketID - m_PreviousPacketID; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 6f8c3bac..90dd3773 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -54,8 +54,9 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(m_Renderer); // Invoke network - if (m_Config->Get("Networking.StartNetwork", false) == true) - boost::thread workerThread(&Game::NetworkFunction, this); + if (m_Config->Get("Networking.StartNetwork", false)) { + boost::thread workerThread(&Game::networkFunction, this); + } m_LastTime = glfwGetTime(); debugInitialize(); @@ -90,8 +91,9 @@ void Game::Tick() m_EventBroker->Swap(); // Update network - if (m_IsClientOrServer) + if (m_IsClientOrServer) { m_ClientOrServer->Update(); + } // Iterate through systems and update world! @@ -134,7 +136,7 @@ void Game::debugTick(double dt) m_EventBroker->Process(); } -void Game::NetworkFunction() +void Game::networkFunction() { std::string inputMessage; LOG_INFO("Start client or server? (c/s)"); From db5b6ad51908cdf1603ec02a4fc00c2675b1150d Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 17 Dec 2015 17:32:49 +0100 Subject: [PATCH 124/185] Added more error code to Packet class --- include/Engine/Network/Package.h | 7 ++++++- src/Engine/Network/Package.cpp | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/Engine/Network/Package.h b/include/Engine/Network/Package.h index 9b45101d..2d9f766f 100644 --- a/include/Engine/Network/Package.h +++ b/include/Engine/Network/Package.h @@ -20,6 +20,10 @@ public: template void AddPrimitive(T val) { + // Check if we are trying to add more than the package can fit. + if (m_MaxPacketSize < m_Offset + sizeof(T)) { + LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!"); + } memcpy(m_Data + m_Offset, &val, sizeof(T)); m_Offset += sizeof(T); } @@ -28,7 +32,7 @@ public: T PopFrontPrimitive() { if (m_Offset < m_ReturnDataOffset + sizeof(T)) { - LOG_WARNING("Package PopFrontPrimitive(): You are trying to remove more than what exists in this package!"); + LOG_WARNING("Packet PopFrontPrimitive(): You are trying to remove more than what exists in this package!"); return -1; } T returnValue; @@ -51,6 +55,7 @@ private: char* m_Data; unsigned int m_ReturnDataOffset = 0; int m_Offset = 0; + unsigned int m_MaxPacketSize = 128; }; #endif \ No newline at end of file diff --git a/src/Engine/Network/Package.cpp b/src/Engine/Network/Package.cpp index 43c28837..be99e4a3 100644 --- a/src/Engine/Network/Package.cpp +++ b/src/Engine/Network/Package.cpp @@ -16,7 +16,11 @@ Package::Package(MessageType type, unsigned int& packageID) Package::Package(char* data, const int sizeOfPackage) { // Create message + + // Resize message + m_MaxPacketSize = sizeOfPackage; m_Data = new char[sizeOfPackage]; + // Copy data newly allocated memory memcpy(m_Data, data, sizeOfPackage); m_Offset = sizeOfPackage; } @@ -29,14 +33,18 @@ Package::~Package() void Package::AddString(std::string str) { // Message, add one extra byte for null terminator - memcpy(m_Data + m_Offset, str.data(), (str.size() + 1) * sizeof(char)); - m_Offset += (str.size() + 1) * sizeof(char); + int sizeOfString = str.size() + 1; + if (m_Offset + sizeOfString > m_MaxPacketSize) { + LOG_WARNING("Package::AddString(): Data size in packet exceeded maximum package size.\n"); + } + memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char)); + m_Offset += sizeOfString * sizeof(char); } void Package::AddData(char * data, int sizeOfData) { - if (m_Offset + sizeOfData > 128) { - LOG_WARNING("Package::AddData(): Data size in package exceeded maximum package size.\n"); + if (m_Offset + sizeOfData > m_MaxPacketSize) { + LOG_WARNING("Package::AddData(): Data size in packet exceeded maximum package size.\n"); } memcpy(m_Data + m_Offset, data, sizeOfData); m_Offset += sizeOfData; @@ -46,7 +54,7 @@ std::string Package::PopFrontString() { std::string returnValue(m_Data + m_ReturnDataOffset); if (m_Offset < m_ReturnDataOffset + returnValue.size()){ - LOG_WARNING("Package PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); + LOG_WARNING("packet PopFrontString(): Oh no! You are trying to remove things outside my memory kingdom"); return "PopFrontString Failed"; } // +1 for null terminator. @@ -56,6 +64,10 @@ std::string Package::PopFrontString() char * Package::PopData(int SizeOfData) { + if (m_Offset < m_ReturnDataOffset + SizeOfData) { + LOG_WARNING("packet PopData(): Oh no! You are trying to remove things outside my memory kingdom"); + return nullptr; + } unsigned int oldReturnDataOffset = m_ReturnDataOffset; m_ReturnDataOffset += SizeOfData; return (m_Data + oldReturnDataOffset); From 5e0fe975f36f62b253b1f935f70cd092aba42d6d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 17:48:00 +0100 Subject: [PATCH 125/185] Small error handling check. --- src/Engine/Collision/Collision.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index dd2adec8..d076d1c2 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -221,6 +221,9 @@ bool attachAABBComponentFromModel(World* world, EntityID id) ComponentWrapper model = world->GetComponent(id, "Model"); ComponentWrapper collision = world->AttachComponent(id, "AABB"); Model* modelRes = ResourceManager::Load(model["Resource"]); + if (modelRes == nullptr) { + return false; + } glm::mat4 modelMatrix = modelRes->m_Matrix; From 4a817613e32cd6623fc6613ac2f9e1b66ced3f80 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 17 Dec 2015 17:55:44 +0100 Subject: [PATCH 126/185] Forward+ semi working --- include/Engine/Rendering/Renderer.h | 2 +- resources/Shaders/ForwardPlus.frag.glsl | 6 +++--- resources/Shaders/GridFrustum.comp.glsl | 12 ++++++------ resources/Shaders/cullLights.comp.glsl | 16 +++++++++------- src/Engine/Rendering/Renderer.cpp | 18 +++++++++++------- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index fad41c5f..82471c6d 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -15,7 +15,7 @@ #define TILE_SIZE 16 -#define NUM_LIGHTS 3 +#define NUM_LIGHTS 25 #include "../Core/EventBroker.h" diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 685a8d22..59456322 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -49,7 +49,7 @@ in VertexData{ out vec4 fragmentColor; -vec4 scene_ambient = vec4(0.0,0.0,0.0,1); +vec4 scene_ambient = vec4(0.3,0.3,0.3,1); struct LightResult { vec4 Diffuse; @@ -115,11 +115,11 @@ void main() } fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; - fragmentColor += vec4(LightGrids.Data[currentTile].Amount/3.0, 0, 0, 1); + fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1); //fragmentColor = texel * Input.DiffuseColor * Color; if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { - //fragmentColor = vec4(0.5, 0, 0, 0); + fragmentColor += vec4(0.5, 0, 0, 0); } else { //fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1); diff --git a/resources/Shaders/GridFrustum.comp.glsl b/resources/Shaders/GridFrustum.comp.glsl index 9e0f5a8e..6e567e14 100644 --- a/resources/Shaders/GridFrustum.comp.glsl +++ b/resources/Shaders/GridFrustum.comp.glsl @@ -24,7 +24,7 @@ vec4 ConvertToView(vec4 ScreenCoords) vec2 normalizedScreenCoords = ScreenCoords.xy / ScreenDimensions; vec4 clipSpace = vec4( vec2(normalizedScreenCoords.x, normalizedScreenCoords.y) * 2.0 - 1.0, ScreenCoords.z, ScreenCoords.w); vec4 view = inverse(P) * clipSpace; - view = view / view.w; + //view = view / view.w; return view; } @@ -46,7 +46,7 @@ void main () //Top-Left = 0 | Top-Right = 1 //Bottom-Left = 2 | Bottom-Right = 3 vec4 ScreenCoords[4]; - ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); + ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0); ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0); ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); @@ -59,10 +59,10 @@ void main () vec3 EyePos = vec3(0,0,0); Frustum f; - f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); - f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); - f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); - f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); + f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); // left plane + f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); // right plane + f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); // top plane + f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); // bottom plane diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index ecb0e8e6..a0da2520 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -8,7 +8,7 @@ -#define NUM_LIGHTS 3 +#define NUM_LIGHTS 25 #define MAX_LIGHTS_PER_TILE 1024 #define NUM_TILES 3600 #define TILE_SIZE 16 @@ -71,12 +71,11 @@ int GroupIndex; bool SphereInsidePlane(vec3 center, float radius, Plane plane) { - return dot(plane.Normal, center) - plane.d < -radius; + return dot(plane.Normal, center) + plane.d > -radius; } bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/) { - bool result = true; //Check depth here //if ( sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar ) @@ -84,14 +83,14 @@ bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zN // result = false; //} - for (int i =0; i < 4 && result; i++) + for (int i =0; i < 4; i++) { - if(SphereInsidePlane(center, radius, frustum.Planes[i])) + if(! SphereInsidePlane(center, radius, frustum.Planes[i])) { - result = false; + return false; } } - return result; + return true; } void AppendLight(int li) @@ -115,6 +114,7 @@ void main () } barrier(); + memoryBarrierShared(); for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE) { @@ -136,6 +136,7 @@ void main () } barrier(); + memoryBarrierShared(); if(gl_LocalInvocationIndex == 0) { @@ -145,6 +146,7 @@ void main () } barrier(); + for (uint i = gl_LocalInvocationIndex; i < GroupLightCount; i += TILE_SIZE * TILE_SIZE ) { diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 24e82cfd..e048b082 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -5,7 +5,7 @@ void Renderer::Initialize() InitializeWindow(); // Create default camera m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); - m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10)); + m_DefaultCamera->SetPosition(glm::vec3(0, 1, 10)); if (m_Camera == nullptr) { m_Camera = m_DefaultCamera; } @@ -254,6 +254,8 @@ void Renderer::CalculateFrustum() m_CalculateFrustumProgram->Bind(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix())); glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height); @@ -264,11 +266,13 @@ void Renderer::CalculateFrustum() void Renderer::TEMPCreateLights() { - for (int i = 0; i < NUM_LIGHTS; i++) { - m_PointLights[i].Position = glm::vec4(5.f * (i-1), 1.f, 0.f, 1.f); - m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f); - m_PointLights[i].Radius = 2.f; - } + for (int z = 0; z < 5; z++) + for (int x = 0; x < 5; x++) + { + m_PointLights[x + z*5].Position = glm::vec4(x*2.f, 0.2f, z * 2.f, 1.f); + m_PointLights[x + z*5].Color = glm::vec4(1.f, 0.5f, 1.f, 1.f); + m_PointLights[x + z*5].Radius = 0.5f; + } } void Renderer::CullLights() @@ -282,7 +286,7 @@ void Renderer::CullLights() m_LightCullProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); From 0b714e593f9ed298cc3bb6962e91b655a68113d5 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 17:56:15 +0100 Subject: [PATCH 127/185] Removed WinLeakCheck. Minor variable name changes. removed IsWASDKeyDown struct --- include/Engine/Network/Client.h | 1 - include/Engine/Network/Server.h | 2 +- include/Engine/Network/SnapshotDefinitions.h | 8 ------ include/Engine/Network/WinLeakCheck.h | 17 ------------ src/Engine/Network/Client.cpp | 27 ++++++++++---------- 5 files changed, 14 insertions(+), 41 deletions(-) delete mode 100644 include/Engine/Network/WinLeakCheck.h diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 1bf2f059..2b1f65f8 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -10,7 +10,6 @@ #include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Network/SnapshotDefinitions.h" -#include "Network/WinLeakCheck.h" #include "Core/World.h" #include "Core/EventBroker.h" #include "Input/EInputCommand.h" diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 17ca7136..4e298213 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -36,7 +36,7 @@ private: // Game logic World* m_World; EventBroker* m_EventBroker; - // size = ammount of players to create, stores playerID's + // vec.size() = ammount of players to create, stores playerID's std::vector m_PlayersToCreate; // Packet loss logic diff --git a/include/Engine/Network/SnapshotDefinitions.h b/include/Engine/Network/SnapshotDefinitions.h index 9fe8beca..b643d18c 100644 --- a/include/Engine/Network/SnapshotDefinitions.h +++ b/include/Engine/Network/SnapshotDefinitions.h @@ -9,12 +9,4 @@ struct SnapshotDefinitions std::string InputRight; }; -struct IsWASDKeyDown -{ - bool W = false; - bool A = false; - bool S = false; - bool D = false; -}; - #endif \ No newline at end of file diff --git a/include/Engine/Network/WinLeakCheck.h b/include/Engine/Network/WinLeakCheck.h deleted file mode 100644 index dc1216a7..00000000 --- a/include/Engine/Network/WinLeakCheck.h +++ /dev/null @@ -1,17 +0,0 @@ -#if defined (_WIN64) | defined(_WIN32) -#ifndef WinLeakeCheck_h__ -#define WinLeakeCheck_h__ - -//For memory leak checking -#define _CRTDBG_MAP_ALLOC -#include -#include - -#ifdef _DEBUG -#ifndef DBG_NEW -#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) -#define new DBG_NEW -#endif -#endif // _DEBUG -#endif -#endif \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index ade0c00e..69513022 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -13,8 +13,7 @@ Client::Client() : m_Socket(m_IOService) Client::~Client() { - // will it work on linux? #if defined (_WIN64) | defined(_WIN32) otherwise. - _CrtDumpMemoryLeaks(); + } void Client::Start(World* world, EventBroker* eventBroker) @@ -182,9 +181,9 @@ void Client::parsePing() void Client::parseServerPing() { - Packet message(MessageType::ServerPing, m_SendPacketID); - message.WriteString("Ping recieved"); - send(message); + Packet packet(MessageType::ServerPing, m_SendPacketID); + packet.WriteString("Ping recieved"); + send(packet); } void Client::parseEventMessage(Packet& packet) @@ -257,25 +256,25 @@ void Client::send(Packet& packet) void Client::connect() { - Packet message(MessageType::Connect, m_SendPacketID); - message.WriteString(m_PlayerName); + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString(m_PlayerName); m_StartPingTime = std::clock(); - send(message); + send(packet); } void Client::disconnect() { - Packet message(MessageType::Connect, m_SendPacketID); - message.WriteString("+Disconnect"); - send(message); + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString("+Disconnect"); + send(packet); } void Client::ping() { - Packet message(MessageType::Connect, m_SendPacketID); - message.WriteString("Ping"); + Packet packet(MessageType::Connect, m_SendPacketID); + packet.WriteString("Ping"); m_StartPingTime = std::clock(); - send(message); + send(packet); } void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize) From 13f7fb25618fc67857302394dabb0320b5948bcb Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 18 Dec 2015 10:01:05 +0100 Subject: [PATCH 128/185] Stashed test fixes for boost 1.6 --- src/Tests/ConfigFileTest.cpp | 76 ++++++++++++++++++------------------ src/Tests/OctTreeTest.cpp | 8 ++-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Tests/ConfigFileTest.cpp b/src/Tests/ConfigFileTest.cpp index dfcfa527..bbe57de2 100644 --- a/src/Tests/ConfigFileTest.cpp +++ b/src/Tests/ConfigFileTest.cpp @@ -16,53 +16,53 @@ BOOST_AUTO_TEST_SUITE(confTest) BOOST_AUTO_TEST_CASE(configFileTest) { - //note: this ConfigFileclass currently has memleaks! + ////note: this ConfigFileclass currently has memleaks! - ResourceManager::RegisterType("ConfigFile"); - auto m_Config = ResourceManager::Load("ConfigTest.ini"); + //ResourceManager::RegisterType("ConfigFile"); + //auto m_Config = ResourceManager::Load("ConfigTest.ini"); - //bägge måste vara av samma typ, T typen är string - //http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html - //"Note that we construct the path to the value by separating the individual keys with dots" + ////bägge måste vara av samma typ, T typen är string + ////http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html + ////"Note that we construct the path to the value by separating the individual keys with dots" - //get from tree tests - auto getSomething = m_Config->Get("Test.Test1", 0); - BOOST_CHECK(getSomething == 423); + ////get from tree tests + //auto getSomething = m_Config->Get("Test.Test1", 0); + //BOOST_CHECK(getSomething == 423); - auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string("")); - BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\""); + //auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string("")); + //BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\""); - //set/get tests - m_Config->Set("Test.4321", 123); - auto getSomething3 = m_Config->Get("Test.4321", 0); - BOOST_CHECK(getSomething3 == 123); + ////set/get tests + //m_Config->Set("Test.4321", 123); + //auto getSomething3 = m_Config->Get("Test.4321", 0); + //BOOST_CHECK(getSomething3 == 123); - m_Config->Set("3_2_1_0_5", "t454j54hj5k32"); - auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string("")); - BOOST_CHECK(getSomething4 == "t454j54hj5k32"); + //m_Config->Set("3_2_1_0_5", "t454j54hj5k32"); + //auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string("")); + //BOOST_CHECK(getSomething4 == "t454j54hj5k32"); - //***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values! - auto m_Config2 = ResourceManager::Load("ConfigTestNotExists.ini"); + ////***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values! + //auto m_Config2 = ResourceManager::Load("ConfigTestNotExists.ini"); - //set value/savetodisk/load/checkvalue... - m_Config->SaveToDisk(); - m_Config->Set("Test.4321", 145); - m_Config->SaveToDisk(); - auto m_Config3 = ResourceManager::Load("ConfigTest.ini"); - auto getSomething5 = m_Config->Get("Test.4321", 0); - BOOST_CHECK(getSomething5 == 145); - - //***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini" - //***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": - auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); + ////set value/savetodisk/load/checkvalue... + //m_Config->SaveToDisk(); + //m_Config->Set("Test.4321", 145); + //m_Config->SaveToDisk(); + //auto m_Config3 = ResourceManager::Load("ConfigTest.ini"); + //auto getSomething5 = m_Config->Get("Test.4321", 0); + //BOOST_CHECK(getSomething5 == 145); + // + ////***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini" + ////***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": + //auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); - //test to try to fix memleaks - failed, probably something else - //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); - //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestNotExists.ini")); - //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); - //ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestFailed.ini")); - //reload,onchildreload unimplemented - _CrtDumpMemoryLeaks(); + ////test to try to fix memleaks - failed, probably something else + ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); + ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestNotExists.ini")); + ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); + ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestFailed.ini")); + ////reload,onchildreload unimplemented + //_CrtDumpMemoryLeaks(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/Tests/OctTreeTest.cpp b/src/Tests/OctTreeTest.cpp index b0b5c25d..03e96c5d 100644 --- a/src/Tests/OctTreeTest.cpp +++ b/src/Tests/OctTreeTest.cpp @@ -39,10 +39,10 @@ BOOST_AUTO_TEST_CASE(octTreeTest) BOOST_AUTO_TEST_CASE(octTreeTest2) { //octtree ritningen osv - Game game(0, nullptr); - while (game.Running()) { - game.Tick(); - } + //Game game(0, nullptr); + //while (game.Running()) { + // game.Tick(); + //} } BOOST_AUTO_TEST_SUITE_END() From 97f8be1915f4f7ed426cf5c3a6915c1b417bbefd Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 18 Dec 2015 10:21:56 +0100 Subject: [PATCH 129/185] Made Network.h's Start() and Update pure virtual and removed cpp. Removed unnecessary code from NetworkDefinitions.h. Renamed sizeOfPackage to sizeOfPacket in Packet.cpp. --- include/Engine/Network/Client.h | 5 +++-- include/Engine/Network/Network.h | 9 +++------ include/Engine/Network/NetworkDefinitions.h | 12 ------------ include/Engine/Network/Server.h | 5 +++-- src/Engine/Network/Client.cpp | 2 +- src/Engine/Network/Network.cpp | 13 ------------- src/Engine/Network/Packet.cpp | 17 +++++++++-------- 7 files changed, 19 insertions(+), 44 deletions(-) delete mode 100644 src/Engine/Network/Network.cpp diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 1bf2f059..743f7510 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -5,6 +5,7 @@ #include #include +#include #include "Network/MessageType.h" #include "Network/NetworkDefinitions.h" @@ -21,8 +22,8 @@ class Client : public Network public: Client(); ~Client(); - void Start(World* world, EventBroker* eventBroker); - void Update(); + void Start(World* world, EventBroker* eventBroker) override; + void Update() override; void Close(); private: // Assio UDP logic diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index d6447a3c..31c6b8b0 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -8,12 +8,9 @@ class Network { public: - Network(); - ~Network(); - virtual void Start(World* m_world, EventBroker *eventBroker); - virtual void Update(); -protected: - + virtual ~Network() { }; + virtual void Start(World* m_world, EventBroker *eventBroker) = 0; + virtual void Update() = 0; }; #endif \ No newline at end of file diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h index 5a86c50d..336daf86 100644 --- a/include/Engine/Network/NetworkDefinitions.h +++ b/include/Engine/Network/NetworkDefinitions.h @@ -1,20 +1,8 @@ #ifndef NetworkDefines_h__ #define NetworkDefines_h__ -#include -#include -#include "Network/Packet.h" - - -#define BOARDSIZE 16 #define MAXCONNECTIONS 8 #define INPUTSIZE 128 #define PLAYERSPEED 0.2f; -typedef boost::shared_ptr socket_ptr; -typedef boost::shared_ptr string_ptr; -typedef boost::shared_ptr> messageQueue_ptr; - - - #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 17ca7136..092c3be0 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -5,6 +5,7 @@ #include #include +#include #include "Network/MessageType.h" #include "Network/NetworkDefinitions.h" @@ -18,8 +19,8 @@ class Server : public Network public: Server(); ~Server(); - void Start(World* m_world, EventBroker *eventBroker); - void Update(); + void Start(World* m_world, EventBroker *eventBroker) override; + void Update() override; void Close(); private: diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index ade0c00e..4966b477 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -5,7 +5,7 @@ using namespace boost::asio::ip; Client::Client() : m_Socket(m_IOService) { - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.6"), 13); // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp deleted file mode 100644 index 51a93407..00000000 --- a/src/Engine/Network/Network.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "Network/Network.h" - -Network::Network() -{ } - -Network::~Network() -{ } - -void Network::Start(World * m_world, EventBroker * eventBroker) -{ } - -void Network::Update() -{ } \ No newline at end of file diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 4a9b77ae..328e0d12 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -12,14 +12,15 @@ Packet::Packet(MessageType type, unsigned int& packetID) packetID++; } - +// Create message Packet::Packet(char* data, const int sizeOfPacket) { - // Create message - // Resize message - m_MaxPacketSize = sizeOfPackage; + m_MaxPacketSize = sizeOfPacket; // Copy data newly allocated memory + m_Data = new char[sizeOfPacket]; + memcpy(m_Data, data, sizeOfPacket); + m_Offset = sizeOfPacket; } Packet::~Packet() @@ -39,7 +40,7 @@ void Packet::WriteString(std::string str) } void Packet::WriteData(char * data, int sizeOfData) -{ +{ if (m_Offset + sizeOfData > m_MaxPacketSize) { LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size.\n"); } @@ -50,10 +51,10 @@ void Packet::WriteData(char * data, int sizeOfData) std::string Packet::ReadString() { std::string returnValue(m_Data + m_ReturnDataOffset); - if (m_Offset < m_ReturnDataOffset + returnValue.size()){ + if (m_Offset < m_ReturnDataOffset + returnValue.size()) { LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom"); return "PopFrontString Failed"; - } + } // +1 for null terminator. m_ReturnDataOffset += returnValue.size() + 1; return returnValue; @@ -68,4 +69,4 @@ char * Packet::ReadData(int SizeOfData) unsigned int oldReturnDataOffset = m_ReturnDataOffset; m_ReturnDataOffset += SizeOfData; return (m_Data + oldReturnDataOffset); -} +} \ No newline at end of file From 30db0b10fdcb464eea3dc919d0bfb1d880082fa5 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 18 Dec 2015 10:36:14 +0100 Subject: [PATCH 130/185] Removed NetworkDefinitions.h and moved #define MAXCONNECTIONS 8 #define INPUTSIZE 128 to Network.h. --- include/Engine/Network/Client.h | 1 - include/Engine/Network/Network.h | 3 +++ include/Engine/Network/NetworkDefinitions.h | 8 -------- include/Engine/Network/Server.h | 1 - 4 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 include/Engine/Network/NetworkDefinitions.h diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 743f7510..bf421ecc 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -8,7 +8,6 @@ #include #include "Network/MessageType.h" -#include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Network/SnapshotDefinitions.h" #include "Network/WinLeakCheck.h" diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index 31c6b8b0..0f7baefe 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -5,6 +5,9 @@ #include "Core/EventBroker.h" #include "Network/Packet.h" +#define MAXCONNECTIONS 8 +#define INPUTSIZE 128 + class Network { public: diff --git a/include/Engine/Network/NetworkDefinitions.h b/include/Engine/Network/NetworkDefinitions.h deleted file mode 100644 index 336daf86..00000000 --- a/include/Engine/Network/NetworkDefinitions.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef NetworkDefines_h__ -#define NetworkDefines_h__ - -#define MAXCONNECTIONS 8 -#define INPUTSIZE 128 -#define PLAYERSPEED 0.2f; - -#endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 092c3be0..a081ec00 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -8,7 +8,6 @@ #include #include "Network/MessageType.h" -#include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Core/World.h" #include "Core/EventBroker.h" From 002e1d8c5a434002e1ddc131117de8871719f293 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 18 Dec 2015 10:52:46 +0100 Subject: [PATCH 131/185] Removed magic number from Packet constructor in Packet.cpp. --- src/Engine/Network/Packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index 328e0d12..52b15065 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -2,7 +2,7 @@ Packet::Packet(MessageType type, unsigned int& packetID) { - m_Data = new char[128]; + m_Data = new char[m_MaxPacketSize]; // Create message header // Add message type int messageType = static_cast(type); From 6cf7c12d3447b2f8418af505362a300119f93814 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Fri, 18 Dec 2015 11:09:54 +0100 Subject: [PATCH 132/185] Forward+ working --- include/Engine/Rendering/Renderer.h | 2 +- resources/Schema/Entities/Test.xml | 2 +- resources/Shaders/ForwardPlus.frag.glsl | 6 +++--- resources/Shaders/GridFrustum.comp.glsl | 6 ++++-- resources/Shaders/cullLights.comp.glsl | 3 +-- src/Engine/Rendering/Renderer.cpp | 16 ++++++++-------- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 82471c6d..2f0dae08 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -15,7 +15,7 @@ #define TILE_SIZE 16 -#define NUM_LIGHTS 25 +#define NUM_LIGHTS 5000 #include "../Core/EventBroker.h" diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index f8be48a7..cf428a77 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -10,7 +10,7 @@ - + Models/Core/UnitPlane.obj diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 59456322..568195ce 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -57,7 +57,7 @@ struct LightResult { }; float CalcAttenuation(float radius, float dist) { - return 1.0 - smoothstep(radius * 1.0, radius, dist); + return 1.0 - smoothstep(radius * 0.3, radius, dist); } vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { @@ -115,11 +115,11 @@ void main() } fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; - fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1); + //fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1); //fragmentColor = texel * Input.DiffuseColor * Color; if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { - fragmentColor += vec4(0.5, 0, 0, 0); + //fragmentColor += vec4(0.5, 0, 0, 0); } else { //fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1); diff --git a/resources/Shaders/GridFrustum.comp.glsl b/resources/Shaders/GridFrustum.comp.glsl index 6e567e14..bb2a4fb7 100644 --- a/resources/Shaders/GridFrustum.comp.glsl +++ b/resources/Shaders/GridFrustum.comp.glsl @@ -24,7 +24,7 @@ vec4 ConvertToView(vec4 ScreenCoords) vec2 normalizedScreenCoords = ScreenCoords.xy / ScreenDimensions; vec4 clipSpace = vec4( vec2(normalizedScreenCoords.x, normalizedScreenCoords.y) * 2.0 - 1.0, ScreenCoords.z, ScreenCoords.w); vec4 view = inverse(P) * clipSpace; - //view = view / view.w; + view = view / view.w; return view; } @@ -51,12 +51,14 @@ void main () ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0); + + vec3 ViewVectors[4]; for(int i = 0; i < 4; i++) { ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i])); } - vec3 EyePos = vec3(0,0,0); + vec3 EyePos = vec3(0.0, 0.0 ,0.0); Frustum f; f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); // left plane diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index a0da2520..69eb5903 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -8,7 +8,6 @@ -#define NUM_LIGHTS 25 #define MAX_LIGHTS_PER_TILE 1024 #define NUM_TILES 3600 #define TILE_SIZE 16 @@ -71,7 +70,7 @@ int GroupIndex; bool SphereInsidePlane(vec3 center, float radius, Plane plane) { - return dot(plane.Normal, center) + plane.d > -radius; + return dot(plane.Normal, center) - plane.d > -radius; } bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/) diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index e048b082..c32fc4f8 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -4,7 +4,7 @@ void Renderer::Initialize() { InitializeWindow(); // Create default camera - m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); + m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(90.0f), 0.01f, 5000.f); m_DefaultCamera->SetPosition(glm::vec3(0, 1, 10)); if (m_Camera == nullptr) { m_Camera = m_DefaultCamera; @@ -266,13 +266,13 @@ void Renderer::CalculateFrustum() void Renderer::TEMPCreateLights() { - for (int z = 0; z < 5; z++) - for (int x = 0; x < 5; x++) - { - m_PointLights[x + z*5].Position = glm::vec4(x*2.f, 0.2f, z * 2.f, 1.f); - m_PointLights[x + z*5].Color = glm::vec4(1.f, 0.5f, 1.f, 1.f); - m_PointLights[x + z*5].Radius = 0.5f; - } + for (int i = 0; i < NUM_LIGHTS; i++) + { + glm::vec3 pos = glm::vec3(cos(i) * i/10.f , 0.5f, sin(i) * i/10.f); + m_PointLights[i].Position = glm::vec4(pos, 1.f); + m_PointLights[i].Color = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand()%255 / 255.f, 1.f); + m_PointLights[i].Radius = 5.0f; + } } void Renderer::CullLights() From 5c1a93021b57ea8b22b03c49be0523082e3f0f73 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 11:22:13 +0100 Subject: [PATCH 133/185] Client now reads address and port from config file. Default address is set to local host. --- include/Engine/Network/Client.h | 5 +++-- resources/DefaultConfig.ini | 5 ++--- src/Engine/Network/Client.cpp | 7 +++++-- src/Game/Game.cpp | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 2b1f65f8..2869bfb2 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -6,19 +6,20 @@ #include +#include "Network/Network.h" #include "Network/MessageType.h" #include "Network/NetworkDefinitions.h" #include "Network/PlayerDefinition.h" #include "Network/SnapshotDefinitions.h" #include "Core/World.h" #include "Core/EventBroker.h" +#include "Core/ConfigFile.h" #include "Input/EInputCommand.h" -#include "Network/Network.h" class Client : public Network { public: - Client(); + Client(ConfigFile* config); ~Client(); void Start(World* world, EventBroker* eventBroker); void Update(); diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 9e4fb885..6c6d4808 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -1,5 +1,4 @@ [Debug] - LogLevel=1 LoadMap= EditorEnabled=false @@ -13,5 +12,5 @@ Height=720 FOV=45 [Networking] StartNetwork=false -Address=0.0.0.0 -Port=0 \ No newline at end of file +Address=127.0.0.1 +Port=13 \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 69513022..a43c16eb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -3,9 +3,12 @@ using namespace boost::asio::ip; -Client::Client() : m_Socket(m_IOService) +Client::Client(ConfigFile* config) : m_Socket(m_IOService) { - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string("192.168.1.2"), 13); + // Default is local host + std::string address = config->Get("Networking.Address", "127.0.0.1"); + int port = config->Get("Networking.Port", 13); + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); // Set up network stream m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 90dd3773..151d9363 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -143,7 +143,7 @@ void Game::networkFunction() std::cin >> inputMessage; if (inputMessage == "c" || inputMessage == "C") { m_IsClientOrServer = true; - m_ClientOrServer = new Client(); + m_ClientOrServer = new Client(m_Config); } if (inputMessage == "s" || inputMessage == "S") { m_IsClientOrServer = true; From 3636ad45afd36b1be9d851bb50e8ac7e15c44f48 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Fri, 18 Dec 2015 11:29:11 +0100 Subject: [PATCH 134/185] Changed to correct branch --- assets | 2 +- include/Engine/Rendering/Renderer.h | 2 +- resources/Schema/Entities/Test.xml | 21 --------------------- src/Engine/Rendering/Renderer.cpp | 2 +- 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/assets b/assets index b3746822..c8e631f4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b37468222e45ec0b2116f1543c578cb9784d43f2 +Subproject commit c8e631f449515cdbe3647b96ce472839748e28f9 diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 2f0dae08..d8928b18 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -15,7 +15,7 @@ #define TILE_SIZE 16 -#define NUM_LIGHTS 5000 +#define NUM_LIGHTS 1000 #include "../Core/EventBroker.h" diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index cf428a77..aed1510c 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -17,27 +17,6 @@ - - - - - - - - Models/ScaleWidget.obj - - - - - - - - - - Models/RotationWidget.obj - - - diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index c32fc4f8..8721127a 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -271,7 +271,7 @@ void Renderer::TEMPCreateLights() glm::vec3 pos = glm::vec3(cos(i) * i/10.f , 0.5f, sin(i) * i/10.f); m_PointLights[i].Position = glm::vec4(pos, 1.f); m_PointLights[i].Color = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand()%255 / 255.f, 1.f); - m_PointLights[i].Radius = 5.0f; + m_PointLights[i].Radius = glm::length(pos) / 5.f; } } From 1e5e24a03647ca8c9fb9241130b11195fef7d3a2 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 18 Dec 2015 11:37:02 +0100 Subject: [PATCH 135/185] The tests seems to work under boost 1.59 but test explorer window is broken in 1.60. also changed ResourceManagerTest.cpp --- {src => include}/Tests/EventFixture.h | 0 {src => include}/Tests/OctTreeTestGameClass.h | 0 .../Tests/OctTreeTestHardCodedTestWorld.h | 0 src/Tests/CMakeLists.txt | 1 + src/Tests/ConfigFileTest.cpp | 73 +++++++++---------- src/Tests/ResourceManagerTest.cpp | 24 +----- 6 files changed, 38 insertions(+), 60 deletions(-) rename {src => include}/Tests/EventFixture.h (100%) rename {src => include}/Tests/OctTreeTestGameClass.h (100%) rename {src => include}/Tests/OctTreeTestHardCodedTestWorld.h (100%) diff --git a/src/Tests/EventFixture.h b/include/Tests/EventFixture.h similarity index 100% rename from src/Tests/EventFixture.h rename to include/Tests/EventFixture.h diff --git a/src/Tests/OctTreeTestGameClass.h b/include/Tests/OctTreeTestGameClass.h similarity index 100% rename from src/Tests/OctTreeTestGameClass.h rename to include/Tests/OctTreeTestGameClass.h diff --git a/src/Tests/OctTreeTestHardCodedTestWorld.h b/include/Tests/OctTreeTestHardCodedTestWorld.h similarity index 100% rename from src/Tests/OctTreeTestHardCodedTestWorld.h rename to include/Tests/OctTreeTestHardCodedTestWorld.h diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt index 697dea29..f4dc710e 100644 --- a/src/Tests/CMakeLists.txt +++ b/src/Tests/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories( ) file(GLOB SOURCE_FILES + "${INCLUDE_PATH}/Tests/*.h" "*.cpp" ) diff --git a/src/Tests/ConfigFileTest.cpp b/src/Tests/ConfigFileTest.cpp index bbe57de2..28be5589 100644 --- a/src/Tests/ConfigFileTest.cpp +++ b/src/Tests/ConfigFileTest.cpp @@ -16,53 +16,50 @@ BOOST_AUTO_TEST_SUITE(confTest) BOOST_AUTO_TEST_CASE(configFileTest) { - ////note: this ConfigFileclass currently has memleaks! + //note: this ConfigFileclass currently has memleaks! - //ResourceManager::RegisterType("ConfigFile"); - //auto m_Config = ResourceManager::Load("ConfigTest.ini"); + ResourceManager::RegisterType("ConfigFile"); + auto m_Config = ResourceManager::Load("ConfigTest.ini"); - ////bägge måste vara av samma typ, T typen är string - ////http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html - ////"Note that we construct the path to the value by separating the individual keys with dots" + //bägge måste vara av samma typ, T typen är string + //http://www.boost.org/doc/libs/1_42_0/doc/html/boost_propertytree/tutorial.html + //"Note that we construct the path to the value by separating the individual keys with dots" - ////get from tree tests - //auto getSomething = m_Config->Get("Test.Test1", 0); - //BOOST_CHECK(getSomething == 423); + //get from tree tests + auto getSomething = m_Config->Get("Test.Test1", 0); + BOOST_CHECK(getSomething == 423); - //auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string("")); - //BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\""); + auto getSomething2 = m_Config->Get("fsdfdsfd.T", std::string("")); + BOOST_CHECK(getSomething2 == "\"gfdjakflsdl!\""); - ////set/get tests - //m_Config->Set("Test.4321", 123); - //auto getSomething3 = m_Config->Get("Test.4321", 0); - //BOOST_CHECK(getSomething3 == 123); + //set/get tests + m_Config->Set("Test.4321", 123); + auto getSomething3 = m_Config->Get("Test.4321", 0); + BOOST_CHECK(getSomething3 == 123); - //m_Config->Set("3_2_1_0_5", "t454j54hj5k32"); - //auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string("")); - //BOOST_CHECK(getSomething4 == "t454j54hj5k32"); + m_Config->Set("3_2_1_0_5", "t454j54hj5k32"); + auto getSomething4 = m_Config->Get("3_2_1_0_5", std::string("")); + BOOST_CHECK(getSomething4 == "t454j54hj5k32"); - ////***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values! - //auto m_Config2 = ResourceManager::Load("ConfigTestNotExists.ini"); + //***check so outputwindow says: EE: Failed to find "DefaultConfigTestNotExists.ini"! Relying on hardcoded default values! + auto m_Config2 = ResourceManager::Load("ConfigTestNotExists.ini"); - ////set value/savetodisk/load/checkvalue... - //m_Config->SaveToDisk(); - //m_Config->Set("Test.4321", 145); - //m_Config->SaveToDisk(); - //auto m_Config3 = ResourceManager::Load("ConfigTest.ini"); - //auto getSomething5 = m_Config->Get("Test.4321", 0); - //BOOST_CHECK(getSomething5 == 145); - // - ////***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini" - ////***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": - //auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); + //set value/savetodisk/load/checkvalue... + m_Config->SaveToDisk(); + m_Config->Set("Test.4321", 145); + m_Config->SaveToDisk(); + auto m_Config3 = ResourceManager::Load("ConfigTest.ini"); + auto getSomething5 = m_Config->Get("Test.4321", 0); + BOOST_CHECK(getSomething5 == 145); + + //***check so outputwindow says: EE: Failed to parse "DefaultConfigTestFailed.ini" + //***check so outputwindow says: EE: Failed to parse "ConfigTestFailed.ini": + auto m_Config4 = ResourceManager::Load("ConfigTestFailed.ini"); - ////test to try to fix memleaks - failed, probably something else - ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); - ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestNotExists.ini")); - ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTest.ini")); - ////ResourceManager::Release(std::string("ConfigFile"), std::string("ConfigTestFailed.ini")); - ////reload,onchildreload unimplemented - //_CrtDumpMemoryLeaks(); + //reload,onchildreload unimplemented + + //NOTE:still massive amount of memoryleaks from this method + _CrtDumpMemoryLeaks(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/Tests/ResourceManagerTest.cpp b/src/Tests/ResourceManagerTest.cpp index e05d8563..a3edb7b8 100644 --- a/src/Tests/ResourceManagerTest.cpp +++ b/src/Tests/ResourceManagerTest.cpp @@ -1,25 +1,15 @@ #include - #include "Core/World.h" +//private->public hack doesnt work, tons of link errors +//so there is currently no good way to test this class //#define private public #include "Core/ResourceManager.h" - #include "Core/ConfigFile.h" - #include "Rendering/Renderer.h" #include "Core/EntityXMLFile.h" #include "Engine\Rendering\Texture.h" -//#include "Core/EventBroker.h" -//#include "Core/InputManager.h" -//#include "GUI/Frame.h" -//#include "Rendering/RenderQueueFactory.h" -//#include "Core/EKeyDown.h" -//#include "Core/SystemPipeline.h" -//#include "RaptorCopterSystem.h" - - BOOST_AUTO_TEST_SUITE(resourceManagerTests) BOOST_AUTO_TEST_CASE(resourceManagerTest) @@ -28,10 +18,6 @@ BOOST_AUTO_TEST_CASE(resourceManagerTest) //private static metoder/variabler - //ugly private->public hack doesnt work, tons of link errors. hence cant test it properly - //its not my job to implement testfunctions for unittests in the class either - - //craptests ahead: ResourceManager::RegisterType("ConfigFile"); BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini")); auto m_Config = ResourceManager::Load("Config.ini"); @@ -45,12 +31,6 @@ BOOST_AUTO_TEST_CASE(resourceManagerTest) BOOST_CHECK(!ResourceManager::IsResourceLoaded("Model", "Models/Core/ScreenQuad.obj")); //there is no error feedback to check if you try to release the wrong resources - hence that cant be tested either - - //registertype (bind with function) - //m_CompilerTypenameToResourceType = global... - //m_FactoryFunctions = global... - //BOOST_CHECK(ResourceManager::m_CompilerTypenameToResourceType.size() != 0); - //BOOST_CHECK(ResourceManager::m_FactoryFunctions.size() != 0); } BOOST_AUTO_TEST_SUITE_END() From a858dab8b665672f98da51d3ba4f72eae0c9894f Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 12:00:14 +0100 Subject: [PATCH 136/185] Network not longer threaded --- include/Engine/Network/Client.h | 10 +++- include/Engine/Network/Server.h | 13 +++++ src/Engine/Input/InputProxy.cpp | 4 +- src/Engine/Network/Client.cpp | 61 ++++++++------------- src/Engine/Network/Server.cpp | 97 ++++++++++++++------------------- src/Game/Game.cpp | 7 ++- 6 files changed, 90 insertions(+), 102 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 642d9bad..95888b1f 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -30,6 +30,12 @@ private: boost::asio::io_service m_IOService; boost::asio::ip::udp::socket m_Socket; + // Sending message to server logic + int bytesRead = -1; + char readBuf[1024] = { 0 }; + int snapshotInterval = 33; + std::clock_t previousSnapshotMessage = std::clock(); + // Packet loss logic unsigned int m_PacketID = 0; unsigned int m_PreviousPacketID = 0; @@ -37,8 +43,6 @@ private: // Game logic World* m_World; - std::vector m_PlayersToCreate; - glm::vec2 m_PlayerPositions[MAXCONNECTIONS]; std::string m_PlayerName; int m_PlayerID = -1; @@ -67,9 +71,9 @@ private: void parsePing(); void parseServerPing(); void parseSnapshot(Packet& packet); - void createNewPlayer(int i); void identifyPacketLoss(); bool isConnected(); + EntityID createPlayer(); // Events EventBroker* m_EventBroker; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 99a1b050..5c1ac1fb 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -29,6 +29,18 @@ private: boost::asio::ip::udp::socket m_Socket; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; + // Sending messages to client logic + char readBuffer[1024] = { 0 }; + int bytesRead = 0; + // time for previouse message + std::clock_t previousePingMessage = std::clock(); + std::clock_t previousSnapshotMessage = std::clock(); + std::clock_t timOutTimer = std::clock(); + // How often we send messages (milliseconds) + int intervalMs = 1000; + int snapshotInterval = 50; + int checkTimeOutInterval = 100; + //Timers std::clock_t m_StartPingTime; std::clock_t m_StopTimes[8]; @@ -67,6 +79,7 @@ private: void parseServerPing(); void parseSnapshot(Packet& packet); void identifyPacketLoss(); + EntityID createPlayer(); }; #endif diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp index c3e4d669..ad589df3 100644 --- a/src/Engine/Input/InputProxy.cpp +++ b/src/Engine/Input/InputProxy.cpp @@ -62,7 +62,7 @@ void InputProxy::Process() e.Command = command; e.Value = currentValue; m_EventBroker->Publish(e); - LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); m_LastCommandValues[command] = currentValue; } } @@ -78,7 +78,7 @@ void InputProxy::Process() } //e.Value = std::max(-1.f, std::min(e.Value, 1.f)); m_EventBroker->Publish(e); - LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); } m_CommandQueue.clear(); } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index a43c16eb..8efd97ce 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -37,21 +37,11 @@ void Client::Start(World* world, EventBroker* eventBroker) } m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); - readFromServer(); } void Client::Update() { - while (m_PlayersToCreate.size() > 0) { - unsigned int i = m_PlayersToCreate.size() - 1; - unsigned int tempID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(tempID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(tempID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; - ComponentWrapper player = m_World->AttachComponent(tempID, "Player"); - m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; - m_PlayersToCreate.pop_back(); - } + readFromServer(); } void Client::Close() @@ -65,27 +55,19 @@ void Client::Close() void Client::readFromServer() { - int bytesRead = -1; - char readBuf[1024] = { 0 }; - - int snapshotInterval = 33; - std::clock_t previousSnapshotMessage = std::clock(); - - while (m_ThreadIsRunning) { - if (m_Socket.available()) { - bytesRead = receive(readBuf, INPUTSIZE); - if (bytesRead > 0) { - Packet packet(readBuf, bytesRead); - parseMessageType(packet); - } + if (m_Socket.available()) { + bytesRead = receive(readBuf, INPUTSIZE); + if (bytesRead > 0) { + Packet packet(readBuf, bytesRead); + parseMessageType(packet); } - std::clock_t currentTime = std::clock(); - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - if (isConnected()) { - sendSnapshotToServer(); - } - previousSnapshotMessage = currentTime; + } + std::clock_t currentTime = std::clock(); + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + if (isConnected()) { + sendSnapshotToServer(); } + previousSnapshotMessage = currentTime; } } @@ -215,7 +197,7 @@ void Client::parseSnapshot(Packet& packet) // New player connected on the server side if (m_PlayerDefinitions[i].Name == "" && tempName != "") { m_PlayerDefinitions[i].Name = tempName; - m_PlayersToCreate.push_back(i); + m_PlayerDefinitions[i].EntityID = createPlayer(); } else if (m_PlayerDefinitions[i].Name != "" && tempName == "") { // Someone disconnected // TODO: Insert code here @@ -321,13 +303,6 @@ bool Client::OnInputCommand(const Events::InputCommand & e) return false; } -void Client::createNewPlayer(int i) -{ - m_PlayerDefinitions[i].EntityID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(m_PlayerDefinitions[i].EntityID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; -} void Client::identifyPacketLoss() { @@ -347,3 +322,13 @@ bool Client::isConnected() } return false; } + +EntityID Client::createPlayer() +{ + EntityID entityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); + return entityID; +} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index cbe7a378..261583cc 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -15,24 +15,11 @@ void Server::Start(World* world, EventBroker* eventBroker) m_StopTimes[i] = std::clock(); } LOG_INFO("I am Server. BIP BOP\n"); - - readFromClients(); } void Server::Update() { - while (m_PlayersToCreate.size() > 0) { - unsigned int i = m_PlayersToCreate.size() - 1; - unsigned int tempID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(tempID, "Transform"); - transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); - ComponentWrapper model = m_World->AttachComponent(tempID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; - model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); - ComponentWrapper player = m_World->AttachComponent(tempID, "Player"); - m_PlayerDefinitions[m_PlayersToCreate[i]].EntityID = tempID; - m_PlayersToCreate.pop_back(); - } + readFromClients(); } void Server::Close() @@ -42,50 +29,37 @@ void Server::Close() void Server::readFromClients() { - char readBuffer[1024] = { 0 }; - int bytesRead = 0; - // time for previouse message - std::clock_t previousePingMessage = std::clock(); - std::clock_t previousSnapshotMessage = std::clock(); - std::clock_t timOutTimer = std::clock(); - // How often we send messages (milliseconds) - int intervalMs = 1000; - int snapshotInterval = 50; - int checkTimeOutInterval = 100; + // m_ThreadIsRunning might be unnecessary but the + // program crashed if it executed m_Socket.available() + // when closing the program. - while (m_ThreadIsRunning) { - // m_ThreadIsRunning might be unnecessary but the - // program crashed if it executed m_Socket.available() - // when closing the program. - - if (m_ThreadIsRunning && m_Socket.available()) { - try { - bytesRead = receive(readBuffer, INPUTSIZE); - Packet packet(readBuffer, bytesRead); - parseMessageType(packet); - } catch (const std::exception& err) { - //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); - } - - } - std::clock_t currentTime = std::clock(); - // Send snapshot - if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { - sendSnapshot(); - previousSnapshotMessage = currentTime; + if (m_Socket.available()) { + try { + bytesRead = receive(readBuffer, INPUTSIZE); + Packet packet(readBuffer, bytesRead); + parseMessageType(packet); + } catch (const std::exception& err) { + //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } - // Send pings each - if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { - sendPing(); - previousePingMessage = currentTime; - } + } + std::clock_t currentTime = std::clock(); + // Send snapshot + if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) { + sendSnapshot(); + previousSnapshotMessage = currentTime; + } - // Time out logic - if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { - checkForTimeOuts(); - timOutTimer = currentTime; - } + // Send pings each + if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) { + sendPing(); + previousePingMessage = currentTime; + } + + // Time out logic + if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) { + checkForTimeOuts(); + timOutTimer = currentTime; } } @@ -291,8 +265,7 @@ void Server::parseConnect(Packet& packet) for (int i = 0; i < MAXCONNECTIONS; i++) { if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) { // Create new player - m_PlayersToCreate.push_back(i); - + m_PlayerDefinitions[i].EntityID = createPlayer(); m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint; m_PlayerDefinitions[i].Name = packet.ReadString(); @@ -368,3 +341,15 @@ void Server::identifyPacketLoss() LOG_INFO("%i Packet(s) were lost...", difference); } } + +EntityID Server::createPlayer() +{ + EntityID entityID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform"); + transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f); + ComponentWrapper model = m_World->AttachComponent(entityID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f); + ComponentWrapper player = m_World->AttachComponent(entityID, "Player"); + return entityID; +} diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 151d9363..e3f710cb 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -55,7 +55,8 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(m_Renderer); // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { - boost::thread workerThread(&Game::networkFunction, this); + //boost::thread workerThread(&Game::networkFunction, this); + networkFunction(); } m_LastTime = glfwGetTime(); @@ -153,7 +154,7 @@ void Game::networkFunction() // I don't think we are reaching this part of the code right now. // ~Game() is not called if the game is exited by closing console windows // When server or client is done set it to false. - m_IsClientOrServer = false; + //m_IsClientOrServer = false; // Destroy it! (with fire) - delete m_ClientOrServer; + //delete m_ClientOrServer; } \ No newline at end of file From ab6af30a28cbc8b72ec00171298d351f8821eac3 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 18 Dec 2015 12:02:02 +0100 Subject: [PATCH 137/185] Base classes for decoupled forward+ renderer and a fix where if you had to many lights in a tile(200-300+) the list would fill up before the end of frustums. --- include/Engine/Rendering/LightCullingPass.h | 28 +++++++++++++++++++ .../Engine/Rendering/LightCullingPassState.h | 0 resources/Shaders/cullLights.comp.glsl | 2 +- src/Engine/Rendering/LightCullingPass.cpp | 0 .../Rendering/LightCullingPassState.cpp | 0 src/Engine/Rendering/Renderer.cpp | 6 ---- 6 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 include/Engine/Rendering/LightCullingPass.h create mode 100644 include/Engine/Rendering/LightCullingPassState.h create mode 100644 src/Engine/Rendering/LightCullingPass.cpp create mode 100644 src/Engine/Rendering/LightCullingPassState.cpp diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h new file mode 100644 index 00000000..cf661e1f --- /dev/null +++ b/include/Engine/Rendering/LightCullingPass.h @@ -0,0 +1,28 @@ +#ifndef LightCullingPass_h__ +#define LightCullingPass_h__ + +#include "IRenderer.h" +#include "LightCullingPassState.h" +#include "ShaderProgram.h" + + +class LightCullingPass +{ +public: + LightCullingPass(); + ~LightCullingPass(); + + + void GenerateNewFrustum(); +private: + void CullLights(); + + void InitializeTextures(); + void InitializeSSBOs(); + void InitializeShaderPrograms(); + + +}; + + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/LightCullingPassState.h b/include/Engine/Rendering/LightCullingPassState.h new file mode 100644 index 00000000..e69de29b diff --git a/resources/Shaders/cullLights.comp.glsl b/resources/Shaders/cullLights.comp.glsl index 69eb5903..bdd3d758 100644 --- a/resources/Shaders/cullLights.comp.glsl +++ b/resources/Shaders/cullLights.comp.glsl @@ -8,7 +8,7 @@ -#define MAX_LIGHTS_PER_TILE 1024 +#define MAX_LIGHTS_PER_TILE 200 #define NUM_TILES 3600 #define TILE_SIZE 16 diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Engine/Rendering/LightCullingPassState.cpp b/src/Engine/Rendering/LightCullingPassState.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 8721127a..28745305 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -218,8 +218,6 @@ void Renderer::InitializeSSBOs() glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); GLERROR("m_LightSSBO"); - - glGenBuffers(1, &m_LightGridSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); @@ -233,7 +231,6 @@ void Renderer::InitializeSSBOs() glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); GLERROR("m_LightOffsetSSBO"); - glGenBuffers(1, &m_LightIndexSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); @@ -254,8 +251,6 @@ void Renderer::CalculateFrustum() m_CalculateFrustumProgram->Bind(); - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix())); glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height); @@ -284,7 +279,6 @@ void Renderer::CullLights() glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - m_LightCullProgram->Bind(); glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); From ef4cbfece887cfd54c5361fddbd6027cb3c87ea8 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Fri, 18 Dec 2015 13:20:55 +0100 Subject: [PATCH 138/185] Added PointLight Component in XML files --- resources/Schema/Components.xsd | 1 + resources/Schema/Components/PointLight.xml | 6 ++++++ resources/Schema/Components/PointLight.xsd | 19 +++++++++++++++++++ resources/Schema/Entities/Test.xml | 22 ++++++++++++++++++++++ resources/Schema/Types/Entity.xsd | 1 + 5 files changed, 49 insertions(+) create mode 100644 resources/Schema/Components/PointLight.xml create mode 100644 resources/Schema/Components/PointLight.xsd diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 12fb870e..b3bffdd5 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -6,4 +6,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/PointLight.xml b/resources/Schema/Components/PointLight.xml new file mode 100644 index 00000000..a1dd5f54 --- /dev/null +++ b/resources/Schema/Components/PointLight.xml @@ -0,0 +1,6 @@ + + + 1.0 + 0.8 + 0.3 + \ No newline at end of file diff --git a/resources/Schema/Components/PointLight.xsd b/resources/Schema/Components/PointLight.xsd new file mode 100644 index 00000000..68e05a84 --- /dev/null +++ b/resources/Schema/Components/PointLight.xsd @@ -0,0 +1,19 @@ + + + + + + + + It's a point light! + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index aed1510c..9c275e35 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -17,6 +17,28 @@ + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.obj + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 92f7dc31..9acfc79a 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -15,6 +15,7 @@ + From a0255f1b318a0089b6e3715d917fe4fc85f675f4 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 13:34:21 +0100 Subject: [PATCH 139/185] Now uses config file to determine if client or server should be started. --- resources/DefaultConfig.ini | 3 +++ resources/DefaultInput.ini | 4 +++- src/Engine/Network/Client.cpp | 12 ++++++------ src/Game/Game.cpp | 21 ++++++++++++++------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 6c6d4808..3ab402ad 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -10,7 +10,10 @@ VSYNC=false Width=1280 Height=720 FOV=45 + [Networking] StartNetwork=false +IsServer=false +Name=Bob Address=127.0.0.1 Port=13 \ No newline at end of file diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 9246de59..95ebbc22 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -19,4 +19,6 @@ F1=ToggleEditor 2=EditorToolRotate 3=EditorToolScale X=EditorToggleTransformSpace -C=ConnectToServer \ No newline at end of file +C=ConnectToServer +N=SwitchToServer +M=SwitchToClient \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 8efd97ce..5c7e9c8f 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -10,6 +10,7 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService) int port = config->Get("Networking.Port", 13); m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); // Set up network stream + m_PlayerName = config->Get("Networking.Name", "Raptorcopter"); m_NextSnapshot.InputForward = ""; m_NextSnapshot.InputRight = ""; } @@ -29,12 +30,11 @@ void Client::Start(World* world, EventBroker* eventBroker) m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EInputCommand); - LOG_INFO("Please enter your name: "); - std::cin >> m_PlayerName; - while (m_PlayerName.size() > 7) { - LOG_INFO("Please enter your name (No longer than 7 characters):"); - std::cin >> m_PlayerName; - } + + //while (m_PlayerName.size() > 7) { + // LOG_INFO("Please enter your name (No longer than 7 characters):"); + // std::cin >> m_PlayerName; + //} m_Socket.connect(m_ReceiverEndpoint); LOG_INFO("I am client. BIP BOP"); } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index e3f710cb..a02e2c62 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -96,7 +96,6 @@ void Game::Tick() m_ClientOrServer->Update(); } - // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); debugTick(dt); @@ -123,6 +122,16 @@ bool Game::debugOnInputCommand(const Events::InputCommand& e) ResourceManager::Load(mapToLoad)->PopulateWorld(m_World); } } + if (e.Command == "SwitchToServer" && e.Value > 0) { + m_ClientOrServer = new Server(); + LOG_INFO("Switching to server"); + m_ClientOrServer->Start(m_World, m_EventBroker); + } + if (e.Command == "SwitchToClient" && e.Value > 0) { + m_ClientOrServer = new Client(m_Config); + m_ClientOrServer->Start(m_World, m_EventBroker); + LOG_INFO("Switching to client"); + } return false; } @@ -139,14 +148,12 @@ void Game::debugTick(double dt) void Game::networkFunction() { - std::string inputMessage; - LOG_INFO("Start client or server? (c/s)"); - std::cin >> inputMessage; - if (inputMessage == "c" || inputMessage == "C") { + bool isServer = m_Config->Get("Networking.IsServer", false); + if (!isServer) { m_IsClientOrServer = true; m_ClientOrServer = new Client(m_Config); } - if (inputMessage == "s" || inputMessage == "S") { + if (isServer) { m_IsClientOrServer = true; m_ClientOrServer = new Server(); } @@ -155,6 +162,6 @@ void Game::networkFunction() // ~Game() is not called if the game is exited by closing console windows // When server or client is done set it to false. //m_IsClientOrServer = false; - // Destroy it! (with fire) + // Destroy it //delete m_ClientOrServer; } \ No newline at end of file From 00bc55370d1d48ad3c7caf1dafc38640260d849b Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 14:19:28 +0100 Subject: [PATCH 140/185] Added error check in Collision.cpp --- src/Engine/Collision/Collision.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d076d1c2..c4af6258 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -252,6 +252,9 @@ bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox) 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"]); From e0cc25dbacb315f62be222a7e81f693618306419 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 18 Dec 2015 14:22:57 +0100 Subject: [PATCH 141/185] Fixed the OctTreeTestGameClass.cpp so it draws the OctTree nicely again --- {include => src}/Tests/EventFixture.h | 0 src/Tests/OctTreeTestAnders.cpp | 6 +--- src/Tests/OctTreeTestGameClass.cpp | 31 ++++++++++++++++--- {include => src}/Tests/OctTreeTestGameClass.h | 12 ++++++- .../Tests/OctTreeTestHardCodedTestWorld.h | 0 5 files changed, 38 insertions(+), 11 deletions(-) rename {include => src}/Tests/EventFixture.h (100%) rename {include => src}/Tests/OctTreeTestGameClass.h (76%) rename {include => src}/Tests/OctTreeTestHardCodedTestWorld.h (100%) diff --git a/include/Tests/EventFixture.h b/src/Tests/EventFixture.h similarity index 100% rename from include/Tests/EventFixture.h rename to src/Tests/EventFixture.h diff --git a/src/Tests/OctTreeTestAnders.cpp b/src/Tests/OctTreeTestAnders.cpp index 12a122ea..b61caead 100644 --- a/src/Tests/OctTreeTestAnders.cpp +++ b/src/Tests/OctTreeTestAnders.cpp @@ -34,16 +34,12 @@ BOOST_AUTO_TEST_CASE(octTreeTest) BOOST_CHECK(someAABB.MaxCorner() == maxCorner); BOOST_CHECK(someAABB.Center() == 0.5f * (minCorner + maxCorner)); - //simple OctTree constructor check - //OctTree someOctTree(someAABB, 5); - //BOOST_CHECK(someOctTree.m_Children[0] != nullptr); - //simple destructor check in the end, just look for memleaks, then it didnt clear the AABB structure } BOOST_AUTO_TEST_CASE(octTreeTest2) { - //octtree ritningen osv + //octtree draw etc Game game(0, nullptr); while (game.Running()) { game.Tick(); diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 1a7deb3f..05aa35d4 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -5,6 +5,8 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl ResourceManager::RegisterType("ConfigFile"); ResourceManager::RegisterType("Model"); ResourceManager::RegisterType("Texture"); + ResourceManager::RegisterType("EntityXMLFile"); + ResourceManager::RegisterType("ShaderProgram"); m_Config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); @@ -25,9 +27,14 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl m_Config->Get("Video.Height", 720) )); m_Renderer->Initialize(); + m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get("Video.FOV", 90.f))); // Create input manager m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker); + m_InputProxy = new InputProxy(m_EventBroker); + m_InputProxy->AddHandler(); + m_InputProxy->AddHandler(); + m_InputProxy->LoadBindings("Input.ini"); // Create the root level GUI frame m_FrameStack = new GUI::Frame(m_EventBroker); @@ -37,6 +44,9 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl // Create a TEST WORLD m_World = new HardcodedTestWorld(); + m_SystemPipeline = new SystemPipeline(m_EventBroker); + m_SystemPipeline->AddSystem(); + m_LastTime = glfwGetTime(); } @@ -52,9 +62,14 @@ void Game::Tick() double dt = currentTime - m_LastTime; m_LastTime = currentTime; + // Handle input in a weird looking but responsive way + m_EventBroker->Process(); m_EventBroker->Swap(); m_InputManager->Update(dt); - m_Renderer->Update(dt); + m_EventBroker->Swap(); + m_InputProxy->Update(dt); + m_EventBroker->Swap(); + m_InputProxy->Process(); m_EventBroker->Swap(); #define TEST1 @@ -70,7 +85,7 @@ void Game::Tick() AABB boxi; boxi.CreateFromCenter(pos, maxPos - minPos); frameCounter++; - if (frameCounter > 50) { + if (frameCounter > 1) { m_World->someOctTree.ClearDynamicObjects(); m_World->someOctTree.AddDynamicObject(boxi); frameCounter = 0; @@ -149,8 +164,8 @@ void Game::Tick() if (someOctTree.BoxCollides(redBox, AABB())) { //this checks AABB vs AABB //if (Collision::AABBVsAABB(redBox, aabb)) { - m_Renderer->Camera()->SetPosition(m_PrevPos); - m_Renderer->Camera()->SetOrientation(m_PrevOri); + //m_Renderer->Camera()->SetPosition(m_PrevPos); + //m_Renderer->Camera()->SetOrientation(m_PrevOri); model["Color"] = greenCol; } else { @@ -163,8 +178,14 @@ void Game::Tick() m_RenderQueueFactory->Update(m_World); #endif - m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); + // Iterate through systems and update world! + m_SystemPipeline->Update(m_World, dt); + m_Renderer->Update(dt); + m_RenderQueueFactory->Update(m_World); + GLERROR("Game::Tick m_RenderQueueFactory->Update"); + m_Renderer->Draw(m_RenderQueueFactory->RenderQueues()); + GLERROR("Game::Tick m_Renderer->Draw"); m_EventBroker->Swap(); m_EventBroker->Clear(); diff --git a/include/Tests/OctTreeTestGameClass.h b/src/Tests/OctTreeTestGameClass.h similarity index 76% rename from include/Tests/OctTreeTestGameClass.h rename to src/Tests/OctTreeTestGameClass.h index 985d34d4..6dc9404e 100644 --- a/include/Tests/OctTreeTestGameClass.h +++ b/src/Tests/OctTreeTestGameClass.h @@ -9,11 +9,19 @@ #include "GUI/Frame.h" #include "Core/World.h" #include "Rendering/RenderQueueFactory.h" +#include "Input/InputProxy.h" +#include "Input/KeyboardInputHandler.h" +#include "Input/MouseInputHandler.h" +#include "Core/EKeyDown.h" +#include "Core/EntityXMLFile.h" +#include "Core/SystemPipeline.h" +#include "RaptorCopterSystem.h" +#include "PlayerSystem.h" +#include "Editor/EditorSystem.h" #include "OctTreeTestHardCodedTestWorld.h" #include "Collision/Collision.h" - class Game { public: @@ -32,6 +40,8 @@ private: GUI::Frame* m_FrameStack; HardcodedTestWorld* m_World; RenderQueueFactory* m_RenderQueueFactory; + InputProxy* m_InputProxy; + SystemPipeline* m_SystemPipeline; //Test1 int frameCounter = 0; diff --git a/include/Tests/OctTreeTestHardCodedTestWorld.h b/src/Tests/OctTreeTestHardCodedTestWorld.h similarity index 100% rename from include/Tests/OctTreeTestHardCodedTestWorld.h rename to src/Tests/OctTreeTestHardCodedTestWorld.h From a550b6077e0daae83d0997148d275d91195283c1 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 14:25:55 +0100 Subject: [PATCH 142/185] Re-enabled InputCommand debugging info in console --- src/Engine/Input/InputProxy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engine/Input/InputProxy.cpp b/src/Engine/Input/InputProxy.cpp index ad589df3..c3e4d669 100644 --- a/src/Engine/Input/InputProxy.cpp +++ b/src/Engine/Input/InputProxy.cpp @@ -62,7 +62,7 @@ void InputProxy::Process() e.Command = command; e.Value = currentValue; m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); m_LastCommandValues[command] = currentValue; } } @@ -78,7 +78,7 @@ void InputProxy::Process() } //e.Value = std::max(-1.f, std::min(e.Value, 1.f)); m_EventBroker->Publish(e); - //LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID); } m_CommandQueue.clear(); } From 069a6756b96eb70167b2948a45418e0dcff72d9e Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 18 Dec 2015 14:31:16 +0100 Subject: [PATCH 143/185] LightcullingPass for forward+ is now separate from Renderer.cpp. --- include/Engine/Rendering/LightCullingPass.h | 59 ++++++++++- include/Engine/Rendering/PickingPass.h | 6 +- include/Engine/Rendering/Renderer.h | 54 +--------- resources/Shaders/ForwardPlus.frag.glsl | 1 + src/Engine/Rendering/LightCullingPass.cpp | 107 ++++++++++++++++++++ src/Engine/Rendering/Renderer.cpp | 105 +------------------ 6 files changed, 177 insertions(+), 155 deletions(-) diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h index cf661e1f..f0ed5d6b 100644 --- a/include/Engine/Rendering/LightCullingPass.h +++ b/include/Engine/Rendering/LightCullingPass.h @@ -1,6 +1,9 @@ #ifndef LightCullingPass_h__ #define LightCullingPass_h__ +#define TILE_SIZE 16 +#define NUM_LIGHTS 1000 + #include "IRenderer.h" #include "LightCullingPassState.h" #include "ShaderProgram.h" @@ -9,19 +12,67 @@ class LightCullingPass { public: - LightCullingPass(); + LightCullingPass(IRenderer* renderer); ~LightCullingPass(); - void GenerateNewFrustum(); -private: void CullLights(); - void InitializeTextures(); + GLuint FrustumSSBO() const { return m_FrustumSSBO; } + GLuint LightSSBO() const { return m_LightSSBO; } + GLuint LightGridSSBO() const { return m_LightGridSSBO; } + GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; } + GLuint LightIndexSSBO() const { return m_LightIndexSSBO; } +private: + void InitializeSSBOs(); void InitializeShaderPrograms(); + const IRenderer* m_Renderer; + GLuint m_FrustumSSBO = 0; + GLuint m_LightSSBO = 0; + GLuint m_LightGridSSBO = 0; + GLuint m_LightOffsetSSBO = 0; + GLuint m_LightIndexSSBO = 0; + + ShaderProgram* m_CalculateFrustumProgram; + ShaderProgram* m_LightCullProgram; + + struct Plane { + glm::vec3 Normal; + float d; + }; + + struct Frustum { + Plane Planes[4]; + }; + Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution + + void TEMPCreateLights(); + + //This should be a component + struct PointLight { + glm::vec4 Position = glm::vec4(0.f); + glm::vec4 Color = glm::vec4(1.f); + float Radius = 5.f; + float Intensity = 0.8f; + float Falloff = 0.3f; + float Padding = 1337; + }; + PointLight m_PointLights[NUM_LIGHTS]; + + struct LightGrid { + float Start; + float Amount; + glm::vec2 Padding; + }; + + LightGrid m_LightGrid[80*45]; //TODO: Renderer: Make this change with resolution + + int m_LightOffset = 0; + + float m_LightIndex[80*45*200]; //TODO: Renderer: Make this change with resolution }; diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index e1bc42db..0c1261ce 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -1,6 +1,8 @@ #ifndef PickingPass_h__ #define PickingPass_h__ + + #include "IRenderer.h" #include "PickingPassState.h" #include "FrameBuffer.h" @@ -9,6 +11,8 @@ #include "../Core/EventBroker.h" #include "EPicking.h" + + class PickingPass { public: @@ -20,7 +24,6 @@ public: void Draw(RenderQueueCollection& rq); - //Getters const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } const std::unordered_map& PickingColorsToEntity() const { return m_PickingColorsToEntity; } @@ -28,7 +31,6 @@ public: GLuint DepthBuffer() const { return m_DepthBuffer; } const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; } - private: void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index d8928b18..048e6f7e 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -12,11 +12,7 @@ #include "../Core/World.h" #include "PickingPass.h" #include "DrawScenePass.h" - - -#define TILE_SIZE 16 -#define NUM_LIGHTS 1000 - +#include "LightCullingPass.h" #include "../Core/EventBroker.h" #include "EPicking.h" @@ -46,12 +42,12 @@ private: DrawScenePass* m_DrawScenePass; PickingPass* m_PickingPass; + LightCullingPass* m_LightCullingPass; //----------------------Functions----------------------// void InitializeWindow(); void InitializeShaders(); void InitializeTextures(); - void InitializeSSBOs(); void InitializeRenderPasses(); //TODO: Renderer: Get InputUpdate out of renderer void InputUpdate(double dt); @@ -59,58 +55,18 @@ private: void DrawScreenQuad(GLuint textureToDraw); //----------------------Forward+-----------------------// - void CalculateFrustum(); - void CullLights(); void DrawForwardPlus(RenderQueueCollection& rq); //Frustum - struct Plane { - glm::vec3 Normal; - float d; - }; - - struct Frustum { - Plane Planes[4]; - }; - Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution - - //Lights - void TEMPCreateLights(); - //TODO: Renderer: Add Directionllights, spotlights and area lights to this as type. - struct PointLight { - glm::vec4 Position = glm::vec4(0.f); - glm::vec4 Color = glm::vec4(1.f); - float Radius = 5.f; - float Intensity = 0.8f; - float Falloff = 0.3f; - float Padding = 1337; - }; - PointLight m_PointLights[NUM_LIGHTS]; - - struct LightGrid { - float Start; - float Amount; - glm::vec2 Padding; - }; - - LightGrid m_LightGrid[80*45]; - - int m_LightOffset = 0; - - float m_LightIndex[80*45*200]; + //-------------------------SSBO------------------------// - GLuint m_FrustumSSBO = 0; - GLuint m_LightSSBO = 0; - GLuint m_LightGridSSBO = 0; - GLuint m_LightOffsetSSBO = 0; - GLuint m_LightIndexSSBO = 0; + void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_DrawScreenQuadProgram; - ShaderProgram* m_CalculateFrustumProgram; - ShaderProgram* m_LightCullProgram; + ShaderProgram* m_ForwardPlusProgram; }; diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 568195ce..79d5411c 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -115,6 +115,7 @@ void main() } fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color; + //fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color; //fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1); //fragmentColor = texel * Input.DiffuseColor * Color; if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index e69de29b..85f27a37 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -0,0 +1,107 @@ +#include "Rendering/LightCullingPass.h" + +LightCullingPass::LightCullingPass(IRenderer* renderer) +{ + m_Renderer = renderer; + TEMPCreateLights(); + InitializeSSBOs(); + InitializeShaderPrograms(); + GenerateNewFrustum(); +} + +LightCullingPass::~LightCullingPass() +{ + +} + +void LightCullingPass::GenerateNewFrustum() +{ + GLERROR("CalculateFrustum Error: Pre"); + + m_CalculateFrustumProgram->Bind(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); + glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glDispatchCompute(5, 3, 1); //TODO: Renderer: This needs change so resolution will be right. + + GLERROR("CalculateFrustum Error: End"); +} + +void LightCullingPass::CullLights() +{ + GLERROR("CullLights Error: Pre"); + m_LightOffset = 0; + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + m_LightCullProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + glDispatchCompute(m_Renderer->Resolution().Width / TILE_SIZE, m_Renderer->Resolution().Height / TILE_SIZE, 1); + + GLERROR("CullLights Error: End"); +} + +void LightCullingPass::InitializeSSBOs() +{ + glGenBuffers(1, &m_FrustumSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + GLERROR("m_FrustumSSBO"); + + glGenBuffers(1, &m_LightSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + GLERROR("m_LightSSBO"); + + glGenBuffers(1, &m_LightGridSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + GLERROR("m_LightGridSSBO"); + + + glGenBuffers(1, &m_LightOffsetSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + GLERROR("m_LightOffsetSSBO"); + + glGenBuffers(1, &m_LightIndexSSBO); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + GLERROR("m_LightIndexSSBO"); +} + +void LightCullingPass::InitializeShaderPrograms() +{ + m_CalculateFrustumProgram = ResourceManager::Load("#CalculateFrustumProgram"); + m_CalculateFrustumProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/GridFrustum.comp.glsl"))); + m_CalculateFrustumProgram->Compile(); + m_CalculateFrustumProgram->Link(); + + m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); + m_LightCullProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); + m_LightCullProgram->Compile(); + m_LightCullProgram->Link(); +} + +void LightCullingPass::TEMPCreateLights() +{ + for (int i = 0; i < NUM_LIGHTS; i++) { + glm::vec3 pos = glm::vec3(cos(i) * i/10.f, 0.5f, sin(i) * i/10.f); + m_PointLights[i].Position = glm::vec4(pos, 1.f); + m_PointLights[i].Color = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand()%255 / 255.f, 1.f); + m_PointLights[i].Radius = glm::length(pos) / 5.f; + } +} diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 28745305..e61c1d7c 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -9,14 +9,11 @@ void Renderer::Initialize() if (m_Camera == nullptr) { m_Camera = m_DefaultCamera; } - TEMPCreateLights(); InitializeRenderPasses(); glfwSwapInterval(m_VSYNC); InitializeShaders(); InitializeTextures(); - InitializeSSBOs(); - CalculateFrustum(); m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); @@ -73,16 +70,6 @@ void Renderer::InitializeShaders() m_DrawScreenQuadProgram->Compile(); m_DrawScreenQuadProgram->Link(); - m_CalculateFrustumProgram = ResourceManager::Load("#CalculateFrustumProgram"); - m_CalculateFrustumProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/GridFrustum.comp.glsl"))); - m_CalculateFrustumProgram->Compile(); - m_CalculateFrustumProgram->Link(); - - m_LightCullProgram = ResourceManager::Load("#LightCullProgram"); - m_LightCullProgram->AddShader(std::shared_ptr(new ComputeShader("Shaders/cullLights.comp.glsl"))); - m_LightCullProgram->Compile(); - m_LightCullProgram->Link(); - m_ForwardPlusProgram = ResourceManager::Load("#ForwardPlusProgram"); m_ForwardPlusProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); m_ForwardPlusProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); @@ -156,7 +143,7 @@ void Renderer::Draw(RenderQueueCollection& rq) { m_PickingPass->Draw(rq); //DrawScreenQuad(m_PickingPass->PickingTexture()); - CullLights(); + m_LightCullingPass->CullLights(); //m_DrawScenePass->Draw(rq); DrawForwardPlus(rq); @@ -203,93 +190,11 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin GLERROR("Texture initialization failed"); } -void Renderer::InitializeSSBOs() -{ - printf("Size: %i\n", sizeof(m_Frustums)); - glGenBuffers(1, &m_FrustumSSBO); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_FrustumSSBO"); - - glGenBuffers(1, &m_LightSSBO); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightSSBO"); - - glGenBuffers(1, &m_LightGridSSBO); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightGridSSBO"); - - - glGenBuffers(1, &m_LightOffsetSSBO); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightOffsetSSBO"); - - glGenBuffers(1, &m_LightIndexSSBO); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLERROR("m_LightIndexSSBO"); - -} - void Renderer::InitializeRenderPasses() { m_DrawScenePass = new DrawScenePass(this); m_PickingPass = new PickingPass(this, m_EventBroker); -} - -void Renderer::CalculateFrustum() -{ - GLERROR("CalculateFrustum Error: Pre"); - - m_CalculateFrustumProgram->Bind(); - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); - glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height); - glDispatchCompute(5, 3, 1); - - GLERROR("CalculateFrustum Error: End"); -} - -void Renderer::TEMPCreateLights() -{ - for (int i = 0; i < NUM_LIGHTS; i++) - { - glm::vec3 pos = glm::vec3(cos(i) * i/10.f , 0.5f, sin(i) * i/10.f); - m_PointLights[i].Position = glm::vec4(pos, 1.f); - m_PointLights[i].Color = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand()%255 / 255.f, 1.f); - m_PointLights[i].Radius = glm::length(pos) / 5.f; - } -} - -void Renderer::CullLights() -{ - GLERROR("CullLights Error: Pre"); - m_LightOffset = 0; - - glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - m_LightCullProgram->Bind(); - glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Camera->ViewMatrix())); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); - glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1); - - GLERROR("CullLights Error: End"); - + m_LightCullingPass = new LightCullingPass(this); } void Renderer::DrawForwardPlus(RenderQueueCollection& rq) @@ -304,9 +209,9 @@ void Renderer::DrawForwardPlus(RenderQueueCollection& rq) m_ForwardPlusProgram->Bind(); GLuint ShaderHandle = m_ForwardPlusProgram->GetHandle(); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); //TODO: Render: Add code for more jobs than modeljobs. for (auto &job : rq.Forward) { auto modelJob = std::dynamic_pointer_cast(job); From 2f6d4fcd0b4d3a9526fbe5ff7582caa83048996e Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 18 Dec 2015 14:49:35 +0100 Subject: [PATCH 144/185] Adjusted some of the corefiles back to the original in preparation for the Pull Request --- include/Engine/Core/InputController.h | 3 +-- include/Game/Game.h | 1 + src/Engine/Core/ConfigFile.cpp | 3 --- src/Engine/Core/EventBroker.cpp | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/Engine/Core/InputController.h b/include/Engine/Core/InputController.h index 0cad346f..b87d1eff 100644 --- a/include/Engine/Core/InputController.h +++ b/include/Engine/Core/InputController.h @@ -17,8 +17,7 @@ public: virtual void Initialize() { - EVENT_SUBSCRIBE_MEMBER( - m_EInputCommand, &InputController::OnCommand); + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand); } virtual bool OnCommand(const Events::InputCommand& e) { return false; } diff --git a/include/Game/Game.h b/include/Game/Game.h index a090827b..7933c8a1 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -39,6 +39,7 @@ private: World* m_World; SystemPipeline* m_SystemPipeline; RenderQueueFactory* m_RenderQueueFactory; + EventRelay m_EInputCommand; bool debugOnInputCommand(const Events::InputCommand& e); diff --git a/src/Engine/Core/ConfigFile.cpp b/src/Engine/Core/ConfigFile.cpp index fbb03b14..00ab4993 100644 --- a/src/Engine/Core/ConfigFile.cpp +++ b/src/Engine/Core/ConfigFile.cpp @@ -27,9 +27,6 @@ ConfigFile::ConfigFile(std::string path) for (auto& topLevelNode : m_PTreeOverrides) { auto& mergedTopLevelNode = m_PTreeMerged.find(topLevelNode.first); for (auto& childOverrideNode : topLevelNode.second) { - //auto ttt = mergedTopLevelNode->second; - //auto ttt2 = childOverrideNode.first; - //auto ttt3 = childOverrideNode.second; mergedTopLevelNode->second.put_child(childOverrideNode.first, childOverrideNode.second); } } diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index c12f915f..76c243e8 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -1,4 +1,4 @@ -#include "Core\EventBroker.h" +#include "Core/EventBroker.h" BaseEventRelay::~BaseEventRelay() { From de8461e2579e567ed328234cb29f95be7bf049af Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 18 Dec 2015 15:33:25 +0100 Subject: [PATCH 145/185] SystemPipeline should update systems in order depending on input update priority in AddSystem. --- include/Engine/Core/SystemPipeline.h | 68 ++++++++++++++++------------ src/Game/Game.cpp | 14 ++++-- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index 78ebc966..fdae834f 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -14,23 +14,29 @@ public: { } ~SystemPipeline() { - for (auto& pair : m_PureSystems) { - for (auto& system : pair.second) { - delete system; + for (UnorderedSystems& group : m_OrderedSystemGroups) { + for (auto& pair : group.PureSystems) { + for (auto& system : pair.second) { + delete system; + } } } } template - void AddSystem(Arguments... args) + void AddSystem(int updateOrderPriority, Arguments... args) { + if (updateOrderPriority + 1 > m_OrderedSystemGroups.size()) { + m_OrderedSystemGroups.resize(updateOrderPriority + 1); + } + UnorderedSystems& group = m_OrderedSystemGroups[updateOrderPriority]; System* system = new T(m_EventBroker, args...); - m_Systems[typeid(T).name()] = system; + group.Systems[typeid(T).name()] = system; if (std::is_base_of::value) { PureSystem* pureSystem = static_cast(system); if (!pureSystem->m_ComponentType.empty()) { - m_PureSystems[pureSystem->m_ComponentType].push_back(pureSystem); + group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem); } else { LOG_ERROR("Failed to add pure system \"%s\": Missing component type!", typeid(T).name()); } @@ -38,41 +44,47 @@ public: if (std::is_base_of::value) { ImpureSystem* impureSystem = static_cast(system); - m_ImpureSystems.push_back(impureSystem); + group.ImpureSystems.push_back(impureSystem); } } void Update(World* world, double dt) { - // Process events - for (auto& pair : m_Systems) { - m_EventBroker->Process(pair.first); - } - - // Update - for (auto& pair : m_PureSystems) { - const std::string& componentName = pair.first; - auto& systems = pair.second; - const ComponentPool* pool = world->GetComponents(componentName); - if (pool == nullptr) { - continue; + for (UnorderedSystems& group : m_OrderedSystemGroups) { + // Process events + for (auto& pair : group.Systems) { + m_EventBroker->Process(pair.first); } - for (auto& component : *pool) { - for (auto& system : systems) { - system->UpdateComponent(world, component, dt); + + // Update + for (auto& pair : group.PureSystems) { + const std::string& componentName = pair.first; + auto& systems = pair.second; + const ComponentPool* pool = world->GetComponents(componentName); + if (pool == nullptr) { + continue; + } + for (auto& component : *pool) { + for (auto& system : systems) { + system->UpdateComponent(world, component, dt); + } } } - } - for (auto& system : m_ImpureSystems) { - system->Update(world, dt); + for (auto& system : group.ImpureSystems) { + system->Update(world, dt); + } } } private: EventBroker* m_EventBroker; - std::map m_Systems; - std::map> m_PureSystems; - std::vector m_ImpureSystems; + struct UnorderedSystems + { + std::map Systems; + std::map> PureSystems; + std::vector ImpureSystems; + }; + std::vector m_OrderedSystemGroups; }; #endif \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index bf990e23..b0628bd8 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -52,11 +52,15 @@ Game::Game(int argc, char* argv[]) // Create system pipeline m_SystemPipeline = new SystemPipeline(m_EventBroker); - m_SystemPipeline->AddSystem(); - m_SystemPipeline->AddSystem(); - m_SystemPipeline->AddSystem(m_Renderer); - m_SystemPipeline->AddSystem(); - m_SystemPipeline->AddSystem(); + unsigned int updateOrderPriority = 0; + m_SystemPipeline->AddSystem(updateOrderPriority); + m_SystemPipeline->AddSystem(updateOrderPriority); + m_SystemPipeline->AddSystem(updateOrderPriority, m_Renderer); + + //Collision and TriggerSystem should update after player. + ++updateOrderPriority; + m_SystemPipeline->AddSystem(updateOrderPriority); + m_SystemPipeline->AddSystem(updateOrderPriority); m_LastTime = glfwGetTime(); From 0ae6c42df834e29e678d5e935d0cae92286e46b4 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 5 Jan 2016 15:22:16 +0100 Subject: [PATCH 146/185] Exit Crash has been dealt with. There is no need to unsubscribe game since m_ContextRelays has already been destroyed at that point --- src/Engine/Core/EventBroker.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index 76c243e8..4d58c087 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -3,7 +3,10 @@ BaseEventRelay::~BaseEventRelay() { if (m_Broker != nullptr) { - m_Broker->Unsubscribe(*this); + //m_ContextRelays has already been destroyed at this point, since, + //this BaseEventRelay is called after EventBroker has been deleted + //hence there is nothing to unsubscribe + //m_Broker->Unsubscribe(*this); } } From 34cbbb3eb1b214b372b3962bc2d6a80ca1c183b9 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 6 Jan 2016 11:20:16 +0100 Subject: [PATCH 147/185] Fixed exit crash(es) --- include/Engine/Core/System.h | 5 +++ include/Engine/Core/SystemPipeline.h | 6 ++-- include/Engine/Rendering/Renderer.h | 3 ++ src/Engine/Rendering/Renderer.cpp | 10 +++--- src/Game/Game.cpp | 46 +++++----------------------- 5 files changed, 21 insertions(+), 49 deletions(-) diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index 57b0d2cc..75bd3882 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -7,10 +7,13 @@ class System { + friend class SystemPipeline; + protected: System(EventBroker* eventBroker) : m_EventBroker(eventBroker) { } + virtual ~System() = default; EventBroker* m_EventBroker; }; @@ -24,6 +27,7 @@ protected: : System(eventBroker) , m_ComponentType(componentType) { } + virtual ~PureSystem() = default; const std::string m_ComponentType; @@ -38,6 +42,7 @@ protected: ImpureSystem(EventBroker* eventBroker) : System(eventBroker) { } + 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 78ebc966..4aaa5163 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -14,10 +14,8 @@ public: { } ~SystemPipeline() { - for (auto& pair : m_PureSystems) { - for (auto& system : pair.second) { - delete system; - } + for (auto& pair : m_Systems) { + delete pair.second; } } diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index b4aae346..19b48e1a 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -12,6 +12,7 @@ #include "../Core/World.h" #include "PickingPass.h" #include "DrawScenePass.h" +#include "DebugCameraInputController.h" #define TILE_SIZE 16 @@ -45,6 +46,8 @@ private: //----------------------Variables----------------------// EventBroker* m_EventBroker; + std::shared_ptr> m_DebugCameraInputController; + Texture* m_ErrorTexture; Texture* m_WhiteTexture; float m_CameraMoveSpeed; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 21ff6c5a..208f339b 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -1,5 +1,4 @@ #include "Rendering/Renderer.h" -#include "Rendering/DebugCameraInputController.h" void Renderer::Initialize() { @@ -10,6 +9,7 @@ void Renderer::Initialize() if (m_Camera == nullptr) { m_Camera = m_DefaultCamera; } + m_DebugCameraInputController = std::make_shared>(m_EventBroker, -1); TEMPCreateLights(); InitializeRenderPasses(); @@ -89,8 +89,6 @@ void Renderer::InitializeShaders() void Renderer::InputUpdate(double dt) { - static DebugCameraInputController firstPersonInputController(m_EventBroker, -1); - glm::vec3 m_Position = m_Camera->Position(); if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS) { @@ -120,9 +118,9 @@ void Renderer::InputUpdate(double dt) m_CameraMoveSpeed = 0.5f; } - firstPersonInputController.Update(dt); - m_Camera->SetOrientation(firstPersonInputController.Orientation()); - m_Camera->SetPosition(firstPersonInputController.Position()); + m_DebugCameraInputController->Update(dt); + m_Camera->SetOrientation(m_DebugCameraInputController->Orientation()); + m_Camera->SetPosition(m_DebugCameraInputController->Position()); } void Renderer::Update(double dt) diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index f1582d5d..033db642 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -27,7 +27,7 @@ Game::Game(int argc, char* argv[]) 0, m_Config->Get("Video.Width", 1280), m_Config->Get("Video.Height", 720) - )); + )); m_Renderer->Initialize(); m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get("Video.FOV", 90.f))); @@ -64,17 +64,17 @@ Game::Game(int argc, char* argv[]) networkFunction(); } m_LastTime = glfwGetTime(); - - debugInitialize(); } Game::~Game() { - // Call before to ensure that thread closes correctly. - //if (m_IsClientOrServer) - // m_ClientOrServer.Close(); - + delete m_SystemPipeline; + delete m_World; delete m_FrameStack; + delete m_InputProxy; + delete m_InputManager; + delete m_Renderer; + delete m_RenderQueueFactory; delete m_EventBroker; } @@ -103,7 +103,6 @@ void Game::Tick() // Iterate through systems and update world! m_SystemPipeline->Update(m_World, dt); - debugTick(dt); m_Renderer->Update(dt); m_EventBroker->Process(); @@ -115,37 +114,6 @@ void Game::Tick() m_EventBroker->Clear(); } - -bool Game::debugOnInputCommand(const Events::InputCommand& e) -{ - if (e.Command == "DebugReload" && e.Value == 1) { - std::string mapToLoad = m_Config->Get("Debug.LoadMap", ""); - if (!mapToLoad.empty()) { - delete m_World; - m_World = new World(); - ResourceManager::Release("EntityXMLFile", mapToLoad); - ResourceManager::Load(mapToLoad)->PopulateWorld(m_World); - } - } - if (e.Command == "SwitchToServer" && e.Value > 0) { - m_ClientOrServer = new Server(); - LOG_INFO("Switching to server"); - m_ClientOrServer->Start(m_World, m_EventBroker); - } - if (e.Command == "SwitchToClient" && e.Value > 0) { - m_ClientOrServer = new Client(m_Config); - m_ClientOrServer->Start(m_World, m_EventBroker); - LOG_INFO("Switching to client"); - } - - return false; -} - -void Game::debugInitialize() -{ - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand); -} - void Game::debugTick(double dt) { m_EventBroker->Process(); From e510f2b88c9fb7e96de583ce258d97e76fca6593 Mon Sep 17 00:00:00 2001 From: Tleety Date: Wed, 6 Jan 2016 11:32:42 +0100 Subject: [PATCH 148/185] Forward plus render pass now removed from Renderer.cpp to it's own class. --- include/Engine/Rendering/DrawFinalPass.h | 38 ++++++++ include/Engine/Rendering/DrawFinalPassState.h | 15 ++++ include/Engine/Rendering/Renderer.h | 13 +-- src/Engine/Rendering/DrawFinalPass.cpp | 65 ++++++++++++++ src/Engine/Rendering/DrawFinalPassState.cpp | 17 ++++ src/Engine/Rendering/DrawScenePass.cpp | 9 +- src/Engine/Rendering/Renderer.cpp | 86 +------------------ 7 files changed, 146 insertions(+), 97 deletions(-) create mode 100644 include/Engine/Rendering/DrawFinalPass.h create mode 100644 include/Engine/Rendering/DrawFinalPassState.h create mode 100644 src/Engine/Rendering/DrawFinalPass.cpp create mode 100644 src/Engine/Rendering/DrawFinalPassState.cpp diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h new file mode 100644 index 00000000..1a201daf --- /dev/null +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -0,0 +1,38 @@ +#ifndef DrawFinalPass_h__ +#define DrawFinalPass_h__ + +#include "IRenderer.h" +#include "DrawFinalPassState.h" +#include "LightCullingPass.h" +#include "FrameBuffer.h" +#include "ShaderProgram.h" +#include "Util/UnorderedMapVec2.h" +#include "Texture.h" + +class DrawFinalPass +{ +public: + DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass); + ~DrawFinalPass() { } + void InitializeTextures(); + void InitializeFrameBuffers(); + void InitializeShaderPrograms(); + + void Draw(RenderQueueCollection& rq); + + //Getters + + +private: + void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; + + Texture* m_WhiteTexture; + + const IRenderer* m_Renderer; + const LightCullingPass* m_LightCullingPass; + + ShaderProgram* m_ForwardPlusProgram; + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPassState.h b/include/Engine/Rendering/DrawFinalPassState.h new file mode 100644 index 00000000..72d8e392 --- /dev/null +++ b/include/Engine/Rendering/DrawFinalPassState.h @@ -0,0 +1,15 @@ +#ifndef DrawFinalPassState_h__ +#define DrawFinalPassState_h__ + +#include "Rendering/RenderState.h" + +class DrawFinalPassState : public RenderState +{ +public: + DrawFinalPassState(); + ~DrawFinalPassState(); +private: + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 83eb8066..501718e7 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -13,6 +13,7 @@ #include "PickingPass.h" #include "DrawScenePass.h" #include "LightCullingPass.h" +#include "DrawFinalPass.h" #include "../Core/EventBroker.h" #include "EPicking.h" @@ -45,6 +46,7 @@ private: PickingPass* m_PickingPass; LightCullingPass* m_LightCullingPass; ImGuiRenderPass* m_ImGuiRenderPass; + DrawFinalPass* m_DrawFinalPass; //----------------------Functions----------------------// void InitializeWindow(); @@ -56,21 +58,10 @@ private: //void PickingPass(RenderQueueCollection& rq); void DrawScreenQuad(GLuint textureToDraw); - //----------------------Forward+-----------------------// - void DrawForwardPlus(RenderQueueCollection& rq); - //Frustum - - - //-------------------------SSBO------------------------// - - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_DrawScreenQuadProgram; - - ShaderProgram* m_ForwardPlusProgram; - }; #endif \ No newline at end of file diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp new file mode 100644 index 00000000..359981d3 --- /dev/null +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -0,0 +1,65 @@ +#include "Rendering/DrawFinalPass.h" + +DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass) +{ + m_Renderer = renderer; + m_LightCullingPass = lightCullingPass; + InitializeTextures(); + InitializeShaderPrograms(); +} + +void DrawFinalPass::InitializeTextures() +{ + m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); +} + +void DrawFinalPass::InitializeShaderPrograms() +{ + m_ForwardPlusProgram = ResourceManager::Load("#ForwardPlusProgram"); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ForwardPlusProgram->Compile(); + m_ForwardPlusProgram->Link(); +} + +void DrawFinalPass::Draw(RenderQueueCollection& rq) +{ + GLERROR("DrawFinalPass::Draw: Pre"); + + DrawFinalPassState state; + m_ForwardPlusProgram->Bind(); + GLuint shaderHandle = m_ForwardPlusProgram->GetHandle(); + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix())); + + //TODO: Render: Add code for more jobs than modeljobs. + for (auto &job : rq.Forward) { + auto modelJob = std::dynamic_pointer_cast(job); + if(modelJob) { + //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); + + if(modelJob->DiffuseTexture != nullptr) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + + glBindVertexArray(modelJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); + + continue; + } + } + GLERROR("DrawFinalPass::Draw: END"); + +} diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp new file mode 100644 index 00000000..7bfb99b5 --- /dev/null +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -0,0 +1,17 @@ +#include "Rendering/DrawFinalPassState.h" + + +DrawFinalPassState::DrawFinalPassState() +{ + BindFramebuffer(0); + + Enable(GL_DEPTH_TEST); + Enable(GL_CULL_FACE); + ClearColor(glm::vec4(200.f / 255, 0.f / 255, 200.f / 255, 0.f)); + Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +DrawFinalPassState::~DrawFinalPassState() +{ + +} diff --git a/src/Engine/Rendering/DrawScenePass.cpp b/src/Engine/Rendering/DrawScenePass.cpp index 34fc6d12..19de3d58 100644 --- a/src/Engine/Rendering/DrawScenePass.cpp +++ b/src/Engine/Rendering/DrawScenePass.cpp @@ -14,15 +14,12 @@ void DrawScenePass::InitializeTextures() void DrawScenePass::InitializeShaderPrograms() { - //Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat. m_BasicForwardProgram = ResourceManager::Load("#BasicForwardProgram"); m_BasicForwardProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/BasicForward.vert.glsl"))); m_BasicForwardProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); m_BasicForwardProgram->Compile(); m_BasicForwardProgram->Link(); - - } void DrawScenePass::Draw(RenderQueueCollection& rq) @@ -61,6 +58,12 @@ void DrawScenePass::Draw(RenderQueueCollection& rq) continue; } + auto spriteJob = std::dynamic_pointer_cast(job); + if(spriteJob) + { + //Hello im a sprite, please draw me. + } + } GLERROR("DrawScenePass::Draw: End"); } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 66b88092..9a0c1c2e 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -72,47 +72,12 @@ void Renderer::InitializeShaders() m_DrawScreenQuadProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl"))); m_DrawScreenQuadProgram->Compile(); m_DrawScreenQuadProgram->Link(); - - m_ForwardPlusProgram = ResourceManager::Load("#ForwardPlusProgram"); - m_ForwardPlusProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); - m_ForwardPlusProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); - m_ForwardPlusProgram->Compile(); - m_ForwardPlusProgram->Link(); } void Renderer::InputUpdate(double dt) { static DebugCameraInputController firstPersonInputController(m_EventBroker, -1); - glm::vec3 m_Position = m_Camera->Position(); - if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS) - { - m_Position = glm::vec3(0.f, 0.f, 5.f); - } - if (glfwGetKey(m_Window, GLFW_KEY_W) == GLFW_PRESS) - { - m_Position += m_Camera->Forward() * m_CameraMoveSpeed * (float)dt; - } - if (glfwGetKey(m_Window, GLFW_KEY_S) == GLFW_PRESS) - { - m_Position -= m_Camera->Forward() * m_CameraMoveSpeed * (float)dt; - } - if (glfwGetKey(m_Window, GLFW_KEY_D) == GLFW_PRESS) - { - m_Position += m_Camera->Right() * m_CameraMoveSpeed * (float)dt; - } - if (glfwGetKey(m_Window, GLFW_KEY_A) == GLFW_PRESS) - { - m_Position -= m_Camera->Right() * m_CameraMoveSpeed * (float)dt; - } - if (glfwGetKey(m_Window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) - { - m_CameraMoveSpeed = 5.f; - } - else { - m_CameraMoveSpeed = 0.5f; - } - firstPersonInputController.Update(dt); m_Camera->SetOrientation(firstPersonInputController.Orientation()); m_Camera->SetPosition(firstPersonInputController.Position()); @@ -132,7 +97,7 @@ void Renderer::Draw(RenderQueueCollection& rq) m_LightCullingPass->CullLights(); //m_DrawScenePass->Draw(rq); - DrawForwardPlus(rq); + m_DrawFinalPass->Draw(rq); glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f); GLERROR("Renderer::Draw m_DrawScenePass->Draw"); m_ImGuiRenderPass->Draw(); @@ -183,50 +148,5 @@ void Renderer::InitializeRenderPasses() m_DrawScenePass = new DrawScenePass(this); m_PickingPass = new PickingPass(this, m_EventBroker); m_LightCullingPass = new LightCullingPass(this); -} - -void Renderer::DrawForwardPlus(RenderQueueCollection& rq) -{ - GLERROR("Renderer::DrawForwardPlus: Pre"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glClearColor(200.f / 255, 0.f / 255, 200.f / 255, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_ForwardPlusProgram->Bind(); - GLuint ShaderHandle = m_ForwardPlusProgram->GetHandle(); - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); - //TODO: Render: Add code for more jobs than modeljobs. - for (auto &job : rq.Forward) { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - - //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); - glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); - - //TODO: Renderer: bättre textur felhantering samt fler texturer stöd - if (modelJob->DiffuseTexture != nullptr) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } - - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); - - continue; - } - } - GLERROR("Renderer::DrawForwardPlus: End"); -} - + m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass); +} \ No newline at end of file From 49884d7e600da087d3268aa543b5f679cbdc2006 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 6 Jan 2016 13:47:02 +0100 Subject: [PATCH 149/185] Fix for crash when unsubscription during event processing (untested) --- include/Engine/Core/EventBroker.h | 8 ++++-- src/Engine/Core/EventBroker.cpp | 47 ++++++++++++++++++------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/Engine/Core/EventBroker.h b/include/Engine/Core/EventBroker.h index f04c7715..dde5242a 100644 --- a/include/Engine/Core/EventBroker.h +++ b/include/Engine/Core/EventBroker.h @@ -13,6 +13,8 @@ relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \ m_EventBroker->Subscribe(relay); +typedef unsigned int EventID; + class EventBroker; class BaseEventRelay @@ -31,6 +33,7 @@ public: virtual bool Receive(const std::shared_ptr event) = 0; protected: + EventID m_EventID; std::string m_ContextTypeName; std::string m_EventTypeName; EventBroker* m_Broker; @@ -95,6 +98,7 @@ public: private: bool m_IsProcessing = false; + EventID m_NextEventID = 0; typedef std::string ContextTypeName_t; // typeid(ContextType).name() typedef std::string EventTypeName_t; // typeid(EventType).name() @@ -103,14 +107,14 @@ private: typedef std::unordered_map ContextRelays_t; ContextRelays_t m_ContextRelays; std::vector m_RelaysToSubscribe; - std::vector m_RelaysToUnsubscribe; + std::vector> m_RelaysToUnsubscribe; typedef std::list>> EventQueue_t; std::shared_ptr m_EventQueueRead; std::shared_ptr m_EventQueueWrite; void subscribeImmediate(BaseEventRelay& relay); - void unsubscribeImmediate(BaseEventRelay& relay); + void unsubscribeImmediate(std::tuple identifier); }; template diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index 76c243e8..6767878f 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -2,21 +2,24 @@ BaseEventRelay::~BaseEventRelay() { - if (m_Broker != nullptr) { - m_Broker->Unsubscribe(*this); - } + if (m_Broker != nullptr) { + m_Broker->Unsubscribe(*this); + } } -void EventBroker::Unsubscribe(BaseEventRelay &relay) // ? +void EventBroker::Unsubscribe(BaseEventRelay& relay) // ? { - if (m_IsProcessing) { - m_RelaysToUnsubscribe.push_back(&relay); - } else { - unsubscribeImmediate(relay); - } + auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName); + + relay.m_Broker = nullptr; + if (m_IsProcessing) { + m_RelaysToUnsubscribe.push_back(identifier); + } else { + unsubscribeImmediate(identifier); + } } -void EventBroker::Subscribe(BaseEventRelay &relay) +void EventBroker::Subscribe(BaseEventRelay& relay) { if (m_IsProcessing) { m_RelaysToSubscribe.push_back(&relay); @@ -38,12 +41,11 @@ int EventBroker::Process(std::string contextTypeName) int eventsProcessed = 0; for (auto &pair : *m_EventQueueRead) { - std::string &eventTypeName = pair.first; + std::string& eventTypeName = pair.first; std::shared_ptr event = pair.second; auto itpair = relays.equal_range(eventTypeName); - for (auto it2 = itpair.first; it2 != itpair.second; it2++) - { + for (auto it2 = itpair.first; it2 != itpair.second; it2++) { std::string name = it2->first; BaseEventRelay* relay = it2->second; relay->Receive(event); @@ -60,8 +62,8 @@ int EventBroker::Process(std::string contextTypeName) m_RelaysToSubscribe.clear(); // Process pending unsubscriptions - for (auto& r : m_RelaysToUnsubscribe) { - unsubscribeImmediate(*r); + for (auto& identifier : m_RelaysToUnsubscribe) { + unsubscribeImmediate(identifier); } m_RelaysToUnsubscribe.clear(); @@ -81,21 +83,26 @@ void EventBroker::Clear() void EventBroker::subscribeImmediate(BaseEventRelay& relay) { relay.m_Broker = this; + relay.m_EventID = m_NextEventID++; m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay)); } -void EventBroker::unsubscribeImmediate(BaseEventRelay& relay) +void EventBroker::unsubscribeImmediate(std::tuple identifier) { - auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName); + EventID eventID; + ContextTypeName_t contextTypeName; + EventTypeName_t eventTypeName; + std::tie(eventID, contextTypeName, eventTypeName) = identifier; + + auto contextIt = m_ContextRelays.find(contextTypeName); if (contextIt == m_ContextRelays.end()) { return; } auto eventRelays = contextIt->second; - auto itpair = eventRelays.equal_range(relay.m_EventTypeName); + auto itpair = eventRelays.equal_range(eventTypeName); for (auto it = itpair.first; it != itpair.second; ++it) { - if (it->second == &relay) { - relay.m_Broker = nullptr; + if (it->second->m_EventID == eventID) { eventRelays.erase(it); break; } From fa8775a72e2a85c05ccf7ef9a53eacdf95592f84 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 7 Jan 2016 10:28:18 +0100 Subject: [PATCH 150/185] Renamed vars and added some comments. --- include/Engine/Core/SystemPipeline.h | 9 +++++---- src/Engine/Collision/CollisionSystem.cpp | 2 -- src/Game/Game.cpp | 16 +++++++++------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index fdae834f..cffa04de 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -24,12 +24,13 @@ public: } template - void AddSystem(int updateOrderPriority, Arguments... args) + //All systems with orderlevel 0 will be updated first, then 1, 2, etc. + void AddSystem(int updateOrderLevel, Arguments... args) { - if (updateOrderPriority + 1 > m_OrderedSystemGroups.size()) { - m_OrderedSystemGroups.resize(updateOrderPriority + 1); + if (updateOrderLevel + 1 > m_OrderedSystemGroups.size()) { + m_OrderedSystemGroups.resize(updateOrderLevel + 1); } - UnorderedSystems& group = m_OrderedSystemGroups[updateOrderPriority]; + UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel]; System* system = new T(m_EventBroker, args...); group.Systems[typeid(T).name()] = system; diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index dec33a20..69929c6d 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -4,8 +4,6 @@ void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt) { - //TODO: Update CollisionSystem system after PlayerSystem. - //Right now, cAABB is a component attached to any entity that should be collideable. AABB thisBox; if (!Collision::GetEntityBox(world, cAABB, thisBox)) { diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index b0628bd8..414f113d 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -52,15 +52,17 @@ Game::Game(int argc, char* argv[]) // Create system pipeline m_SystemPipeline = new SystemPipeline(m_EventBroker); - unsigned int updateOrderPriority = 0; - m_SystemPipeline->AddSystem(updateOrderPriority); - m_SystemPipeline->AddSystem(updateOrderPriority); - m_SystemPipeline->AddSystem(updateOrderPriority, m_Renderer); + + //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); //Collision and TriggerSystem should update after player. - ++updateOrderPriority; - m_SystemPipeline->AddSystem(updateOrderPriority); - m_SystemPipeline->AddSystem(updateOrderPriority); + ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_LastTime = glfwGetTime(); From 85ff86a2fe7c0c48195b0f87b7c4d5ff13b0fad0 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 7 Jan 2016 14:50:13 +0100 Subject: [PATCH 151/185] Revert "Exit Crash has been dealt with. There is no need to unsubscribe game since m_ContextRelays has already been destroyed at that point" This reverts commit 0ae6c42df834e29e678d5e935d0cae92286e46b4. --- src/Engine/Core/EventBroker.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index 4d58c087..76c243e8 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -3,10 +3,7 @@ BaseEventRelay::~BaseEventRelay() { if (m_Broker != nullptr) { - //m_ContextRelays has already been destroyed at this point, since, - //this BaseEventRelay is called after EventBroker has been deleted - //hence there is nothing to unsubscribe - //m_Broker->Unsubscribe(*this); + m_Broker->Unsubscribe(*this); } } From f67f22c82d392f5af5bd7c52e28d62707474eb11 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 6 Jan 2016 13:36:53 +0100 Subject: [PATCH 152/185] Added Healthrelated events and start of HealthSystem, also reverted the crash "fix" --- include/Engine/Core/EPlayerDamage.h | 18 +++++++++++ include/Engine/Core/EPlayerDeath.h | 18 +++++++++++ include/Engine/Core/EPlayerHealthPickup.h | 18 +++++++++++ include/Game/HealthSystem.h | 32 +++++++++++++++++++ src/Engine/Core/EventBroker.cpp | 2 +- src/Game/Game.cpp | 2 ++ src/Game/HealthSystem.cpp | 38 +++++++++++++++++++++++ 7 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 include/Engine/Core/EPlayerDamage.h create mode 100644 include/Engine/Core/EPlayerDeath.h create mode 100644 include/Engine/Core/EPlayerHealthPickup.h create mode 100644 include/Game/HealthSystem.h create mode 100644 src/Game/HealthSystem.cpp diff --git a/include/Engine/Core/EPlayerDamage.h b/include/Engine/Core/EPlayerDamage.h new file mode 100644 index 00000000..db070159 --- /dev/null +++ b/include/Engine/Core/EPlayerDamage.h @@ -0,0 +1,18 @@ +#ifndef EPlayerDamage_h__ +#define EPlayerDamage_h__ + +#include "EventBroker.h" +#include "../Core/Entity.h" + +namespace Events +{ + +struct PlayerDamage : Event +{ + int DamageAmount; + EntityID PlayerID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h new file mode 100644 index 00000000..278b11e6 --- /dev/null +++ b/include/Engine/Core/EPlayerDeath.h @@ -0,0 +1,18 @@ +#ifndef EPlayerDeath_h__ +#define EPlayerDeath_h__ + +#include "EventBroker.h" +#include "../Core/Entity.h" + +namespace Events +{ + +struct PlayerDeath : Event +{ + std::string KilledBy; + EntityID PlayerID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h new file mode 100644 index 00000000..2071f8b2 --- /dev/null +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -0,0 +1,18 @@ +#ifndef EPlayerHealthPickup_h__ +#define EPlayerHealthPickup_h__ + +#include "EventBroker.h" +#include "../Core/Entity.h" + +namespace Events +{ + +struct PlayerHealthPickup : Event +{ + int HealthAmount; + EntityID HealthPickupID; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Game/HealthSystem.h b/include/Game/HealthSystem.h new file mode 100644 index 00000000..fad2c616 --- /dev/null +++ b/include/Game/HealthSystem.h @@ -0,0 +1,32 @@ +#ifndef HealthSystem_h__ +#define HealthSystem_h__ + +#include +#include + +#include "Common.h" +#include "Core/System.h" +#include "Core\EPlayerDamage.h"; +#include "Core\EPlayerHealthPickup.h"; +#include "Core\EPlayerDeath.h"; + +class HealthSystem : public PureSystem +{ +public: + HealthSystem(EventBroker* eventBroker); + + virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override; +private: + float m_Speed = 5; + + //create the methods which will take care of specific events + EventRelay m_EPlayerDamage; + bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e); + EventRelay m_EPlayerHealthPickup; + bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); + + int playerDeltaHealth; + +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index 6767878f..d847e1a2 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -3,7 +3,7 @@ BaseEventRelay::~BaseEventRelay() { if (m_Broker != nullptr) { - m_Broker->Unsubscribe(*this); + m_Broker->Unsubscribe(*this); } } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 033db642..4242aa9c 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,6 +1,7 @@ #include "Game.h" #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" +#include "Game/HealthSystem.h" Game::Game(int argc, char* argv[]) { @@ -57,6 +58,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(m_Renderer); m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(); // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp new file mode 100644 index 00000000..2e52f44c --- /dev/null +++ b/src/Game/HealthSystem.cpp @@ -0,0 +1,38 @@ +#include "HealthSystem.h" + +HealthSystem::HealthSystem(EventBroker* eventBroker) + : PureSystem(eventBroker, "Health") +{ + //subscribe/listenTo playerdamage,healthpickup events with the eventbroker + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup); + playerDeltaHealth = 0; +} +void HealthSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) +{ + //Health is only affected by pickup/shoot events + player["Health"] += playerDeltaHealth; + playerDeltaHealth = 0; + if (player["Health"] < 0) { + //sendout/publish death event + Events::PlayerDeath e; + e.PlayerID = player.EntityID; + m_EventBroker->Publish(e); + } +} +bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e) +{ + //vem skadades? + //antagligen spelaren själv + //såna här events skickas av network te spelare som kan lyssna på / kolla på de och tar hand om sina egna +-hp endast + //just add that damage to a variable, which will later be taken care of by UpdateComponent + playerDeltaHealth -= e.DamageAmount; + //ev skicka ut playerdeath event + return true; +} +bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) +{ + //vem tog upp hp? + playerDeltaHealth += e.HealthAmount; + return true; +} From 638c236ceb14a11752e804a01d2b1a9b6844e437 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 6 Jan 2016 16:38:50 +0100 Subject: [PATCH 153/185] HealthSystem tested and working. Also the 3 new PlayerEvents seems to work. TODO: a proper test in the testclass --- include/Engine/Core/EPlayerDamage.h | 4 +- include/Engine/Core/EPlayerHealthPickup.h | 3 +- include/Game/HealthSystem.h | 14 ++++--- resources/Schema/Components.xsd | 1 + resources/Schema/Components/Health.xml | 4 ++ resources/Schema/Components/Health.xsd | 14 +++++++ resources/Schema/Types/Entity.xsd | 1 + src/Game/Game.cpp | 23 +++++++++++- src/Game/HealthSystem.cpp | 46 +++++++++++++++-------- 9 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 resources/Schema/Components/Health.xml create mode 100644 resources/Schema/Components/Health.xsd diff --git a/include/Engine/Core/EPlayerDamage.h b/include/Engine/Core/EPlayerDamage.h index db070159..e0f2acd7 100644 --- a/include/Engine/Core/EPlayerDamage.h +++ b/include/Engine/Core/EPlayerDamage.h @@ -9,8 +9,8 @@ namespace Events struct PlayerDamage : Event { - int DamageAmount; - EntityID PlayerID; + double DamageAmount; + EntityID PlayerDamagedID; }; } diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h index 2071f8b2..e7d01a4e 100644 --- a/include/Engine/Core/EPlayerHealthPickup.h +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -9,8 +9,9 @@ namespace Events struct PlayerHealthPickup : Event { - int HealthAmount; + double HealthAmount; EntityID HealthPickupID; + EntityID playerHealedID; }; } diff --git a/include/Game/HealthSystem.h b/include/Game/HealthSystem.h index fad2c616..c4ea4695 100644 --- a/include/Game/HealthSystem.h +++ b/include/Game/HealthSystem.h @@ -10,23 +10,27 @@ #include "Core\EPlayerHealthPickup.h"; #include "Core\EPlayerDeath.h"; +#include +#include + class HealthSystem : public PureSystem { public: HealthSystem(EventBroker* eventBroker); - virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override; -private: - float m_Speed = 5; + //updatecomponent + virtual void UpdateComponent(World* world, ComponentWrapper& health, double dt) override; +private: //create the methods which will take care of specific events EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); - int playerDeltaHealth; - + //create the vector which will keep track of health changes + std::vector> m_DeltaHealthVector; + }; #endif \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index fd04fd39..7fcdd565 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -8,4 +8,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/Health.xml b/resources/Schema/Components/Health.xml new file mode 100644 index 00000000..143a91d1 --- /dev/null +++ b/resources/Schema/Components/Health.xml @@ -0,0 +1,4 @@ + + 100 + 100 + \ No newline at end of file diff --git a/resources/Schema/Components/Health.xsd b/resources/Schema/Components/Health.xsd new file mode 100644 index 00000000..0da80c1f --- /dev/null +++ b/resources/Schema/Components/Health.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 92f7dc31..5178b525 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -15,6 +15,7 @@ + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 4242aa9c..8f479e03 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -28,7 +28,7 @@ Game::Game(int argc, char* argv[]) 0, m_Config->Get("Video.Width", 1280), m_Config->Get("Video.Height", 720) - )); + )); m_Renderer->Initialize(); m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get("Video.FOV", 90.f))); @@ -60,7 +60,26 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - // Invoke network + //TEMP TEST DEL LATER + //skapar entityn som har komponenterna transf,model,player,health i sig. dvs är en spelare + EntityID playerID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); + ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); + Events::PlayerDamage e; + e.DamageAmount = 50.0f; + e.PlayerDamagedID = 9; + m_EventBroker->Publish(e); + Events::PlayerHealthPickup e2; + e2.HealthAmount = 40.0f; + e2.playerHealedID = 9; + m_EventBroker->Publish(e2); + + //END TEST + + // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { //boost::thread workerThread(&Game::networkFunction, this); networkFunction(); diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp index 2e52f44c..9ab8f13a 100644 --- a/src/Game/HealthSystem.cpp +++ b/src/Game/HealthSystem.cpp @@ -1,4 +1,5 @@ #include "HealthSystem.h" +#include HealthSystem::HealthSystem(EventBroker* eventBroker) : PureSystem(eventBroker, "Health") @@ -6,33 +7,48 @@ HealthSystem::HealthSystem(EventBroker* eventBroker) //subscribe/listenTo playerdamage,healthpickup events with the eventbroker EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged); EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup); - playerDeltaHealth = 0; } -void HealthSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt) + +void HealthSystem::UpdateComponent(World * world, ComponentWrapper & health, double dt) { - //Health is only affected by pickup/shoot events - player["Health"] += playerDeltaHealth; - playerDeltaHealth = 0; - if (player["Health"] < 0) { - //sendout/publish death event + //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) + ComponentWrapper player = world->GetComponent(health.EntityID, "Player"); + double currentHealth = (double) world->GetComponent(health.EntityID, "Health")["Health"]; + double maxHealth = (double)world->GetComponent(health.EntityID, "Health")["MaxHealth"]; + + //process the DeltaHealthVector and change the entitys health accordingly + for (size_t i = m_DeltaHealthVector.size(); i >0; i--) + { + auto deltaHP = m_DeltaHealthVector[i-1]; + if (std::get<0>(deltaHP) == player.EntityID) { + //re-read currentHealth for each iteration + currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; + //get the deltaHP value from the tuple and make sure you dont get more than maxHealth + double newHealth = std::min(currentHealth + (double)std::get<1>(deltaHP), maxHealth); + health.SetProperty("Health", newHealth); + m_DeltaHealthVector.erase(m_DeltaHealthVector.begin()+i-1); + } + } + + currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; + if (currentHealth < 0.0f) { + //publish death event Events::PlayerDeath e; e.PlayerID = player.EntityID; m_EventBroker->Publish(e); } } + bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e) { - //vem skadades? - //antagligen spelaren själv - //såna här events skickas av network te spelare som kan lyssna på / kolla på de och tar hand om sina egna +-hp endast - //just add that damage to a variable, which will later be taken care of by UpdateComponent - playerDeltaHealth -= e.DamageAmount; - //ev skicka ut playerdeath event + //save the changed HP to a vector. it will be taken care of in UpdateComponent + m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount)); return true; } + bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) { - //vem tog upp hp? - playerDeltaHealth += e.HealthAmount; + //save the changed HP to a vector. it will be taken care of in UpdateComponent + m_DeltaHealthVector.push_back(std::make_tuple(e.playerHealedID, e.HealthAmount)); return true; } From a1ed79dfbf0282dbc890c8609df96a0505b58573 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 7 Jan 2016 14:29:04 +0100 Subject: [PATCH 154/185] HealthSystemTest has been created. This runs a single test simple test with HealthEvents and HealthSystem. Also some minor changes --- include/Engine/Core/EPlayerDamage.h | 2 + include/Engine/Core/EPlayerDeath.h | 4 +- include/Engine/Core/EPlayerHealthPickup.h | 3 +- include/Game/HealthSystem.h | 4 +- src/Game/Game.cpp | 21 +--- src/Game/HealthSystem.cpp | 18 ++-- src/Tests/HealthSystemTest.cpp | 114 ++++++++++++++++++++++ src/Tests/HealthSystemTest.h | 40 ++++++++ 8 files changed, 173 insertions(+), 33 deletions(-) create mode 100644 src/Tests/HealthSystemTest.cpp create mode 100644 src/Tests/HealthSystemTest.h diff --git a/include/Engine/Core/EPlayerDamage.h b/include/Engine/Core/EPlayerDamage.h index e0f2acd7..87ad67aa 100644 --- a/include/Engine/Core/EPlayerDamage.h +++ b/include/Engine/Core/EPlayerDamage.h @@ -11,6 +11,8 @@ struct PlayerDamage : Event { double DamageAmount; EntityID PlayerDamagedID; + //optional TypeOfDamage + std::string TypeOfDamage; }; } diff --git a/include/Engine/Core/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h index 278b11e6..00ede5ed 100644 --- a/include/Engine/Core/EPlayerDeath.h +++ b/include/Engine/Core/EPlayerDeath.h @@ -9,8 +9,10 @@ namespace Events struct PlayerDeath : Event { - std::string KilledBy; + //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system + EntityID KilledBy; EntityID PlayerID; + std::string KilledByWhat; }; } diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h index e7d01a4e..f3158f92 100644 --- a/include/Engine/Core/EPlayerHealthPickup.h +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -10,8 +10,7 @@ namespace Events struct PlayerHealthPickup : Event { double HealthAmount; - EntityID HealthPickupID; - EntityID playerHealedID; + EntityID PlayerHealedID; }; } diff --git a/include/Game/HealthSystem.h b/include/Game/HealthSystem.h index c4ea4695..a836e797 100644 --- a/include/Game/HealthSystem.h +++ b/include/Game/HealthSystem.h @@ -22,13 +22,13 @@ public: virtual void UpdateComponent(World* world, ComponentWrapper& health, double dt) override; private: - //create the methods which will take care of specific events + //methods which will take care of specific events EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); - //create the vector which will keep track of health changes + //vector which will keep track of health changes std::vector> m_DeltaHealthVector; }; diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 8f479e03..18a533d0 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -60,26 +60,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - //TEMP TEST DEL LATER - //skapar entityn som har komponenterna transf,model,player,health i sig. dvs är en spelare - EntityID playerID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.obj"; - ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); - ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); - Events::PlayerDamage e; - e.DamageAmount = 50.0f; - e.PlayerDamagedID = 9; - m_EventBroker->Publish(e); - Events::PlayerHealthPickup e2; - e2.HealthAmount = 40.0f; - e2.playerHealedID = 9; - m_EventBroker->Publish(e2); - - //END TEST - - // Invoke network + // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { //boost::thread workerThread(&Game::networkFunction, this); networkFunction(); diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp index 9ab8f13a..188bfb5a 100644 --- a/src/Game/HealthSystem.cpp +++ b/src/Game/HealthSystem.cpp @@ -4,34 +4,36 @@ HealthSystem::HealthSystem(EventBroker* eventBroker) : PureSystem(eventBroker, "Health") { - //subscribe/listenTo playerdamage,healthpickup events with the eventbroker + //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &HealthSystem::OnPlayerDamaged); EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup); } -void HealthSystem::UpdateComponent(World * world, ComponentWrapper & health, double dt) +void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, double dt) { //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) ComponentWrapper player = world->GetComponent(health.EntityID, "Player"); - double currentHealth = (double) world->GetComponent(health.EntityID, "Health")["Health"]; + double currentHealth; double maxHealth = (double)world->GetComponent(health.EntityID, "Health")["MaxHealth"]; //process the DeltaHealthVector and change the entitys health accordingly - for (size_t i = m_DeltaHealthVector.size(); i >0; i--) + for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) { - auto deltaHP = m_DeltaHealthVector[i-1]; + auto deltaHP = m_DeltaHealthVector[i - 1]; + //if we have a healthchange for the current player, then apply it if (std::get<0>(deltaHP) == player.EntityID) { //re-read currentHealth for each iteration currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; //get the deltaHP value from the tuple and make sure you dont get more than maxHealth double newHealth = std::min(currentHealth + (double)std::get<1>(deltaHP), maxHealth); health.SetProperty("Health", newHealth); - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin()+i-1); + m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); } } currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; - if (currentHealth < 0.0f) { + //check if health is <= 0 + if (currentHealth <= 0.0f) { //publish death event Events::PlayerDeath e; e.PlayerID = player.EntityID; @@ -49,6 +51,6 @@ bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e) bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) { //save the changed HP to a vector. it will be taken care of in UpdateComponent - m_DeltaHealthVector.push_back(std::make_tuple(e.playerHealedID, e.HealthAmount)); + m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount)); return true; } diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp new file mode 100644 index 00000000..7ba2b89d --- /dev/null +++ b/src/Tests/HealthSystemTest.cpp @@ -0,0 +1,114 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; + +#include "HealthSystemTest.h" +#include "Game/HealthSystem.h" + +BOOST_AUTO_TEST_SUITE(HealthSystemSuite) + +BOOST_AUTO_TEST_CASE(HealthSystemTest) +{ + //this tests 2 healthevents and the healthsystem + GameHealthSystemTest game; + //100 loops will be more than enough to do the test + int loops = 100; + bool success = false; + while (loops > 0) { + game.Tick(); + if (game.TestSucceeded) { + success = true; + break; + } + loops--; + } + //The system will process the events, hence it will take a while before we can read anything + BOOST_TEST(success); +} +BOOST_AUTO_TEST_SUITE_END() + +GameHealthSystemTest::GameHealthSystemTest() +{ + ResourceManager::RegisterType("ConfigFile"); + ResourceManager::RegisterType("EntityXMLFile"); + + m_Config = ResourceManager::Load("Config.ini"); + LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); + + // Create the core event broker + m_EventBroker = new EventBroker(); + + // Create a world + m_World = new World(); + std::string mapToLoad = m_Config->Get("Debug.LoadMap", ""); + if (!mapToLoad.empty()) { + ResourceManager::Load(mapToLoad)->PopulateWorld(m_World); + } + + // Create system pipeline + m_SystemPipeline = new SystemPipeline(m_EventBroker); + m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(); + + //The Test + //create entity which has transorm,player,model,health in it. i.e. is a player + EntityID playerID = m_World->CreateEntity(); + ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); + ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); + model["Resource"] = "Models/Core/UnitSphere.obj"; + ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); + ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); + healthsID = playerID; + double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"]; + + //heal player with 40 + Events::PlayerHealthPickup e3; + e3.HealthAmount = 40.0f; + e3.PlayerHealedID = healthsID; + m_EventBroker->Publish(e3); + //damage player with 50 + Events::PlayerDamage e; + e.DamageAmount = 50.0f; + e.PlayerDamagedID = healthsID; + m_EventBroker->Publish(e); + //heal some other player with 40 + Events::PlayerHealthPickup e2; + e2.HealthAmount = 40.0f; + e2.PlayerHealedID = healthsID+1; + m_EventBroker->Publish(e2); + + EntityID playerID2 = m_World->CreateEntity(); + ComponentWrapper transform2 = m_World->AttachComponent(playerID2, "Transform"); + ComponentWrapper model2 = m_World->AttachComponent(playerID2, "Model"); + model2["Resource"] = "Models/Core/UnitSphere.obj"; + ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); + ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); + //END TEST +} + +GameHealthSystemTest::~GameHealthSystemTest() +{ + delete m_SystemPipeline; + delete m_World; + delete m_EventBroker; +} + +void GameHealthSystemTest::Tick() +{ + glfwPollEvents(); + + double currentTime = glfwGetTime(); + double dt = currentTime - m_LastTime; + m_LastTime = currentTime; + + // Iterate through systems and update world! + m_SystemPipeline->Update(m_World, dt); + + m_EventBroker->Swap(); + m_EventBroker->Clear(); + + //if health reaches 90 then we know the test has succeeded (start with 100hp, remove 50hp, add 40hp) + double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"]; + if (currentHealth==90) + TestSucceeded = true; +} diff --git a/src/Tests/HealthSystemTest.h b/src/Tests/HealthSystemTest.h new file mode 100644 index 00000000..664d2ef3 --- /dev/null +++ b/src/Tests/HealthSystemTest.h @@ -0,0 +1,40 @@ +#ifndef HealthTest_h__ +#define HealthTest_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 "Input/InputProxy.h" +#include "Input/KeyboardInputHandler.h" +#include "Input/MouseInputHandler.h" +#include "Core/EKeyDown.h" +#include "Core/EntityXMLFile.h" +#include "Core/SystemPipeline.h" +#include "RaptorCopterSystem.h" +#include "PlayerSystem.h" +#include "Editor/EditorSystem.h" + +class GameHealthSystemTest +{ +public: + GameHealthSystemTest(); + ~GameHealthSystemTest(); + + void Tick(); + bool TestSucceeded = false; + +private: + double m_LastTime; + ConfigFile* m_Config = nullptr; + EventBroker* m_EventBroker; + World* m_World; + SystemPipeline* m_SystemPipeline; + int healthsID; +}; + +#endif From 4048ce6bd4d6dd67315e34cb5b2d44064aa46c4a Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 7 Jan 2016 15:18:35 +0100 Subject: [PATCH 155/185] Small fix. --- src/Tests/OctTreeTestGameClass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 05aa35d4..10d4d6a5 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -45,7 +45,7 @@ Game::Game(int argc, char* argv[]) : someOctTree(AABB(-0.5f*worldSize, 0.5f*worl m_World = new HardcodedTestWorld(); m_SystemPipeline = new SystemPipeline(m_EventBroker); - m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(0); m_LastTime = glfwGetTime(); } From e52c0c963334c0afe68612159b03a5f9fb7a470d Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 7 Jan 2016 15:27:39 +0100 Subject: [PATCH 156/185] Now using the easier/cleaner way of getting/setting the HealthProperties --- src/Game/HealthSystem.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp index 188bfb5a..41f60ce5 100644 --- a/src/Game/HealthSystem.cpp +++ b/src/Game/HealthSystem.cpp @@ -13,8 +13,7 @@ void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, doubl { //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) ComponentWrapper player = world->GetComponent(health.EntityID, "Player"); - double currentHealth; - double maxHealth = (double)world->GetComponent(health.EntityID, "Health")["MaxHealth"]; + double maxHealth = (double)health["MaxHealth"]; //process the DeltaHealthVector and change the entitys health accordingly for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) @@ -22,18 +21,15 @@ void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, doubl auto deltaHP = m_DeltaHealthVector[i - 1]; //if we have a healthchange for the current player, then apply it if (std::get<0>(deltaHP) == player.EntityID) { - //re-read currentHealth for each iteration - currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; //get the deltaHP value from the tuple and make sure you dont get more than maxHealth - double newHealth = std::min(currentHealth + (double)std::get<1>(deltaHP), maxHealth); - health.SetProperty("Health", newHealth); + double newHealth = std::min((double)health["Health"] + (double)std::get<1>(deltaHP), maxHealth); + health["Health"] = newHealth; m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); } } - currentHealth = (double)world->GetComponent(health.EntityID, "Health")["Health"]; //check if health is <= 0 - if (currentHealth <= 0.0f) { + if ((double)health["Health"] <= 0.0f) { //publish death event Events::PlayerDeath e; e.PlayerID = player.EntityID; From 7fb71f17b282438ac9faa0dbd0ad6af717d80c53 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 7 Jan 2016 16:13:52 +0100 Subject: [PATCH 157/185] Destruct all systems properly in the pipeline. --- include/Engine/Core/SystemPipeline.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index cffa04de..d6a6b371 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -15,10 +15,8 @@ public: ~SystemPipeline() { for (UnorderedSystems& group : m_OrderedSystemGroups) { - for (auto& pair : group.PureSystems) { - for (auto& system : pair.second) { - delete system; - } + for (auto& pair : group.Systems) { + delete pair.second; } } } From 0e0a361a3843a8307194d6bbbbddd5c56a6a274f Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 7 Jan 2016 16:36:18 +0100 Subject: [PATCH 158/185] HotFix: Updated the CMakeList.txt in src/Game so it has the HealthSystem.cpp. This is needed otherwise the solution cant find that file --- src/Game/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Game/CMakeLists.txt b/src/Game/CMakeLists.txt index 18b80f93..04146670 100644 --- a/src/Game/CMakeLists.txt +++ b/src/Game/CMakeLists.txt @@ -19,6 +19,7 @@ file(GLOB SOURCE_FILES set(SOURCE_FILES ${SOURCE_FILES} "Game.cpp" + "HealthSystem.cpp" "PlayerSystem.cpp" ) From ef9ce7932a60f758158adfb6dfb7b1fb310d73dc Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 7 Jan 2016 17:40:47 +0100 Subject: [PATCH 159/185] New small fix. --- src/Tests/HealthSystemTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 7ba2b89d..84d6199d 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -47,8 +47,8 @@ GameHealthSystemTest::GameHealthSystemTest() // Create system pipeline m_SystemPipeline = new SystemPipeline(m_EventBroker); - m_SystemPipeline->AddSystem(); - m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(0); + m_SystemPipeline->AddSystem(0); //The Test //create entity which has transorm,player,model,health in it. i.e. is a player From 592776e783204a7294c901ce10f2c31b971ab67d Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 8 Jan 2016 11:37:51 +0100 Subject: [PATCH 160/185] Fixed so the PlayerDeath event doesn't get spammed while the player is dead. Also made sure that any remaining healthDeltas are cleared when dead. --- src/Game/HealthSystem.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Game/HealthSystem.cpp b/src/Game/HealthSystem.cpp index 41f60ce5..7a1d5005 100644 --- a/src/Game/HealthSystem.cpp +++ b/src/Game/HealthSystem.cpp @@ -19,22 +19,29 @@ void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, doubl for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) { auto deltaHP = m_DeltaHealthVector[i - 1]; - //if we have a healthchange for the current player, then apply it - if (std::get<0>(deltaHP) == player.EntityID) { + //if we have a healthchange for the current player and health is greater than 0, then apply it + if (std::get<0>(deltaHP) == player.EntityID && (double)health["Health"] > 0.0f) { //get the deltaHP value from the tuple and make sure you dont get more than maxHealth double newHealth = std::min((double)health["Health"] + (double)std::get<1>(deltaHP), maxHealth); health["Health"] = newHealth; m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); + //check if health is <= 0 + if ((double)health["Health"] <= 0.0f) { + //publish death event + Events::PlayerDeath e; + e.PlayerID = player.EntityID; + m_EventBroker->Publish(e); + //clear the remaining hpDeltas for the dead player + for (size_t j = m_DeltaHealthVector.size(); j > 0; j--) + { + if (std::get<0>(m_DeltaHealthVector[j - 1]) == player.EntityID) + m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1); + } + //break the loop if the player is dead + break; + } } } - - //check if health is <= 0 - if ((double)health["Health"] <= 0.0f) { - //publish death event - Events::PlayerDeath e; - e.PlayerID = player.EntityID; - m_EventBroker->Publish(e); - } } bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e) From 25a99a04c5fc365993eb916d50c203038f568432 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 8 Jan 2016 14:11:35 +0100 Subject: [PATCH 161/185] Added Visable bool and a better description to Pointlight component. --- resources/Schema/Components/PointLight.xml | 1 + resources/Schema/Components/PointLight.xsd | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/Schema/Components/PointLight.xml b/resources/Schema/Components/PointLight.xml index a1dd5f54..6b1382db 100644 --- a/resources/Schema/Components/PointLight.xml +++ b/resources/Schema/Components/PointLight.xml @@ -3,4 +3,5 @@ 1.0 0.8 0.3 + true \ No newline at end of file diff --git a/resources/Schema/Components/PointLight.xsd b/resources/Schema/Components/PointLight.xsd index 68e05a84..d1a9f52c 100644 --- a/resources/Schema/Components/PointLight.xsd +++ b/resources/Schema/Components/PointLight.xsd @@ -5,7 +5,7 @@ - It's a point light! + A pointlight that lights up geometry in a radius. @@ -13,6 +13,7 @@ + From dab4ba2164a893ce8ade9b3a325910d4bc854318 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 8 Jan 2016 14:12:09 +0100 Subject: [PATCH 162/185] Pointlights are now using the pointlight component and the Light renderqueue to draw. --- include/Engine/Rendering/LightCullingPass.h | 5 +-- include/Engine/Rendering/RenderQueue.h | 11 +++--- src/Engine/Rendering/LightCullingPass.cpp | 41 +++++++++++++++------ src/Engine/Rendering/RenderQueueFactory.cpp | 28 ++++++++++++++ src/Engine/Rendering/Renderer.cpp | 1 + 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h index f0ed5d6b..e08aacdf 100644 --- a/include/Engine/Rendering/LightCullingPass.h +++ b/include/Engine/Rendering/LightCullingPass.h @@ -17,6 +17,7 @@ public: void GenerateNewFrustum(); void CullLights(); + void FillLightList(RenderQueueCollection& rq); GLuint FrustumSSBO() const { return m_FrustumSSBO; } GLuint LightSSBO() const { return m_LightSSBO; } @@ -49,8 +50,6 @@ private: }; Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution - void TEMPCreateLights(); - //This should be a component struct PointLight { glm::vec4 Position = glm::vec4(0.f); @@ -60,7 +59,7 @@ private: float Falloff = 0.3f; float Padding = 1337; }; - PointLight m_PointLights[NUM_LIGHTS]; + std::vector m_PointLights; struct LightGrid { float Start; diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index 2942c743..44d5e172 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -82,11 +82,12 @@ struct SpriteJob : RenderJob struct PointLightJob : RenderJob { - glm::vec3 Position; - glm::vec3 SpecularColor = glm::vec3(1, 1, 1); - glm::vec3 DiffuseColor = glm::vec3(1, 1, 1); - float Radius = 1.f; - float Intensity = 0.8f; + glm::vec4 Position; + glm::vec4 Color; + float Radius; + float Intensity; + float Falloff; + float padding = 123; void CalculateHash() override { diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index 85f27a37..5a3e7609 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -3,7 +3,6 @@ LightCullingPass::LightCullingPass(IRenderer* renderer) { m_Renderer = renderer; - TEMPCreateLights(); InitializeSSBOs(); InitializeShaderPrograms(); GenerateNewFrustum(); @@ -35,6 +34,14 @@ void LightCullingPass::CullLights() glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); + if (m_PointLights.size() > 0) { + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY); + } else { + GLfloat zero = 0.f; + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &zero , GL_DYNAMIC_COPY); + + } glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); @@ -49,6 +56,25 @@ void LightCullingPass::CullLights() GLERROR("CullLights Error: End"); } +void LightCullingPass::FillLightList(RenderQueueCollection& rq) +{ + m_PointLights.clear(); + for(auto &job : rq.Lights) { + auto pointLightjob = std::dynamic_pointer_cast(job); + if (pointLightjob) { + PointLight p; + p.Color = pointLightjob->Color; + p.Falloff = pointLightjob->Falloff; + p.Intensity = pointLightjob->Intensity; + p.Position = glm::vec4(glm::vec3(pointLightjob->Position), 1.f); + p.Radius = pointLightjob->Radius; + p.Padding = 123.f; + m_PointLights.push_back(p); + continue; + } + } +} + void LightCullingPass::InitializeSSBOs() { glGenBuffers(1, &m_FrustumSSBO); @@ -59,7 +85,9 @@ void LightCullingPass::InitializeSSBOs() glGenBuffers(1, &m_LightSSBO); glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY); + if(m_PointLights.size() > 0) { + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY); + } glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); GLERROR("m_LightSSBO"); @@ -96,12 +124,3 @@ void LightCullingPass::InitializeShaderPrograms() m_LightCullProgram->Link(); } -void LightCullingPass::TEMPCreateLights() -{ - for (int i = 0; i < NUM_LIGHTS; i++) { - glm::vec3 pos = glm::vec3(cos(i) * i/10.f, 0.5f, sin(i) * i/10.f); - m_PointLights[i].Position = glm::vec4(pos, 1.f); - m_PointLights[i].Color = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand()%255 / 255.f, 1.f); - m_PointLights[i].Radius = glm::length(pos) / 5.f; - } -} diff --git a/src/Engine/Rendering/RenderQueueFactory.cpp b/src/Engine/Rendering/RenderQueueFactory.cpp index 8d5bb420..015c6477 100644 --- a/src/Engine/Rendering/RenderQueueFactory.cpp +++ b/src/Engine/Rendering/RenderQueueFactory.cpp @@ -111,6 +111,34 @@ void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue) void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue) { + auto pointLights = world->GetComponents("PointLight"); + if(pointLights == nullptr) { + return; + } + for(auto& pointlightC : *pointLights) { + bool visible = pointlightC["Visible"]; + if(!visible) { + continue; + } + auto transformC = world->GetComponent(pointlightC.EntityID, "Transform"); + if(&transformC == nullptr) { + return; + } + + glm::vec4 color = pointlightC["Color"]; + float radius = (double)pointlightC["Radius"]; + float intensity = (double)pointlightC["Intensity"]; + float falloff = (double)pointlightC["Falloff"]; + + PointLightJob job; + job.Position = transformC["Position"]; + job.Color = color; + job.Radius = radius; + job.Intensity = intensity; + job.Falloff = falloff; + + renderQueue->Add(job); + } } diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 752dd8c0..8d3863e2 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -92,6 +92,7 @@ void Renderer::Draw(RenderQueueCollection& rq) { m_PickingPass->Draw(rq); //DrawScreenQuad(m_PickingPass->PickingTexture()); + m_LightCullingPass->FillLightList(rq); m_LightCullingPass->CullLights(); //m_DrawScenePass->Draw(rq); From 9f871bbe7cb26c1785676d0e61515d80bdcfb844 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 8 Jan 2016 14:31:44 +0100 Subject: [PATCH 163/185] Lights now use the absolute position instead of it's local position. --- src/Engine/Rendering/RenderQueueFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Rendering/RenderQueueFactory.cpp b/src/Engine/Rendering/RenderQueueFactory.cpp index 015c6477..429d773c 100644 --- a/src/Engine/Rendering/RenderQueueFactory.cpp +++ b/src/Engine/Rendering/RenderQueueFactory.cpp @@ -132,7 +132,7 @@ void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue) float falloff = (double)pointlightC["Falloff"]; PointLightJob job; - job.Position = transformC["Position"]; + job.Position = glm::vec4(AbsolutePosition(world, transformC.EntityID), 1.f); job.Color = color; job.Radius = radius; job.Intensity = intensity; From 6e6460a00053887e1f4e76e5717d4dd367688aaf Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 8 Jan 2016 16:15:18 +0100 Subject: [PATCH 164/185] Commented out the bugged models --- resources/Schema/Entities/Test.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 528c7e95..809bca51 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -10,7 +10,7 @@ - + + - +