From 6760d16052b42354518785b3d40ff8247fc713f0 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 15 Jan 2026 22:57:04 +0300 Subject: [PATCH] update vcm::parse semantics --- src/assets/assetload_funcs.cpp | 4 +- src/coders/vcm.cpp | 82 +++++++++++----------- src/coders/vcm.hpp | 13 ++-- src/logic/scripting/lua/libs/libassets.cpp | 7 +- 4 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index a1c04dfcc..1bf76e6af 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -381,8 +381,8 @@ assetload::postfunc assetload::model( auto text = io::read_string(path); try { - auto model = vcm::parse(path.string(), text, path.extension() == ".xml") - .release(); + auto vcmModel = vcm::parse(path.string(), text, path.extension() == ".xml"); + auto model = std::make_unique(std::move(vcmModel.squash())).release(); return [=](Assets* assets) { request_textures(loader, *model); assets->store(std::unique_ptr(model), name); diff --git a/src/coders/vcm.cpp b/src/coders/vcm.cpp index 4acf8b631..8a0119e59 100644 --- a/src/coders/vcm.cpp +++ b/src/coders/vcm.cpp @@ -2,7 +2,6 @@ #include "xml.hpp" #include "util/stringutil.hpp" -#include "objects/rigging.hpp" #include "io/io.hpp" #include @@ -16,6 +15,45 @@ using namespace xml; using namespace model; using namespace rigging; +static int calc_offsets( + const Bone& bone, std::vector& dst, int index, int depth, int parent +) { + if (depth == 0) { + dst[0] = bone.getOffset(); + } else { + dst[index] = dst[parent] + bone.getOffset(); + } + const auto& subBones = bone.getSubnodes(); + + int subIndex = index + 1; + for (int i = 0; i < subBones.size(); i++) { + subIndex += calc_offsets(*subBones[i], dst, subIndex, depth + 1, index); + } + return subIndex - index; +} + +model::Model& VcmModel::squash() { + std::vector fullOffsets(skeleton->getBones().size()); + calc_offsets(*skeleton->getRoot(), fullOffsets, 0, 0, 0); + + Model squashed; + for (auto& [name, model] : parts) { + if (auto bone = skeleton->find(name)) { + model.translate(fullOffsets[bone->getIndex()]); + } else { + throw std::runtime_error("invalid state: bones/parts mismatch"); + } + squashed.merge(std::move(model)); + } + parts = { {"", std::move(squashed)} }; + skeleton.reset(); + return parts.at(""); +} + +model::Model VcmModel::squashed() const { + return std::move(VcmModel {parts, std::nullopt}).squash(); +} + static const std::unordered_map side_indices { {"north", 0}, {"south", 1}, @@ -376,13 +414,13 @@ static VcmModel load_model(const xmlelement& root) { } vcmModel.parts["root"] = std::move(model); - vcmModel.skeleton = std::make_unique( + vcmModel.skeleton = SkeletonConfig( "", std::make_unique(std::move(rootBone)), boneIndex ); return vcmModel; } -VcmModel vcm::parseFull( +VcmModel vcm::parse( std::string_view file, std::string_view src, bool usexml ) { try { @@ -399,41 +437,3 @@ VcmModel vcm::parseFull( throw std::runtime_error(err.errorLog()); } } - -static int calc_offsets( - const Bone& bone, std::vector& dst, int index, int depth, int parent -) { - if (depth == 0) { - dst[0] = bone.getOffset(); - } else { - dst[index] = dst[parent] + bone.getOffset(); - } - const auto& subBones = bone.getSubnodes(); - - int subIndex = index + 1; - for (int i = 0; i < subBones.size(); i++) { - subIndex += calc_offsets(*subBones[i], dst, subIndex, depth + 1, index); - } - return subIndex - index; -} - -std::unique_ptr vcm::parse( - std::string_view file, std::string_view src, bool usexml -) { - auto vcmModel = parseFull(file, src, usexml); - - std::vector fullOffsets(vcmModel.skeleton->getBones().size()); - calc_offsets(*vcmModel.skeleton->getRoot(), fullOffsets, 0, 0, 0); - - Model fullModel; - for (auto& [name, model] : vcmModel.parts) { - if (auto bone = vcmModel.skeleton->find(name)) { - model.translate(fullOffsets[bone->getIndex()]); - } else { - throw std::runtime_error("invalid state: bones/parts mismatch"); - } - fullModel.merge(std::move(model)); - } - - return std::make_unique(std::move(fullModel)); -} diff --git a/src/coders/vcm.hpp b/src/coders/vcm.hpp index 1487ca847..4f97ea8d3 100644 --- a/src/coders/vcm.hpp +++ b/src/coders/vcm.hpp @@ -2,9 +2,11 @@ #include #include +#include #include #include "graphics/commons/Model.hpp" +#include "objects/rigging.hpp" namespace rigging { class SkeletonConfig; @@ -13,14 +15,13 @@ namespace rigging { namespace vcm { struct VcmModel { std::unordered_map parts; - std::unique_ptr skeleton; + std::optional skeleton; + + model::Model& squash(); + model::Model squashed() const; }; - VcmModel parseFull( - std::string_view file, std::string_view src, bool usexml - ); - - std::unique_ptr parse( + VcmModel parse( std::string_view file, std::string_view src, bool usexml ); } diff --git a/src/logic/scripting/lua/libs/libassets.cpp b/src/logic/scripting/lua/libs/libassets.cpp index 35720195e..6a16c3cfd 100644 --- a/src/logic/scripting/lua/libs/libassets.cpp +++ b/src/logic/scripting/lua/libs/libassets.cpp @@ -57,11 +57,14 @@ static int l_parse_model(lua::State* L) { auto name = lua::require_string(L, 3); if (format == "xml" || format == "vcm") { + auto vcmModel = vcm::parse(name, string, format == "xml"); engine->getAssets()->store( - vcm::parse(name, string, format == "xml"), name + std::make_unique(std::move(vcmModel.squash())), name ); } else { - throw std::runtime_error("unknown format " + util::quote(std::string(format))); + throw std::runtime_error( + "unknown format " + util::quote(std::string(format)) + ); } return 0; }