#include "rigging.hpp" #include "../assets/Assets.hpp" #include "../graphics/render/ModelBatch.hpp" #include "../graphics/core/Model.hpp" #include "../coders/json.hpp" using namespace rigging; RigNode::RigNode( size_t index, std::string name, std::string model, std::vector> subnodes) : index(index), name(std::move(name)), modelName(std::move(model)), subnodes(std::move(subnodes)) {} void RigNode::setModel(const std::string& name) { if (modelName == name) { return; } modelName = name; modelUpdated = true; } void RigNode::refreshModel(const Assets* assets) { if (modelUpdated) { model = assets->get(modelName); modelUpdated = false; } } static void get_all_nodes(std::vector& nodes, RigNode* node) { nodes[node->getIndex()] = node; for (auto& subnode : node->getSubnodes()) { get_all_nodes(nodes, subnode.get()); } } RigConfig::RigConfig(const std::string& name, std::unique_ptr root, size_t nodesCount) : name(name), root(std::move(root)), nodes(nodesCount) { get_all_nodes(nodes, this->root.get()); } size_t RigConfig::update( size_t index, Rig& rig, RigNode* node, glm::mat4 matrix) const { rig.calculated.matrices[index] = matrix * rig.pose.matrices[index]; size_t count = 1; for (auto& subnode : node->getSubnodes()) { count += update(index+count, rig, subnode.get(), rig.calculated.matrices[index]); } return count; } void RigConfig::update(Rig& rig, glm::mat4 matrix) const { update(0, rig, root.get(), matrix); } void RigConfig::render( Assets* assets, ModelBatch& batch, Rig& rig, const glm::mat4& matrix) const { update(rig, matrix); for (size_t i = 0; i < nodes.size(); i++) { auto* node = nodes[i]; node->refreshModel(assets); if (auto model = node->getModel()) { batch.pushMatrix(rig.calculated.matrices[i]); batch.draw(model, &rig.textures); batch.popMatrix(); } } } static std::tuple> read_node( dynamic::Map* root, size_t index ) { std::string name; std::string model; root->str("name", name); root->str("model", model); std::vector> subnodes; size_t count = 1; if (auto nodesList = root->list("nodes")) { for (size_t i = 0; i < nodesList->size(); i++) { if (const auto& map = nodesList->map(i)) { auto [subcount, subNode] = read_node(map.get(), index+count); subcount += count; subnodes.push_back(std::move(subNode)); } } } return {index + count, std::make_unique(index, name, model, std::move(subnodes))}; } std::unique_ptr RigConfig::parse( std::string_view src, std::string_view file, std::string_view name ) { auto root = json::parse(file, src); auto rootNodeMap = root->map("root"); if (rootNodeMap == nullptr) { throw std::runtime_error("missing 'root' element"); } auto [count, rootNode] = read_node(rootNodeMap.get(), 0); return std::make_unique(std::string(name), std::move(rootNode), count); }