Improve parsing Prim metadataum and pprint.

This commit is contained in:
Syoyo Fujita
2022-08-22 23:00:56 +09:00
parent 3402b2c739
commit a3eaae1c01
10 changed files with 246 additions and 46 deletions

View File

@@ -200,6 +200,7 @@ static void RegisterStageMetas(
metas["subLayers"] = AsciiParser::VariableDef(value::kAssetPath, "subLayers");
}
#if 0
// T = better-enums
template<class T>
class OneOf
@@ -218,12 +219,14 @@ class OneOf
return nonstd::make_unexpected(err_msg);
}
};
#endif
static void RegisterPrimMetas(
std::map<std::string, AsciiParser::VariableDef> &metas) {
metas.clear();
metas["kind"] = AsciiParser::VariableDef(value::kString, "kind", OneOf<Kind>());
//metas["kind"] = AsciiParser::VariableDef(value::kString, "kind", OneOf<Kind>());
metas["kind"] = AsciiParser::VariableDef(value::kToken, "kind");
// Composition arcs
// Type can be array. i.e. path, path[]
@@ -2371,7 +2374,7 @@ bool AsciiParser::ParseDictElement(std::string *out_key,
//
// Supports limited types for customData/Dictionary.
// TODO: array_qual
// TODO: support more types?
//
MetaVariable var;
if (type_name == value::kBool) {
@@ -2381,17 +2384,33 @@ bool AsciiParser::ParseDictElement(std::string *out_key,
}
var.value = val;
} else if (type_name == "float") {
float val;
if (!ReadBasicType(&val)) {
PUSH_ERROR_AND_RETURN("Failed to parse `float`");
if (array_qual) {
std::vector<float> vss;
if (!ParseBasicTypeArray(&vss)) {
PUSH_ERROR_AND_RETURN("Failed to parse `float[]`");
}
var.value = vss;
} else {
float val;
if (!ReadBasicType(&val)) {
PUSH_ERROR_AND_RETURN("Failed to parse `float`");
}
var.value = val;
}
var.value = val;
} else if (type_name == "string") {
std::string str;
if (!ReadStringLiteral(&str)) {
PUSH_ERROR_AND_RETURN("Failed to parse `string`");
if (array_qual) {
std::vector<std::string> strs;
if (!ParseBasicTypeArray(&strs)) {
PUSH_ERROR_AND_RETURN("Failed to parse `string[]`");
}
var.value = strs;
} else {
std::string str;
if (!ReadStringLiteral(&str)) {
PUSH_ERROR_AND_RETURN("Failed to parse `string`");
}
var.value = str;
}
var.value = str;
} else if (type_name == "token") {
if (array_qual) {
std::vector<std::string> strs;
@@ -2414,13 +2433,24 @@ bool AsciiParser::ParseDictElement(std::string *out_key,
} else if (type_name == "dictionary") {
std::map<std::string, MetaVariable> dict;
DCOUT("Parse dictionary");
if (!ParseDict(&dict)) {
PUSH_ERROR_AND_RETURN("Failed to parse `dictionary`");
}
var.obj_value = dict;
} else {
PUSH_ERROR_AND_RETURN("TODO: type = " + type_name);
}
var.type = type_name;
if (array_qual) {
// TODO: 2D array
var.type += "[]";
}
var.name = key_name;
DCOUT("key: " << key_name << ", type: " << type_name);
(*out_key) = key_name;
(*out_var) = var;
@@ -2482,8 +2512,11 @@ bool AsciiParser::ParseDict(std::map<std::string, MetaVariable> *out_dict) {
return false;
}
assert(var.valid());
if (!var.valid()) {
PUSH_ERROR_AND_RETURN("Invalid Dict element(probably internal issue).");
}
DCOUT("Add to dict: " << key);
(*out_dict)[key] = var;
}
}
@@ -3789,11 +3822,41 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def,
}
DCOUT("bool = " << value);
var.value = value;
} else if (vartype == value::kToken) {
value::token value;
if (!ReadBasicType(&value)) {
std::string msg = "Token expected for `" + varname + "`.\n";
PushError(msg);
return false;
}
DCOUT("token = " << value);
#if 0 // TODO
auto ret = def.post_parse_handler(value);
if (!ret) {
DCOUT("error = " << ret.error());
PUSH_ERROR_AND_RETURN("Invalid token for `" + varname + "`. " + ret.error());
}
#endif
var.value = value;
} else if (vartype == "token[]") {
std::vector<value::token> value;
if (!ParseBasicTypeArray(&value)) {
std::string msg = "Token array expected for `" + varname + "`.\n";
PushError(msg);
return false;
}
// TODO
//DCOUT("token[] = " << to_string(value));
var.value = value;
} else if (vartype == value::kString) {
std::string value;
DCOUT("parse meta = " << value);
if (!ReadStringLiteral(&value)) {
std::string msg = "String literal expected for `" + varname + "`.\n";
PushError(msg);
@@ -3904,6 +3967,7 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def,
var.value = values;
} else if (vartype == value::kDictionary) {
#if 0
DCOUT("dict type");
if (!Expect('{')) {
PushError("'{' expected.\n");
@@ -3935,10 +3999,20 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def,
}
PUSH_WARN("TODO: Implement object type(customData)");
#else
DCOUT("Parse dict in Prim meta.");
std::map<std::string, MetaVariable> dict;
if (!ParseDict(&dict)) {
PUSH_ERROR_AND_RETURN("Failed to parse `dictonary` in Prim meta.");
}
var.obj_value = dict;
#endif
} else {
PUSH_ERROR_AND_RETURN("TODO: vartype = " + vartype);
}
var.type = vartype;
(*outvar) = var;
return true;
@@ -4323,6 +4397,7 @@ AsciiParser::ParsePrimMeta() {
PushError("Failed to parse Prim meta value.\n");
return nonstd::nullopt;
}
var.name = varname;
return std::make_tuple(qual, var);
}
@@ -4386,7 +4461,7 @@ bool AsciiParser::ParsePrimMetas(
// ty = std::tuple<ListEditQual, MetaVariable>;
if (auto m = ParsePrimMeta()) {
DCOUT("arg: list-edit qual = " << tinyusdz::to_string(std::get<0>(m.value()))
DCOUT("PrimMeta: list-edit qual = " << tinyusdz::to_string(std::get<0>(m.value()))
<< ", name = " << std::get<1>(m.value()).name);
(*args)[std::get<1>(m.value()).name] = m.value();
@@ -5508,7 +5583,7 @@ bool AsciiParser::ParseDefBlock(const int64_t primIdx, const int64_t parentPrimI
// DCOUT("`references.size` = " + std::to_string(references.size()));
}
#if 0
#if 0 // TODO
if (auto v = ReconstructPrimMetas(in_metas)) {
DCOUT("TODO: ");
} else {
@@ -5709,7 +5784,7 @@ bool AsciiParser::ParseDefBlock(const int64_t primIdx, const int64_t parentPrimI
Path fullpath(GetCurrentPath(), "");
Path pname(prim_name, "");
nonstd::expected<bool, std::string> ret = construct_fun(fullpath, pname, primIdx, parentPrimIdx, props, references);
nonstd::expected<bool, std::string> ret = construct_fun(fullpath, pname, primIdx, parentPrimIdx, props, references, in_metas);
if (!ret) {
// construction failed.

View File

@@ -5,11 +5,11 @@
#pragma once
#include <clocale>
#include <functional>
#include <stack>
#include "external/better-enums/enum.h"
//#include "external/better-enums/enum.h"
#include "prim-types.hh"
#include "stream-reader.hh"
#include "tinyusdz.hh"
@@ -59,7 +59,7 @@ enum class LoadState {
// Prim Kind
// https://graphics.pixar.com/usd/release/glossary.html#usdglossary-kind
#if 0
#if 1
enum class Kind {
Model, // "model"
Group, // "group"
@@ -89,6 +89,7 @@ bool IsUSDA(const std::string &filename, size_t max_filesize = 0);
class AsciiParser {
public:
// TODO: refactor
struct PrimMetas {
// Frequently used prim metas
nonstd::optional<Kind> kind;
@@ -230,7 +231,10 @@ class AsciiParser {
///
/// Prim Meta construction callback function
///
using PrimMetaProcessFunction = std::function<bool(const PrimMetas &metas)>;
//using PrimMetaProcessFunction = std::function<bool(const PrimMetas &metas)>;
using PrimMetaInput = std::map<std::string, std::tuple<ListEditQual, MetaVariable>>;
///
/// Prim construction callback function
@@ -243,7 +247,7 @@ class AsciiParser {
std::function<nonstd::expected<bool, std::string>(
const Path &full_path, const Path &prim_name, const int64_t primIdx, const int64_t parentPrimIdx,
const std::map<std::string, Property> &properties,
std::vector<std::pair<ListEditQual, Reference>> &references)>;
std::vector<std::pair<ListEditQual, Reference>> &references, const PrimMetaInput &in_meta)>;
///
/// Register Prim construction callback function.
@@ -655,7 +659,7 @@ class AsciiParser {
//
PrimIdxAssignFunctin _prim_idx_assign_fun;
StageMetaProcessFunction _stage_meta_process_fun;
PrimMetaProcessFunction _prim_meta_process_fun;
//PrimMetaProcessFunction _prim_meta_process_fun;
std::map<std::string, PrimConstructFunction> _prim_construct_fun_map;
std::map<std::string, PostPrimConstructFunction> _post_prim_construct_fun_map;

View File

@@ -129,8 +129,18 @@ std::string print_animatable(const Animatable<T> &v, const uint32_t indent = 0)
std::string print_meta(const MetaVariable &meta, const uint32_t indent) {
std::stringstream ss;
ss << pprint::Indent(indent) << meta.type << " " << meta.name;
ss << " [TODO]\n";
//ss << "TODO: isObject " << meta.IsObject() << ", isValue " << meta.IsValue() << "\n";
if (meta.IsObject()) {
// dict
ss << pprint::Indent(indent) << "dictionary " << meta.name << " {\n";
for (const auto &item : meta.obj_value) {
ss << print_meta(item.second, indent+1);
}
ss << pprint::Indent(indent) << "}\n";
} else {
ss << pprint::Indent(indent) << meta.type << " " << meta.name << " = " << pprint_value(meta.value) << "\n";
}
return ss.str();
}
@@ -142,7 +152,7 @@ std::string print_customData(const CustomDataType &customData, const uint32_t in
for (const auto &item : customData) {
ss << print_meta(item.second, indent+1);
}
ss << pprint::Indent(indent) << "\n}\n";
ss << pprint::Indent(indent) << "}\n";
return ss.str();
}
@@ -180,11 +190,10 @@ std::string print_attr_metas(const AttrMeta &meta, const uint32_t indent) {
}
if (meta.customData) {
ss << pprint::Indent(indent) << "customData = {\n";
ss << pprint::Indent(indent+1) << "TODO:\n";
ss << pprint::Indent(indent) << "}\n";
ss << print_customData(meta.customData.value(), indent);
}
// other user defined metadataum.
for (const auto &item : meta.meta) {
ss << pprint::Indent(indent) << item.first << " = TODO\n";
}
@@ -635,7 +644,7 @@ std::string to_string(const Xform &xform, const uint32_t indent, bool closing_br
ss << pprint::Indent(indent) << "def Xform \"" << xform.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(xform.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -739,7 +748,9 @@ std::string to_string(const GeomMesh &mesh, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def Mesh \"" << mesh.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
if (mesh.meta.authorized()) {
ss << print_prim_metas(mesh.meta, indent+1);
}
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -792,7 +803,7 @@ std::string to_string(const GeomSubset &geom, const uint32_t indent, bool closin
ss << pprint::Indent(indent) << "def GeomSubset \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -810,7 +821,7 @@ std::string to_string(const GeomPoints &geom, const uint32_t indent, bool closin
ss << pprint::Indent(indent) << "def Points \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -871,7 +882,7 @@ std::string to_string(const GeomBasisCurves &geom, const uint32_t indent, bool c
ss << pprint::Indent(indent) << "def BasisCurves \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -911,7 +922,7 @@ std::string to_string(const GeomCube &geom, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def Cube \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -932,7 +943,7 @@ std::string to_string(const GeomCone &geom, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def Cone \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -954,7 +965,7 @@ std::string to_string(const GeomCylinder &geom, const uint32_t indent, bool clos
ss << pprint::Indent(indent) << "def Cylinder \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -987,7 +998,7 @@ std::string to_string(const GeomCapsule &geom, const uint32_t indent, bool closi
ss << pprint::Indent(indent) << "def Capsule \"" << geom.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(geom.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1020,7 +1031,7 @@ std::string to_string(const SkelRoot &root, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def SkelRoot \"" << root.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(root.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1042,7 +1053,7 @@ std::string to_string(const Material &material, const uint32_t indent, bool clos
ss << pprint::Indent(indent) << "def Material \"" << material.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
//print_prim_metas(material.metas, indent);
ss << print_prim_metas(material.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1210,7 +1221,7 @@ std::string to_string(const Shader &shader, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def Shader \"" << shader.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
//print_prim_metas(shader.metas, indent);
ss << print_prim_metas(shader.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1243,7 +1254,7 @@ std::string to_string(const Skeleton &skel, const uint32_t indent, bool closing_
ss << pprint::Indent(indent) << "def Skeleton \"" << skel.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(skel.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1263,7 +1274,7 @@ std::string to_string(const LuxSphereLight &light, const uint32_t indent, bool c
ss << pprint::Indent(indent) << "def SphereLight \"" << light.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(light.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";
@@ -1285,7 +1296,7 @@ std::string to_string(const LuxDomeLight &light, const uint32_t indent, bool clo
ss << pprint::Indent(indent) << "def DomeLight \"" << light.name << "\"\n";
ss << pprint::Indent(indent) << "(\n";
// args
ss << print_prim_metas(light.meta, indent+1);
ss << pprint::Indent(indent) << ")\n";
ss << pprint::Indent(indent) << "{\n";

View File

@@ -755,6 +755,7 @@ class Connection
};
// Variable class for Prim and Attribute Metadataum.
// TODO: use tiny-any
class MetaVariable {
public:
std::string type; // Explicit name of type
@@ -795,7 +796,7 @@ class MetaVariable {
// infer type from value content
if (v.IsObject()) {
return "dict";
return "dictionary";
} else if (v.IsTimeSamples()) {
std::string ts_type = "TODO: TimeSample typee";
// FIXME
@@ -878,7 +879,7 @@ struct PrimMeta {
std::map<std::string, MetaVariable> meta; // other meta values
bool authorizerd() const {
bool authorized() const {
return (kind || customData || meta.size());
}

View File

@@ -57,6 +57,9 @@ struct GPrim {
// child nodes
std::vector<GPrim> children;
// Prim metadataum.
PrimMeta meta;
};
struct Xform : GPrim {
@@ -139,6 +142,7 @@ struct GeomSubset {
std::vector<uint32_t> indices;
std::map<std::string, Property> props; // custom Properties
PrimMeta meta;
};
// Polygon mesh geometry

View File

@@ -41,6 +41,7 @@ struct LuxSphereLight {
Purpose purpose{Purpose::Default};
std::map<std::string, Property> props;
PrimMeta meta;
};
struct LuxDomeLight {
@@ -87,6 +88,7 @@ struct LuxDomeLight {
std::vector<value::token> xformOpOrder;
std::map<std::string, Property> props;
PrimMeta meta;
};

View File

@@ -16,6 +16,8 @@ struct Material {
int64_t parent_id{-1};
PrimMeta meta;
Relation surface; // outputs:surface.connect
Relation volume; // outputs:volume.connect
@@ -26,12 +28,16 @@ struct NodeGraph {
std::string name;
int64_t parent_id{-1};
PrimMeta meta;
};
template <typename T>
struct UsdPrimvarReader {
std::string name;
PrimMeta meta;
nonstd::optional<T> fallback; // "inputs:fallback"
nonstd::optional<value::token> varname; // "token inputs:varname". Name of the primvar to be fetched from the geometry("primvar" namespace is omitted).
@@ -101,6 +107,8 @@ struct UsdUVTexture {
// Custom properties
std::map<std::string, Property> props;
PrimMeta meta;
// TODO: orientation?
// https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html#UsdPreviewSurfaceProposal-TextureCoordinateOrientationinUSD
};
@@ -146,6 +154,8 @@ struct UsdPreviewSurface {
// Custom properties
std::map<std::string, Property> props;
PrimMeta meta;
};
#if 0 // TODO: Move to Tydra
@@ -207,6 +217,8 @@ struct Shader {
PrimvarReader_float2>
value;
#endif
PrimMeta meta;
};

View File

@@ -47,6 +47,8 @@ struct Skeleton {
AnimatableVisibility visibility{Visibility::Inherited};
std::vector<value::token> xformOpOrder;
PrimMeta meta;
};
struct SkelRoot {
@@ -64,6 +66,8 @@ struct SkelRoot {
int64_t skeleton_id{-1}; // index to scene.skeletons
// Skeleton skeleton;
PrimMeta meta;
};
struct SkelAnimation {

View File

@@ -413,7 +413,7 @@ class USDAReader::Impl {
[&](const Path &full_path, const Path &prim_name, const int64_t primIdx,
const int64_t parentPrimIdx,
const std::map<std::string, Property> &properties,
const std::vector<std::pair<ListEditQual, Reference>> &references)
const std::vector<std::pair<ListEditQual, Reference>> &references, const ascii::AsciiParser::PrimMetaInput &in_meta)
-> nonstd::expected<bool, std::string> {
if (!prim_name.IsValid()) {
return nonstd::make_unexpected("Invalid Prim name: " +
@@ -440,6 +440,11 @@ class USDAReader::Impl {
T prim;
if (!ReconstructPrimMeta(in_meta, &prim.meta)) {
return nonstd::make_unexpected("Failed to process Prim metadataum.");
}
DCOUT("primType = " << value::TypeTrait<T>::type_name()
<< ", node.size "
<< std::to_string(_prim_nodes.size())
@@ -538,6 +543,61 @@ class USDAReader::Impl {
});
}
bool ReconstructPrimMeta(
const ascii::AsciiParser::PrimMetaInput &in_meta,
PrimMeta *out) {
DCOUT("ReconstructPrimMeta");
for (const auto &meta : in_meta) {
DCOUT("meta.name = " << meta.first);
if (meta.first == "kind") {
// std::tuple<ListEditQual, MetaVariable>
// TODO: list-edit qual
const MetaVariable &var = std::get<1>(meta.second);
DCOUT("kind. type = " << var.type);
if (var.type == "token") {
if (auto pv = var.value.get_value<value::token>()) {
const value::token tok = pv.value();
if (tok.str() == "subcomponent") {
out->kind = Kind::Subcomponent;
} else if (tok.str() == "component") {
out->kind = Kind::Component;
} else if (tok.str() == "model") {
out->kind = Kind::Model;
} else if (tok.str() == "group") {
out->kind = Kind::Group;
} else if (tok.str() == "assembly") {
out->kind = Kind::Assembly;
} else {
PUSH_ERROR_AND_RETURN("Invalid token for `kind` metadataum.");
}
DCOUT("Added kind: " << to_string(out->kind.value()));
} else {
PUSH_ERROR_AND_RETURN("(Internal error?) `kind` metadataum is not type `token`.");
}
} else {
PUSH_ERROR_AND_RETURN("(Internal error?) `kind` metadataum is not type `token`. got `" << var.type << "`.");
}
} else if (meta.first == "customData") {
const MetaVariable &var = std::get<1>(meta.second);
DCOUT("customData. type = " << var.type);
if (var.type == "dictionary") {
CustomDataType customData;
customData = var.obj_value;
DCOUT("dict size = " << var.obj_value.size());
out->customData = customData;
} else {
PUSH_ERROR_AND_RETURN("(Internal error?) `customData` metadataum is not type `dictionary`. got type `" << var.type << "`\n");
}
} else {
PUSH_WARN("TODO: Prim metadataum : " << meta.first);
}
}
return true;
}
///
/// Reader entry point
/// TODO: Use callback function(visitor) so that Reconstruct**** function is
@@ -1246,7 +1306,7 @@ bool USDAReader::Impl::RegisterReconstructCallback<GeomSubset>() {
[&](const Path &full_path, const Path &prim_name, const int64_t primIdx,
const int64_t parentPrimIdx,
const std::map<std::string, Property> &properties,
std::vector<std::pair<ListEditQual, Reference>> &references)
const std::vector<std::pair<ListEditQual, Reference>> &references, const ascii::AsciiParser::PrimMetaInput &in_meta)
-> nonstd::expected<bool, std::string> {
const Path& parent = full_path.GetParentPrim();
@@ -1269,6 +1329,11 @@ bool USDAReader::Impl::RegisterReconstructCallback<GeomSubset>() {
"Unexpected parentPrimIdx for GeomSubset.");
}
PrimMeta meta;
if (!ReconstructPrimMeta(in_meta, &meta)) {
return nonstd::make_unexpected("Failed to process Prim metadataum.");
}
// TODO: Construct GeomMesh first
#if 0
const std::string parent_primpath = parent.GetPrimPart();
@@ -1443,6 +1508,7 @@ bool USDAReader::Impl::RegisterReconstructCallback<GeomSubset>() {
}
subset.name = prim_name.GetPrimPart();
subset.meta = meta;
// Add to scene graph.
// NOTE: Scene graph is constructed from bottom up manner(Children

View File

@@ -0,0 +1,21 @@
#usda 1.0
def Xform "teapot" (
kind = "component"
)
{
def Mesh "Teapot" (
customData = {
bool zUp = 1
dictionary Maya = {
bool generated = 1
}
}
)
{
color3f[] primvars:displayColor = [(1, 1, 1)] (
)
}
}