mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Fix Prim.elementPath is not set at constructor.
Refactor API. Add `api_tutorial` example to demonstrate TinyUSDZ API.
This commit is contained in:
@@ -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()
|
||||
|
||||
15
examples/api_tutorial/CMakeLists.txt
Normal file
15
examples/api_tutorial/CMakeLists.txt
Normal 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}")
|
||||
213
examples/api_tutorial/api-tutorial-main.cc
Normal file
213
examples/api_tutorial/api-tutorial-main.cc
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
113
src/stage.cc
113
src/stage.cc
@@ -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()) {
|
||||
|
||||
57
src/stage.hh
57
src/stage.hh
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user