Variant refator W.I.P.

This commit is contained in:
Syoyo Fujita
2023-01-14 23:00:15 +09:00
parent e310639ff2
commit bca8dd1f72
8 changed files with 174 additions and 20 deletions

View File

@@ -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.");
}

View File

@@ -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";
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -0,0 +1,17 @@
#usda 1.0
def "bora" (
append variantSets = "shapeVariant"
)
{
variantSet "shapeVariant" = {
"Capsule" {
def Skeleketon "myskel" {
}
}
"Cone" {
def Mesh "mymesh" {
}
}
}
}

Binary file not shown.