diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index f6fa7830a..bba7092c5 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -49,7 +49,6 @@ set(CUBOS_CORE_SOURCE "src/cubos/core/data/fs/file_system.cpp" "src/cubos/core/data/fs/standard_archive.cpp" "src/cubos/core/data/fs/embedded_archive.cpp" - "src/cubos/core/data/qb_parser.cpp" "src/cubos/core/data/context.cpp" "src/cubos/core/io/window.cpp" @@ -63,11 +62,7 @@ set(CUBOS_CORE_SOURCE "src/cubos/core/gl/render_device.cpp" "src/cubos/core/gl/ogl_render_device.hpp" "src/cubos/core/gl/ogl_render_device.cpp" - "src/cubos/core/gl/material.cpp" - "src/cubos/core/gl/palette.cpp" - "src/cubos/core/gl/grid.cpp" "src/cubos/core/gl/util.cpp" - "src/cubos/core/gl/vertex.cpp" "src/cubos/core/al/audio_device.cpp" "src/cubos/core/al/oal_audio_device.cpp" diff --git a/core/include/cubos/core/data/qb_parser.hpp b/core/include/cubos/core/data/qb_parser.hpp deleted file mode 100644 index d1feba34f..000000000 --- a/core/include/cubos/core/data/qb_parser.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include -#include - -namespace cubos::core::data -{ - /// Represents the data read from a matrix in a QB file. - struct QBMatrix - { - gl::Grid grid; ///< The grid of the matrix. - gl::Palette palette; ///< The palette of the matrix. - glm::ivec3 position; ///< The position of the matrix. - }; - - /// Parses a Qubicle file (.qb), pushing every matrix found in the file to the passed vector. - /// @param matrices The matrices to output. - /// @param stream The stream to read from. - /// @return True if the file was parsed successfully, otherwise false. - bool parseQB(std::vector& matrices, memory::Stream& stream); -} // namespace cubos::core::data diff --git a/core/include/cubos/core/gl/module.dox b/core/include/cubos/core/gl/module.dox index 79eae2c1a..c0509a261 100644 --- a/core/include/cubos/core/gl/module.dox +++ b/core/include/cubos/core/gl/module.dox @@ -13,5 +13,5 @@ namespace cubos::core::gl { /// @defgroup core-gl Graphics /// @ingroup core - /// @brief Provides a graphics API abstraction and some voxel utilities. + /// @brief Provides a graphics API abstraction. } // namespace cubos::core::gl diff --git a/core/src/cubos/core/data/qb_parser.cpp b/core/src/cubos/core/data/qb_parser.cpp deleted file mode 100644 index ac0a78ab3..000000000 --- a/core/src/cubos/core/data/qb_parser.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include - -#include -#include -#include - -bool cubos::core::data::parseQB(std::vector& matrices, memory::Stream& stream) -{ - uint8_t version[4] = {0, 0, 0, 0}; - uint32_t colorFormat; - uint32_t zAxisOrientation; - uint32_t compressed; - uint32_t visibilityMaskEncoded; - uint32_t numMatrices; - - // Parse the version of the file. - stream.read(version, 4); - if (stream.eof()) - { - CUBOS_ERROR("Unexpected end of file while reading file version"); - return false; - } - if (version[0] != 1 || version[1] != 1 || version[2] != 0 || version[3] != 0) - { - CUBOS_ERROR("Unsupported version {}.{}.{}.{}, only 1.1.0.0 is supported", version[0], version[1], version[2], - version[3]); - return false; - } - - // Parse the rest of the header. - stream.read(&colorFormat, 4); - stream.read(&zAxisOrientation, 4); - stream.read(&compressed, 4); - stream.read(&visibilityMaskEncoded, 4); - stream.read(&numMatrices, 4); - colorFormat = memory::fromLittleEndian(colorFormat); - zAxisOrientation = memory::fromLittleEndian(zAxisOrientation); - compressed = memory::fromLittleEndian(compressed); - visibilityMaskEncoded = memory::fromLittleEndian(visibilityMaskEncoded); - numMatrices = memory::fromLittleEndian(numMatrices); - - if (stream.eof()) - { - CUBOS_ERROR("Unexpected end of file while reading file header"); - return false; - } - if (visibilityMaskEncoded != 0U) - { - CUBOS_ERROR("Visibility mask encoding is not supported"); - return false; - } - - // Parse the matrices. - matrices.resize(numMatrices); - for (uint32_t i = 0; i < numMatrices; ++i) - { - uint8_t nameLen; - uint32_t sizeX; - uint32_t sizeY; - uint32_t sizeZ; - int32_t posX; - int32_t posY; - int32_t posZ; - - // Read the matrix name. - stream.read(&nameLen, 1); - std::string name(nameLen, ' '); - stream.read(name.data(), nameLen); - - // Read the matrix size. - stream.read(&sizeX, 4); - stream.read(&sizeY, 4); - stream.read(&sizeZ, 4); - sizeX = memory::fromLittleEndian(sizeX); - sizeY = memory::fromLittleEndian(sizeY); - sizeZ = memory::fromLittleEndian(sizeZ); - matrices[i].grid.setSize({sizeX, sizeY, sizeZ}); - - // Read the matrix position. - stream.read(&posX, 4); - stream.read(&posY, 4); - stream.read(&posZ, 4); - posX = memory::fromLittleEndian(posX); - posY = memory::fromLittleEndian(posY); - posZ = memory::fromLittleEndian(posZ); - matrices[i].position = glm::ivec3(posX, posY, posZ); - - // Read the matrix voxels. - if (compressed == 0) - { - uint8_t color[4]; - std::size_t nextMat = 1; - - for (uint32_t z = 0; z < sizeZ; ++z) - { - for (uint32_t y = 0; y < sizeY; ++y) - { - for (uint32_t x = 0; x < sizeX; ++x) - { - stream.read(color, 4); - if (color[3] == 0) - { - continue; - } - if (colorFormat != 0U) - { // BGRA -> RGBA - std::swap(color[0], color[2]); - } - glm::vec4 colorVec(static_cast(color[0]) / 255.0F, static_cast(color[1]) / 255.0F, - static_cast(color[2]) / 255.0F, - static_cast(color[3]) / 255.0F); - - // Check if the material is already in the palette. - std::size_t mat; - for (mat = 1; mat < nextMat; ++mat) - { - if (matrices[i].palette.get(static_cast(mat)).color == colorVec) - { - break; - } - } - if (mat == nextMat) - { - if (mat >= 65536) - { - CUBOS_ERROR("Too many materials, max is 65536"); - return false; - } - - // Add the material to the palette. - gl::Material desc; - desc.color = colorVec; - matrices[i].palette.set(static_cast(mat), desc); - nextMat += 1; - } - - // Set the voxel. - matrices[i].grid.set(glm::ivec3(x, y, z), static_cast(mat)); - } - } - } - } - else - { - CUBOS_ERROR("Compressed QB files are not supported"); - return false; - } - } - - return true; -} diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index c67b4f912..4c9228c0b 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -42,6 +42,9 @@ set(CUBOS_ENGINE_SOURCE "src/cubos/engine/scene/bridge.cpp" "src/cubos/engine/voxels/plugin.cpp" + "src/cubos/engine/voxels/grid.cpp" + "src/cubos/engine/voxels/material.cpp" + "src/cubos/engine/voxels/palette.cpp" "src/cubos/engine/collisions/plugin.cpp" "src/cubos/engine/collisions/broad_phase.cpp" @@ -54,6 +57,7 @@ set(CUBOS_ENGINE_SOURCE "src/cubos/engine/input/axis.cpp" "src/cubos/engine/renderer/plugin.cpp" + "src/cubos/engine/renderer/vertex.cpp" "src/cubos/engine/renderer/frame.cpp" "src/cubos/engine/renderer/renderer.cpp" "src/cubos/engine/renderer/deferred_renderer.cpp" diff --git a/engine/include/cubos/engine/renderer/deferred_renderer.hpp b/engine/include/cubos/engine/renderer/deferred_renderer.hpp index 69bbc0a1a..cfce0eeb9 100644 --- a/engine/include/cubos/engine/renderer/deferred_renderer.hpp +++ b/engine/include/cubos/engine/renderer/deferred_renderer.hpp @@ -7,9 +7,9 @@ #include #include -#include #include +#include #include // TODO: make these defines proper constants (we're using C++!) @@ -40,8 +40,8 @@ namespace cubos::engine // Implement interface methods. - RendererGrid upload(const core::gl::Grid& grid) override; - void setPalette(const core::gl::Palette& palette) override; + RendererGrid upload(const Grid& grid) override; + void setPalette(const Palette& palette) override; protected: // Implement interface methods. diff --git a/engine/include/cubos/engine/renderer/plugin.hpp b/engine/include/cubos/engine/renderer/plugin.hpp index a2e51048a..d31bb6b43 100644 --- a/engine/include/cubos/engine/renderer/plugin.hpp +++ b/engine/include/cubos/engine/renderer/plugin.hpp @@ -9,11 +9,10 @@ #pragma once -#include -#include - #include #include +#include +#include namespace cubos::engine { @@ -68,7 +67,7 @@ namespace cubos::engine /// @ingroup renderer-plugin struct [[cubos::component("cubos/renderable_grid", VecStorage)]] RenderableGrid { - Asset asset; ///< Handle to the grid asset to be rendered. + Asset asset; ///< Handle to the grid asset to be rendered. glm::vec3 offset = {0.0F, 0.0F, 0.0F}; ///< Translation applied to the voxel grid before any other. [[cubos::ignore]] RendererGrid handle = nullptr; ///< Handle to the uploaded grid - set automatically. }; diff --git a/engine/include/cubos/engine/renderer/renderer.hpp b/engine/include/cubos/engine/renderer/renderer.hpp index 03c69e28f..d082d910a 100644 --- a/engine/include/cubos/engine/renderer/renderer.hpp +++ b/engine/include/cubos/engine/renderer/renderer.hpp @@ -9,14 +9,14 @@ #include -#include -#include #include -#include #include #include #include +#include +#include +#include namespace cubos::engine { @@ -74,11 +74,11 @@ namespace cubos::engine /// @brief Uploads a grid to the GPU and returns an handle which can be used to draw it. /// @param grid Grid to upload. /// @return Handle of the grid. - virtual RendererGrid upload(const core::gl::Grid& grid) = 0; + virtual RendererGrid upload(const Grid& grid) = 0; /// @brief Sets the current palette of the renderer. /// @param palette Palette to set. - virtual void setPalette(const core::gl::Palette& palette) = 0; + virtual void setPalette(const Palette& palette) = 0; /// @brief Resizes the renderer's framebuffers. /// @param size New size of the window. diff --git a/core/include/cubos/core/gl/vertex.hpp b/engine/include/cubos/engine/renderer/vertex.hpp similarity index 65% rename from core/include/cubos/core/gl/vertex.hpp rename to engine/include/cubos/engine/renderer/vertex.hpp index da7964790..8b0c392b4 100644 --- a/core/include/cubos/core/gl/vertex.hpp +++ b/engine/include/cubos/engine/renderer/vertex.hpp @@ -1,6 +1,6 @@ /// @file -/// @brief Class @ref cubos::core::gl::Vertex and function @ref cubos::core::gl::triangulate. -/// @ingroup core-gl +/// @brief Class @ref cubos::engine::Vertex and function @ref cubos::engine::triangulate. +/// @ingroup renderer-plugin #pragma once @@ -9,12 +9,12 @@ #include #include -namespace cubos::core::gl +namespace cubos::engine { class Grid; /// @brief Represents a voxel vertex. - /// @ingroup core-gl + /// @ingroup renderer-plugin struct Vertex { glm::uvec3 position; ///< Position of the vertex. @@ -26,12 +26,12 @@ namespace cubos::core::gl /// @param grid Grid to triangulate. /// @param vertices Vertices of the mesh. /// @param indices Indices of the mesh. - /// @ingroup core-gl + /// @ingroup renderer-plugin void triangulate(const Grid& grid, std::vector& vertices, std::vector& indices); -} // namespace cubos::core::gl +} // namespace cubos::engine namespace cubos::core::data { - void serialize(Serializer& serializer, const gl::Vertex& vertex, const char* name); - void deserialize(Deserializer& deserializer, gl::Vertex& vertex); + void serialize(Serializer& serializer, const engine::Vertex& vertex, const char* name); + void deserialize(Deserializer& deserializer, engine::Vertex& vertex); } // namespace cubos::core::data diff --git a/core/include/cubos/core/gl/grid.hpp b/engine/include/cubos/engine/voxels/grid.hpp similarity index 82% rename from core/include/cubos/core/gl/grid.hpp rename to engine/include/cubos/engine/voxels/grid.hpp index 305d67be8..3c3d5953b 100644 --- a/core/include/cubos/core/gl/grid.hpp +++ b/engine/include/cubos/engine/voxels/grid.hpp @@ -1,6 +1,6 @@ /// @file -/// @brief Class @ref cubos::core::gl::Grid. -/// @ingroup core-gl +/// @brief Class @ref cubos::engine::Grid. +/// @ingroup voxels-plugin #pragma once @@ -11,23 +11,23 @@ #include #include -namespace cubos::core::gl +namespace cubos::engine { class Palette; class Grid; -} // namespace cubos::core::gl +} // namespace cubos::engine namespace cubos::core::data { - void serialize(Serializer& serializer, const gl::Grid& grid, const char* name); - void deserialize(Deserializer& deserializer, gl::Grid& grid); + void serialize(Serializer& serializer, const engine::Grid& grid, const char* name); + void deserialize(Deserializer& deserializer, engine::Grid& grid); } // namespace cubos::core::data -namespace cubos::core::gl +namespace cubos::engine { /// @brief Represents a voxel object using a 3D grid. /// @see Each voxel stores a material index to be used with a @ref Palette. - /// @ingroup core-gl + /// @ingroup voxels-plugin class Grid final { public: @@ -89,10 +89,11 @@ namespace cubos::core::gl bool convert(const Palette& src, const Palette& dst, float minSimilarity); private: - friend void data::serialize(data::Serializer& /*serializer*/, const Grid& /*grid*/, const char* /*name*/); - friend void data::deserialize(data::Deserializer& /*deserializer*/, Grid& /*grid*/); + friend void core::data::serialize(core::data::Serializer& /*serializer*/, const Grid& /*grid*/, + const char* /*name*/); + friend void core::data::deserialize(core::data::Deserializer& /*deserializer*/, Grid& /*grid*/); glm::uvec3 mSize; ///< Size of the grid. std::vector mIndices; ///< Indices of the grid. }; -} // namespace cubos::core::gl +} // namespace cubos::engine diff --git a/core/include/cubos/core/gl/material.hpp b/engine/include/cubos/engine/voxels/material.hpp similarity index 73% rename from core/include/cubos/core/gl/material.hpp rename to engine/include/cubos/engine/voxels/material.hpp index 6007625b7..37bb63572 100644 --- a/core/include/cubos/core/gl/material.hpp +++ b/engine/include/cubos/engine/voxels/material.hpp @@ -1,6 +1,6 @@ /// @file -/// @brief Class @ref cubos::core::gl::Material. -/// @ingroup core-gl +/// @brief Class @ref cubos::engine::Material. +/// @ingroup voxels-plugin #pragma once @@ -9,10 +9,10 @@ #include #include -namespace cubos::core::gl +namespace cubos::engine { /// @brief Describes a voxel material. - /// @ingroup core-gl + /// @ingroup voxels-plugin struct Material { static const Material Empty; ///< Empty material, used for voxels with index 0. @@ -29,10 +29,10 @@ namespace cubos::core::gl /// @return Similarity between the two materials. float similarity(const Material& other) const; }; -} // namespace cubos::core::gl +} // namespace cubos::engine namespace cubos::core::data { - void serialize(Serializer& serializer, const gl::Material& mat, const char* name); - void deserialize(Deserializer& deserializer, gl::Material& mat); + void serialize(Serializer& serializer, const engine::Material& mat, const char* name); + void deserialize(Deserializer& deserializer, engine::Material& mat); } // namespace cubos::core::data diff --git a/core/include/cubos/core/gl/palette.hpp b/engine/include/cubos/engine/voxels/palette.hpp similarity index 81% rename from core/include/cubos/core/gl/palette.hpp rename to engine/include/cubos/engine/voxels/palette.hpp index 8641e4404..f4ae4cfaa 100644 --- a/core/include/cubos/core/gl/palette.hpp +++ b/engine/include/cubos/engine/voxels/palette.hpp @@ -1,25 +1,25 @@ /// @file -/// @brief Class @ref cubos::core::gl::Palette. -/// @ingroup core-gl +/// @brief Class @ref cubos::engine::Palette. +/// @ingroup voxels-plugin #pragma once #include -#include +#include -namespace cubos::core::gl +namespace cubos::engine { class Palette; } namespace cubos::core::data { - void serialize(Serializer& serializer, const gl::Palette& palette, const char* name); - void deserialize(Deserializer& deserializer, gl::Palette& palette); + void serialize(Serializer& serializer, const engine::Palette& palette, const char* name); + void deserialize(Deserializer& deserializer, engine::Palette& palette); } // namespace cubos::core::data -namespace cubos::core::gl +namespace cubos::engine { /// @brief Holds a palette of materials. Supports up to 65535 materials. /// @@ -31,7 +31,7 @@ namespace cubos::core::gl /// of storing the whole material per each voxel, we just store a 16-bit /// integer. /// - /// @ingroup core-gl + /// @ingroup voxels-plugin class Palette final { public: @@ -84,9 +84,10 @@ namespace cubos::core::gl void merge(const Palette& palette, float similarity = 1.0F); private: - friend void data::serialize(data::Serializer& /*serializer*/, const Palette& /*palette*/, const char* /*name*/); - friend void data::deserialize(data::Deserializer& /*deserializer*/, Palette& /*palette*/); + friend void core::data::serialize(core::data::Serializer& /*serializer*/, const Palette& /*palette*/, + const char* /*name*/); + friend void core::data::deserialize(core::data::Deserializer& /*deserializer*/, Palette& /*palette*/); std::vector mMaterials; ///< Materials in the palette. }; -} // namespace cubos::core::gl +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/voxels/plugin.hpp b/engine/include/cubos/engine/voxels/plugin.hpp index 7d73a1d4d..bececd694 100644 --- a/engine/include/cubos/engine/voxels/plugin.hpp +++ b/engine/include/cubos/engine/voxels/plugin.hpp @@ -8,7 +8,6 @@ #pragma once #include -#include namespace cubos::engine { @@ -17,10 +16,8 @@ namespace cubos::engine /// @brief Adds grid and palette assets to @b CUBOS. /// /// ## Bridges - /// - @ref BinaryBridge - registered with the `.grd` extension, loads @ref - /// cubos::core::gl::Grid assets. - /// - @ref BinaryBridge - registered with the `.pal` extension, loads @ref - /// cubos::core::gl::Palette assets. + /// - @ref BinaryBridge - registered with the `.grd` extension, loads @ref Grid assets. + /// - @ref BinaryBridge - registered with the `.pal` extension, loads @ref Palette assets. /// /// ## Dependencies /// - @ref assets-plugin diff --git a/engine/samples/renderer/main.cpp b/engine/samples/renderer/main.cpp index 6c516e7c0..1aea8fe67 100644 --- a/engine/samples/renderer/main.cpp +++ b/engine/samples/renderer/main.cpp @@ -20,8 +20,6 @@ static void settingsSystem(Write settings) /// [Setting the palette] static void setPaletteSystem(Write renderer) { - using cubos::core::gl::Palette; - // Create a simple palette with 3 materials (red, green and blue). (*renderer)->setPalette(Palette{{ {{1, 0, 0, 1}}, @@ -34,8 +32,6 @@ static void setPaletteSystem(Write renderer) /// [Spawning a voxel grid] static void spawnVoxelGridSystem(Commands commands, Write assets) { - using cubos::core::gl::Grid; - // Create a 2x2x2 grid whose voxels alternate between the materials defined in the palette. auto gridAsset = assets->create(Grid{{2, 2, 2}, {1, 2, 3, 1, 2, 3, 1, 2}}); diff --git a/engine/samples/renderer/page.md b/engine/samples/renderer/page.md index d2e49c37b..4055e2d05 100644 --- a/engine/samples/renderer/page.md +++ b/engine/samples/renderer/page.md @@ -13,13 +13,13 @@ You may need to include other headers, depending on what you want to access. @snippet renderer/main.cpp Adding the plugin The first thing we're going to worry about is setting the -@ref cubos::core::gl::Palette "Palette" the renderer will use. This palette +@ref cubos::engine::Palette "Palette" the renderer will use. This palette would usually be loaded from a file, but for this example we'll just create it manually. @snippet renderer/main.cpp Setting the palette -We should also spawn a @ref cubos::core::gl::Grid "voxel grid", so we have +We should also spawn a @ref cubos::engine::Grid "voxel grid", so we have something to render. @snippet renderer/main.cpp Spawning a voxel grid diff --git a/engine/samples/voxels/main.cpp b/engine/samples/voxels/main.cpp index a8d629d4d..627c6f8a8 100644 --- a/engine/samples/voxels/main.cpp +++ b/engine/samples/voxels/main.cpp @@ -7,8 +7,7 @@ using cubos::core::ecs::Commands; using cubos::core::ecs::Read; using cubos::core::ecs::Write; -using cubos::core::gl::Grid; -using cubos::core::gl::Palette; + using namespace cubos::engine; /// [Get handles to assets] diff --git a/engine/src/cubos/engine/renderer/deferred_renderer.cpp b/engine/src/cubos/engine/renderer/deferred_renderer.cpp index 9c67880d0..dd650d93b 100644 --- a/engine/src/cubos/engine/renderer/deferred_renderer.cpp +++ b/engine/src/cubos/engine/renderer/deferred_renderer.cpp @@ -7,11 +7,11 @@ #include #include -#include #include #include #include +#include using namespace cubos::core::gl; using cubos::engine::DeferredRenderer; @@ -547,7 +547,7 @@ cubos::engine::RendererGrid DeferredRenderer::upload(const Grid& grid) return deferredGrid; } -void DeferredRenderer::setPalette(const core::gl::Palette& palette) +void DeferredRenderer::setPalette(const Palette& palette) { // Get the colors from the palette. // Magenta is used for non-existent materials in order to easily identify errors. diff --git a/core/src/cubos/core/gl/vertex.cpp b/engine/src/cubos/engine/renderer/vertex.cpp similarity index 95% rename from core/src/cubos/core/gl/vertex.cpp rename to engine/src/cubos/engine/renderer/vertex.cpp index 8de642a43..1bb0b4d44 100644 --- a/core/src/cubos/core/gl/vertex.cpp +++ b/engine/src/cubos/engine/renderer/vertex.cpp @@ -1,12 +1,11 @@ #include -#include -#include +#include +#include -using namespace cubos; -using namespace cubos::core::gl; +using namespace cubos::engine; -void cubos::core::data::serialize(Serializer& serializer, const gl::Vertex& vertex, const char* name) +void cubos::core::data::serialize(Serializer& serializer, const Vertex& vertex, const char* name) { serializer.beginObject(name); serializer.write(vertex.position, "position"); @@ -15,7 +14,7 @@ void cubos::core::data::serialize(Serializer& serializer, const gl::Vertex& vert serializer.endObject(); } -void cubos::core::data::deserialize(Deserializer& deserializer, gl::Vertex& vertex) +void cubos::core::data::deserialize(Deserializer& deserializer, Vertex& vertex) { deserializer.beginObject(); deserializer.read(vertex.position); @@ -24,7 +23,7 @@ void cubos::core::data::deserialize(Deserializer& deserializer, gl::Vertex& vert deserializer.endObject(); } -void cubos::core::gl::triangulate(const Grid& grid, std::vector& vertices, std::vector& indices) +void cubos::engine::triangulate(const Grid& grid, std::vector& vertices, std::vector& indices) { std::vector mask; diff --git a/core/src/cubos/core/gl/grid.cpp b/engine/src/cubos/engine/voxels/grid.cpp similarity index 96% rename from core/src/cubos/core/gl/grid.cpp rename to engine/src/cubos/engine/voxels/grid.cpp index b622edca7..dd81bac06 100644 --- a/core/src/cubos/core/gl/grid.cpp +++ b/engine/src/cubos/engine/voxels/grid.cpp @@ -1,10 +1,11 @@ #include -#include -#include #include -using namespace cubos::core::gl; +#include +#include + +using namespace cubos::engine; Grid::Grid(const glm::uvec3& size) { @@ -142,7 +143,7 @@ bool Grid::convert(const Palette& src, const Palette& dst, float minSimilarity) return true; } -void cubos::core::data::serialize(Serializer& serializer, const gl::Grid& grid, const char* name) +void cubos::core::data::serialize(Serializer& serializer, const Grid& grid, const char* name) { serializer.beginObject(name); serializer.write(grid.mSize, "size"); @@ -150,7 +151,7 @@ void cubos::core::data::serialize(Serializer& serializer, const gl::Grid& grid, serializer.endObject(); } -void cubos::core::data::deserialize(Deserializer& deserializer, gl::Grid& grid) +void cubos::core::data::deserialize(Deserializer& deserializer, Grid& grid) { deserializer.beginObject(); deserializer.read(grid.mSize); diff --git a/core/src/cubos/core/gl/material.cpp b/engine/src/cubos/engine/voxels/material.cpp similarity index 93% rename from core/src/cubos/core/gl/material.cpp rename to engine/src/cubos/engine/voxels/material.cpp index a6d744e2a..a3a00945e 100644 --- a/core/src/cubos/core/gl/material.cpp +++ b/engine/src/cubos/engine/voxels/material.cpp @@ -1,6 +1,6 @@ -#include +#include -using namespace cubos::core::gl; +using namespace cubos::engine; const Material Material::Empty = {{0, 0, 0, 0}}; diff --git a/core/src/cubos/core/gl/palette.cpp b/engine/src/cubos/engine/voxels/palette.cpp similarity index 96% rename from core/src/cubos/core/gl/palette.cpp rename to engine/src/cubos/engine/voxels/palette.cpp index 71ba0cfac..d4d1f9309 100644 --- a/core/src/cubos/core/gl/palette.cpp +++ b/engine/src/cubos/engine/voxels/palette.cpp @@ -1,9 +1,10 @@ #include -#include #include -using namespace cubos::core::gl; +#include + +using namespace cubos::engine; Palette::Palette(std::vector&& materials) : mMaterials(std::move(materials)) @@ -97,7 +98,7 @@ void Palette::merge(const Palette& palette, float similarity) } } -void cubos::core::data::serialize(Serializer& serializer, const gl::Palette& palette, const char* name) +void cubos::core::data::serialize(Serializer& serializer, const Palette& palette, const char* name) { // Count non-empty materials. std::size_t count = 0; @@ -121,7 +122,7 @@ void cubos::core::data::serialize(Serializer& serializer, const gl::Palette& pal serializer.endDictionary(); } -void cubos::core::data::deserialize(Deserializer& deserializer, gl::Palette& palette) +void cubos::core::data::deserialize(Deserializer& deserializer, Palette& palette) { palette.mMaterials.clear(); diff --git a/engine/src/cubos/engine/voxels/plugin.cpp b/engine/src/cubos/engine/voxels/plugin.cpp index 24872ae8c..a5346ec14 100644 --- a/engine/src/cubos/engine/voxels/plugin.cpp +++ b/engine/src/cubos/engine/voxels/plugin.cpp @@ -1,13 +1,10 @@ -#include -#include - #include #include +#include +#include #include using cubos::core::ecs::Write; -using cubos::core::gl::Grid; -using cubos::core::gl::Palette; using namespace cubos::engine; static void bridges(Write assets) diff --git a/tools/quadrados/src/convert.cpp b/tools/quadrados/src/convert.cpp index a3f4ad4ca..a5719792f 100644 --- a/tools/quadrados/src/convert.cpp +++ b/tools/quadrados/src/convert.cpp @@ -5,13 +5,18 @@ #include #include -#include -#include +#include +#include #include +#include +#include + #include "tools.hpp" -using namespace cubos::core; +namespace data = cubos::core::data; +namespace memory = cubos::core::memory; +using namespace cubos::engine; namespace fs = std::filesystem; @@ -28,6 +33,14 @@ struct ConvertOptions float similarity = 1.0F; ///< The similarity threshold. }; +/// @brief Represents the data read from a matrix in a QB file. +struct QBMatrix +{ + Grid grid; ///< Grid of the matrix. + Palette palette; ///< Palette of the matrix. + glm::ivec3 position; ///< Position of the matrix. +}; + /// Prints the help message of the program. static void printHelp() { @@ -154,10 +167,160 @@ static bool parseArguments(int argc, char** argv, ConvertOptions& options) return true; } +/// @brief Parses a Qubicle file (.qb), pushing every matrix found in the file to the passed vector. +/// @param[out] matrices Parsed matrices. +/// @param stream Stream to read from. +/// @return Whether the file was parsed successfully. +bool parseQB(std::vector& matrices, memory::Stream& stream) +{ + uint8_t version[4] = {0, 0, 0, 0}; + uint32_t colorFormat; + uint32_t zAxisOrientation; + uint32_t compressed; + uint32_t visibilityMaskEncoded; + uint32_t numMatrices; + + // Parse the version of the file. + stream.read(version, 4); + if (stream.eof()) + { + CUBOS_ERROR("Unexpected end of file while reading file version"); + return false; + } + if (version[0] != 1 || version[1] != 1 || version[2] != 0 || version[3] != 0) + { + CUBOS_ERROR("Unsupported version {}.{}.{}.{}, only 1.1.0.0 is supported", version[0], version[1], version[2], + version[3]); + return false; + } + + // Parse the rest of the header. + stream.read(&colorFormat, 4); + stream.read(&zAxisOrientation, 4); + stream.read(&compressed, 4); + stream.read(&visibilityMaskEncoded, 4); + stream.read(&numMatrices, 4); + colorFormat = memory::fromLittleEndian(colorFormat); + zAxisOrientation = memory::fromLittleEndian(zAxisOrientation); + compressed = memory::fromLittleEndian(compressed); + visibilityMaskEncoded = memory::fromLittleEndian(visibilityMaskEncoded); + numMatrices = memory::fromLittleEndian(numMatrices); + + if (stream.eof()) + { + CUBOS_ERROR("Unexpected end of file while reading file header"); + return false; + } + if (visibilityMaskEncoded != 0U) + { + CUBOS_ERROR("Visibility mask encoding is not supported"); + return false; + } + + // Parse the matrices. + matrices.resize(numMatrices); + for (uint32_t i = 0; i < numMatrices; ++i) + { + uint8_t nameLen; + uint32_t sizeX; + uint32_t sizeY; + uint32_t sizeZ; + int32_t posX; + int32_t posY; + int32_t posZ; + + // Read the matrix name. + stream.read(&nameLen, 1); + std::string name(nameLen, ' '); + stream.read(name.data(), nameLen); + + // Read the matrix size. + stream.read(&sizeX, 4); + stream.read(&sizeY, 4); + stream.read(&sizeZ, 4); + sizeX = memory::fromLittleEndian(sizeX); + sizeY = memory::fromLittleEndian(sizeY); + sizeZ = memory::fromLittleEndian(sizeZ); + matrices[i].grid.setSize({sizeX, sizeY, sizeZ}); + + // Read the matrix position. + stream.read(&posX, 4); + stream.read(&posY, 4); + stream.read(&posZ, 4); + posX = memory::fromLittleEndian(posX); + posY = memory::fromLittleEndian(posY); + posZ = memory::fromLittleEndian(posZ); + matrices[i].position = glm::ivec3(posX, posY, posZ); + + // Read the matrix voxels. + if (compressed == 0) + { + uint8_t color[4]; + std::size_t nextMat = 1; + + for (uint32_t z = 0; z < sizeZ; ++z) + { + for (uint32_t y = 0; y < sizeY; ++y) + { + for (uint32_t x = 0; x < sizeX; ++x) + { + stream.read(color, 4); + if (color[3] == 0) + { + continue; + } + if (colorFormat != 0U) + { // BGRA -> RGBA + std::swap(color[0], color[2]); + } + glm::vec4 colorVec(static_cast(color[0]) / 255.0F, static_cast(color[1]) / 255.0F, + static_cast(color[2]) / 255.0F, + static_cast(color[3]) / 255.0F); + + // Check if the material is already in the palette. + std::size_t mat; + for (mat = 1; mat < nextMat; ++mat) + { + if (matrices[i].palette.get(static_cast(mat)).color == colorVec) + { + break; + } + } + if (mat == nextMat) + { + if (mat >= 65536) + { + CUBOS_ERROR("Too many materials, max is 65536"); + return false; + } + + // Add the material to the palette. + Material desc; + desc.color = colorVec; + matrices[i].palette.set(static_cast(mat), desc); + nextMat += 1; + } + + // Set the voxel. + matrices[i].grid.set(glm::ivec3(x, y, z), static_cast(mat)); + } + } + } + } + else + { + CUBOS_ERROR("Compressed QB files are not supported"); + return false; + } + } + + return true; +} + /// Tries to load the palette from the given path. /// @param path The path of the palette. /// @param palette The palette to fill. -static bool loadPalette(const fs::path& path, gl::Palette& palette) +static bool loadPalette(const fs::path& path, Palette& palette) { auto* file = fopen(path.string().c_str(), "rb"); if (file == nullptr) @@ -180,7 +343,7 @@ static bool loadPalette(const fs::path& path, gl::Palette& palette) /// Tries to load a QBModel from the given path. /// @param path The path of the QBModel. /// @param model The model to fill. -static bool loadQB(const fs::path& path, std::vector& model) +static bool loadQB(const fs::path& path, std::vector& model) { auto* file = fopen(path.string().c_str(), "rb"); if (file == nullptr) @@ -189,13 +352,13 @@ static bool loadQB(const fs::path& path, std::vector& model) } auto stream = memory::StandardStream(file, true); - return data::parseQB(model, stream); + return parseQB(model, stream); } /// Saves the given palette to the given path. /// @param path The path of the palette. /// @param palette The palette to save. -static bool savePalette(const fs::path& path, const gl::Palette& palette) +static bool savePalette(const fs::path& path, const Palette& palette) { auto* file = fopen(path.string().c_str(), "wb"); if (file == nullptr) @@ -218,7 +381,7 @@ static bool savePalette(const fs::path& path, const gl::Palette& palette) /// Saves the given grid to the given path. /// @param path The path of the grid. /// @param grid The grid to export. -static bool saveGrid(const fs::path& path, const gl::Grid& grid) +static bool saveGrid(const fs::path& path, const Grid& grid) { auto* file = fopen(path.string().c_str(), "wb"); if (file == nullptr) @@ -244,7 +407,7 @@ static bool saveGrid(const fs::path& path, const gl::Grid& grid) static bool convert(const ConvertOptions& options) { // First, load the palette. - gl::Palette palette; + Palette palette; if (!options.palette.empty()) { if (!loadPalette(options.palette, palette)) @@ -268,7 +431,7 @@ static bool convert(const ConvertOptions& options) std::cerr << "Failed to load model: unsupported format " << options.input.extension() << "." << std::endl; } - std::vector model; + std::vector model; if (!loadQB(options.input, model)) { std::cerr << "Failed to load model: " << options.input << " not found." << std::endl;