Fix Prim.elementPath is not set at constructor.

Refactor API.
Add `api_tutorial` example to demonstrate TinyUSDZ API.
This commit is contained in:
Syoyo Fujita
2022-10-26 21:11:08 +09:00
parent a60e91c634
commit 72c125d638
13 changed files with 415 additions and 74 deletions

View File

@@ -737,6 +737,7 @@ endif()
if(TINYUSDZ_BUILD_EXAMPLES)
add_subdirectory(examples/simple_usdz_dump)
add_subdirectory(examples/tydra_convert)
add_subdirectory(examples/api_tutorial)
if(TINYUSDZ_WITH_MODULE_USDA_WRITER)
add_subdirectory(examples/save_usda)
endif()

View File

@@ -0,0 +1,15 @@
# Assume this cmake is called from tinyusdz root(../../)
set(EXAMPLE_TARGET "api_tutorial")
set(TINYUSDZ_API_TUTORIAL_SOURCES
api-tutorial-main.cc
)
add_executable(${EXAMPLE_TARGET} ${TINYUSDZ_API_TUTORIAL_SOURCES})
add_sanitizers(${EXAMPLE_TARGET})
target_include_directories(${EXAMPLE_TARGET} PRIVATE ${PROJECT_SOURCE_DIR}/src)
target_link_libraries(${EXAMPLE_TARGET} tinyusdz_static)
set_target_properties(${EXAMPLE_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")

View File

@@ -0,0 +1,213 @@
// All-in-one TinyUSDZ core
#include "tinyusdz.hh"
// Import to_string() features
#include "pprinter.hh"
// Tydra is a collection of APIs to access/convert USD Prim data
// (e.g. Can get attribute by name)
#include <iostream>
#include "tydra/scene-access.hh"
//
// create a Scene
//
void CreateScene(tinyusdz::Stage *stage) {
// TinyUSDZ does not use mutex, smart pointers(e.g. shared_ptr) and C++
// exception. API is not multi-thread safe, thus if you need to manipulate a
// scene in multi-threaded context, The app must take care of resource locks
// in the app layer.
//
// To construct Prim, first create concrete Prim object(e.g. Xform, GeomMesh),
// then add it to tinyusdz::Prim.
//
//
tinyusdz::Xform xform;
{
xform.name = "root"; // Prim's name(elementPath)
// `xformOp:***` attribute is represented as XformOp class
tinyusdz::XformOp op;
op.op = tinyusdz::XformOp::OpType::Translate;
tinyusdz::value::double3 translate;
translate[0] = 1.0;
translate[1] = 2.0;
translate[2] = 3.0;
op.set_scalar(translate);
// `xformOpOrder`(token[]) is represented as std::vector<XformOp>
xform.xformOps.push_back(op);
}
tinyusdz::GeomMesh mesh;
{
mesh.name = "quad";
{
std::vector<tinyusdz::value::point3f> pts;
pts.push_back({0.0f, 0.0f, 0.0f});
pts.push_back({1.0f, 0.0f, 0.0f});
pts.push_back({1.0f, 1.0f, 0.0f});
pts.push_back({0.0f, 1.0f, 0.0f});
mesh.points.set_value(pts);
}
{
// quad plane composed of 2 triangles.
std::vector<int> indices;
std::vector<int> counts;
counts.push_back(3);
counts.push_back(3);
mesh.faceVertexCounts.set_value(counts);
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);
mesh.faceVertexIndices.set_value(indices);
}
// primvar and custom attribute can be added to generic Property container
// `props`(map<std::string, Property>)
{
// primvar is simply an attribute with prefix `primvars:`
//
// texCoord2f[] primvars:uv = [ ... ] ( interpolation = "vertex" )
// int[] primvars:uv:indices = [ ... ]
//
{
tinyusdz::Attribute uvAttr;
std::vector<tinyusdz::value::texcoord2f> uvs;
uvs.push_back({0.0f, 0.0f});
uvs.push_back({1.0f, 0.0f});
uvs.push_back({1.0f, 1.0f});
uvs.push_back({0.0f, 1.0f});
// Fast path. Set the value directly to Attribute.
uvAttr.set_value(uvs);
// or we can first build primvar::PrimVar
// tinyusdz::primvar::PrimVar uvVar;
// uvVar.set_scalar(uvs);
// uvAttr.set_var(std::move(uvVar));
// Currently `interpolation` is described in Attribute metadataum.
// You can set builtin(predefined) Attribute Metadatum(e.g.
// `interpolation`, `hidden`) through `metas()`.
uvAttr.metas().interpolation = tinyusdz::Interpolation::Vertex;
tinyusdz::Property uvProp(uvAttr, /* custom*/ false);
mesh.props.emplace("primvars:uv", uvProp);
// ----------------------
tinyusdz::Attribute uvIndexAttr;
std::vector<int> uvIndices;
// FIXME: Validate
uvIndices.push_back(0);
uvIndices.push_back(1);
uvIndices.push_back(2);
uvIndices.push_back(3);
tinyusdz::primvar::PrimVar uvIndexVar;
uvIndexVar.set_scalar(uvIndices);
uvIndexAttr.set_var(std::move(uvIndexVar));
// Or you can use this approach(if you want to keep a copy of PrimVar
// data)
// uvIndexAttr.set_var(uvIndexVar);
tinyusdz::Property uvIndexProp(uvIndexAttr, /* custom*/ false);
mesh.props.emplace("primvars:uv:indices", uvIndexProp);
}
// `custom uniform double myvalue = 3.0 ( hidden = 0 )`
{
tinyusdz::Attribute attrib;
double myvalue = 3.0;
tinyusdz::primvar::PrimVar var;
var.set_scalar(myvalue);
attrib.set_var(std::move(var));
attrib.variability() = tinyusdz::Variability::Uniform;
attrib.metas().hidden = false;
// NOTE: `custom` keyword would be deprecated in the future USD syntax,
// so you can set it false.
tinyusdz::Property prop(attrib, /* custom*/ true);
mesh.props.emplace("myvalue", prop);
}
}
}
//
// Create Scene(Stage) hierarchy.
// You can add child Prim to parent Prim's `children()`.
//
// [Xform]
// |
// +- [Mesh]
//
// Prim's elementName is read from concrete Prim class(GeomMesh::name,
// Xform::name, ...)
tinyusdz::Prim meshPrim(mesh);
tinyusdz::Prim xformPrim(xform);
xformPrim.children().emplace_back(std::move(meshPrim));
// Use GetRootPrims() to retrieve Stage's root Prim array.
stage->root_prims().emplace_back(std::move(xformPrim));
// You can add Stage metadatum through
tinyusdz::StringData sdata;
sdata.value = "Generated by TinyUSDZ api_tutorial.";
stage->metas().comment = sdata;
}
int main(int argc, char **argv) {
tinyusdz::Stage stage; // empty scene
CreateScene(&stage);
std::cout << stage.ExportToString() << "\n";
tinyusdz::Path path(/* absolute prim path */ "/root/quad",
/* property path */ "");
const tinyusdz::Prim *prim{nullptr};
std::string err;
bool ret = stage.find_prim_at_path(path, prim, &err);
if (ret) {
std::cout << "Found Prim at path: " << tinyusdz::to_string(path) << "\n";
} else {
std::cerr << err << "\n";
}
// std::string warn;
// std::string err;
// bool ret = tinyusdz::usda::SaveAsUSDA("output.udsa", stage, &warn, &err);
// if (warn.size()) {
// std::cout << "WARN: " << warn << "\n";
// }
// if (err.size()) {
// std::cerr << "ERR: " << err << "\n";
// }
return EXIT_SUCCESS;
}

View File

@@ -80,7 +80,7 @@ void SimpleScene(tinyusdz::Stage *stage)
// Fast path. Set the value directly to Attribute.
uvAttr.set_value(uvs);
// or we can first build primvar::PrimVar
//tinyusdz::primvar::PrimVar uvVar;
//uvVar.set_scalar(uvs);
@@ -146,7 +146,7 @@ void SimpleScene(tinyusdz::Stage *stage)
//
xformPrim.children().emplace_back(std::move(meshPrim));
stage->GetRootPrims().emplace_back(std::move(xformPrim));
stage->root_prims().emplace_back(std::move(xformPrim));
}
int main(int argc, char **argv)

View File

@@ -104,7 +104,7 @@ class AsciiParser {
///
std::vector<value::AssetPath> subLayers; // 'subLayers'
value::token defaultPrim; // 'defaultPrim'
StringData doc; // 'doc'
StringData doc; // 'doc' or 'documentation'
nonstd::optional<Axis> upAxis; // not specified = nullopt
nonstd::optional<double> metersPerUnit;
nonstd::optional<double> timeCodesPerSecond;

View File

@@ -186,7 +186,11 @@ std::string print_rel_prop(const Property &prop, const std::string &name, uint32
std::string print_prop(const Property &prop, const std::string &prop_name, uint32_t indent);
std::string print_props(const std::map<std::string, Property> &props, uint32_t indent);
// Forwad decl
class Stage;
// Stage::ExportToString() in pxrUSD
std::string to_string(const Stage &stage);
} // namespace tinyusdz

View File

@@ -698,6 +698,10 @@ struct PrimMeta {
// USDZ extensions
nonstd::optional<std::string> sceneName; // 'sceneName'
// Omniverse extensions(TODO: Use UTF8 string type?)
// https://github.com/PixarAnimationStudios/USD/pull/2055
nonstd::optional<std::string> displayName; // 'displayName'
std::map<std::string, MetaVariable> meta; // other meta values
// String only metadataum.
@@ -707,7 +711,7 @@ struct PrimMeta {
// FIXME: Find a better way to detect Prim meta is authored...
bool authored() const {
return (active || hidden || kind || customData || references || payload ||
inherits || variants || variantSets || specializes || sceneName ||
inherits || variants || variantSets || specializes || displayName || sceneName ||
doc || comment || meta.size() || apiSchemas || stringData.size() ||
assetInfo);
}
@@ -2086,6 +2090,13 @@ struct Scope {
std::map<std::string, Property> props;
};
///
/// Get elementName from Prim(e.g., Xform::name, GeomMesh::name)
/// `v` must be the value of Prim class.
///
nonstd::optional<std::string> GetPrimElementName(const value::Value &v);
//
// For `Stage` scene graph.
// Similar to `Prim` in pxrUSD.
@@ -2095,14 +2106,28 @@ struct Scope {
class Prim {
public:
// elementName is read from `rhs`(if it is a class of Prim)
Prim(const value::Value &rhs);
Prim(value::Value &&rhs);
Prim(const std::string &elementName, const value::Value &rhs);
Prim(const std::string &elementName, value::Value &&rhs);
template<typename T>
Prim(const T &prim) {
// Check if T is Prim class type.
static_assert((value::TypeId::TYPE_ID_MODEL_BEGIN <= value::TypeTraits<T>::type_id) && (value::TypeId::TYPE_ID_MODEL_END > value::TypeTraits<T>::type_id), "T is not a Prim class type");
_data = prim;
// Use prim.name for elementName?
_elementPath = Path(prim.name, "");
}
template<typename T>
Prim(const std::string &elementName, const T &prim) {
// Check if T is Prim class type.
static_assert((value::TypeId::TYPE_ID_MODEL_BEGIN <= value::TypeTraits<T>::type_id) && (value::TypeId::TYPE_ID_MODEL_END > value::TypeTraits<T>::type_id), "T is not a Prim class type");
_data = prim;
_elementPath = Path(elementName, "");
}
std::vector<Prim> &children() {

View File

@@ -143,9 +143,7 @@ class Node {
// TODO: Move to prim-types.cc
//
namespace {
nonstd::optional<Path> GetPrimElementName(const value::Value &v) {
nonstd::optional<std::string> GetPrimElementName(const value::Value &v) {
// Since multiple get_value() call consumes lots of stack size(depends on
// sizeof(T)?), Following code would produce 100KB of stack in debug build. So
// use as() instead(as() => roughly 2000 bytes for stack size).
@@ -218,9 +216,7 @@ nonstd::optional<Path> GetPrimElementName(const value::Value &v) {
#define EXTRACT_NAME_AND_RETURN_PATH(__ty) \
if (v.as<__ty>()) { \
Path p(v.as<__ty>()->name, ""); \
p.element_name() = v.as<__ty>()->name; \
return std::move(p); \
return v.as<__ty>()->name; \
}
EXTRACT_NAME_AND_RETURN_PATH(Model)
@@ -257,14 +253,13 @@ nonstd::optional<Path> GetPrimElementName(const value::Value &v) {
return nonstd::nullopt;
}
} // namespace
Prim::Prim(const value::Value &rhs) {
// Check if type is Prim(Model(GPrim), usdShade, usdLux, etc.)
if ((value::TypeId::TYPE_ID_MODEL_BEGIN <= rhs.type_id()) &&
(value::TypeId::TYPE_ID_MODEL_END > rhs.type_id())) {
if (auto pv = GetPrimElementName(rhs)) {
_path = pv.value();
_path = Path(pv.value(), /* prop part*/ "");
_elementPath = Path(pv.value(), /* prop part */ "");
}
_data = rhs;
@@ -280,7 +275,8 @@ Prim::Prim(value::Value &&rhs) {
_data = std::move(rhs);
if (auto pv = GetPrimElementName(_data)) {
_path = pv.value();
_path = Path(pv.value(), "");
_elementPath = Path(pv.value(), "");
}
} else {
@@ -288,33 +284,63 @@ Prim::Prim(value::Value &&rhs) {
}
}
Prim::Prim(const std::string &elementPath, const value::Value &rhs) {
// Check if type is Prim(Model(GPrim), usdShade, usdLux, etc.)
if ((value::TypeId::TYPE_ID_MODEL_BEGIN <= rhs.type_id()) &&
(value::TypeId::TYPE_ID_MODEL_END > rhs.type_id())) {
_path = Path(elementPath, /* prop part*/ "");
_elementPath = Path(elementPath, /* prop part */ "");
_data = rhs;
} else {
// TODO: Raise an error if rhs is not an Prim
}
}
Prim::Prim(const std::string &elementPath, value::Value &&rhs) {
// Check if type is Prim(Model(GPrim), usdShade, usdLux, etc.)
if ((value::TypeId::TYPE_ID_MODEL_BEGIN <= rhs.type_id()) &&
(value::TypeId::TYPE_ID_MODEL_END > rhs.type_id())) {
_data = std::move(rhs);
_path = Path(elementPath, "");
_elementPath = Path(elementPath, "");
} else {
// TODO: Raise an error if rhs is not an Prim
}
}
namespace {
nonstd::optional<const Prim *> GetPrimAtPathRec(const Prim *parent,
const std::string &parent_path,
const Path &path, const uint32_t depth) {
const Path &path,
const uint32_t depth) {
std::string abs_path;
// if (auto pv = GetPrimElementName(parent->data())) {
{
// TODO: Use elementPath
std::string elementName = parent->local_path().prim_part();
std::string elementName = parent->element_path().prim_part();
DCOUT(pprint::Indent(depth) << "Prim elementName = " << elementName);
DCOUT(pprint::Indent(depth) << "Given Path = " << path);
// fully absolute path
abs_path = parent_path + "/" + elementName;
DCOUT(pprint::Indent(depth) << "abs_path = " << abs_path);
DCOUT(pprint::Indent(depth) << "queriying path = " << path.full_path_name());
DCOUT(pprint::Indent(depth)
<< "queriying path = " << path.full_path_name());
if (abs_path == path.full_path_name()) {
DCOUT(pprint::Indent(depth) << "Got it! Found Prim at Path = " << abs_path);
DCOUT(pprint::Indent(depth)
<< "Got it! Found Prim at Path = " << abs_path);
return parent;
}
}
DCOUT(pprint::Indent(depth) << "# of children : " << parent->children().size());
DCOUT(pprint::Indent(depth)
<< "# of children : " << parent->children().size());
for (const auto &child : parent->children()) {
//const std::string &p = parent->elementPath.full_path_name();
DCOUT(pprint::Indent(depth+1) << "Parent path : " << abs_path);
if (auto pv = GetPrimAtPathRec(&child, abs_path, path, depth+1)) {
// const std::string &p = parent->elementPath.full_path_name();
DCOUT(pprint::Indent(depth + 1) << "Parent path : " << abs_path);
if (auto pv = GetPrimAtPathRec(&child, abs_path, path, depth + 1)) {
return pv.value();
}
}
@@ -326,7 +352,8 @@ nonstd::optional<const Prim *> GetPrimAtPathRec(const Prim *parent,
nonstd::expected<const Prim *, std::string> Stage::GetPrimAtPath(
const Path &path) const {
DCOUT("GerPrimAtPath : " << path.prim_part() << "(input path: " << path << ")");
DCOUT("GerPrimAtPath : " << path.prim_part() << "(input path: " << path
<< ")");
if (_dirty) {
// Clear cache.
@@ -357,7 +384,8 @@ nonstd::expected<const Prim *, std::string> Stage::GetPrimAtPath(
// Brute-force search.
for (const auto &parent : root_nodes) {
if (auto pv = GetPrimAtPathRec(&parent, /* root */"", path, /* depth */0)) {
if (auto pv =
GetPrimAtPathRec(&parent, /* root */ "", path, /* depth */ 0)) {
// Add to cache.
// Assume pointer address does not change unless dirty state.
_prim_path_cache[path.prim_part()] = pv.value();
@@ -369,6 +397,20 @@ nonstd::expected<const Prim *, std::string> Stage::GetPrimAtPath(
"> int the Stage.\n");
}
bool Stage::find_prim_at_path(const Path &path, const Prim *&prim,
std::string *err) const {
nonstd::expected<const Prim *, std::string> ret = GetPrimAtPath(path);
if (ret) {
prim = ret.value();
return true;
} else {
if (err) {
(*err) = ret.error();
}
return false;
}
}
nonstd::expected<const Prim *, std::string> Stage::GetPrimFromRelativePath(
const Prim &root, const Path &path) const {
// TODO: Resolve "../"
@@ -389,8 +431,8 @@ nonstd::expected<const Prim *, std::string> Stage::GetPrimFromRelativePath(
return nonstd::make_unexpected("Invalid Path.\n");
}
#if 0 // TODO
Path abs_path = root.local_path();
#if 0 // TODO
Path abs_path = root.element_path();
abs_path.AppendElement(path.GetPrimPart());
DCOUT("root path = " << root.path());
@@ -410,10 +452,29 @@ nonstd::expected<const Prim *, std::string> Stage::GetPrimFromRelativePath(
#endif
}
bool Stage::find_prim_from_relative_path(const Prim &root,
const Path &relative_path,
const Prim *&prim,
std::string *err) const {
nonstd::expected<const Prim *, std::string> ret =
GetPrimFromRelativePath(root, relative_path);
if (ret) {
prim = ret.value();
return true;
} else {
if (err) {
(*err) = ret.error();
}
return false;
}
}
namespace {
void PrimPrintRec(std::stringstream &ss, const Prim &prim, uint32_t indent) {
ss << "\n";
// Currently, Prim's elementName is read from name variable in concrete Prim class(e.g. Xform::name).
// TODO: use prim.elementPath for elementName.
ss << pprint_value(prim.data(), indent, /* closing_brace */ false);
DCOUT("num_children = " << prim.children().size());
@@ -449,8 +510,8 @@ std::string Stage::ExportToString() const {
}
if (stage_metas.timeCodesPerSecond.authored()) {
ss << " timeCodesPerSecond = " << stage_metas.timeCodesPerSecond.get_value()
<< "\n";
ss << " timeCodesPerSecond = "
<< stage_metas.timeCodesPerSecond.get_value() << "\n";
}
if (stage_metas.startTimeCode.authored()) {
@@ -471,7 +532,7 @@ std::string Stage::ExportToString() const {
<< "\n";
}
if (!stage_metas.comment.value.empty()) {
ss << " doc = " << to_string(stage_metas.comment) << "\n";
ss << " comment = " << to_string(stage_metas.comment) << "\n";
}
if (stage_metas.customLayerData.size()) {

View File

@@ -35,6 +35,7 @@ class PrimRange;
class Stage {
public:
// pxrUSD compat API ----------------------------------------
static Stage CreateInMemory() {
return Stage();
}
@@ -53,6 +54,20 @@ class Stage {
///
nonstd::expected<const Prim *, std::string> GetPrimAtPath(const Path &path) const;
///
/// pxrUSD Compat API
///
bool Flatten(bool addSourceFileComment = true) const {
return compose(addSourceFileComment);
}
///
/// Dump Stage as ASCII(USDA) representation.
///
std::string ExportToString() const;
// pxrUSD compat API ----------------------------------------
///
/// Get Prim from a children of given root Prim.
/// Path must be relative Path.
@@ -61,40 +76,48 @@ class Stage {
///
nonstd::expected<const Prim *, std::string> GetPrimFromRelativePath(const Prim &root, const Path &path) const;
///
/// Dump Stage as ASCII(USDA) representation.
///
std::string ExportToString() const;
/// Find(Get) Prim at a Path.
/// Path must be absolute Path.
///
/// @param[in] path Absolute path(e.g. `/bora/dora`)
/// @param[out] prim const reference to Prim(if found)
/// @param[out] err Error message(filled when false is returned)
///
/// @returns true if found a Prim.
bool find_prim_at_path(const Path &path, const Prim *&prim, std::string *err = nullptr) const;
const std::vector<Prim> &GetRootPrims() const {
/// Find(Get) Prim from a relative Path.
/// Path must be relative Path.
///
/// @param[in] root Find from this Prim
/// @param[in] relative_path relative path(e.g. `dora/muda`)
/// @param[out] prim const reference to Prim(if found)
/// @param[out] err Error message(filled when false is returned)
///
/// @returns true if found a Prim.
bool find_prim_from_relative_path(const Prim &root, const Path &relative_path, const Prim *&prim, std::string *err) const;
const std::vector<Prim> &root_prims() const {
return root_nodes;
}
std::vector<Prim> &GetRootPrims() {
std::vector<Prim> &root_prims() {
return root_nodes;
}
const StageMetas &GetMetas() const {
const StageMetas &metas() const {
return stage_metas;
}
StageMetas &GetMetas() {
StageMetas &metas() {
return stage_metas;
}
///
/// Compose scene.
///
bool Compose(bool addSourceFileComment = true) const;
///
/// pxrUSD Compat API
///
bool Flatten(bool addSourceFileComment = true) const {
return Compose(addSourceFileComment);
}
bool compose(bool addSourceFileComment = true) const;
private:

View File

@@ -135,7 +135,7 @@ bool ListPrims(const tinyusdz::Stage &stage, PathPrimMap<T> &m /* output */) {
return false;
}
for (const auto &root_prim : stage.GetRootPrims()) {
for (const auto &root_prim : stage.root_prims()) {
TraverseRec(/* root path is empty */ "", root_prim, /* depth */ 0, m);
}
@@ -160,7 +160,7 @@ bool ListShaders(const tinyusdz::Stage &stage,
return false;
}
for (const auto &root_prim : stage.GetRootPrims()) {
for (const auto &root_prim : stage.root_prims()) {
TraverseShaderRec(/* root path is empty */ "", root_prim, /* depth */ 0, m);
}
@@ -1395,7 +1395,7 @@ bool EvaluateAttributeImpl(
void VisitPrims(const tinyusdz::Stage &stage, VisitPrimFunction visitor_fun,
void *userdata) {
for (const auto &root : stage.GetRootPrims()) {
for (const auto &root : stage.root_prims()) {
if (!VisitPrimsRec(root, /* root level */ 0, visitor_fun, userdata)) {
return;
}

View File

@@ -187,7 +187,7 @@ nonstd::expected<std::string, std::string> ToJSON(
const tinyusdz::Stage& stage) {
json j; // root
auto jstageMetas = ToJSON(stage.GetMetas());
auto jstageMetas = ToJSON(stage.metas());
if (!jstageMetas) {
return nonstd::make_unexpected(jstageMetas.error());
}
@@ -198,7 +198,7 @@ nonstd::expected<std::string, std::string> ToJSON(
j["version"] = 1.0;
json cj;
for (const auto& item : stage.GetRootPrims()) {
for (const auto& item : stage.root_prims()) {
if (!PrimToJSONRec(cj, item, 0)) {
return nonstd::make_unexpected("Failed to convert Prim to JSON.");
}

View File

@@ -118,6 +118,7 @@ namespace {
struct PrimNode {
value::Value prim;
std::string elementName;
int64_t parent{-1}; // -1 = root node
std::vector<size_t> children; // index to USDAReader._prims[]
@@ -578,40 +579,40 @@ class USDAReader::Impl {
[&](const ascii::AsciiParser::StageMetas &metas) {
DCOUT("StageMeta CB:");
_stage.GetMetas().doc = metas.doc;
_stage.metas().doc = metas.doc;
if (metas.upAxis) {
_stage.GetMetas().upAxis = metas.upAxis.value();
_stage.metas().upAxis = metas.upAxis.value();
}
if (metas.subLayers.size()) {
_stage.GetMetas().subLayers = metas.subLayers;
_stage.metas().subLayers = metas.subLayers;
}
_stage.GetMetas().defaultPrim = metas.defaultPrim;
_stage.metas().defaultPrim = metas.defaultPrim;
if (metas.metersPerUnit) {
_stage.GetMetas().metersPerUnit = metas.metersPerUnit.value();
_stage.metas().metersPerUnit = metas.metersPerUnit.value();
}
if (metas.timeCodesPerSecond) {
_stage.GetMetas().timeCodesPerSecond =
_stage.metas().timeCodesPerSecond =
metas.timeCodesPerSecond.value();
}
if (metas.startTimeCode) {
_stage.GetMetas().startTimeCode = metas.startTimeCode.value();
_stage.metas().startTimeCode = metas.startTimeCode.value();
}
if (metas.endTimeCode) {
_stage.GetMetas().endTimeCode = metas.endTimeCode.value();
_stage.metas().endTimeCode = metas.endTimeCode.value();
}
if (metas.framesPerSecond) {
_stage.GetMetas().framesPerSecond = metas.framesPerSecond.value();
_stage.metas().framesPerSecond = metas.framesPerSecond.value();
}
_stage.GetMetas().customLayerData = metas.customLayerData;
_stage.metas().customLayerData = metas.customLayerData;
_stage.GetMetas().stringData = metas.strings;
_stage.metas().stringData = metas.strings;
return true; // ok
});
@@ -1079,14 +1080,15 @@ void ReconstructNodeRec(const size_t idx,
bool USDAReader::Impl::ReconstructStage() {
_stage.GetRootPrims().clear();
_stage.root_prims().clear();
for (const auto &idx : _toplevel_prims) {
DCOUT("Toplevel prim idx: " << std::to_string(idx));
const auto &node = _prim_nodes[idx];
Prim prim(node.prim);
// root's elementPath is empty(which is interpreted as "/").
Prim prim("", node.prim);
DCOUT("prim[" << idx << "].type = " << node.prim.type_name());
for (const auto &cidx : node.children) {
@@ -1100,15 +1102,12 @@ bool USDAReader::Impl::ReconstructStage() {
#endif
}
// root's elementPath is empty"/"
prim.element_path() = Path("", "");
DCOUT("root prim[" << idx << "].elementPath = " << dump_path(prim.element_path()));
DCOUT("root prim[" << idx << "].num_children = " << prim.children().size());
_stage.GetRootPrims().emplace_back(std::move(prim));
_stage.root_prims().emplace_back(std::move(prim));
DCOUT("num_children = " << _stage.GetRootPrims()[size_t(_stage.GetRootPrims().size() - 1)].children().size());
DCOUT("num_children = " << _stage.root_prims()[size_t(_stage.root_prims().size() - 1)].children().size());
}
return true;

View File

@@ -1485,7 +1485,7 @@ nonstd::optional<Prim> USDCReader::Impl::ReconstructPrimFromTypeName(
typed_prim.name = __prim_name; \
typed_prim.spec = __spec; \
value::Value primdata = typed_prim; \
return Prim(primdata); \
return Prim(__prim_name, primdata); \
} else
RECONSTRUCT_PRIM(Xform, typeName, prim_name, spec)
@@ -1963,7 +1963,7 @@ bool USDCReader::Impl::ReconstructPrimNode(int parent, int current, int level,
}
std::vector<value::token> primChildren;
if (!ReconstrcutStageMeta(fvs, &stage->GetMetas(), &primChildren)) {
if (!ReconstrcutStageMeta(fvs, &stage->metas(), &primChildren)) {
PUSH_ERROR_AND_RETURN("Failed to reconstruct StageMeta.");
}
@@ -2333,7 +2333,7 @@ bool USDCReader::Impl::ReconstructPrimRecursively(
if (parent == 0) { // root prim
if (prim) {
stage->GetRootPrims().emplace_back(std::move(prim.value()));
stage->root_prims().emplace_back(std::move(prim.value()));
}
} else {
// Add to root prim.
@@ -2384,7 +2384,7 @@ bool USDCReader::Impl::ReconstructStage(Stage *stage) {
}
}
stage->GetRootPrims().clear();
stage->root_prims().clear();
int root_node_id = 0;
bool ret = ReconstructPrimRecursively(/* no further root for root_node */ -1,