feat: add vec3 type to nhollman json / fix: scene serialisation stuff

This commit is contained in:
2026-10-18 15:20:01 +02:00
parent 7223e9ce07
commit 94fa2bb4b2
18 changed files with 670 additions and 289 deletions
@@ -1,7 +1,9 @@
#include <destrum/Graphics/Resources/PrimitiveMeshes.h>
#include <array>
#include <charconv>
#include <cstdint>
#include <format>
CPUMesh PrimitiveMeshes::MakeBox(const glm::vec3& size)
{
@@ -22,7 +24,8 @@ CPUMesh PrimitiveMeshes::MakeBox(const glm::vec3& size)
}};
CPUMesh mesh{};
mesh.name = "Box";
// The name becomes the mesh cache key, saved scenes rebuild the box from it
mesh.name = BoxKey(size);
mesh.minPos = -size * 0.5f;
mesh.maxPos = size * 0.5f;
@@ -50,3 +53,65 @@ CPUMesh PrimitiveMeshes::MakeBox(const glm::vec3& size)
return mesh;
}
namespace {
constexpr std::string_view PrimitiveScheme = "prim://";
constexpr std::string_view BoxPrefix = "prim://box?size=";
}
std::string PrimitiveMeshes::BoxKey(const glm::vec3& size)
{
return std::format("{}{},{},{}", BoxPrefix, size.x, size.y, size.z);
}
bool PrimitiveMeshes::IsPrimitiveKey(std::string_view key)
{
return key.starts_with(PrimitiveScheme);
}
std::string_view PrimitiveMeshes::StripDuplicateSuffix(std::string_view key)
{
// MeshCache appends "#N" when the same key is added more than once
const auto separator = key.rfind('#');
if (separator == std::string_view::npos || separator + 1 >= key.size()) {
return key;
}
for (const char c : key.substr(separator + 1)) {
if (c < '0' || c > '9') {
return key;
}
}
return key.substr(0, separator);
}
std::optional<CPUMesh> PrimitiveMeshes::MakeFromKey(std::string_view key)
{
key = StripDuplicateSuffix(key);
if (!key.starts_with(BoxPrefix)) {
return std::nullopt;
}
std::string_view rest = key.substr(BoxPrefix.size());
glm::vec3 size{0.0f};
for (int i = 0; i < 3; ++i) {
const char* end = rest.data() + rest.size();
float value = 0.0f;
const auto [next, error] = std::from_chars(rest.data(), end, value);
if (error != std::errc{} || !(value > 0.0f)) {
return std::nullopt;
}
size[i] = value;
rest.remove_prefix(static_cast<std::size_t>(next - rest.data()));
if (i < 2) {
if (!rest.starts_with(',')) {
return std::nullopt;
}
rest.remove_prefix(1);
}
}
if (!rest.empty()) {
return std::nullopt;
}
return MakeBox(size);
}