diff --git a/.clang-format b/.clang-format index 9b0d41cb..f36c26ab 100644 --- a/.clang-format +++ b/.clang-format @@ -29,7 +29,7 @@ AttributeMacros: BinPackArguments: false BinPackParameters: false BraceWrapping: - AfterCaseLabel: false + AfterCaseLabel: true AfterClass: true AfterControlStatement: Always AfterEnum: true diff --git a/engine/core/Makefile b/engine/core/Makefile index 16624d81..970b67c1 100644 --- a/engine/core/Makefile +++ b/engine/core/Makefile @@ -15,13 +15,6 @@ coreSources := $(call rwildcard,$(coreSrcDir)/,*.cpp) coreObjects := $(call findobjs,$(coreSrcDir),$(coreBinDir),$(coreSources)) coreDepends := $(patsubst %.o, %.d, $(call rwildcard,$(coreBinDir)/,*.o)) -# Set build vars -ifeq ($(platform), windows) - libGenDir := src -else ifeq ($(platform), macos) - libGenDir := src -endif - # Build the static library $(coreLib): $(coreObjects) $(call MKDIR,$(call platformpth,$(libDir))) diff --git a/engine/core/scene/SceneFile.cpp b/engine/core/scene/SceneFile.cpp index e9c016e3..da2607cf 100644 --- a/engine/core/scene/SceneFile.cpp +++ b/engine/core/scene/SceneFile.cpp @@ -10,6 +10,7 @@ #include "SceneFile.h" #include +#include #include #include #include @@ -105,11 +106,11 @@ bool SceneFile::Deserialise(std::vector& entities) }; // TODO: Implement proper write-mode handling for scene system - String ScenePath = MakeScenePath(sceneName); + String scenePath = MakeScenePath(sceneName); if (!SceneSystem::GetBaseDirectory().IsEmpty()) { bool result = FileSystem::ForEachFileInDir( - ScenePath, + scenePath, [&deserialiseEntityString](const std::filesystem::path& path) { if (path.extension() != ENTITY_FILE_EXT) return; String entityData = FileSystem::Read(path.c_str()); @@ -117,7 +118,7 @@ bool SceneFile::Deserialise(std::vector& entities) }); if (!result) { - CC_LOG_ERROR("Failed to read scene file at path \"{}\"", ScenePath) + CC_LOG_ERROR("Failed to read scene file at path \"{}\"", scenePath) return false; } } @@ -125,15 +126,16 @@ bool SceneFile::Deserialise(std::vector& entities) { PackFile* packFile = ResourceSystem::GetInstance().GetPackFile(); - SceneData* sceneData = packFile->FindData(ScenePath); + std::shared_ptr sceneData = packFile->FindDataDeserialised(scenePath); if (!sceneData) { - CC_LOG_WARNING("Failed to find scene \"{}\" in pack file", ScenePath) + CC_LOG_WARNING( + "Failed to retrieve deserialised scene data for scene \"{}\" from pack file", + scenePath) return false; } - String sceneString(sceneData->data); - for (const String& entityData : sceneString.Split('|')) + for (const String& entityData : sceneData->entities) { deserialiseEntityString(entityData.Str(), ""); } diff --git a/engine/render/Makefile b/engine/render/Makefile index b628f597..d0ae4cfa 100644 --- a/engine/render/Makefile +++ b/engine/render/Makefile @@ -15,7 +15,7 @@ renderSources := $(call rwildcard,$(renderSrcDir)/,*.cpp) renderObjects := $(call findobjs,$(renderSrcDir),$(renderBinDir),$(renderSources)) renderDepends := $(patsubst %.o, %.d, $(call rwildcard,$(renderBinDir)/,*.o)) renderBuildDir := $(renderBinDir)/build -renderLibs := $(vendorDir)/zlib/build/lib/libz.a $(vendorDir)/libpng/build/libpng.a $(vendorDir)/freetype/build/libfreetype.a +renderLibs := $(vendorDir)/libpng/build/libpng.a $(vendorDir)/freetype/build/libfreetype.a # Set shader build vars vertSources := $(call rwildcard,assets/shaders,*.vert) @@ -23,10 +23,10 @@ fragSources := $(call rwildcard,assets/shaders,*.frag) vertObjects := $(patsubst %.vert,$(renderBuildDir)/%.vert.spv,$(vertSources)) fragObjects := $(patsubst %.frag,$(renderBuildDir)/%.frag.spv,$(fragSources)) +# Set build vars linkFlags += -l utils -l window - -compileFlags += -I $(vendorDir)/vulkan/include -I $(vendorDir)/glfw/include -I $(vendorDir)/glm \ - -I $(vendorDir)/zlib/build/include -I $(vendorDir)/libpng -I $(vendorDir)/include/freetype +compileFlags += -I $(vendorDir)/vulkan/include -I $(vendorDir)/glfw/include \ + -I $(vendorDir)/libpng -I $(vendorDir)/include/freetype .PHONY: all diff --git a/engine/render/renderer/platform/vulkan/Font.cpp b/engine/render/renderer/platform/vulkan/Font.cpp index eddeb44f..375782d3 100644 --- a/engine/render/renderer/platform/vulkan/Font.cpp +++ b/engine/render/renderer/platform/vulkan/Font.cpp @@ -10,8 +10,8 @@ #include "Font.h" #include -#include #include +#include #include #include #include @@ -27,7 +27,7 @@ namespace Siege::Vulkan Font::Font(const char* filePath) { PackFile* packFile = ResourceSystem::GetInstance().GetPackFile(); - GenericFileData* fileData = packFile->FindData(filePath); + std::shared_ptr fileData = packFile->FindData(filePath); FT_Open_Args args; args.flags = FT_OPEN_MEMORY; diff --git a/engine/render/renderer/platform/vulkan/Shader.cpp b/engine/render/renderer/platform/vulkan/Shader.cpp index 82248ac7..31a25dc3 100644 --- a/engine/render/renderer/platform/vulkan/Shader.cpp +++ b/engine/render/renderer/platform/vulkan/Shader.cpp @@ -9,8 +9,8 @@ #include "Shader.h" -#include #include +#include #include #include @@ -174,7 +174,7 @@ void Shader::Destroy() MHArray Shader::ReadFileAsBinary(const String& filePath) { PackFile* packFile = ResourceSystem::GetInstance().GetPackFile(); - GenericFileData* fileData = packFile->FindData(filePath); + std::shared_ptr fileData = packFile->FindData(filePath); MHArray buffer(fileData->data, fileData->dataSize); return buffer; } diff --git a/engine/render/renderer/platform/vulkan/StaticMesh.cpp b/engine/render/renderer/platform/vulkan/StaticMesh.cpp index 371df47f..29890939 100644 --- a/engine/render/renderer/platform/vulkan/StaticMesh.cpp +++ b/engine/render/renderer/platform/vulkan/StaticMesh.cpp @@ -11,10 +11,10 @@ #include #include +#include #include #include "Swapchain.h" -#include "resources/StaticMeshData.h" namespace Siege::Vulkan { @@ -43,22 +43,25 @@ StaticMesh::StaticMesh(const char* filePath, Material* material) { // TODO(Aryeh): How to extract material data from object files? PackFile* packFile = ResourceSystem::GetInstance().GetPackFile(); - StaticMeshData* vertexData = packFile->FindData(filePath); + std::shared_ptr staticMeshData = + packFile->FindDataDeserialised(filePath); - CC_ASSERT(vertexData->verticesCount > 0, "Cannot load in a file with no vertices!") - CC_ASSERT(vertexData->indicesCount > 0, "Cannot load in a file with no indices!") + CC_ASSERT(!staticMeshData->vertices.empty(), "Cannot load in a file with no vertices!") + CC_ASSERT(!staticMeshData->indices.empty(), "Cannot load in a file with no indices!") - CC_ASSERT(vertexData->verticesCount < MAX_VERTICES, "The provided model has too many vertices!") - CC_ASSERT(vertexData->indicesCount < MAX_INDICES, "The provided model has too many indices!") + CC_ASSERT(staticMeshData->vertices.size() < MAX_VERTICES, + "The provided model has too many vertices!") + CC_ASSERT(staticMeshData->indices.size() < MAX_INDICES, + "The provided model has too many indices!") - vertexBuffer = VertexBuffer(sizeof(BaseVertex) * vertexData->verticesCount); - vertexBuffer.Copy(vertexData->GetVertices(), sizeof(BaseVertex) * vertexData->verticesCount); + vertexCount = staticMeshData->vertices.size(); + indexCount = staticMeshData->indices.size(); - indexBuffer = IndexBuffer(sizeof(unsigned int) * vertexData->indicesCount); - indexBuffer.Copy(vertexData->GetIndices(), sizeof(unsigned int) * vertexData->indicesCount); + vertexBuffer = VertexBuffer(sizeof(BaseVertex) * vertexCount); + vertexBuffer.Copy(staticMeshData->vertices.data(), sizeof(BaseVertex) * vertexCount); - vertexCount = vertexData->verticesCount; - indexCount = vertexData->indicesCount; + indexBuffer = IndexBuffer(sizeof(unsigned int) * indexCount); + indexBuffer.Copy(staticMeshData->indices.data(), sizeof(unsigned int) * indexCount); subMeshes = MHArray(1); materials = MHArray(1); diff --git a/engine/render/renderer/platform/vulkan/Texture2D.cpp b/engine/render/renderer/platform/vulkan/Texture2D.cpp index c4ee71a0..b876f07f 100644 --- a/engine/render/renderer/platform/vulkan/Texture2D.cpp +++ b/engine/render/renderer/platform/vulkan/Texture2D.cpp @@ -9,13 +9,14 @@ #include "Texture2D.h" +#include +#include +#include #include #include "Constants.h" #include "Context.h" #include "render/renderer/buffer/Buffer.h" -#include "resources/ResourceSystem.h" -#include "resources/Texture2DData.h" #include "utils/Descriptor.h" #include "utils/TypeAdaptor.h" @@ -93,14 +94,13 @@ Texture2D& Texture2D::operator=(Texture2D&& other) void Texture2D::LoadFromFile(const char* filePath) { PackFile* packFile = ResourceSystem::GetInstance().GetPackFile(); - Texture2DData* texture2dData = packFile->FindData(filePath); - uint64_t imageSize = texture2dData->GetImageSize(); - const uint8_t* pixelPtr = texture2dData->GetPixels(); + std::shared_ptr texture2dData = + packFile->FindDataDeserialised(filePath); Buffer::Buffer stagingBuffer; defer([&stagingBuffer] { Buffer::DestroyBuffer(stagingBuffer); }); - Buffer::CreateBuffer(imageSize, + Buffer::CreateBuffer(texture2dData->GetImageSize(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // specifies that data is accessible on the CPU. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | @@ -109,7 +109,7 @@ void Texture2D::LoadFromFile(const char* filePath) OUT stagingBuffer.buffer, OUT stagingBuffer.bufferMemory); - Buffer::CopyData(stagingBuffer, imageSize, pixelPtr); + Buffer::CopyData(stagingBuffer, texture2dData->GetImageSize(), texture2dData->pixels.data()); extent = {static_cast(texture2dData->texWidth), static_cast(texture2dData->texHeight)}; diff --git a/engine/resources/Makefile b/engine/resources/Makefile index 9b279834..b4595d18 100644 --- a/engine/resources/Makefile +++ b/engine/resources/Makefile @@ -14,13 +14,16 @@ resourcesBinDir := $(binDir)/engine/resources resourcesSources := $(call rwildcard,$(resourcesSrcDir)/,*.cpp) resourcesObjects := $(call findobjs,$(resourcesSrcDir),$(resourcesBinDir),$(resourcesSources)) resourcesDepends := $(patsubst %.o, %.d, $(call rwildcard,$(resourcesBinDir)/,*.o)) +resourcesLibs := $(vendorDir)/zlib/build/lib/libz.a -linkFlags += -l utils +# Set build vars +linkFlags += -l utils -l z +compileFlags += -I $(vendorDir)/zlib/build/include # Build the static library $(resourcesLib): $(resourcesObjects) $(call MKDIR,$(call platformpth,$(libDir))) - ar -crs $(resourcesLib) $(resourcesObjects) + $(call COMBINE_LIBS, $(resourcesLibs), $(resourcesObjects), $(libDir), resources) # Add all rules from dependency files -include $(resourcesDepends) diff --git a/engine/resources/PackFile.cpp b/engine/resources/PackFile.cpp index 4aa91d46..204494b0 100644 --- a/engine/resources/PackFile.cpp +++ b/engine/resources/PackFile.cpp @@ -28,7 +28,7 @@ bool PackFile::LoadFromPath(const String& filepath) { std::ifstream inputFileStream; inputFileStream.open(filepath, std::ios::in | std::ios::binary); - inputFileStream.read(reinterpret_cast(&header), sizeof(PackFile::Header)); + inputFileStream.read(reinterpret_cast(&header), sizeof(Header)); body = reinterpret_cast(malloc(header.bodySize)); inputFileStream.read(body, (uint32_t) header.bodySize); @@ -41,7 +41,7 @@ bool PackFile::LoadFromPath(const String& filepath) char* tocEnd = body + header.bodySize; while (tocCurr < tocEnd) { - PackFile::TocEntry* toc = reinterpret_cast(tocCurr); + TocEntry* toc = reinterpret_cast(tocCurr); if (!toc) { break; @@ -52,6 +52,27 @@ bool PackFile::LoadFromPath(const String& filepath) return true; } +std::shared_ptr PackFile::FindData(const String& filepath) +{ + const TocEntry* toc = entries[filepath]; + if (!toc) + { + return nullptr; + } + + uLongf bodyDataSizeUncompressed = toc->dataSize; + uLongf bodyDataSizeCompressed = toc->dataSizeCompressed; + + PackFileData* packFileData = new (malloc(bodyDataSizeUncompressed)) PackFileData(); + int result = uncompress(reinterpret_cast(packFileData), + &bodyDataSizeUncompressed, + reinterpret_cast(body + toc->dataOffset), + bodyDataSizeCompressed); + CC_ASSERT(result == Z_OK, "Decompression failed for filepath: " + filepath); + + return {packFileData, free}; +} + const std::map& PackFile::GetEntries() { return entries; @@ -69,7 +90,7 @@ PackFile::TocEntry* PackFile::TocEntry::Create(const String& name, uint32_t nameDataSize = name.Size() + 1; void* mem = malloc(sizeof(TocEntry) + nameDataSize); - PackFile::TocEntry* tocEntry = new (mem) TocEntry(); + TocEntry* tocEntry = new (mem) TocEntry(); tocEntry->dataOffset = dataOffset; tocEntry->dataSize = dataSize; strcpy(&tocEntry->name[0], name.Str()); diff --git a/engine/resources/PackFile.h b/engine/resources/PackFile.h index 0b96397b..2772f400 100644 --- a/engine/resources/PackFile.h +++ b/engine/resources/PackFile.h @@ -10,11 +10,19 @@ #ifndef SIEGE_ENGINE_PACKFILE_H #define SIEGE_ENGINE_PACKFILE_H +#include +#include #include +#include #include #include +#include "PackFileData.h" +#include "SceneData.h" +#include "StaticMeshData.h" +#include "Texture2DData.h" + #define PACKER_MAGIC_NUMBER_FILE "pck" #define PACKER_MAGIC_NUMBER_TOC "toc!" #define PACKER_MAGIC_NUMBER_SIZE sizeof(uint32_t) @@ -46,6 +54,7 @@ class PackFile { uint32_t dataOffset; uint32_t dataSize; + uint32_t dataSizeCompressed; char name[]; uint32_t GetDataSize() const @@ -65,15 +74,25 @@ class PackFile bool LoadFromPath(const String& filepath); + std::shared_ptr FindData(const String& filepath); + template - T* FindData(const String& filepath) + std::shared_ptr FindDataDeserialised(const String& filepath) { - PackFile::TocEntry* toc = entries[filepath]; - if (!toc) + std::shared_ptr packFileData = FindData(filepath); + if (!packFileData) { + CC_LOG_WARNING("Failed to find data for filepath \"{}\"", filepath); return nullptr; } - return reinterpret_cast(body + toc->dataOffset); + + BinarySerialisation::Buffer dataBuffer; + dataBuffer.Fill(reinterpret_cast(packFileData->data), packFileData->dataSize); + + T* typedData = new T(); + BinarySerialisation::serialise(dataBuffer, *typedData, BinarySerialisation::DESERIALISE); + + return std::shared_ptr(typedData); } const std::map& GetEntries(); diff --git a/engine/resources/GenericFileData.h b/engine/resources/PackFileData.h similarity index 50% rename from engine/resources/GenericFileData.h rename to engine/resources/PackFileData.h index ecf5d010..f0b3c902 100644 --- a/engine/resources/GenericFileData.h +++ b/engine/resources/PackFileData.h @@ -7,16 +7,19 @@ // https://opensource.org/licenses/Zlib // -#ifndef SIEGE_ENGINE_GENERICFILEDATA_H -#define SIEGE_ENGINE_GENERICFILEDATA_H +#ifndef SIEGE_ENGINE_PACKFILEDATA_H +#define SIEGE_ENGINE_PACKFILEDATA_H -#include "PackFile.h" +#include +#include +#include +#include namespace Siege { #pragma pack(push, 1) -struct GenericFileData +struct PackFileData { uint32_t dataSize = 0; char data[]; @@ -26,28 +29,22 @@ struct GenericFileData return &data[0]; } - static GenericFileData* Create(char* data, uint32_t dataSize) + uint32_t GetDataSize() const { - uint32_t totalDataSize = sizeof(GenericFileData) + dataSize; - - void* mem = malloc(totalDataSize); - GenericFileData* fileData = new (mem) GenericFileData(); + return sizeof(PackFileData) + dataSize; + } + static PackFileData* Create(char* data, uint32_t dataSize) + { + void* mem = malloc(sizeof(PackFileData) + dataSize); + PackFileData* fileData = new (mem) PackFileData(); fileData->dataSize = dataSize; memcpy(&fileData->data[0], data, dataSize); - return fileData; } - - static uint32_t GetDataSize(void* objectData) - { - if (!objectData) return 0; - GenericFileData* fileData = reinterpret_cast(objectData); - return sizeof(GenericFileData) + fileData->dataSize; - } }; #pragma pack(pop) } // namespace Siege -#endif // SIEGE_ENGINE_GENERICFILEDATA_H +#endif // SIEGE_ENGINE_PACKFILEDATA_H diff --git a/engine/resources/SceneData.h b/engine/resources/SceneData.h index be317f3f..bfc704ab 100644 --- a/engine/resources/SceneData.h +++ b/engine/resources/SceneData.h @@ -10,43 +10,25 @@ #ifndef SIEGE_ENGINE_SCENEDATA_H #define SIEGE_ENGINE_SCENEDATA_H -#include "PackFile.h" +#include namespace Siege { -#pragma pack(push, 1) struct SceneData { - uint32_t dataSize = 0; - char data[]; - - const char* GetData() const - { - return &data[0]; - } - - static SceneData* Create(char* data, uint32_t dataSize) - { - uint32_t totalDataSize = sizeof(SceneData) + dataSize; - - void* mem = malloc(totalDataSize); - SceneData* sceneData = new (mem) SceneData(); + std::vector entities; +}; - sceneData->dataSize = dataSize; - memcpy(&sceneData->data[0], data, dataSize); +namespace BinarySerialisation +{ - return sceneData; - } +inline void serialise(Buffer& buffer, SceneData& value, SerialisationMode mode) +{ + serialise(buffer, value.entities, mode); +} - static uint32_t GetDataSize(void* objectData) - { - if (!objectData) return 0; - SceneData* sceneData = reinterpret_cast(objectData); - return sizeof(SceneData) + sceneData->dataSize; - } -}; -#pragma pack(pop) +} // namespace BinarySerialisation } // namespace Siege diff --git a/engine/resources/StaticMeshData.h b/engine/resources/StaticMeshData.h index f0180a75..1201e3b0 100644 --- a/engine/resources/StaticMeshData.h +++ b/engine/resources/StaticMeshData.h @@ -10,6 +10,7 @@ #ifndef SIEGE_ENGINE_STATICMESHDATA_H #define SIEGE_ENGINE_STATICMESHDATA_H +#include #include #include #include @@ -39,50 +40,32 @@ inline bool operator!=(const BaseVertex& left, const BaseVertex& right) return !(left == right); } -#pragma pack(push, 1) -struct StaticMeshData +inline void serialise(BinarySerialisation::Buffer& buffer, + BaseVertex& value, + BinarySerialisation::SerialisationMode mode) { - uint64_t indicesCount = 0; - uint64_t verticesCount = 0; - char data[]; - - uint32_t* GetIndices() const - { - return (uint32_t*) data; - } - - BaseVertex* GetVertices() const - { - return (BaseVertex*) (data + sizeof(uint32_t) * indicesCount); - } - - static StaticMeshData* Create(const std::vector& objIndices, - const std::vector& objVertices) - { - uint32_t indicesDataSize = sizeof(uint32_t) * objIndices.size(); - uint32_t verticesDataSize = sizeof(BaseVertex) * objVertices.size(); - uint32_t totalDataSize = sizeof(StaticMeshData) + indicesDataSize + verticesDataSize; + serialise(buffer, value.position, mode); + serialise(buffer, value.color, mode); + serialise(buffer, value.normal, mode); + serialise(buffer, value.uv, mode); +} - void* mem = malloc(totalDataSize); - StaticMeshData* staticMeshData = new (mem) StaticMeshData(); +struct StaticMeshData +{ + std::vector indices; + std::vector vertices; +}; - staticMeshData->indicesCount = objIndices.size(); - staticMeshData->verticesCount = objVertices.size(); - memcpy(&staticMeshData->data[0], objIndices.data(), indicesDataSize); - memcpy(&staticMeshData->data[0] + indicesDataSize, objVertices.data(), verticesDataSize); +namespace BinarySerialisation +{ - return staticMeshData; - } +inline void serialise(Buffer& buffer, StaticMeshData& value, SerialisationMode mode) +{ + serialise(buffer, value.indices, mode); + serialise(buffer, value.vertices, mode); +} - static uint32_t GetDataSize(void* objectData) - { - if (!objectData) return 0; - StaticMeshData* staticMeshData = reinterpret_cast(objectData); - return sizeof(StaticMeshData) + sizeof(uint32_t) * staticMeshData->indicesCount + - sizeof(BaseVertex) * staticMeshData->verticesCount; - } -}; -#pragma pack(pop) +} // namespace BinarySerialisation } // namespace Siege diff --git a/engine/resources/Texture2DData.h b/engine/resources/Texture2DData.h index 8a7e38e6..b8749754 100644 --- a/engine/resources/Texture2DData.h +++ b/engine/resources/Texture2DData.h @@ -10,7 +10,7 @@ #ifndef SIEGE_ENGINE_TEXTURE2DDATA_H #define SIEGE_ENGINE_TEXTURE2DDATA_H -#include "PackFile.h" +#include // TODO - Remove this hard-coded value and support various texture channel sizes #define TEXTURE2D_TEXTURE_CHANNELS 4 @@ -18,54 +18,31 @@ namespace Siege { -#pragma pack(push, 1) struct Texture2DData { int32_t texWidth = 0; int32_t texHeight = 0; - int32_t texChannels = 0; - uint8_t pixels[]; - - const uint8_t* GetPixels() const - { - return &pixels[0]; - } + int32_t texChannels = TEXTURE2D_TEXTURE_CHANNELS; + std::vector pixels; uint64_t GetImageSize() const { - return texWidth * texHeight * TEXTURE2D_TEXTURE_CHANNELS; + return texWidth * texHeight * texChannels; } +}; - static Texture2DData* Create(uint8_t* pixels, - int32_t texWidth, - int32_t texHeight, - int32_t texChannels) - { - uint64_t imageSize = texWidth * texHeight * TEXTURE2D_TEXTURE_CHANNELS; - uint32_t pixelDataSize = sizeof(uint8_t) * imageSize; - uint32_t totalDataSize = sizeof(Texture2DData) + pixelDataSize; - - void* mem = malloc(totalDataSize); - Texture2DData* texture2dData = new (mem) Texture2DData(); - - texture2dData->texWidth = texWidth; - texture2dData->texHeight = texHeight; - texture2dData->texChannels = texChannels; - // Ensure we get no garbage data in the pixel array - memset(&texture2dData->pixels[0], 0, imageSize); - memcpy(&texture2dData->pixels[0], pixels, sizeof(uint8_t) * imageSize); +namespace BinarySerialisation +{ - return texture2dData; - } +inline void serialise(Buffer& buffer, Texture2DData& value, SerialisationMode mode) +{ + serialise(buffer, value.texWidth, mode); + serialise(buffer, value.texHeight, mode); + serialise(buffer, value.texChannels, mode); + serialise(buffer, value.pixels, mode); +} - static uint32_t GetDataSize(void* objectData) - { - if (!objectData) return 0; - Texture2DData* textureData = reinterpret_cast(objectData); - return sizeof(Texture2DData) + sizeof(uint8_t) * textureData->GetImageSize(); - } -}; -#pragma pack(pop) +} // namespace BinarySerialisation } // namespace Siege diff --git a/engine/utils/BinarySerialisation.h b/engine/utils/BinarySerialisation.h new file mode 100644 index 00000000..91f65979 --- /dev/null +++ b/engine/utils/BinarySerialisation.h @@ -0,0 +1,251 @@ +// +// Copyright (c) 2020-present Caps Collective & contributors +// Originally authored by Jonathan Moallem (@jonjondev) & Aryeh Zinn (@Raelr) +// +// This code is released under an unmodified zlib license. +// For conditions of distribution and use, please see: +// https://opensource.org/licenses/Zlib +// + +#ifndef SIEGE_ENGINE_BINARYSERIALISATION_H +#define SIEGE_ENGINE_BINARYSERIALISATION_H + +#include +#include +#include + +#include "Colour.h" +#include "String.h" +#include "math/vec/Vec.h" +#include "math/vec/Vec2.h" +#include "math/vec/Vec3.h" + +namespace Siege::BinarySerialisation +{ + +enum SerialisationMode : uint8_t +{ + SERIALISE, + DESERIALISE, +}; + +#define SERIALISE_NATIVE(type) \ + inline void serialise(Buffer& buffer, type& value, SerialisationMode mode) \ + { \ + serialiseNative(buffer, value, mode); \ + } \ + inline void serialise(Buffer& buffer, const type& value, SerialisationMode mode) \ + { \ + serialiseNative(buffer, value, mode); \ + } + +struct Buffer +{ + std::basic_string data; + uint32_t cursor = 0; + + void Fill(const uint8_t* sourceData, uint32_t size) + { + data.assign(sourceData, size); + } + + void Reset() + { + data.clear(); + cursor = 0; + } +}; + +template +void serialiseNative(Buffer& buffer, T& value, SerialisationMode mode) +{ + switch (mode) + { + case SERIALISE: + { + size_t was = buffer.data.size(); + buffer.data.resize(was + sizeof(value)); + *(T*) &buffer.data[was] = value; + break; + } + case DESERIALISE: + { + value = *(const T*) (buffer.data.data() + buffer.cursor); + buffer.cursor += sizeof(value); + break; + } + } +} + +template +void serialiseNative(Buffer& buffer, const T& value, SerialisationMode mode) +{ + T& nonConstValue = const_cast(value); + serialiseNative(buffer, nonConstValue, mode); +} + +SERIALISE_NATIVE(bool) +SERIALISE_NATIVE(char) +SERIALISE_NATIVE(unsigned char) +SERIALISE_NATIVE(uint32_t) +SERIALISE_NATIVE(int32_t) +SERIALISE_NATIVE(float) +SERIALISE_NATIVE(double) + +template +void serialise(Buffer& buffer, std::pair& value, SerialisationMode mode) +{ + serialise(buffer, value.first, mode); + serialise(buffer, value.second, mode); +} + +template +void serialiseContainer(Buffer& buffer, T& value) +{ + uint32_t size = value.size(); + serialise(buffer, size, SERIALISE); + for (auto& entry : value) + { + serialise(buffer, entry, SERIALISE); + } +} + +inline void serialise(Buffer& buffer, Vec2& value, SerialisationMode mode) +{ + serialiseNative(buffer, value.x, mode); + serialiseNative(buffer, value.y, mode); +} + +inline void serialise(Buffer& buffer, Vec3& value, SerialisationMode mode) +{ + serialiseNative(buffer, value.x, mode); + serialiseNative(buffer, value.y, mode); + serialiseNative(buffer, value.z, mode); +} + +inline void serialise(Buffer& buffer, FColour& value, SerialisationMode mode) +{ + serialiseNative(buffer, value.r, mode); + serialiseNative(buffer, value.g, mode); + serialiseNative(buffer, value.b, mode); + serialiseNative(buffer, value.a, mode); +} + +inline void serialise(Buffer& buffer, String& value, SerialisationMode mode) +{ + switch (mode) + { + case SERIALISE: + { + uint32_t size = value.Size() + 1; + serialise(buffer, size, mode); + + size_t was = buffer.data.size(); + buffer.data.resize(was + size); + + memcpy(&buffer.data[was], value.Str(), size); + break; + } + case DESERIALISE: + { + value.Clear(); + + uint32_t size; + serialise(buffer, size, mode); + value.Reserve(size); + + value.Append(reinterpret_cast(buffer.data.data() + buffer.cursor), size); + buffer.cursor += size; + break; + } + } +} + +template +void serialise(Buffer& buffer, std::vector& value, SerialisationMode mode) +{ + switch (mode) + { + case SERIALISE: + { + serialiseContainer(buffer, value); + break; + } + case DESERIALISE: + { + value.clear(); + + uint32_t size; + serialise(buffer, size, mode); + value.reserve(size); + + T entry {}; + while (size--) + { + serialise(buffer, entry, mode); + value.push_back(entry); + } + break; + } + } +} + +template +void serialise(Buffer& buffer, std::set& value, SerialisationMode mode) +{ + switch (mode) + { + case SERIALISE: + { + serialiseContainer(buffer, value); + break; + } + case DESERIALISE: + { + value.clear(); + + uint32_t size; + serialise(buffer, size, mode); + + T entry {}; + while (size--) + { + serialise(buffer, entry, mode); + value.insert(entry); + } + break; + } + } +} + +template +void serialise(Buffer& buffer, std::map& value, SerialisationMode mode) +{ + switch (mode) + { + case SERIALISE: + { + serialiseContainer(buffer, value); + break; + } + case DESERIALISE: + { + value.clear(); + + uint32_t size; + serialise(buffer, size, mode); + + std::pair entry; + while (size--) + { + serialise(buffer, entry, mode); + value.insert(entry); + } + break; + } + } +} + +} // namespace Siege::BinarySerialisation + +#endif // SIEGE_ENGINE_BINARYSERIALISATION_H diff --git a/engine/utils/String.cpp b/engine/utils/String.cpp index 174a4bd9..7a1ac612 100644 --- a/engine/utils/String.cpp +++ b/engine/utils/String.cpp @@ -549,6 +549,19 @@ void String::Append(char character) Assign(cstr); } +void String::Append(const char* string, size_t size) +{ + const char* data = Data(); + size_t lhsLength = Size(); + size_t fullLength = lhsLength + size; + + char* cstr = static_cast(alloca(fullLength + 1)); + strcpy(cstr, data); + strncpy(cstr + lhsLength, string, size); + + Assign(cstr); +} + void String::Prepend(const String& string) { // Mirrors c-string implementation diff --git a/engine/utils/String.h b/engine/utils/String.h index e58c76e2..582901a4 100644 --- a/engine/utils/String.h +++ b/engine/utils/String.h @@ -183,6 +183,12 @@ class String */ String& operator+=(const char* rhs); + /** + * Wide-char c-string addition compound assignment operator overload for appending wide char + * c-strings + * @param rhs - the wide char c-string to append + * @return a reference to the original String object + */ String& operator+=(const wchar_t* rhs); /** @@ -439,6 +445,13 @@ class String */ void Append(char character); + /** + * Appends the value of a c-string to the String for a number of characters + * @param string - the c-string to append + * @param length - the length of the string to append + */ + void Append(const char* string, size_t length); + /** * Prepends the value of another String * @param string - the String to prepend diff --git a/engine/window/Makefile b/engine/window/Makefile index 68754bc7..c31bde66 100644 --- a/engine/window/Makefile +++ b/engine/window/Makefile @@ -16,6 +16,7 @@ windowObjects := $(call findobjs,$(windowSrcDir),$(windowBinDir),$(windowSources windowDepends := $(patsubst %.o, %.d, $(call rwildcard,$(windowBinDir)/,*.o)) windowLibs := $(vendorDir)/glfw/build/src/libglfw3.a +# Set build vars linkFlags += -l utils compileFlags += -I $(vendorDir)/glfw/include diff --git a/examples/game/Makefile b/examples/game/Makefile index 50fcc890..6ee7e441 100644 --- a/examples/game/Makefile +++ b/examples/game/Makefile @@ -69,12 +69,12 @@ $(exampleGameBinDir)/%.o: $(exampleGameSrcDir)/%.cpp # Copy assets directory to the build directory and pack them pack-assets: + $(RM) "$(exampleGameBuildDir)/assets" $(call MKDIR,$(call platformpth,$(exampleGameBuildDir)/assets)) $(call COPY,$(exampleGameSrcDir)/assets,$(exampleGameBuildDir)/assets,$(RWCARDGLOB)) $(call MKDIR,$(call platformpth,$(exampleGameBuildDir)/assets/shaders)) $(call COPY,$(binDir)/engine/render/build/assets/shaders,$(exampleGameBuildDir)/assets/shaders,$(RWCARDGLOB)) $(packerApp) $(exampleGameBuildDir)/app.pck $(exampleGameBuildDir) $(exampleGameAssets) - $(RM) "$(exampleGameBuildDir)/assets" $(call PACK_LIBS_SCRIPT,$(vendorDir)/vulkan/lib,$(exampleGameBuildDir)) diff --git a/examples/game/src/tools/EditorController.cpp b/examples/game/src/tools/EditorController.cpp index e7220ada..bc0124aa 100644 --- a/examples/game/src/tools/EditorController.cpp +++ b/examples/game/src/tools/EditorController.cpp @@ -130,7 +130,8 @@ void EditorController::OnUpdate() // Run the appropriate editor mode logic on the selected entity switch (currentMode) { - case POSITION: { + case POSITION: + { // Calculate move from input Siege::Vec3 move = Siege::Vec3::Zero(); float precision = MOVE_LEVELS[movePrecision]; @@ -149,7 +150,8 @@ void EditorController::OnUpdate() selectedEntity->SetPosition(entityPosition + move); break; } - case ROTATION: { + case ROTATION: + { // Calculate rotation from input and apply it to the rotation of the entity float precision = ROTATE_LEVELS[rotatePrecision]; float rotation = @@ -254,7 +256,8 @@ void EditorController::AdjustPrecision(int adjustment) // Precision adjust for the relevant mode switch (currentMode) { - case POSITION: { + case POSITION: + { // Check boundaries on move precision int newPrecision = movePrecision + adjustment; if (newPrecision >= 0 && newPrecision < sizeof(MOVE_LEVELS) / sizeof(int)) @@ -266,7 +269,8 @@ void EditorController::AdjustPrecision(int adjustment) } break; } - case ROTATION: { + case ROTATION: + { // Check boundaries on rotate precision int newPrecision = rotatePrecision + adjustment; if (newPrecision >= 0 && newPrecision < sizeof(ROTATE_LEVELS) / sizeof(int)) diff --git a/examples/render/Makefile b/examples/render/Makefile index 09a9464d..f2e8ac2c 100644 --- a/examples/render/Makefile +++ b/examples/render/Makefile @@ -68,12 +68,12 @@ $(exampleRenderBinDir)/%.o: $(exampleRenderSrcDir)/%.cpp # Copy assets directory to the build directory and pack them pack-assets: + $(RM) "$(exampleRenderBuildDir)/assets" $(call MKDIR,$(call platformpth,$(exampleRenderBuildDir)/assets)) $(call COPY,$(exampleRenderSrcDir)/assets,$(exampleRenderBuildDir)/assets,$(RWCARDGLOB)) $(call MKDIR,$(call platformpth,$(exampleRenderBuildDir)/assets/shaders)) $(call COPY,$(binDir)/engine/render/build/assets/shaders,$(exampleRenderBuildDir)/assets/shaders,$(RWCARDGLOB)) $(packerApp) $(exampleRenderBuildDir)/app.pck $(exampleRenderBuildDir) $(exampleRenderAssets) - $(RM) "$(exampleRenderBuildDir)/assets" $(call PACK_LIBS_SCRIPT,$(vendorDir)/vulkan/lib,$(exampleRenderBuildDir)) # Package the built application and all its assets to the output directory diff --git a/examples/tilemap/Makefile b/examples/tilemap/Makefile index 2f9f8051..b158a111 100644 --- a/examples/tilemap/Makefile +++ b/examples/tilemap/Makefile @@ -67,12 +67,12 @@ $(exampleTilemapBinDir)/%.o: $(exampleTilemapSrcDir)/%.cpp # Copy assets directory to the build directory and pack them pack-assets: + $(RM) "$(exampleTilemapBuildDir)/assets" $(call MKDIR,$(call platformpth,$(exampleTilemapBuildDir)/assets)) $(call COPY,$(exampleTilemapSrcDir)/assets,$(exampleTilemapBuildDir)/assets,$(RWCARDGLOB)) $(call MKDIR,$(call platformpth,$(exampleTilemapBuildDir)/assets/shaders)) $(call COPY,$(binDir)/engine/render/build/assets/shaders,$(exampleTilemapBuildDir)/assets/shaders,$(RWCARDGLOB)) $(packerApp) $(exampleTilemapBuildDir)/app.pck $(exampleTilemapBuildDir) $(exampleTilemapAssets) - $(RM) "$(exampleTilemapBuildDir)/assets" $(call PACK_LIBS_SCRIPT,$(vendorDir)/vulkan/lib,$(exampleTilemapBuildDir)) # Package the built application and all its assets to the output directory diff --git a/packer/Makefile b/packer/Makefile index 96029355..9354698d 100644 --- a/packer/Makefile +++ b/packer/Makefile @@ -17,7 +17,7 @@ packerDepends := $(patsubst %.o, %.d, $(call rwildcard,$(packerBinDir)/,*.o)) packerBuildDir := $(packerBinDir)/build # Set build vars -linkFlags += -l resources -l utils -L $(vendorDir)/zlib/build/lib -L $(vendorDir)/assimp/build/lib -l assimp -l z -l stdc++ +linkFlags += -l resources -l utils -L $(vendorDir)/assimp/build/lib -l assimp -l stdc++ compileFlags += -I $(vendorDir)/stb_image -I $(vendorDir)/assimp/include -I $(vendorDir)/assimp/build/include .PHONY: all diff --git a/packer/src/main.cpp b/packer/src/main.cpp index ebfa87d4..1be0c7d4 100644 --- a/packer/src/main.cpp +++ b/packer/src/main.cpp @@ -7,13 +7,13 @@ // https://opensource.org/licenses/Zlib // -#include #include +#include #include #include #include -#include #include +#include #include @@ -43,46 +43,33 @@ int main(int argc, char* argv[]) inputFiles.emplace_back(argv[currentArg]); } - uint32_t dataSize = 0; - uint32_t entriesSize = 0; + uint32_t entriesDataSize = 0; + uint32_t entriesTocSize = 0; - struct BodyDataEntry - { - void* ptr; - uint32_t size; - }; - - std::vector dynamicAllocations; - std::vector tocEntries; - std::vector bodyDataEntries; + std::vector> entries; for (auto& file : inputFiles) { if (file.empty()) continue; CC_LOG_INFO("Reading asset at path {}", file.c_str()) - void* data = nullptr; - uint32_t bodyDataSize = 0; + Siege::PackFileData* data = nullptr; Siege::String fullPath = assetsDir + "/" + Siege::String(file.c_str()); std::filesystem::path extension = file.extension(); if (extension == ".sm") { data = PackStaticMeshFile(fullPath, assetsDir); - bodyDataSize = Siege::StaticMeshData::GetDataSize(data); } else if (extension == ".jpg" || extension == ".jpeg" || extension == ".png") { data = PackTexture2DFile(fullPath); - bodyDataSize = Siege::Texture2DData::GetDataSize(data); } else if (extension == ".spv" || extension == ".ttf") { data = PackGenericFile(fullPath); - bodyDataSize = Siege::GenericFileData::GetDataSize(data); } else if (extension == ".scene") { data = PackSceneFile(fullPath); - bodyDataSize = Siege::SceneData::GetDataSize(data); } if (!data) @@ -92,23 +79,20 @@ int main(int argc, char* argv[]) continue; } + uint32_t dataSize = data->GetDataSize(); PackFile::TocEntry* tocEntry = - PackFile::TocEntry::Create(file.c_str(), dataSize, bodyDataSize); + PackFile::TocEntry::Create(file.c_str(), entriesDataSize, dataSize); - bodyDataEntries.push_back({data, bodyDataSize}); - tocEntries.push_back(tocEntry); + entries.emplace_back(tocEntry, data); - dataSize += bodyDataSize; - entriesSize += tocEntry->GetDataSize(); - - dynamicAllocations.push_back(data); - dynamicAllocations.push_back(tocEntry); + entriesDataSize += dataSize; + entriesTocSize += tocEntry->GetDataSize(); } PackFile::Header header {{PACKER_MAGIC_NUMBER_FILE}, PACKER_FILE_VERSION, - dataSize + PACKER_MAGIC_NUMBER_SIZE + entriesSize, - dataSize}; + entriesDataSize + PACKER_MAGIC_NUMBER_SIZE + entriesTocSize, + entriesDataSize}; CC_LOG_INFO( "Beginning pack file version {} write process for body size {} and ToC offset of {}...", @@ -116,7 +100,6 @@ int main(int argc, char* argv[]) header.bodySize, header.tocOffset) uint64_t writeTotal = 0; - uint64_t dataOffset = 0; std::ofstream outputFileStream; outputFileStream.open(outputFile, std::ios::out | std::ios::binary); @@ -127,17 +110,42 @@ int main(int argc, char* argv[]) sizeof(PackFile::Header), writeTotal) - for (auto entry : bodyDataEntries) + entriesDataSize = 0; + Bytef* bodyDataBufferCompressed = nullptr; + for (const std::pair& entry : entries) { - uint32_t bodyDataSize = entry.size; - outputFileStream.write(reinterpret_cast(entry.ptr), bodyDataSize); - writeTotal += bodyDataSize; - CC_LOG_INFO("Adding DATA (offset: {}) to pack file with size: {} (write total: {})", - dataOffset, - bodyDataSize, - writeTotal) - dataOffset += bodyDataSize; + uLongf bodyDataSizeUncompressed = entry.first->dataSize; + uLongf bodyDataSizeCompressed = compressBound(bodyDataSizeUncompressed); + + Bytef* tempBuffer = + static_cast(realloc(bodyDataBufferCompressed, bodyDataSizeCompressed)); + bodyDataBufferCompressed = tempBuffer; + + int result = compress2(bodyDataBufferCompressed, + &bodyDataSizeCompressed, + static_cast(entry.second), + bodyDataSizeUncompressed, + Z_BEST_COMPRESSION); + CC_ASSERT(result == Z_OK, + "Compression failed for entry: " + Siege::String(entry.first->name)); + + outputFileStream.write(reinterpret_cast(bodyDataBufferCompressed), + static_cast(bodyDataSizeCompressed)); + entry.first->dataOffset = entriesDataSize; + entry.first->dataSizeCompressed = bodyDataSizeCompressed; + writeTotal += bodyDataSizeCompressed; + entriesDataSize += bodyDataSizeCompressed; + CC_LOG_INFO( + "Adding DATA \"{}\" to pack file with size: {} from {}, compressed to ~{}% (write " + "total: {})", + entry.first->name, + bodyDataSizeCompressed, + bodyDataSizeUncompressed, + static_cast(ceilf(static_cast(bodyDataSizeCompressed) / + static_cast(bodyDataSizeUncompressed) * 100.f)), + writeTotal) } + if (bodyDataBufferCompressed) free(bodyDataBufferCompressed); outputFileStream.write(PACKER_MAGIC_NUMBER_TOC, PACKER_MAGIC_NUMBER_SIZE); writeTotal += PACKER_MAGIC_NUMBER_SIZE; @@ -145,18 +153,22 @@ int main(int argc, char* argv[]) PACKER_MAGIC_NUMBER_SIZE, writeTotal) - for (Siege::PackFile::TocEntry* toc : tocEntries) + for (const std::pair& entry : entries) { - outputFileStream.write(reinterpret_cast(toc), toc->GetDataSize()); - writeTotal += toc->GetDataSize(); - CC_LOG_INFO( - "Adding TOC ENTRY \"{}\" (offset: {}) to pack file with size: {} (write total: {})", - toc->name, - toc->dataOffset, - toc->GetDataSize(), - writeTotal) + outputFileStream.write(reinterpret_cast(entry.first), entry.first->GetDataSize()); + writeTotal += entry.first->GetDataSize(); + CC_LOG_INFO("Adding TOC \"{}\" (offset: {}) to pack file with size: {} (write total: {})", + entry.first->name, + entry.first->dataOffset, + entry.first->GetDataSize(), + writeTotal) } + header.bodySize = entriesDataSize + PACKER_MAGIC_NUMBER_SIZE + entriesTocSize; + header.tocOffset = entriesDataSize; + outputFileStream.seekp(0); + outputFileStream.write(reinterpret_cast(&header), sizeof(PackFile::Header)); + outputFileStream.close(); CC_LOG_INFO("Ended pack file write process (write total: {})", writeTotal) @@ -176,7 +188,6 @@ int main(int argc, char* argv[]) { CC_LOG_WARNING("Missing ToC entry for input file \"{}\"", file.c_str()) errors = true; - continue; } } @@ -184,7 +195,11 @@ int main(int argc, char* argv[]) resourceSystem.UnmountPackFile(); CC_LOG_INFO("Freeing dynamically allocated memory from packer...") - for (void* allocation : dynamicAllocations) free(allocation); + for (const std::pair& entry : entries) + { + free(entry.first); + free(entry.second); + } if (errors) { diff --git a/packer/src/types/GenericFileDataPacker.cpp b/packer/src/types/GenericFileDataPacker.cpp index 6e7cee75..44239718 100644 --- a/packer/src/types/GenericFileDataPacker.cpp +++ b/packer/src/types/GenericFileDataPacker.cpp @@ -9,13 +9,13 @@ #include "GenericFileDataPacker.h" -#include +#include #include #include #include -void* PackGenericFile(const Siege::String& filePath) +Siege::PackFileData* PackGenericFile(const Siege::String& filePath) { CC_LOG_INFO("Reading file data as generic binary asset") @@ -27,7 +27,6 @@ void* PackGenericFile(const Siege::String& filePath) // Since we consumed the entire file, we can tell the size by checking where // the file stream is reading from (which presumably is at the end of the file). uint32_t fileSize = file.tellg(); - char* data = static_cast(malloc(fileSize)); defer([&data] { free(data); }); @@ -35,6 +34,6 @@ void* PackGenericFile(const Siege::String& filePath) file.read(data, fileSize); file.close(); - Siege::GenericFileData* fileData = Siege::GenericFileData::Create(&data[0], fileSize); + Siege::PackFileData* fileData = Siege::PackFileData::Create(&data[0], fileSize); return fileData; } diff --git a/packer/src/types/GenericFileDataPacker.h b/packer/src/types/GenericFileDataPacker.h index 8698e9d9..6cd9b7c1 100644 --- a/packer/src/types/GenericFileDataPacker.h +++ b/packer/src/types/GenericFileDataPacker.h @@ -12,6 +12,6 @@ #include -void* PackGenericFile(const Siege::String& filePath); +Siege::PackFileData* PackGenericFile(const Siege::String& filePath); #endif // SIEGE_ENGINE_GENERICFILEDATAPACKER_H diff --git a/packer/src/types/SceneDataPacker.cpp b/packer/src/types/SceneDataPacker.cpp index 05548192..b3978c8a 100644 --- a/packer/src/types/SceneDataPacker.cpp +++ b/packer/src/types/SceneDataPacker.cpp @@ -10,21 +10,25 @@ #include "SceneDataPacker.h" #include -#include #include #include #include #include -void* PackSceneFile(const Siege::String& filePath) +#include "render/renderer/buffer/Buffer.h" +#include "resources/PackFileData.h" + +Siege::PackFileData* PackSceneFile(const Siege::String& filePath) { - Siege::String bodyString; - auto appendFile = [&bodyString](const std::filesystem::path& path) { + Siege::SceneData sceneData; + auto appendFile = [&sceneData](const std::filesystem::path& path) { if (path.extension() != ".entity") return; CC_LOG_INFO("Reading entity file {}", path.filename().c_str()) - bodyString += Siege::FileSystem::Read(path.c_str()); - bodyString += '|'; + + Siege::String content = Siege::FileSystem::Read(path.c_str()); + content = Siege::FileSystem::StripNewLines(content); + sceneData.entities.emplace_back(content); }; bool result = Siege::FileSystem::ForEachFileInDir(filePath, appendFile); @@ -34,14 +38,12 @@ void* PackSceneFile(const Siege::String& filePath) return nullptr; } - bodyString = Siege::FileSystem::StripNewLines(bodyString); - - uint32_t fileSize = bodyString.Size() + 1; - char* data = static_cast(malloc(fileSize)); - defer([&data] { free(data); }); - - memcpy(data, bodyString.Str(), fileSize); + Siege::BinarySerialisation::Buffer dataBuffer; + Siege::BinarySerialisation::serialise(dataBuffer, + sceneData, + Siege::BinarySerialisation::SERIALISE); - Siege::SceneData* sceneData = Siege::SceneData::Create(&data[0], fileSize); - return sceneData; + char* data = reinterpret_cast(dataBuffer.data.data()); + Siege::PackFileData* fileData = Siege::PackFileData::Create(data, dataBuffer.data.size()); + return fileData; } diff --git a/packer/src/types/SceneDataPacker.h b/packer/src/types/SceneDataPacker.h index 862f2434..b8332690 100644 --- a/packer/src/types/SceneDataPacker.h +++ b/packer/src/types/SceneDataPacker.h @@ -12,6 +12,6 @@ #include -void* PackSceneFile(const Siege::String& filePath); +Siege::PackFileData* PackSceneFile(const Siege::String& filePath); #endif // SIEGE_ENGINE_SCENEDATAPACKER_H diff --git a/packer/src/types/StaticMeshDataPacker.cpp b/packer/src/types/StaticMeshDataPacker.cpp index 3f36c37b..a9b579bb 100644 --- a/packer/src/types/StaticMeshDataPacker.cpp +++ b/packer/src/types/StaticMeshDataPacker.cpp @@ -11,7 +11,9 @@ #include #include +#include #include +#include #include #include @@ -140,7 +142,8 @@ static void GetMeshesForNode(const aiScene* scene, } }; -void* PackStaticMeshFile(const Siege::String& filePath, const Siege::String& assetsPath) +Siege::PackFileData* PackStaticMeshFile(const Siege::String& filePath, + const Siege::String& assetsPath) { Siege::String contents = Siege::FileSystem::Read(filePath); std::map attributes = @@ -208,10 +211,21 @@ void* PackStaticMeshFile(const Siege::String& filePath, const Siege::String& ass } } - std::vector vertices; - std::vector indices; - GetMeshesForNode(scene, scene->mRootNode, requestedNodePath, '/', baseXform, vertices, indices); - - Siege::StaticMeshData* staticMeshData = Siege::StaticMeshData::Create(indices, vertices); - return staticMeshData; + Siege::StaticMeshData staticMeshData; + GetMeshesForNode(scene, + scene->mRootNode, + requestedNodePath, + '/', + baseXform, + staticMeshData.vertices, + staticMeshData.indices); + + Siege::BinarySerialisation::Buffer dataBuffer; + Siege::BinarySerialisation::serialise(dataBuffer, + staticMeshData, + Siege::BinarySerialisation::SERIALISE); + + char* data = reinterpret_cast(dataBuffer.data.data()); + Siege::PackFileData* fileData = Siege::PackFileData::Create(data, dataBuffer.data.size()); + return fileData; } diff --git a/packer/src/types/StaticMeshDataPacker.h b/packer/src/types/StaticMeshDataPacker.h index 8d2cf9cb..d954cbc8 100644 --- a/packer/src/types/StaticMeshDataPacker.h +++ b/packer/src/types/StaticMeshDataPacker.h @@ -17,6 +17,7 @@ REGISTER_TOKEN(SOURCE_PATH); REGISTER_TOKEN(NODE_PATH); REGISTER_TOKEN(FLIP_AXES); -void* PackStaticMeshFile(const Siege::String& filePath, const Siege::String& assetsPath); +Siege::PackFileData* PackStaticMeshFile(const Siege::String& filePath, + const Siege::String& assetsPath); #endif // SIEGE_ENGINE_STATICMESHDATAPACKER_H diff --git a/packer/src/types/Texture2DDataPacker.cpp b/packer/src/types/Texture2DDataPacker.cpp index 528d8316..f6ccbffe 100644 --- a/packer/src/types/Texture2DDataPacker.cpp +++ b/packer/src/types/Texture2DDataPacker.cpp @@ -10,12 +10,16 @@ #include "Texture2DDataPacker.h" #define STB_IMAGE_IMPLEMENTATION +#include #include #include +#include #include #include -void* PackTexture2DFile(const Siege::String& filePath) +#include + +Siege::PackFileData* PackTexture2DFile(const Siege::String& filePath) { int32_t texWidth, texHeight, texChannels; stbi_uc* pixels = stbi_load(filePath, &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); @@ -27,7 +31,18 @@ void* PackTexture2DFile(const Siege::String& filePath) texHeight, texChannels) - Siege::Texture2DData* texture2dData = - Siege::Texture2DData::Create(pixels, texWidth, texHeight, texChannels); - return texture2dData; + Siege::Texture2DData texture2dData; + texture2dData.texWidth = texWidth; + texture2dData.texHeight = texHeight; + texture2dData.texChannels = TEXTURE2D_TEXTURE_CHANNELS; + std::copy_n(pixels, texture2dData.GetImageSize(), std::back_inserter(texture2dData.pixels)); + + Siege::BinarySerialisation::Buffer dataBuffer; + Siege::BinarySerialisation::serialise(dataBuffer, + texture2dData, + Siege::BinarySerialisation::SERIALISE); + + char* data = reinterpret_cast(dataBuffer.data.data()); + Siege::PackFileData* fileData = Siege::PackFileData::Create(data, dataBuffer.data.size()); + return fileData; } diff --git a/packer/src/types/Texture2DDataPacker.h b/packer/src/types/Texture2DDataPacker.h index f029386c..ce4ba36d 100644 --- a/packer/src/types/Texture2DDataPacker.h +++ b/packer/src/types/Texture2DDataPacker.h @@ -12,6 +12,6 @@ #include -void* PackTexture2DFile(const Siege::String& filePath); +Siege::PackFileData* PackTexture2DFile(const Siege::String& filePath); #endif // SIEGE_ENGINE_TEXTURE2DDATAPACKER_H diff --git a/tests/Makefile b/tests/Makefile index 37fd3930..3604af36 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -49,6 +49,7 @@ $(utestIncludeDir): # Copy the assets directory to the build directory, and pack them pack-assets: + $(RM) "$(testBuildDir)/assets" $(call MKDIR,$(call platformpth,$(testBuildDir)/assets)) $(call COPY,$(testSrcDir)/assets,$(testBuildDir)/assets,$(RWCARDGLOB)) $(packerApp) $(testBuildDir)/app.pck $(testBuildDir) $(testAssets) diff --git a/tests/assets/scene1.scene/TestEntity.1.entity b/tests/assets/scene1.scene/TestEntity.1.entity index 1b01b0bc..cf363b28 100644 --- a/tests/assets/scene1.scene/TestEntity.1.entity +++ b/tests/assets/scene1.scene/TestEntity.1.entity @@ -2,4 +2,3 @@ TYPE:TestEntity; POSITION:0.000000,0.000000,0.000000; ROTATION:0.000000; Z_INDEX:0; - diff --git a/tests/src/resources/test_ResourceSystem.cpp b/tests/src/resources/test_ResourceSystem.cpp index b1adc154..d75e8943 100644 --- a/tests/src/resources/test_ResourceSystem.cpp +++ b/tests/src/resources/test_ResourceSystem.cpp @@ -7,8 +7,8 @@ // https://opensource.org/licenses/Zlib // -#include #include +#include #include #include #include @@ -57,8 +57,8 @@ UTEST_F(test_ResourceSystem, ReadAllPackedEntries) const PackFile::Header& header = packFile->GetHeader(); ASSERT_STREQ("pck", header.magic.string); - ASSERT_EQ(259415, header.bodySize); - ASSERT_EQ(259247, header.tocOffset); + ASSERT_EQ(48703, header.bodySize); + ASSERT_EQ(48511, header.tocOffset); std::vector packedFilepaths {"assets/scene2.scene", "assets/scene1.scene", @@ -79,16 +79,16 @@ UTEST_F(test_ResourceSystem, LoadNonExistentData) ResourceSystem& resourceSystem = ResourceSystem::GetInstance(); PackFile* packFile = resourceSystem.GetPackFile(); - GenericFileData* data = packFile->FindData("assets/nonexistent.filetype"); + std::shared_ptr data = packFile->FindData("assets/nonexistent.filetype"); ASSERT_FALSE(data); } -UTEST_F(test_ResourceSystem, LoadGenericFileData) +UTEST_F(test_ResourceSystem, LoadPackFileData) { ResourceSystem& resourceSystem = ResourceSystem::GetInstance(); PackFile* packFile = resourceSystem.GetPackFile(); - GenericFileData* data = packFile->FindData("assets/PublicPixel.ttf"); + std::shared_ptr data = packFile->FindData("assets/PublicPixel.ttf"); ASSERT_TRUE(data); ASSERT_EQ(97456, data->dataSize); } @@ -98,15 +98,15 @@ UTEST_F(test_ResourceSystem, LoadStaticMeshData) ResourceSystem& resourceSystem = ResourceSystem::GetInstance(); PackFile* packFile = resourceSystem.GetPackFile(); - StaticMeshData* data = packFile->FindData("assets/cube.sm"); + std::shared_ptr data = + packFile->FindDataDeserialised("assets/cube.sm"); ASSERT_TRUE(data); - ASSERT_EQ(36, data->indicesCount); - ASSERT_EQ(24, data->verticesCount); - ASSERT_EQ(1312, StaticMeshData::GetDataSize(data)); + ASSERT_EQ(36, data->indices.size()); + ASSERT_EQ(24, data->vertices.size()); uint32_t expectedIndices[36] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 18, 1, 3, 19, 4, 6, 20, 7, 9, 21, 10, 12, 22, 13, 15, 23, 16}; - uint32_t* actualIndices = data->GetIndices(); + uint32_t* actualIndices = data->indices.data(); ASSERT_TRUE(actualIndices); bool indicesCorrect = true; @@ -143,14 +143,13 @@ UTEST_F(test_ResourceSystem, LoadStaticMeshData) {{1, 1, -1}, {1, 1, 1, 1}, {0, 1, 0}, {0.375, 0.75}}, {{1, -1, -1}, {1, 1, 1, 1}, {1, 0, 0}, {0.625, 0.75}}, {{1, -1, 1}, {1, 1, 1, 1}, {0, 0, 1}, {0.625, 0.5}}}; - BaseVertex* actualVertices = data->GetVertices(); - ASSERT_TRUE(actualVertices); + ASSERT_FALSE(data->vertices.empty()); bool verticesCorrect = true; for (int i = 0; i < 24; i++) { const BaseVertex& expectedVertex = expectedVertices[i]; - const BaseVertex& actualVertex = actualVertices[i]; + const BaseVertex& actualVertex = data->vertices[i]; if (expectedVertex != actualVertex) { verticesCorrect = false; @@ -164,12 +163,11 @@ UTEST_F(test_ResourceSystem, LoadTextureData) ResourceSystem& resourceSystem = ResourceSystem::GetInstance(); PackFile* packFile = resourceSystem.GetPackFile(); - Texture2DData* data = packFile->FindData("assets/cappy.png"); + std::shared_ptr data = + packFile->FindDataDeserialised("assets/cappy.png"); ASSERT_TRUE(data); ASSERT_EQ(160000, data->GetImageSize()); - - const uint8_t* actualPixels = data->GetPixels(); - ASSERT_TRUE(actualPixels); + ASSERT_EQ(160000, data->pixels.size()); } UTEST_F(test_ResourceSystem, LoadSceneData) @@ -177,23 +175,27 @@ UTEST_F(test_ResourceSystem, LoadSceneData) ResourceSystem& resourceSystem = ResourceSystem::GetInstance(); PackFile* packFile = resourceSystem.GetPackFile(); - const char* expectedSceneData = "TYPE:TestEntity;" - "POSITION:0.000000,0.000000,0.000000;" - "ROTATION:0.000000;" - "Z_INDEX:0;" - "|" - "TYPE:TestEntity;" - "POSITION:0.000000,0.000000,0.000000;" - "ROTATION:0.000000;" - "Z_INDEX:0;" - "|" - "TYPE:TestEntity;" - "POSITION:0.000000,0.000000,0.000000;" - "ROTATION:0.000000;" - "Z_INDEX:0;" - "|"; - - SceneData* data = packFile->FindData("assets/scene1.scene"); + std::vector expectedSceneData = {"TYPE:TestEntity;" + "POSITION:0.000000,0.000000,0.000000;" + "ROTATION:0.000000;" + "Z_INDEX:0;", + "TYPE:TestEntity;" + "POSITION:0.000000,0.000000,0.000000;" + "ROTATION:0.000000;" + "Z_INDEX:0;", + "TYPE:TestEntity;" + "POSITION:0.000000,0.000000,0.000000;" + "ROTATION:0.000000;" + "Z_INDEX:0;"}; + + std::shared_ptr data = + packFile->FindDataDeserialised("assets/scene1.scene"); ASSERT_TRUE(data); - ASSERT_STREQ(expectedSceneData, data->GetData()); + ASSERT_EQ(expectedSceneData.size(), data->entities.size()); + for (int i = 0; i < expectedSceneData.size(); ++i) + { + const String& expectedEntityData = expectedSceneData[i]; + const String& actualEntityData = data->entities[i]; + ASSERT_STREQ(expectedEntityData.Str(), actualEntityData.Str()); + } } \ No newline at end of file diff --git a/tests/src/utils/test_BinarySerialisation.cpp b/tests/src/utils/test_BinarySerialisation.cpp new file mode 100644 index 00000000..804371bf --- /dev/null +++ b/tests/src/utils/test_BinarySerialisation.cpp @@ -0,0 +1,254 @@ +// +// Copyright (c) 2020-present Caps Collective & contributors +// Originally authored by Jonathan Moallem (@jonjondev) & Aryeh Zinn (@Raelr) +// +// This code is released under an unmodified zlib license. +// For conditions of distribution and use, please see: +// https://opensource.org/licenses/Zlib +// + +#include +#include + +#include + +struct TestBinarySerialisable1 +{ + bool b = false; + int i = 0; + float f = 0; + double d = 0; +}; + +struct TestBinarySerialisable2 +{ + TestBinarySerialisable1 test; +}; + +inline void serialise(Siege::BinarySerialisation::Buffer& buffer, + TestBinarySerialisable1& value, + Siege::BinarySerialisation::SerialisationMode mode) +{ + Siege::BinarySerialisation::serialise(buffer, value.b, mode); + Siege::BinarySerialisation::serialise(buffer, value.i, mode); + Siege::BinarySerialisation::serialise(buffer, value.f, mode); + Siege::BinarySerialisation::serialise(buffer, value.d, mode); +} + +inline void serialise(Siege::BinarySerialisation::Buffer& buffer, + TestBinarySerialisable2& value, + Siege::BinarySerialisation::SerialisationMode mode) +{ + serialise(buffer, value.test, mode); +} + +UTEST(test_BinarySerialisation, Native) +{ + Siege::BinarySerialisation::Buffer buffer; + { + bool b = true; + Siege::BinarySerialisation::serialise(buffer, b, Siege::BinarySerialisation::SERIALISE); + } + bool b; + Siege::BinarySerialisation::serialise(buffer, b, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(true, b); + buffer.Reset(); + + { + int32_t i = 36; + Siege::BinarySerialisation::serialise(buffer, i, Siege::BinarySerialisation::SERIALISE); + } + int32_t i; + Siege::BinarySerialisation::serialise(buffer, i, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(36, i); + buffer.Reset(); + + { + float f = 3.14f; + Siege::BinarySerialisation::serialise(buffer, f, Siege::BinarySerialisation::SERIALISE); + } + float f; + Siege::BinarySerialisation::serialise(buffer, f, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(3.14f, f); + buffer.Reset(); + + { + double d = 1.21; + Siege::BinarySerialisation::serialise(buffer, d, Siege::BinarySerialisation::SERIALISE); + } + double d; + Siege::BinarySerialisation::serialise(buffer, d, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(1.21, d); + buffer.Reset(); +} + +UTEST(test_BinarySerialisation, String) +{ + Siege::BinarySerialisation::Buffer buffer; + { + Siege::String s("Hello, world!"); + Siege::BinarySerialisation::serialise(buffer, s, Siege::BinarySerialisation::SERIALISE); + } + Siege::String s; + Siege::BinarySerialisation::serialise(buffer, s, Siege::BinarySerialisation::DESERIALISE); + ASSERT_STREQ("Hello, world!", s.Str()); + buffer.Reset(); +} + +UTEST(test_BinarySerialisation, Struct) +{ + Siege::BinarySerialisation::Buffer buffer; + { + TestBinarySerialisable1 test1; + test1.b = true; + test1.i = 36; + test1.f = 3.14f; + test1.d = 1.21; + serialise(buffer, test1, Siege::BinarySerialisation::SERIALISE); + } + TestBinarySerialisable1 test1; + serialise(buffer, test1, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(true, test1.b); + ASSERT_EQ(36, test1.i); + ASSERT_EQ(3.14f, test1.f); + ASSERT_EQ(1.21, test1.d); + buffer.Reset(); + + { + TestBinarySerialisable2 test2; + test2.test.b = true; + test2.test.i = 36; + test2.test.f = 3.14f; + test2.test.d = 1.21; + serialise(buffer, test1, Siege::BinarySerialisation::SERIALISE); + } + TestBinarySerialisable2 test2; + serialise(buffer, test2, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(true, test2.test.b); + ASSERT_EQ(36, test2.test.i); + ASSERT_EQ(3.14f, test2.test.f); + ASSERT_EQ(1.21, test2.test.d); + buffer.Reset(); +} + +UTEST(test_BinarySerialisation, Vector) +{ + Siege::BinarySerialisation::Buffer buffer; + { + std::vector vec1 = {2, 5, 41}; + Siege::BinarySerialisation::serialise(buffer, vec1, Siege::BinarySerialisation::SERIALISE); + } + std::vector vec1; + Siege::BinarySerialisation::serialise(buffer, vec1, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(3, vec1.size()); + ASSERT_EQ(2, vec1[0]); + ASSERT_EQ(5, vec1[1]); + ASSERT_EQ(41, vec1[2]); + buffer.Reset(); + + { + TestBinarySerialisable1 test1; + test1.b = true; + test1.i = 36; + test1.f = 3.14f; + test1.d = 1.21; + TestBinarySerialisable1 test2; + test2.b = false; + test2.i = 35; + test2.f = 3.13f; + test2.d = 1.20; + std::vector vec2 = {test1, test2}; + Siege::BinarySerialisation::serialise(buffer, vec2, Siege::BinarySerialisation::SERIALISE); + } + std::vector vec2; + Siege::BinarySerialisation::serialise(buffer, vec2, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(2, vec2.size()); + ASSERT_EQ(true, vec2[0].b); + ASSERT_EQ(36, vec2[0].i); + ASSERT_EQ(3.14f, vec2[0].f); + ASSERT_EQ(1.21, vec2[0].d); + ASSERT_EQ(false, vec2[1].b); + ASSERT_EQ(35, vec2[1].i); + ASSERT_EQ(3.13f, vec2[1].f); + ASSERT_EQ(1.20, vec2[1].d); + buffer.Reset(); +} + +UTEST(test_BinarySerialisation, Set) +{ + Siege::BinarySerialisation::Buffer buffer; + { + std::set set1 = {2, 5, 41}; + Siege::BinarySerialisation::serialise(buffer, set1, Siege::BinarySerialisation::SERIALISE); + } + std::set set1; + Siege::BinarySerialisation::serialise(buffer, set1, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(3, set1.size()); + auto it1 = set1.find(2); + ASSERT_TRUE(it1 != set1.end()); + it1 = set1.find(5); + ASSERT_TRUE(it1 != set1.end()); + it1 = set1.find(41); + ASSERT_TRUE(it1 != set1.end()); + buffer.Reset(); +} + +UTEST(test_BinarySerialisation, Map) +{ + Siege::BinarySerialisation::Buffer buffer; + { + std::map map1 = { + {2, true}, + {5, false}, + {41, true}, + }; + Siege::BinarySerialisation::serialise(buffer, map1, Siege::BinarySerialisation::SERIALISE); + } + std::map map1; + Siege::BinarySerialisation::serialise(buffer, map1, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(3, map1.size()); + auto it1 = map1.find(2); + ASSERT_TRUE(it1 != map1.end()); + ASSERT_EQ(true, it1->second); + it1 = map1.find(5); + ASSERT_TRUE(it1 != map1.end()); + ASSERT_EQ(false, it1->second); + it1 = map1.find(41); + ASSERT_TRUE(it1 != map1.end()); + ASSERT_EQ(true, it1->second); + buffer.Reset(); + + { + TestBinarySerialisable1 test1; + test1.b = true; + test1.i = 36; + test1.f = 3.14f; + test1.d = 1.21; + TestBinarySerialisable1 test2; + test2.b = false; + test2.i = 35; + test2.f = 3.13f; + test2.d = 1.20; + std::map map2 = { + {2, test1}, + {5, test2}, + }; + Siege::BinarySerialisation::serialise(buffer, map2, Siege::BinarySerialisation::SERIALISE); + } + std::map map2; + Siege::BinarySerialisation::serialise(buffer, map2, Siege::BinarySerialisation::DESERIALISE); + ASSERT_EQ(2, map2.size()); + auto it2 = map2.find(2); + ASSERT_TRUE(it2 != map2.end()); + ASSERT_EQ(true, it2->second.b); + ASSERT_EQ(36, it2->second.i); + ASSERT_EQ(3.14f, it2->second.f); + ASSERT_EQ(1.21, it2->second.d); + it2 = map2.find(5); + ASSERT_TRUE(it2 != map2.end()); + ASSERT_EQ(false, it2->second.b); + ASSERT_EQ(35, it2->second.i); + ASSERT_EQ(3.13f, it2->second.f); + ASSERT_EQ(1.20, it2->second.d); + buffer.Reset(); +}