From a1b4e01149d4f618eebe91f659b190cba3a04796 Mon Sep 17 00:00:00 2001 From: Harrand Date: Sat, 16 Nov 2024 17:46:54 +0000 Subject: [PATCH] [core.hier] get/set local/global transform --- include/tz/core/hier.hpp | 5 +++ src/tz/core/hier.cpp | 69 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/include/tz/core/hier.hpp b/include/tz/core/hier.hpp index 8c3f0f5159..7bfeb4319d 100644 --- a/include/tz/core/hier.hpp +++ b/include/tz/core/hier.hpp @@ -34,6 +34,11 @@ namespace tz hier_handle create_hier(); std::expected hier_create_node(hier_handle hier, tz::trs transform = {}, node_handle parent = tz::nullhand, void* userdata = nullptr); tz::error_code hier_destroy_node(hier_handle hier, node_handle node); + + std::expected hier_node_get_local_transform(hier_handle hier, node_handle node); + void hier_node_set_local_transform(hier_handle hier, node_handle node, tz::trs transform); + std::expected hier_node_get_global_transform(hier_handle hier, node_handle node); + void hier_node_set_global_transform(hier_handle hier, node_handle node, tz::trs transform); } #endif // TOPAZ_CORE_HIER_HPP \ No newline at end of file diff --git a/src/tz/core/hier.cpp b/src/tz/core/hier.cpp index 3ffe184b62..81e4657b9a 100644 --- a/src/tz/core/hier.cpp +++ b/src/tz/core/hier.cpp @@ -81,7 +81,7 @@ namespace tz auto iter = std::find(hier.free_list.begin(), hier.free_list.end(), node); if(iter != hier.free_list.end()) { - RETERR(tz::error_code::invalid_value, "double destroy of node {}", node.peek()); + RETERR(tz::error_code::precondition_failure, "double destroy of node {}", node.peek()); } hier.free_list.push_back(node); hier.nodes[node.peek()] = {}; @@ -98,4 +98,71 @@ namespace tz return tz::error_code::success; } + + void hier_node_set_local_transform(hier_handle hier, node_handle node, tz::trs transform) + { + hiers[hier.peek()].nodes[node.peek()].local_transform = transform; + } + + std::expected hier_node_get_local_transform(hier_handle hierh, node_handle node) + { + if(hiers.size() <= hierh.peek()) + { + UNERR(tz::error_code::invalid_value, "invalid hierarchy {} when retrieving local transform of node {}", hierh.peek(), node.peek()); + } + const auto& hier = hiers[hierh.peek()]; + if(hier.nodes.size() <= node.peek()) + { + UNERR(tz::error_code::invalid_value, "attempt to retrieve local transform within hierarchy {} of invalid node {}", hierh.peek(), node.peek()); + } + auto iter = std::find(hier.free_list.begin(), hier.free_list.end(), node); + if(iter != hier.free_list.end()) + { + UNERR(tz::error_code::precondition_failure, "attempt to retrieve local transform within hierarchy of previously-deleted node {}", hierh.peek(), node.peek()); + } + return hier.nodes[node.peek()].local_transform; + } + + std::expected hier_node_get_global_transform(hier_handle hierh, node_handle node) + { + tz::trs parent_transform = {}; + if(hiers.size() <= hierh.peek()) + { + UNERR(tz::error_code::invalid_value, "invalid hierarchy {} when retrieving global transform of node {}", hierh.peek(), node.peek()); + } + const auto& hier = hiers[hierh.peek()]; + if(hier.nodes.size() <= node.peek()) + { + UNERR(tz::error_code::invalid_value, "attempt to retrieve global transform within hierarchy {} of invalid node {}", hierh.peek(), node.peek()); + } + auto iter = std::find(hier.free_list.begin(), hier.free_list.end(), node); + if(iter != hier.free_list.end()) + { + UNERR(tz::error_code::precondition_failure, "attempt to retrieve global transform within hierarchy of previously-deleted node {}", hierh.peek(), node.peek()); + } + if(hier.nodes[node.peek()].parent != tz::nullhand) + { + auto maybe_parent_transform = hier_node_get_global_transform(hierh, hier.nodes[node.peek()].parent); + if(maybe_parent_transform.has_value()) + { + parent_transform = maybe_parent_transform.value(); + } + else + { + UNERR(tz::error_code::unknown_error, "error occurred when getting global transform of node {} - {} occurred while getting global transform of parent node", node.peek(), tz::error_code_name(maybe_parent_transform.error())); + } + } + return parent_transform.combine(hier.nodes[node.peek()].local_transform); + } + + void hier_node_set_global_transform(hier_handle hier, node_handle node, tz:: trs transform) + { + node_handle parent = hiers[hier.peek()].nodes[node.peek()].parent; + tz::trs parent_global = {}; + if(parent != tz::nullhand) + { + parent_global = tz_must(hier_node_get_global_transform(hier, parent)); + } + hier_node_set_local_transform(hier, node, transform.combine(parent_global.inverse())); + } } \ No newline at end of file