From a918ca0401432844cbfc1e6e6e1700c21a04bdea Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 7 Aug 2023 23:38:53 +0900 Subject: [PATCH] Fix typo. Implementing Variant resolver(W.I.P.) --- examples/tusdcat/main.cc | 10 +- src/composition.cc | 96 +++++++++++++++++++- src/composition.hh | 6 +- src/prim-types.cc | 44 ++++++++- src/prim-types.hh | 6 +- tests/usda/variantSet-listop-append-001.usda | 15 +++ tests/usda/variantSet-nometa-001.usda | 18 ++++ tests/usda/variants-only-001.usda | 13 +++ 8 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 tests/usda/variantSet-listop-append-001.usda create mode 100644 tests/usda/variantSet-nometa-001.usda create mode 100644 tests/usda/variants-only-001.usda diff --git a/examples/tusdcat/main.cc b/examples/tusdcat/main.cc index a0ceeabf9..8e34c1d38 100644 --- a/examples/tusdcat/main.cc +++ b/examples/tusdcat/main.cc @@ -49,7 +49,7 @@ int main(int argc, char **argv) { bool has_flatten{false}; bool has_relative{false}; bool has_extract_variants{false}; - + constexpr int kMaxIteration = 128; std::string filepath; @@ -196,12 +196,12 @@ int main(int argc, char **argv) { src_layer = std::move(composited_layer); } - // TODO: Find more better way to Recursively resolve references/payload + // TODO: Find more better way to Recursively resolve references/payload/variants bool all_resolved = true; for (int i = 0; i < kMaxIteration; i++) { if (comp_features.references) { - if (!src_layer.check_unresoled_references()) { + if (!src_layer.check_unresolved_references()) { all_resolved = true; } else { all_resolved = false; @@ -224,7 +224,7 @@ int main(int argc, char **argv) { } if (comp_features.payload) { - if (!src_layer.check_unresoled_payload()) { + if (!src_layer.check_unresolved_payload()) { all_resolved = true; } else { all_resolved = false; @@ -247,7 +247,7 @@ int main(int argc, char **argv) { } // TODO... more composition features - + if (all_resolved) { std::cout << "# of composition resolve iteration: " << (i + 1) << "\n"; diff --git a/src/composition.cc b/src/composition.cc index f98f850ec..e4474d439 100644 --- a/src/composition.cc +++ b/src/composition.cc @@ -1005,7 +1005,7 @@ bool HasReferences(const Layer &layer, const bool force_check, return layer.has_unresolved_references(); } - return layer.check_unresoled_references(options.max_depth); + return layer.check_unresolved_references(options.max_depth); } bool HasPayload(const Layer &layer, const bool force_check, @@ -1014,7 +1014,7 @@ bool HasPayload(const Layer &layer, const bool force_check, return layer.has_unresolved_payload(); } - return layer.check_unresoled_payload(options.max_depth); + return layer.check_unresolved_payload(options.max_depth); } namespace { @@ -1157,7 +1157,7 @@ bool ExtractVariantsRec(uint32_t depth, const std::string &root_path, } vsetdict[item.first] = variantStmtNames; - } + } } if (vsetdict.size()) { @@ -1218,4 +1218,94 @@ bool ExtractVariants(const Stage &stage, Dictionary *dict, std::string *err) { return true; } +bool VariantSelectPrimSpec(PrimSpec &dst, const PrimSpec &src, + const std::map &variant_selection, std::string *warn, + std::string *err) { + + if (src.metas().variants && src.metas().variantSets) { + // ok + } else if (src.metas().variants) { + if (warn) { + (*warn) += "`variants` are authored, but `variantSets` is not authored.\n"; + } + dst = src; + dst.metas().variants.reset(); + dst.metas().variantSets.reset(); + dst.variantSets().clear(); + return true; + } else if (src.metas().variantSets) { + if (warn) { + (*warn) += "`variantSets` are authored, but `variants` is not authored.\n"; + } + dst = src; + dst.metas().variants.reset(); + dst.metas().variantSets.reset(); + dst.variantSets().clear(); + // nothing to do. + return true; + } + + const auto &variantSetMeta = src.metas().variantSets.value(); + + const ListEditQual qual = variantSetMeta.first; + (void)qual; + + dst = src; + + for (const auto &item : variant_selection) { + + // Check if variantSet name exists in metadata. + const auto it = std::find_if(variantSetMeta.second.begin(), variantSetMeta.second.end(), [&](const std::string &name) { + if (name == item.first) { + return true; + } + return false; + }); + + if (it == variantSetMeta.second.end()) { + continue; + } + + if (dst.variantSets().count(item.first)) { + const auto &vss = dst.variantSets().at(item.first); + + if (vss.variantSet.count(item.second)) { + const PrimSpec &vs = vss.variantSet.at(item.second); + + // + // Promote variant content to this Prim. + // Some notes: + // - local metadataum and property always wins. + // + + // over-like operation + dst.metas().update_from(vs.metas()); + + for (const auto &prop : vs.props()) { + // local wins + if (!dst.props().count(prop.first)) { + dst.props().emplace(prop.first, prop.second); + } + } + + // TODO: + // - [ ] primChildren + // - [ ] update `primChildren` and `properties` metadataum if required. + if (err) { + (*err) += "TODO: implement.\n"; + } + + return false; + + } + } + + } + + dst.variantSets().clear(); + + return true; +} + + } // namespace tinyusdz diff --git a/src/composition.hh b/src/composition.hh index 10ec9d7bf..82427798f 100644 --- a/src/composition.hh +++ b/src/composition.hh @@ -165,12 +165,12 @@ bool ListVariantSelectionMaps(const Layer &layer, VariantSelectorMap &m); /// /// @param[inout] dst PrimSpec where selected variant are written. /// @param[in] src Source PrimSpec. Source PrimSpec. +/// @param[in] variant_selection Variant Selection list. key = variantSet name, value = variant name. /// -/// @return true upon success. false when error(e.g. no corresponding -/// `variant_name` exists in `src` PrimSpec). +/// @return true upon success. false when error. No error when any of variant_selection does not exist in `src` PrimSpec. /// bool VariantSelectPrimSpec(PrimSpec &dst, const PrimSpec &src, - const std::string &variant_name, std::string *warn, + const std::map &variant_selection, std::string *warn, std::string *err); /// diff --git a/src/prim-types.cc b/src/prim-types.cc index 670605a99..694fef131 100644 --- a/src/prim-types.cc +++ b/src/prim-types.cc @@ -1849,6 +1849,30 @@ bool HasPayloadRec(uint32_t depth, } +bool HasVariantRec(uint32_t depth, + const PrimSpec &primspec, + const uint32_t max_depth = 1024*128) { + if (depth > max_depth) { + // too deep + return false; + } + + // TODO: Also check if PrimSpec::variantSets is empty? + if (primspec.metas().variants && primspec.metas().variantSets) { + return true; + } + + for (auto &child : primspec.children()) { + if (HasPayloadRec(depth + 1, child, + max_depth)) { + return true; + } + } + + return false; + +} + } // namespace bool Layer::find_primspec_at(const Path &path, const PrimSpec **ps, std::string *err) { @@ -1910,7 +1934,7 @@ bool Layer::find_primspec_at(const Path &path, const PrimSpec **ps, std::string return false; } -bool Layer::check_unresoled_references(const uint32_t max_depth) const { +bool Layer::check_unresolved_references(const uint32_t max_depth) const { bool ret = false; @@ -1926,7 +1950,7 @@ bool Layer::check_unresoled_references(const uint32_t max_depth) const { return _has_unresolved_references; } -bool Layer::check_unresoled_payload(const uint32_t max_depth) const { +bool Layer::check_unresolved_payload(const uint32_t max_depth) const { bool ret = false; @@ -1942,4 +1966,20 @@ bool Layer::check_unresoled_payload(const uint32_t max_depth) const { return _has_unresolved_payload; } +bool Layer::check_unresolved_variant(const uint32_t max_depth) const { + + bool ret = false; + + for (const auto &item : _prim_specs) { + if (HasVariantRec(/* depth */0, + item.second, max_depth)) { + ret = true; + break; + } + } + + _has_unresolved_variant = ret; + return _has_unresolved_variant; +} + } // namespace tinyusdz diff --git a/src/prim-types.hh b/src/prim-types.hh index 1f8e16b6a..52dc33301 100644 --- a/src/prim-types.hh +++ b/src/prim-types.hh @@ -3424,7 +3424,7 @@ struct Layer { /// @param[in] max_depth Maximum PrimSpec traversal depth. /// @returns true if PrimSpec tree contains any (unresolved) `references`. false if not. /// - bool check_unresoled_references(const uint32_t max_depth = 1024 * 1024) const; + bool check_unresolved_references(const uint32_t max_depth = 1024 * 1024) const; /// /// Check if PrimSpec tree contains any `payload` and cache the result. @@ -3432,7 +3432,7 @@ struct Layer { /// @param[in] max_depth Maximum PrimSpec traversal depth. /// @returns true if PrimSpec tree contains any (unresolved) `payload`. false if not. /// - bool check_unresoled_payload(const uint32_t max_depth = 1024 * 1024) const; + bool check_unresolved_payload(const uint32_t max_depth = 1024 * 1024) const; /// /// Check if PrimSpec tree contains any `variant` and cache the result. @@ -3440,7 +3440,7 @@ struct Layer { /// @param[in] max_depth Maximum PrimSpec traversal depth. /// @returns true if PrimSpec tree contains any (unresolved) `variant`. false if not. /// - bool check_unresoled_variant(const uint32_t max_depth = 1024 * 1024) const; + bool check_unresolved_variant(const uint32_t max_depth = 1024 * 1024) const; /// /// Check if PrimSpec tree contains any Prim with `over` specifier and cache the result. diff --git a/tests/usda/variantSet-listop-append-001.usda b/tests/usda/variantSet-listop-append-001.usda new file mode 100644 index 000000000..f5bfe9904 --- /dev/null +++ b/tests/usda/variantSet-listop-append-001.usda @@ -0,0 +1,15 @@ +#usda 1.0 + +def Xform "Implicits" ( + variants = { string shapeVariant = "Capsule" } + append variantSets = "shapeVariant" +) +{ + float myval = 1.0 + + variantSet "shapeVariant" = { + "Capsule" { + float myval = 2.0 + } + } +} diff --git a/tests/usda/variantSet-nometa-001.usda b/tests/usda/variantSet-nometa-001.usda new file mode 100644 index 000000000..d5c77891b --- /dev/null +++ b/tests/usda/variantSet-nometa-001.usda @@ -0,0 +1,18 @@ +#usda 1.0 + +def "bora" ( +) +{ + variantSet "shapeVariant" = { + "Capsule" { + def Skeleketon "myskel" { + } + } + "Cone" { + def Xform "myxform" { + def Mesh "mymesh" { + } + } + } + } +} diff --git a/tests/usda/variants-only-001.usda b/tests/usda/variants-only-001.usda new file mode 100644 index 000000000..746f0ba90 --- /dev/null +++ b/tests/usda/variants-only-001.usda @@ -0,0 +1,13 @@ +#usda 1.0 +( + defaultPrim = "hello" +) + +def Xform "hello" ( + variants = { + string shadingVariant = "green" + } +) +{ + +}