mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Variant refator W.I.P.
This commit is contained in:
@@ -4554,7 +4554,7 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
|
||||
const uint32_t depth,
|
||||
std::map<std::string, VariantContent> *variantSetOut) {
|
||||
|
||||
if (variantSetOut) {
|
||||
if (!variantSetOut) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kAscii, "[InternalError] variantSetOut arg is nullptr.");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
|
||||
//#include <ctime>
|
||||
|
||||
//
|
||||
#include "pprinter.hh"
|
||||
#include "prim-types.hh"
|
||||
@@ -13,7 +10,8 @@
|
||||
#include "common-macros.inc"
|
||||
|
||||
// TODO:
|
||||
// - [ ] Print properties based on its appearance(USDA) or "properties" Prim field(USDC)
|
||||
// - [ ] Print properties based on lexcographically(USDA)
|
||||
// - [ ] Refactor variantSet stmt print.
|
||||
|
||||
namespace tinyusdz {
|
||||
namespace {
|
||||
@@ -1890,10 +1888,12 @@ std::string to_string(const tinyusdz::Klass &klass, uint32_t indent, bool closin
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string print_variantSetList(
|
||||
|
||||
std::string print_variantSetStmt(
|
||||
const std::map<std::string, VariantSet> &vslist, const uint32_t indent) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "# variantSet.size = " << std::to_string(vslist.size()) << "\n";
|
||||
for (const auto &variantSet : vslist) {
|
||||
|
||||
if (variantSet.second.variantSet.empty()) {
|
||||
@@ -1903,20 +1903,56 @@ std::string print_variantSetList(
|
||||
ss << pprint::Indent(indent) << "variantSet " << quote(variantSet.first) << " = {\n";
|
||||
|
||||
for (const auto &item : variantSet.second.variantSet) {
|
||||
ss << pprint::Indent(indent+1) << quote(item.first);
|
||||
ss << pprint::Indent(indent+1) << quote(item.first) << " ";
|
||||
|
||||
if (item.second.metas().authored()) {
|
||||
ss << " (\n";
|
||||
ss << "(\n";
|
||||
ss << print_prim_metas(item.second.metas(), indent+2);
|
||||
ss << pprint::Indent(indent+1) << ") ";
|
||||
}
|
||||
|
||||
ss << "{\n";
|
||||
ss << pprint::Indent(indent+1) << "{\n";
|
||||
|
||||
// props
|
||||
ss << print_props(item.second.properties(), indent+2);
|
||||
|
||||
// primChildren
|
||||
// TODO: print child Prims based on `primChildren` Prim metadata
|
||||
const auto &variantPrimMetas = item.second.metas();
|
||||
const auto &variantPrimChildren = item.second.primChildren();
|
||||
|
||||
if (variantPrimMetas.primChildren.size() == variantPrimChildren.size()) {
|
||||
std::map<std::string, const Prim *> primNameTable;
|
||||
for (size_t i = 0; i < variantPrimChildren.size(); i++) {
|
||||
primNameTable.emplace(variantPrimChildren[i].element_name(), &variantPrimChildren[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < variantPrimMetas.primChildren.size(); i++) {
|
||||
value::token nameTok = variantPrimMetas.primChildren[i];
|
||||
DCOUT(fmt::format("variantPrimChildren {}/{} = {}", i, variantPrimMetas.primChildren.size(), nameTok.str()));
|
||||
const auto it = primNameTable.find(nameTok.str());
|
||||
if (it != primNameTable.end()) {
|
||||
ss << pprint_value(it->second->data(), indent + 2, /* closing_brace */true);
|
||||
} else {
|
||||
// TODO: Report warning?
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ss << "variantPrimChildren.size = " << std::to_string(variantPrimChildren.size()) << "\n";
|
||||
for (const auto &child : variantPrimChildren) {
|
||||
ss << pprint_value(child.data(), indent+2, /* closing_brace */true);
|
||||
}
|
||||
}
|
||||
|
||||
ss << "# variantSet end\n";
|
||||
ss << pprint::Indent(indent+1) << "}\n";
|
||||
|
||||
}
|
||||
|
||||
ss << pprint::Indent(indent) << "{\n";
|
||||
|
||||
}
|
||||
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -1939,10 +1975,6 @@ std::string to_string(const Model &model, const uint32_t indent, bool closing_br
|
||||
std::set<std::string> tokset;
|
||||
ss << print_props(model.props, tokset, model.propertyNames(), indent+1);
|
||||
|
||||
if (model.variantSetList.size()) {
|
||||
ss << print_variantSetList(model.variantSetList, indent+1);
|
||||
}
|
||||
|
||||
if (closing_brace) {
|
||||
ss << pprint::Indent(indent) << "}\n";
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ std::string print_meta(const MetaVariable &meta, const uint32_t indent, const st
|
||||
std::string print_prim_metas(const PrimMeta &meta, const uint32_t indent);
|
||||
std::string print_customData(const CustomDataType &customData, const std::string &name, const uint32_t indent);
|
||||
std::string print_variantSelectionMap(const VariantSelectionMap &m, const uint32_t indent);
|
||||
std::string print_variantSetList(const std::map<std::string, VariantSet> &vslist, const uint32_t indent);
|
||||
std::string print_variantSetStmt(const std::map<std::string, VariantSet> &vslist, const uint32_t indent);
|
||||
std::string print_payload(const prim::PayloadList &payload, const uint32_t indent);
|
||||
std::string print_timesamples(const value::TimeSamples &v, const uint32_t indent);
|
||||
std::string print_rel_prop(const Property &prop, const std::string &name, uint32_t indent);
|
||||
|
||||
@@ -2214,6 +2214,7 @@ struct Variant {
|
||||
PrimMeta &metas() { return _metas; }
|
||||
|
||||
std::map<std::string, Property> &properties() { return _props; }
|
||||
const std::map<std::string, Property> &properties() const { return _props; }
|
||||
|
||||
const std::vector<Prim> &primChildren() const { return _primChildren; }
|
||||
std::vector<Prim> &primChildren() { return _primChildren; }
|
||||
@@ -2232,6 +2233,12 @@ struct Variant {
|
||||
|
||||
struct VariantSet {
|
||||
|
||||
// variantSet name = {
|
||||
// "variant1" ...
|
||||
// "variant2" ...
|
||||
// ...
|
||||
// }
|
||||
|
||||
std::string name;
|
||||
std::map<std::string, Variant> variantSet;
|
||||
|
||||
@@ -2252,7 +2259,7 @@ struct Model {
|
||||
std::pair<ListEditQual, std::vector<Reference>> references;
|
||||
std::pair<ListEditQual, std::vector<Payload>> payload;
|
||||
|
||||
std::map<std::string, VariantSet> variantSetList;
|
||||
//std::map<std::string, VariantSet> variantSets;
|
||||
|
||||
std::map<std::string, Property> props;
|
||||
|
||||
@@ -2590,6 +2597,14 @@ class Prim {
|
||||
return _prim_id;
|
||||
}
|
||||
|
||||
const std::map<std::string, VariantSet> &variantSets() const {
|
||||
return _variantSets;
|
||||
}
|
||||
|
||||
std::map<std::string, VariantSet> &variantSets() {
|
||||
return _variantSets;
|
||||
}
|
||||
|
||||
///
|
||||
/// Get indices for children().
|
||||
///
|
||||
@@ -2638,6 +2653,8 @@ class Prim {
|
||||
|
||||
int64_t _prim_id{-1}; // Unique Prim id when positive(starts with 1). Id is assigned by Stage::compute_absolute_prim_path_and_assign_prim_id. Usually [1, NumPrimsInStage)
|
||||
|
||||
std::map<std::string, VariantSet> _variantSets;
|
||||
|
||||
#if defined(TINYUSDZ_ENABLE_THREAD)
|
||||
mutable std::mutex _mutex;
|
||||
#endif
|
||||
|
||||
@@ -420,7 +420,7 @@ void PrimPrintRec(std::stringstream &ss, const Prim &prim, uint32_t indent) {
|
||||
// TODO: use prim.elementPath for elementName.
|
||||
ss << pprint_value(prim.data(), indent, /* closing_brace */ false);
|
||||
|
||||
DCOUT("num_children = " << prim.children().size());
|
||||
DCOUT(prim.element_name() << " num_children = " << prim.children().size());
|
||||
|
||||
if (prim.metas().primChildren.size() == prim.children().size()) {
|
||||
// Use primChildren info to determine the order of the traversal.
|
||||
|
||||
@@ -116,13 +116,23 @@ constexpr auto kTag = "[USDA]";
|
||||
|
||||
namespace {
|
||||
|
||||
// intermediate data structure for VariantSet
|
||||
struct VariantNode {
|
||||
PrimMeta metas;
|
||||
std::map<std::string, Property> props;
|
||||
std::vector<int64_t> primChildren;
|
||||
};
|
||||
|
||||
struct PrimNode {
|
||||
value::Value prim; // stores typed Prim value. Xform, GeomMesh, ...
|
||||
std::string elementName;
|
||||
std::string typeName; // Prim's typeName
|
||||
|
||||
int64_t parent{-1}; // -1 = root node
|
||||
std::vector<size_t> children; // index to USDAReader._prims[]
|
||||
bool parent_is_variant{false}; // True when this Prim is defined under variantSet stmt.
|
||||
std::vector<size_t> children; // index to USDAReader._prims[] of childPrims. it contains variant's primChildren also.
|
||||
|
||||
std::map<std::string, std::map<std::string, VariantNode>> variantNodeMap;
|
||||
};
|
||||
|
||||
// For USD scene read for composition(read by references, subLayers, payloads)
|
||||
@@ -489,6 +499,43 @@ class USDAReader::Impl {
|
||||
prim.spec = spec;
|
||||
prim.name = prim_name.prim_part();
|
||||
|
||||
//
|
||||
// variants
|
||||
// NOTE: variantChildren setup is delayed. It will be processed in ReconstructNodeRec()
|
||||
//
|
||||
std::map<std::string, std::map<std::string, VariantNode>> variantSets;
|
||||
for (const auto &variantContext : in_variants) {
|
||||
const std::string variant_name = variantContext.first;
|
||||
|
||||
// Convert VariantContent -> VariantNode
|
||||
std::map<std::string, VariantNode> variantNodes;
|
||||
for (const auto &item : variantContext.second) {
|
||||
VariantNode variant;
|
||||
if (!ReconstructPrimMeta(item.second.metas, &variant.metas)) {
|
||||
return nonstd::make_unexpected(fmt::format("Failed to process Prim metadataum in variantSet {} item {} ", variant_name, item.first));
|
||||
}
|
||||
variant.props = item.second.props;
|
||||
|
||||
// child Prim should be already reconstructed.
|
||||
for (const auto &childPrimIdx : item.second.primIndices) {
|
||||
if (childPrimIdx < 0) {
|
||||
return nonstd::make_unexpected(fmt::format("[InternalError] Invalid primIndex found within VariantSet."));
|
||||
}
|
||||
|
||||
if (size_t(childPrimIdx) >= _prim_nodes.size()) {
|
||||
return nonstd::make_unexpected(fmt::format("[InternalError] Invalid primIndex found within VariantSet. variantChildPrimIdsx {} Exceeds _prim_nodes.size() {}", childPrimIdx, _prim_nodes.size()));
|
||||
}
|
||||
|
||||
variant.primChildren.push_back(childPrimIdx);
|
||||
|
||||
_prim_nodes[size_t(childPrimIdx)].parent_is_variant = true;
|
||||
}
|
||||
variantNodes.emplace(item.first, std::move(variant));
|
||||
}
|
||||
|
||||
variantSets.emplace(variant_name, std::move(variantNodes));
|
||||
}
|
||||
|
||||
// Add to scene graph.
|
||||
// NOTE: Scene graph is constructed from bottom up manner(Children
|
||||
// first), so add this primIdx to parent's children.
|
||||
@@ -500,6 +547,8 @@ class USDAReader::Impl {
|
||||
|
||||
_prim_nodes[size_t(primIdx)].prim = std::move(prim);
|
||||
_prim_nodes[size_t(primIdx)].typeName = primTypeName;
|
||||
_prim_nodes[size_t(primIdx)].variantNodeMap = variantSets;
|
||||
|
||||
|
||||
// Store actual Prim typeName also for Model Prim type.
|
||||
// TODO: Find more better way.
|
||||
@@ -520,7 +569,7 @@ class USDAReader::Impl {
|
||||
_toplevel_prims.push_back(size_t(primIdx));
|
||||
} else {
|
||||
_prim_nodes[size_t(parentPrimIdx)].children.push_back(
|
||||
size_t(primIdx));
|
||||
size_t(primIdx));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -530,6 +579,7 @@ class USDAReader::Impl {
|
||||
}
|
||||
|
||||
void RegisterPrimSpecHandler() {
|
||||
// W.I.P.
|
||||
_parser.RegisterPrimSpecFunction(
|
||||
[&](const Path &full_path, const Specifier spec, const std::string &typeName, const Path &prim_name, const int64_t primIdx,
|
||||
const int64_t parentPrimIdx,
|
||||
@@ -570,6 +620,14 @@ class USDAReader::Impl {
|
||||
primspec.specifier() = spec;
|
||||
primspec.typeName() = typeName;
|
||||
|
||||
// TODO: Prim metas
|
||||
// if (!ReconstructPrimMeta(in_meta, &primspec.metas())) {
|
||||
// return nonstd::make_unexpected(
|
||||
// "Failed to process Prim metadataum.");
|
||||
// }
|
||||
|
||||
// TODO: props, variants
|
||||
|
||||
DCOUT("primspec name, primType = " << prim_name.prim_part() << ", " << typeName);
|
||||
|
||||
// Assign index for PrimSpec
|
||||
@@ -1113,7 +1171,7 @@ class USDAReader::Impl {
|
||||
// toplevel prims
|
||||
std::vector<size_t> _toplevel_prims; // index to _prim_nodes
|
||||
|
||||
// Flattened array of prim nodes.
|
||||
// 1D Linearized array of prim nodes.
|
||||
std::vector<PrimNode> _prim_nodes;
|
||||
|
||||
// Path(prim part only) -> index to _prim_nodes[]
|
||||
@@ -1224,6 +1282,36 @@ void ReconstructNodeRec(const size_t idx,
|
||||
DCOUT("prim[" << idx << "].type = " << node.prim.type_name());
|
||||
//prim.prim_id() = int64_t(idx);
|
||||
|
||||
// First process variants.
|
||||
std::set<int64_t> variantChildrenIndices; // record variantChildren indices
|
||||
|
||||
std::map<std::string, VariantSet> variantSets;
|
||||
for (const auto &variantNodes : node.variantNodeMap) {
|
||||
VariantSet variantSet;
|
||||
for (const auto &item : variantNodes.second) {
|
||||
Variant variant;
|
||||
for (const int64_t vidx : item.second.primChildren) {
|
||||
if (variantChildrenIndices.count(vidx)) {
|
||||
// Duplicated variant childrenIndices
|
||||
// TODO: Report error.
|
||||
} else {
|
||||
// Add prim to variants
|
||||
if ((vidx >= 0) && (size_t(vidx) <= prim_nodes.size())) {
|
||||
variant.primChildren().emplace_back(std::move(prim_nodes[size_t(vidx)]));
|
||||
}
|
||||
|
||||
variantChildrenIndices.insert(idx);
|
||||
}
|
||||
}
|
||||
variant.metas() = std::move(item.second.metas);
|
||||
variant.properties() = std::move(item.second.props);
|
||||
|
||||
variantSet.name = variantNodes.first;
|
||||
variantSet.variantSet.emplace(item.first, std::move(variant));
|
||||
}
|
||||
variantSets.emplace(variantNodes.first, std::move(variantSet));
|
||||
}
|
||||
|
||||
for (const auto &cidx : node.children) {
|
||||
ReconstructNodeRec(cidx, prim_nodes, prim);
|
||||
}
|
||||
|
||||
17
tests/usda/variantSet-007.usda
Normal file
17
tests/usda/variantSet-007.usda
Normal file
@@ -0,0 +1,17 @@
|
||||
#usda 1.0
|
||||
|
||||
def "bora" (
|
||||
append variantSets = "shapeVariant"
|
||||
)
|
||||
{
|
||||
variantSet "shapeVariant" = {
|
||||
"Capsule" {
|
||||
def Skeleketon "myskel" {
|
||||
}
|
||||
}
|
||||
"Cone" {
|
||||
def Mesh "mymesh" {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
tests/usdc/variantSet-007.usdc
Normal file
BIN
tests/usdc/variantSet-007.usdc
Normal file
Binary file not shown.
Reference in New Issue
Block a user