From 1d19c6901eadce9dc0b40fe552020164a9a4f134 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 2 Dec 2015 11:18:52 +0100 Subject: [PATCH 001/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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/116] 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 f377d9ba7045f6c0deef120df0cff88fca207caa Mon Sep 17 00:00:00 2001 From: Jocke Date: Thu, 10 Dec 2015 14:14:36 +0100 Subject: [PATCH 050/116] 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 051/116] 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 58952725e91dad639250ebf70d4ccab47cb64646 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 10 Dec 2015 17:07:18 +0100 Subject: [PATCH 052/116] 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 37f9ab232223a9aefa31c720d07f0dfd07740246 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 10 Dec 2015 17:53:33 +0100 Subject: [PATCH 053/116] 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 054/116] 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 055/116] 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 056/116] 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 057/116] 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 36ae451ea62c2f9067794e7f431dcdc59a55da31 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 11 Dec 2015 16:22:14 +0100 Subject: [PATCH 058/116] 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 059/116] 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 060/116] 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 061/116] 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 5fce7490a9d547e37d673d78f1c714ea5e6dc718 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 14 Dec 2015 11:57:18 +0100 Subject: [PATCH 062/116] 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 063/116] 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 064/116] 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 065/116] 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 066/116] 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 067/116] 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 ae7d4b90979bf901160da16bfce4cdea3fa0aa16 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 14 Dec 2015 17:35:39 +0100 Subject: [PATCH 068/116] 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 069/116] 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 070/116] 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 071/116] 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 454ed0032b45e391fd3803ec3b6dee682db77e36 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 15 Dec 2015 14:01:49 +0100 Subject: [PATCH 072/116] 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 073/116] 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 074/116] 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 075/116] 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 472a8db81a28ef3da07f0ce988b0ce7f4f8473ae Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 15:32:31 +0100 Subject: [PATCH 076/116] 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 077/116] 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 1669649186a507a5273f85695d4f28526e7ebcd3 Mon Sep 17 00:00:00 2001 From: stiffly Date: Tue, 15 Dec 2015 16:24:09 +0100 Subject: [PATCH 078/116] 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 079/116] 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 080/116] 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 081/116] 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 082/116] 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 083/116] 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 084/116] 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 085/116] 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 086/116] 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 50ccf962682048f4e69e3ca6ec6525ad549c7d55 Mon Sep 17 00:00:00 2001 From: stiffly Date: Wed, 16 Dec 2015 13:52:16 +0100 Subject: [PATCH 087/116] 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 088/116] 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 089/116] 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 090/116] 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 091/116] 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 092/116] 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 093/116] 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 4c29e071af1bfa04c1722179df77117e23d2db34 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 10:47:08 +0100 Subject: [PATCH 094/116] 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 095/116] 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 096/116] 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 097/116] 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 098/116] 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 099/116] 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 100/116] 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 101/116] 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 102/116] 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 0f59b863eedb9f154c01de26c5df8aecc1cb123d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 17 Dec 2015 17:08:47 +0100 Subject: [PATCH 103/116] 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 104/116] 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 105/116] 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 106/116] 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 0b714e593f9ed298cc3bb6962e91b655a68113d5 Mon Sep 17 00:00:00 2001 From: stiffly Date: Thu, 17 Dec 2015 17:56:15 +0100 Subject: [PATCH 107/116] 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 97f8be1915f4f7ed426cf5c3a6915c1b417bbefd Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 18 Dec 2015 10:21:56 +0100 Subject: [PATCH 108/116] 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 109/116] 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 110/116] 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 5c1a93021b57ea8b22b03c49be0523082e3f0f73 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 11:22:13 +0100 Subject: [PATCH 111/116] 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 a858dab8b665672f98da51d3ba4f72eae0c9894f Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 12:00:14 +0100 Subject: [PATCH 112/116] 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 a0255f1b318a0089b6e3715d917fe4fc85f675f4 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 13:34:21 +0100 Subject: [PATCH 113/116] 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 114/116] 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 a550b6077e0daae83d0997148d275d91195283c1 Mon Sep 17 00:00:00 2001 From: stiffly Date: Fri, 18 Dec 2015 14:25:55 +0100 Subject: [PATCH 115/116] 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 34cbbb3eb1b214b372b3962bc2d6a80ca1c183b9 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 6 Jan 2016 11:20:16 +0100 Subject: [PATCH 116/116] 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();