diff --git a/CMakeLists.txt b/CMakeLists.txt index 16d3d414..556b53c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,8 @@ source/Test/MemoryCorrectnessItem.hpp source/Test/MemoryCorrectnessItem.cpp source/Test/TestManager.hpp source/Test/TestManager.cpp +source/Test/Tests/ComponentSerialiseTester.hpp +source/Test/Tests/ComponentSerialiseTester.cpp source/Test/Tests/ECSTester.hpp source/Test/Tests/ECSTester.cpp source/Test/Tests/ResourceManagerTester.hpp diff --git a/source/Component/Lights.cpp b/source/Component/Lights.cpp index bbd57923..d83f9a2e 100644 --- a/source/Component/Lights.cpp +++ b/source/Component/Lights.cpp @@ -1,6 +1,7 @@ #include "Lights.hpp" #include "Component/Transform.hpp" #include "Geometry/AABB.hpp" +#include "Utility/Serialise.hpp" #include "glm/trigonometric.hpp" #include "imgui.h" @@ -51,6 +52,32 @@ namespace Component } } + void DirectionalLight::Serialise(const DirectionalLight& p_light, std::ofstream& p_out, uint16_t p_version) + { (void)p_version; + Utility::write_binary(p_out, p_light.m_direction); + Utility::write_binary(p_out, p_light.m_colour); + Utility::write_binary(p_out, p_light.m_ambient_intensity); + Utility::write_binary(p_out, p_light.m_diffuse_intensity); + Utility::write_binary(p_out, p_light.m_specular_intensity); + Utility::write_binary(p_out, p_light.m_shadow_near_plane); + Utility::write_binary(p_out, p_light.m_shadow_far_plane); + Utility::write_binary(p_out, p_light.m_ortho_size); + } + + DirectionalLight DirectionalLight::Deserialise(std::ifstream& p_in, uint16_t p_version) + { (void)p_version; + DirectionalLight light; + Utility::read_binary(p_in, light.m_direction); + Utility::read_binary(p_in, light.m_colour); + Utility::read_binary(p_in, light.m_ambient_intensity); + Utility::read_binary(p_in, light.m_diffuse_intensity); + Utility::read_binary(p_in, light.m_specular_intensity); + Utility::read_binary(p_in, light.m_shadow_near_plane); + Utility::read_binary(p_in, light.m_shadow_far_plane); + Utility::read_binary(p_in, light.m_ortho_size); + return light; + } + glm::mat4 DirectionalLight::get_view_proj(const Geometry::AABB& p_scene_AABB) { // DirectionalLight has no position, instead consider at the extents of the scene in the opposite direction its casting. @@ -99,6 +126,31 @@ namespace Component } } + void PointLight::Serialise(const PointLight& p_light, std::ofstream& p_out, uint16_t p_version) + { (void)p_version; + Utility::write_binary(p_out, p_light.m_position); + Utility::write_binary(p_out, p_light.m_colour); + Utility::write_binary(p_out, p_light.m_ambient_intensity); + Utility::write_binary(p_out, p_light.m_diffuse_intensity); + Utility::write_binary(p_out, p_light.m_specular_intensity); + Utility::write_binary(p_out, p_light.m_constant); + Utility::write_binary(p_out, p_light.m_linear); + Utility::write_binary(p_out, p_light.m_quadratic); + } + PointLight PointLight::Deserialise(std::ifstream& p_in, uint16_t p_version) + { (void)p_version; + PointLight light; + Utility::read_binary(p_in, light.m_position); + Utility::read_binary(p_in, light.m_colour); + Utility::read_binary(p_in, light.m_ambient_intensity); + Utility::read_binary(p_in, light.m_diffuse_intensity); + Utility::read_binary(p_in, light.m_specular_intensity); + Utility::read_binary(p_in, light.m_constant); + Utility::read_binary(p_in, light.m_linear); + Utility::read_binary(p_in, light.m_quadratic); + return light; + } + SpotLight::SpotLight() noexcept : m_position{glm::vec3(0.f, 0.f, 0.f)} , m_direction{glm::vec3(0.f, 0.f, -1.f)} @@ -131,4 +183,34 @@ namespace Component ImGui::TreePop(); } } -} \ No newline at end of file + void SpotLight::Serialise(const SpotLight& p_light, std::ofstream& p_out, uint16_t p_version) + { (void)p_version; + Utility::write_binary(p_out, p_light.m_position); + Utility::write_binary(p_out, p_light.m_direction); + Utility::write_binary(p_out, p_light.m_colour); + Utility::write_binary(p_out, p_light.m_ambient_intensity); + Utility::write_binary(p_out, p_light.m_diffuse_intensity); + Utility::write_binary(p_out, p_light.m_specular_intensity); + Utility::write_binary(p_out, p_light.m_constant); + Utility::write_binary(p_out, p_light.m_linear); + Utility::write_binary(p_out, p_light.m_quadratic); + Utility::write_binary(p_out, p_light.m_cutoff); + Utility::write_binary(p_out, p_light.m_outer_cutoff); + } + SpotLight SpotLight::Deserialise(std::ifstream& p_in, uint16_t p_version) + { (void)p_version; + SpotLight light; + Utility::read_binary(p_in, light.m_position); + Utility::read_binary(p_in, light.m_direction); + Utility::read_binary(p_in, light.m_colour); + Utility::read_binary(p_in, light.m_ambient_intensity); + Utility::read_binary(p_in, light.m_diffuse_intensity); + Utility::read_binary(p_in, light.m_specular_intensity); + Utility::read_binary(p_in, light.m_constant); + Utility::read_binary(p_in, light.m_linear); + Utility::read_binary(p_in, light.m_quadratic); + Utility::read_binary(p_in, light.m_cutoff); + Utility::read_binary(p_in, light.m_outer_cutoff); + return light; + } +} // namespace Component \ No newline at end of file diff --git a/source/Component/Lights.hpp b/source/Component/Lights.hpp index 3f69a20e..90d4ac83 100644 --- a/source/Component/Lights.hpp +++ b/source/Component/Lights.hpp @@ -3,6 +3,8 @@ #include "glm/vec3.hpp" #include "glm/mat4x4.hpp" +#include + namespace Geometry { class AABB; @@ -32,6 +34,8 @@ namespace Component glm::mat4 get_view_proj(const Geometry::AABB& scene_AABB); void draw_UI(); + static void Serialise(const DirectionalLight& p_light, std::ofstream& p_out, uint16_t p_version); + static DirectionalLight Deserialise(std::ifstream& p_in, uint16_t p_version); }; class PointLight @@ -54,6 +58,8 @@ namespace Component float m_quadratic; void draw_UI(); + static void Serialise(const PointLight& p_light, std::ofstream& p_out, uint16_t p_version); + static PointLight Deserialise(std::ifstream& p_in, uint16_t p_version); }; class SpotLight @@ -78,5 +84,7 @@ namespace Component float m_outer_cutoff; void draw_UI(); + static void Serialise(const SpotLight& p_light, std::ofstream& p_out, uint16_t p_version); + static SpotLight Deserialise(std::ifstream& p_in, uint16_t p_version); }; } \ No newline at end of file diff --git a/source/Test/TestMain.cpp b/source/Test/TestMain.cpp index 2e0ada0d..8d9c0609 100644 --- a/source/Test/TestMain.cpp +++ b/source/Test/TestMain.cpp @@ -1,4 +1,5 @@ #include "Test/TestManager.hpp" +#include "Test/Tests/ComponentSerialiseTester.hpp" #include "Test/Tests/ECSTester.hpp" #include "Test/Tests/GeometryTester.hpp" #include "Test/Tests/ResourceManagerTester.hpp" @@ -25,6 +26,7 @@ int main(int argc, char* argv[]) const char* seperator = "--------------------------------------------------\n"; std::vector> test_managers; + test_managers.emplace_back(std::make_unique()); test_managers.emplace_back(std::make_unique()); test_managers.emplace_back(std::make_unique()); test_managers.emplace_back(std::make_unique()); @@ -40,23 +42,23 @@ int main(int argc, char* argv[]) Utility::Stopwatch tester_stopwatch; tester->run_unit_tests(); printf("***************** %s SUMMARY *****************\nTOTAL TESTS: %zu\nPASSED: %zu\nFAILED: %zu\nTIME TAKEN: %fms\n%s\n\n", - tester->m_name.c_str(), - tester->m_unit_tests_pass_count + tester->m_unit_tests_fail_count, - tester->m_unit_tests_pass_count, - tester->m_unit_tests_fail_count, - tester_stopwatch.duration_since_start().count(), - seperator); + tester->m_name.c_str(), + tester->m_unit_tests_pass_count + tester->m_unit_tests_fail_count, + tester->m_unit_tests_pass_count, + tester->m_unit_tests_fail_count, + tester_stopwatch.duration_since_start().count(), + seperator); unit_test_overall_pass_count += tester->m_unit_tests_pass_count; unit_test_overall_fail_count += tester->m_unit_tests_fail_count; unit_tests_failed_messages += tester->m_unit_tests_failed_messages; } printf("\n\n***************** OVERALL SUMMARY *****************\nTOTAL TESTS: %zu\nPASSED: %zu\nFAILED: %zu\nTIME TAKEN: %fms\n%s", - unit_test_overall_pass_count + unit_test_overall_fail_count, - unit_test_overall_pass_count, - unit_test_overall_fail_count, - all_unit_tests_stopwatch.duration_since_start().count(), - seperator); + unit_test_overall_pass_count + unit_test_overall_fail_count, + unit_test_overall_pass_count, + unit_test_overall_fail_count, + all_unit_tests_stopwatch.duration_since_start().count(), + seperator); if (unit_test_overall_fail_count > 0) printf("***************** FAILED TESTS *****************\n%s", unit_tests_failed_messages.c_str()); diff --git a/source/Test/Tests/ComponentSerialiseTester.cpp b/source/Test/Tests/ComponentSerialiseTester.cpp new file mode 100644 index 00000000..2bbba3af --- /dev/null +++ b/source/Test/Tests/ComponentSerialiseTester.cpp @@ -0,0 +1,132 @@ +#include "ComponentSerialiseTester.hpp" + +#include "Component/Lights.hpp" +#include "Utility/Logger.hpp" + +#include + +namespace Test +{ + // Helper function to serialise and deserialise a component into a file. + //@param p_to_serialise The component to serialise. + //@param p_deserialised The component to deserialise into. + //@return True if the serialisation and deserialisation was successful, false otherwise. + template + bool ComponentSerialiseTester::test_serialisation(const ComponentType& p_to_serialise, ComponentType& p_deserialised) + { + try + { + std::ofstream out("test.bin", std::ios::binary); + out.exceptions(std::ofstream::failbit | std::ofstream::badbit); + ComponentType::Serialise(p_to_serialise, out, 0); + out.close(); + + std::ifstream in("test.bin", std::ios::binary); + in.exceptions(std::ifstream::failbit | std::ifstream::badbit); + p_deserialised = ComponentType::Deserialise(in, 0); + in.close(); + } + catch (std::ofstream::failure& e) + { + CHECK_TRUE(false, e.what()); + std::remove("test.bin"); + return false; + } + + std::remove("test.bin"); + return true; + } + + void ComponentSerialiseTester::run_unit_tests() + { + SCOPE_SECTION("Component serialise"); + + {SCOPE_SECTION("Directional light"); + + Component::DirectionalLight serialised_light; + serialised_light.m_direction = glm::vec3(0.8f, 0.2f, 0.1f); + serialised_light.m_colour = glm::vec3(0.7f, 0.4f, 1.0f); + serialised_light.m_ambient_intensity = 0.42f; + serialised_light.m_diffuse_intensity = 0.7f; + serialised_light.m_specular_intensity = 0.11f; + serialised_light.m_shadow_near_plane = 0.57f; + serialised_light.m_shadow_far_plane = 0.2f; + serialised_light.m_ortho_size = 0.7f; + + Component::DirectionalLight deserialised_light; + if (test_serialisation(serialised_light, deserialised_light)) + { + CHECK_EQUAL(serialised_light.m_direction, deserialised_light.m_direction, "Direction"); + CHECK_EQUAL(serialised_light.m_colour, deserialised_light.m_colour, "Colour"); + CHECK_EQUAL(serialised_light.m_ambient_intensity, deserialised_light.m_ambient_intensity, "Ambient intensity"); + CHECK_EQUAL(serialised_light.m_diffuse_intensity, deserialised_light.m_diffuse_intensity, "Diffuse intensity"); + CHECK_EQUAL(serialised_light.m_specular_intensity, deserialised_light.m_specular_intensity, "Specular intensity"); + CHECK_EQUAL(serialised_light.m_shadow_near_plane, deserialised_light.m_shadow_near_plane, "Shadow near plane"); + CHECK_EQUAL(serialised_light.m_shadow_far_plane, deserialised_light.m_shadow_far_plane, "Shadow far plane"); + CHECK_EQUAL(serialised_light.m_ortho_size, deserialised_light.m_ortho_size, "Ortho size"); + } + } + + {SCOPE_SECTION("Point light"); + + Component::PointLight serialised_light; + serialised_light.m_position = glm::vec3(0.8f, 0.2f, 0.1f); + serialised_light.m_colour = glm::vec3(0.7f, 0.4f, 1.0f); + serialised_light.m_ambient_intensity = 0.42f; + serialised_light.m_diffuse_intensity = 0.7f; + serialised_light.m_specular_intensity = 0.11f; + serialised_light.m_constant = 0.57f; + serialised_light.m_linear = 0.2f; + serialised_light.m_quadratic = 0.7f; + + Component::PointLight deserialised_light; + if (test_serialisation(serialised_light, deserialised_light)) + { + CHECK_EQUAL(serialised_light.m_position, deserialised_light.m_position, "Position"); + CHECK_EQUAL(serialised_light.m_colour, deserialised_light.m_colour, "Colour"); + CHECK_EQUAL(serialised_light.m_ambient_intensity, deserialised_light.m_ambient_intensity, "Ambient intensity"); + CHECK_EQUAL(serialised_light.m_diffuse_intensity, deserialised_light.m_diffuse_intensity, "Diffuse intensity"); + CHECK_EQUAL(serialised_light.m_specular_intensity, deserialised_light.m_specular_intensity, "Specular intensity"); + CHECK_EQUAL(serialised_light.m_constant, deserialised_light.m_constant, "Constant"); + CHECK_EQUAL(serialised_light.m_linear, deserialised_light.m_linear, "Linear"); + CHECK_EQUAL(serialised_light.m_quadratic, deserialised_light.m_quadratic, "Quadratic"); + } + } + + {SCOPE_SECTION("Spotlight"); + + Component::SpotLight serialised_light; + serialised_light.m_position = glm::vec3(0.8f, 0.2f, 0.1f); + serialised_light.m_direction = glm::vec3(0.7f, 0.4f, 1.0f); + serialised_light.m_colour = glm::vec3(0.7f, 0.4f, 1.0f); + serialised_light.m_ambient_intensity = 0.42f; + serialised_light.m_diffuse_intensity = 0.7f; + serialised_light.m_specular_intensity = 0.11f; + serialised_light.m_constant = 0.57f; + serialised_light.m_linear = 0.2f; + serialised_light.m_quadratic = 0.7f; + serialised_light.m_cutoff = 0.5f; + serialised_light.m_outer_cutoff = 0.7f; + + Component::SpotLight deserialised_light; + if (test_serialisation(serialised_light, deserialised_light)) + { + CHECK_EQUAL(serialised_light.m_position, deserialised_light.m_position, "Position"); + CHECK_EQUAL(serialised_light.m_direction, deserialised_light.m_direction, "Direction"); + CHECK_EQUAL(serialised_light.m_colour, deserialised_light.m_colour, "Colour"); + CHECK_EQUAL(serialised_light.m_ambient_intensity, deserialised_light.m_ambient_intensity, "Ambient intensity"); + CHECK_EQUAL(serialised_light.m_diffuse_intensity, deserialised_light.m_diffuse_intensity, "Diffuse intensity"); + CHECK_EQUAL(serialised_light.m_specular_intensity, deserialised_light.m_specular_intensity, "Specular intensity"); + CHECK_EQUAL(serialised_light.m_constant, deserialised_light.m_constant, "Constant"); + CHECK_EQUAL(serialised_light.m_linear, deserialised_light.m_linear, "Linear"); + CHECK_EQUAL(serialised_light.m_quadratic, deserialised_light.m_quadratic, "Quadratic"); + CHECK_EQUAL(serialised_light.m_cutoff, deserialised_light.m_cutoff, "Cutoff"); + CHECK_EQUAL(serialised_light.m_outer_cutoff, deserialised_light.m_outer_cutoff, "Outer cutoff"); + } + } + } + + void ComponentSerialiseTester::run_performance_tests() + { + } +} // namespace Test \ No newline at end of file diff --git a/source/Test/Tests/ComponentSerialiseTester.hpp b/source/Test/Tests/ComponentSerialiseTester.hpp new file mode 100644 index 00000000..2586605b --- /dev/null +++ b/source/Test/Tests/ComponentSerialiseTester.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "TestManager.hpp" + +namespace Test +{ + class ComponentSerialiseTester : public TestManager + { + public: + ComponentSerialiseTester() : TestManager(std::string("Component serialisation")) {} + + protected: + void run_unit_tests() override; + void run_performance_tests() override; + + private: + // Used only inside ComponentSerialiseTester.cpp, no need to expose it to the public. + template + bool test_serialisation(const ComponentType& p_to_serialise, ComponentType& p_deserialised); + }; +} // namespace Test \ No newline at end of file