Skip to content

Commit

Permalink
fix(voxels): resolve conversations
Browse files Browse the repository at this point in the history
  • Loading branch information
Dacops committed Mar 20, 2024
1 parent e0fd3b5 commit eb5422c
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Return direct references to resources instead of guards on World (#922, **@RiscadoA**).
- Stop using old serialization to load Settings (#1100, **@RiscadoA**).

### Changed

- Palette & Grid saving/loading now use streams instead of serialization (#572, **@Dacops**).

### Fixed

- Crash in multiple samples due to missing plugin dependencies (**@RiscadoA**).
Expand Down
21 changes: 20 additions & 1 deletion engine/include/cubos/engine/voxels/grid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/assets/bridges/file.hpp>
namespace cubos::core::memory
{
class Stream;
} // namespace cubos::core::memory

namespace cubos::engine
{
Expand Down Expand Up @@ -85,7 +88,23 @@ namespace cubos::engine
/// @return Whether the conversion was successful.
bool convert(const VoxelPalette& src, const VoxelPalette& dst, float minSimilarity);

/// @brief Loads the grid's data from the given stream.
///
/// Assumes the data is stored in big-endian (network byte order).
/// The first bytes correspond to three uint32_t, which represent the size of the grid (x, y, z).
/// The next bytes correspond to `size.x * size.y * size.z` uint16_t, which represent the actual voxel
/// materials. The voxel data is indexed by `x + y * size.x + z * size.x * size.y`.
///
/// @param stream Stream to read from.
/// @return Whether the stream contained valid data.
bool loadFrom(core::memory::Stream& stream);

/// @brief Writes the grid's data to the given stream.
///
/// Writes in the format specified in @ref loadFrom.
///
/// @param stream Stream to write to.
/// @return Whether the write was successful.
bool writeTo(core::memory::Stream& stream) const;

private:
Expand Down
9 changes: 4 additions & 5 deletions engine/include/cubos/engine/voxels/grid_bridge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ namespace cubos::engine
{
/// @brief Bridge which loads and saves @ref Grid assets.
///
/// Grids are composed by their size and their indices.
/// They're stored as an array of unsigned integers (first 3 equal the grid size, the remainder the grid indexes)
/// Uses the format specified in @ref VoxelGrid::loadFrom and @ref VoxelGrid::writeTo
///
/// @ingroup scene-plugin
class GridBridge : public FileBridge
/// @ingroup voxels-plugin
class VoxelGridBridge : public FileBridge
{
public:
/// @brief Constructs a bridge.
GridBridge();
VoxelGridBridge();

protected:
bool loadFromFile(Assets& assets, const AnyAsset& handle, core::memory::Stream& stream) override;
Expand Down
16 changes: 16 additions & 0 deletions engine/include/cubos/engine/voxels/palette.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,23 @@ namespace cubos::engine
/// @return Iterator.
Iterator end();

/// @brief Loads the palette's data from the given stream.
///
/// Assumes the data is stored in big-endian (network byte order).
/// The first bytes correspond to an uint16_t, which represents the number of materials in the palette.
/// The next bytes correspond to `numMaterials * 4` floats (each material is represented by 4 floats (r, g, b,
/// a)), which represents the actual palette data.
///
/// @param stream Stream to read from.
/// @return Whether the stream contained valid data.
bool loadFrom(core::memory::Stream& stream);

/// @brief Writes the palette's data to the given stream.
///
/// Writes in the format specified in @ref loadFrom.
///
/// @param stream Stream to write to.
/// @return Whether the write was successful.
bool writeTo(core::memory::Stream& stream) const;

private:
Expand Down
7 changes: 3 additions & 4 deletions engine/include/cubos/engine/voxels/palette_bridge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ namespace cubos::engine
{
/// @brief Bridge which loads and saves @ref Palette assets.
///
/// Palettes are composed by n materials.
/// They're stored as an array of floats (each 4 floats equal a material).
/// Uses the format specified in @ref VoxelPalette::loadFrom and @ref VoxelPalette::writeTo
///
/// @ingroup scene-plugin
class PaletteBridge : public FileBridge
class VoxelPaletteBridge : public FileBridge
{
public:
/// @brief Constructs a bridge.
PaletteBridge();
VoxelPaletteBridge();

protected:
bool loadFromFile(Assets& assets, const AnyAsset& handle, core::memory::Stream& stream) override;
Expand Down
Binary file modified engine/samples/voxels/assets/main.pal
Binary file not shown.
55 changes: 45 additions & 10 deletions engine/src/voxels/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,19 +159,38 @@ bool VoxelGrid::convert(const VoxelPalette& src, const VoxelPalette& dst, float

bool VoxelGrid::loadFrom(Stream& stream)
{
uint32_t x, y, z;
stream.read(&x, sizeof(uint32_t));
stream.read(&y, sizeof(uint32_t));
stream.read(&z, sizeof(uint32_t));
uint32_t x;
uint32_t y;
uint32_t z;
if (stream.read(&x, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to load voxel grid, unexpected end of file");
return false;
}
if (stream.read(&y, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to load voxel grid, unexpected end of file");
return false;
}
if (stream.read(&z, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to load voxel grid, unexpected end of file");
return false;
}
x = fromBigEndian(x);
y = fromBigEndian(y);
z = fromBigEndian(z);
mSize = glm::uvec3(x, y, z);

while (!stream.eof())
mIndices.clear();
for (uint32_t i = 0; i < x * y * z; i++)
{
uint16_t idx;
stream.read(&idx, sizeof(uint16_t));
if (stream.read(&idx, sizeof(uint16_t)) != sizeof(uint16_t))
{
CUBOS_ERROR("Failed to load voxel grid, unexpected end of file");
return false;
}
idx = fromBigEndian(idx);
mIndices.push_back(idx);
}
Expand All @@ -183,14 +202,30 @@ bool VoxelGrid::writeTo(Stream& stream) const
uint32_t x = toBigEndian(mSize.x);
uint32_t y = toBigEndian(mSize.y);
uint32_t z = toBigEndian(mSize.z);
stream.write(&x, sizeof(uint32_t));
stream.write(&y, sizeof(uint32_t));
stream.write(&z, sizeof(uint32_t));
if (stream.write(&x, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to save voxel grid, couldn't write it to stream");
return false;
}
if (stream.write(&y, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to save voxel grid, couldn't write it to stream");
return false;
}
if (stream.write(&z, sizeof(uint32_t)) != sizeof(uint32_t))
{
CUBOS_ERROR("Failed to save voxel grid, couldn't write it to stream");
return false;
}

for (const auto& indice : mIndices)
{
uint16_t idx = toBigEndian(indice);
stream.write(&idx, sizeof(uint16_t));
if (stream.write(&idx, sizeof(uint16_t)) != sizeof(uint16_t))
{
CUBOS_ERROR("Failed to save voxel grid, couldn't write it to stream");
return false;
}
}
return true;
}
6 changes: 3 additions & 3 deletions engine/src/voxels/grid_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ using cubos::engine::VoxelGrid;

using namespace cubos::engine;

GridBridge::GridBridge()
VoxelGridBridge::VoxelGridBridge()
: FileBridge(core::reflection::reflect<VoxelGrid>())
{
}

bool GridBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream& stream)
bool VoxelGridBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream& stream)
{
VoxelGrid grid{};
if (grid.loadFrom(stream))
Expand All @@ -22,7 +22,7 @@ bool GridBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream& st
return false;
}

bool GridBridge::saveToFile(const Assets& assets, const AnyAsset& handle, Stream& stream)
bool VoxelGridBridge::saveToFile(const Assets& assets, const AnyAsset& handle, Stream& stream)
{
auto grid = assets.read<VoxelGrid>(handle);
return grid->writeTo(stream);
Expand Down
72 changes: 62 additions & 10 deletions engine/src/voxels/palette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,41 @@ VoxelPalette::Iterator VoxelPalette::end()

bool VoxelPalette::loadFrom(Stream& stream)
{
while (!stream.eof())
uint16_t numMaterials;
if (stream.read(&numMaterials, sizeof(uint16_t)) != sizeof(uint16_t))
{
float r, g, b, a;
stream.read(&r, sizeof(float));
stream.read(&g, sizeof(float));
stream.read(&b, sizeof(float));
stream.read(&a, sizeof(float));
CUBOS_ERROR("Failed to load palette, unexpected end of file");
return false;
}
numMaterials = fromBigEndian(numMaterials);

mMaterials.clear();
for (uint16_t i = 0; i < numMaterials; i++)
{
float r;
float g;
float b;
float a;
if (stream.read(&r, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to load palette, unexpected end of file");
return false;
}
if (stream.read(&g, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to load palette, unexpected end of file");
return false;
}
if (stream.read(&b, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to load palette, unexpected end of file");
return false;
}
if (stream.read(&a, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to load palette, unexpected end of file");
return false;
}
r = fromBigEndian(r);
g = fromBigEndian(g);
b = fromBigEndian(b);
Expand All @@ -176,16 +204,40 @@ bool VoxelPalette::loadFrom(Stream& stream)

bool VoxelPalette::writeTo(Stream& stream) const
{
auto numMaterials = static_cast<uint16_t>(mMaterials.size());
numMaterials = toBigEndian(numMaterials);
if (stream.write(&numMaterials, sizeof(uint16_t)) != sizeof(uint16_t))
{
CUBOS_ERROR("Failed to save palette, couldn't write it to stream");
return false;
}

for (const auto& material : mMaterials)
{
float r = toBigEndian(material.color.r);
float g = toBigEndian(material.color.g);
float b = toBigEndian(material.color.b);
float a = toBigEndian(material.color.a);
stream.write(&r, sizeof(float));
stream.write(&g, sizeof(float));
stream.write(&b, sizeof(float));
stream.write(&a, sizeof(float));
if (stream.write(&r, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to save palette, couldn't write it to stream");
return false;
}
if (stream.write(&g, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to save palette, couldn't write it to stream");
return false;
}
if (stream.write(&b, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to save palette, couldn't write it to stream");
return false;
}
if (stream.write(&a, sizeof(float)) != sizeof(float))
{
CUBOS_ERROR("Failed to save palette, couldn't write it to stream");
return false;
}
}
return true;
}
6 changes: 3 additions & 3 deletions engine/src/voxels/palette_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ using cubos::engine::VoxelPalette;

using namespace cubos::engine;

PaletteBridge::PaletteBridge()
VoxelPaletteBridge::VoxelPaletteBridge()
: FileBridge(core::reflection::reflect<VoxelPalette>())
{
}

bool PaletteBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream& stream)
bool VoxelPaletteBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream& stream)
{
VoxelPalette palette{};
if (palette.loadFrom(stream))
Expand All @@ -22,7 +22,7 @@ bool PaletteBridge::loadFromFile(Assets& assets, const AnyAsset& handle, Stream&
return false;
}

bool PaletteBridge::saveToFile(const Assets& assets, const AnyAsset& handle, Stream& stream)
bool VoxelPaletteBridge::saveToFile(const Assets& assets, const AnyAsset& handle, Stream& stream)
{
auto palette = assets.read<VoxelPalette>(handle);
return palette->writeTo(stream);
Expand Down
4 changes: 2 additions & 2 deletions engine/src/voxels/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void cubos::engine::voxelsPlugin(Cubos& cubos)
.tagged(assetsBridgeTag)
.call([](Assets& assets) {
// Add the bridges to load .grd and .pal files.
assets.registerBridge(".grd", std::make_unique<GridBridge>());
assets.registerBridge(".pal", std::make_unique<PaletteBridge>());
assets.registerBridge(".grd", std::make_unique<VoxelGridBridge>());
assets.registerBridge(".pal", std::make_unique<VoxelPaletteBridge>());
});
}

0 comments on commit eb5422c

Please sign in to comment.