mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Construct PrimSpec tree from USD(for Composition. W.I.P.)
This commit is contained in:
@@ -5,4 +5,3 @@ TabWidth: 2
|
|||||||
UseTab: Never
|
UseTab: Never
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
Standard: Cpp11
|
Standard: Cpp11
|
||||||
IndentPPDirective: BeforeHash
|
|
||||||
|
|||||||
@@ -8,12 +8,21 @@
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
std::cout << "Need input.usda\n";
|
std::cout << "Need input.usda (--flatten)\n";
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filename = argv[1];
|
std::string filename = argv[1];
|
||||||
|
|
||||||
|
bool do_compose =false;
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
std::string arg = argv[2];
|
||||||
|
if (arg == "--flatten") {
|
||||||
|
do_compose = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string base_dir;
|
std::string base_dir;
|
||||||
base_dir = tinyusdz::io::GetBaseDir(filename);
|
base_dir = tinyusdz::io::GetBaseDir(filename);
|
||||||
|
|
||||||
@@ -41,8 +50,15 @@ int main(int argc, char **argv) {
|
|||||||
#endif
|
#endif
|
||||||
reader.SetBaseDir(base_dir);
|
reader.SetBaseDir(base_dir);
|
||||||
|
|
||||||
|
tinyusdz::LoadState state = tinyusdz::LoadState::Toplevel;
|
||||||
|
if (do_compose) {
|
||||||
|
// FIXME
|
||||||
|
state = tinyusdz::LoadState::Sublayer;
|
||||||
|
std::cout << "Enable composition.\n";
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
bool ret = reader.Read();
|
bool ret = reader.Read(state);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
std::cerr << "Failed to parse .usda: \n";
|
std::cerr << "Failed to parse .usda: \n";
|
||||||
|
|||||||
@@ -4295,29 +4295,49 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
|
|||||||
|
|
||||||
std::string pTy = prim_type;
|
std::string pTy = prim_type;
|
||||||
|
|
||||||
if (prim_type.empty()) {
|
if (IsToplevel()) {
|
||||||
// No Prim type specified. Treat it as Model
|
|
||||||
|
|
||||||
pTy = "Model";
|
if (prim_type.empty()) {
|
||||||
}
|
// No Prim type specified. Treat it as Model
|
||||||
|
|
||||||
if (_prim_construct_fun_map.count(pTy)) {
|
pTy = "Model";
|
||||||
auto construct_fun = _prim_construct_fun_map[pTy];
|
}
|
||||||
|
|
||||||
Path fullpath(GetCurrentPath(), "");
|
if (_prim_construct_fun_map.count(pTy)) {
|
||||||
Path pname(prim_name, "");
|
auto construct_fun = _prim_construct_fun_map[pTy];
|
||||||
nonstd::expected<bool, std::string> ret = construct_fun(
|
|
||||||
fullpath, spec, pname, primIdx, parentPrimIdx, props, in_metas);
|
|
||||||
|
|
||||||
if (!ret) {
|
Path fullpath(GetCurrentPath(), "");
|
||||||
// construction failed.
|
Path pname(prim_name, "");
|
||||||
PUSH_ERROR_AND_RETURN("Constructing Prim type `" + pTy +
|
nonstd::expected<bool, std::string> ret = construct_fun(
|
||||||
"` failed: " + ret.error());
|
fullpath, spec, pname, primIdx, parentPrimIdx, props, in_metas);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
// construction failed.
|
||||||
|
PUSH_ERROR_AND_RETURN("Constructing Prim type `" + pTy +
|
||||||
|
"` failed: " + ret.error());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PUSH_WARN(fmt::format(
|
||||||
|
"TODO: Unsupported/Unimplemented Prim type: `{}`. Skipping parsing.",
|
||||||
|
pTy));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PUSH_WARN(fmt::format(
|
// Load scene as PrimSpec tree
|
||||||
"TODO: Unsupported/Unimplemented Prim type: `{}`. Skipping parsing.",
|
if (_primspec_fun) {
|
||||||
pTy));
|
Path fullpath(GetCurrentPath(), "");
|
||||||
|
Path pname(prim_name, "");
|
||||||
|
|
||||||
|
// pass prim_type as is(empty = empty string)
|
||||||
|
nonstd::expected<bool, std::string> ret = _primspec_fun(
|
||||||
|
fullpath, spec, prim_type, pname, primIdx, parentPrimIdx, props, in_metas);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
// construction failed.
|
||||||
|
PUSH_ERROR_AND_RETURN(fmt::format("Constructing PrimSpec typeName `{}`, elementName `{}` failed: {}", prim_type, prim_name, ret.error()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PUSH_ERROR_AND_RETURN_TAG(kAscii, "[Internal Error] PrimSpec handler is not found.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PopPath();
|
PopPath();
|
||||||
@@ -4327,12 +4347,12 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// Parser entry point
|
/// Parser entry point
|
||||||
/// TODO: Refactor
|
/// TODO: Refactor and use unified code path regardless of LoadState.
|
||||||
///
|
///
|
||||||
bool AsciiParser::Parse(LoadState state) {
|
bool AsciiParser::Parse(LoadState state) {
|
||||||
_sub_layered = (state == LoadState::SUBLAYER);
|
_sub_layered = (state == LoadState::Sublayer);
|
||||||
_referenced = (state == LoadState::REFERENCE);
|
_referenced = (state == LoadState::Reference);
|
||||||
_payloaded = (state == LoadState::PAYLOAD);
|
_payloaded = (state == LoadState::Payload);
|
||||||
|
|
||||||
bool header_ok = ParseMagicHeader();
|
bool header_ok = ParseMagicHeader();
|
||||||
if (!header_ok) {
|
if (!header_ok) {
|
||||||
@@ -4355,13 +4375,14 @@ bool AsciiParser::Parse(LoadState state) {
|
|||||||
|
|
||||||
if (c == '(') {
|
if (c == '(') {
|
||||||
// stage meta.
|
// stage meta.
|
||||||
|
// TODO: We could skip parsing stage meta in flatten(composition) mode.
|
||||||
if (!ParseStageMetas()) {
|
if (!ParseStageMetas()) {
|
||||||
PUSH_ERROR_AND_RETURN("Failed to parse Stage metas.");
|
PUSH_ERROR_AND_RETURN("Failed to parse Stage metas.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stage_meta_process_fun) {
|
if (IsToplevel() && _stage_meta_process_fun) {
|
||||||
DCOUT("StageMeta callback.");
|
DCOUT("StageMeta callback.");
|
||||||
bool ret = _stage_meta_process_fun(_stage_metas);
|
bool ret = _stage_meta_process_fun(_stage_metas);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cerrno>
|
//#include <functional>
|
||||||
#include <functional>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
//#include "external/better-enums/enum.h"
|
//#include "external/better-enums/enum.h"
|
||||||
|
#include "composition.hh"
|
||||||
#include "prim-types.hh"
|
#include "prim-types.hh"
|
||||||
#include "stream-reader.hh"
|
#include "stream-reader.hh"
|
||||||
#include "tinyusdz.hh"
|
#include "tinyusdz.hh"
|
||||||
@@ -49,38 +51,6 @@ struct PathIdentifier : std::string {
|
|||||||
// using std::string;
|
// using std::string;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class LoadState {
|
|
||||||
TOPLEVEL, // toplevel .usda input
|
|
||||||
SUBLAYER, // .usda is read by 'subLayers'
|
|
||||||
REFERENCE, // .usda is read by `references`
|
|
||||||
PAYLOAD, // .usda is read by `payload`
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prim Kind
|
|
||||||
// https://graphics.pixar.com/usd/release/glossary.html#usdglossary-kind
|
|
||||||
#if 1
|
|
||||||
enum class Kind {
|
|
||||||
Model, // "model"
|
|
||||||
Group, // "group"
|
|
||||||
Assembly, // "assembly"
|
|
||||||
Component, // "component"
|
|
||||||
Subcomponent, // "subcomponent"
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Weverything"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BETTER_ENUM(Kind, int, model, group, assembly, component, subcomponent);
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Test if input file is USDA ascii format.
|
/// Test if input file is USDA ascii format.
|
||||||
///
|
///
|
||||||
@@ -93,8 +63,9 @@ class AsciiParser {
|
|||||||
// Frequently used prim metas
|
// Frequently used prim metas
|
||||||
nonstd::optional<Kind> kind;
|
nonstd::optional<Kind> kind;
|
||||||
|
|
||||||
value::dict customData; // `customData`
|
value::dict customData; // `customData`
|
||||||
std::vector<value::StringData> strings; // String only unregistered metadata.
|
std::vector<value::StringData>
|
||||||
|
strings; // String only unregistered metadata.
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Unifity class with StageMetas in prim-types.hh
|
// TODO: Unifity class with StageMetas in prim-types.hh
|
||||||
@@ -104,7 +75,7 @@ class AsciiParser {
|
|||||||
///
|
///
|
||||||
std::vector<value::AssetPath> subLayers; // 'subLayers'
|
std::vector<value::AssetPath> subLayers; // 'subLayers'
|
||||||
value::token defaultPrim; // 'defaultPrim'
|
value::token defaultPrim; // 'defaultPrim'
|
||||||
value::StringData doc; // 'doc' or 'documentation'
|
value::StringData doc; // 'doc' or 'documentation'
|
||||||
nonstd::optional<Axis> upAxis; // not specified = nullopt
|
nonstd::optional<Axis> upAxis; // not specified = nullopt
|
||||||
nonstd::optional<double> metersPerUnit;
|
nonstd::optional<double> metersPerUnit;
|
||||||
nonstd::optional<double> timeCodesPerSecond;
|
nonstd::optional<double> timeCodesPerSecond;
|
||||||
@@ -211,11 +182,6 @@ class AsciiParser {
|
|||||||
|
|
||||||
~AsciiParser();
|
~AsciiParser();
|
||||||
|
|
||||||
///
|
|
||||||
/// Callback functions which is called from a class outside of
|
|
||||||
/// AsciiParser(i.e. USDAReader)
|
|
||||||
///
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Assign index to primitive for index-based prim scene graph representation.
|
/// Assign index to primitive for index-based prim scene graph representation.
|
||||||
/// -1 = root
|
/// -1 = root
|
||||||
@@ -289,6 +255,18 @@ class AsciiParser {
|
|||||||
_post_prim_construct_fun_map[prim_type] = fun;
|
_post_prim_construct_fun_map[prim_type] = fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// For composition(Treat Prim as generic container).
|
||||||
|
/// AsciiParser(i.e. USDAReader)
|
||||||
|
///
|
||||||
|
using PrimSpecFunction = std::function<nonstd::expected<bool, std::string>(
|
||||||
|
const Path &full_path, const Specifier spec, const std::string &primTypeName,
|
||||||
|
const Path &prim_name, const int64_t primIdx, const int64_t parentPrimIdx,
|
||||||
|
const std::map<std::string, Property> &properties,
|
||||||
|
const PrimMetaMap &in_meta)>;
|
||||||
|
|
||||||
|
void RegisterPrimSpecFunction(PrimSpecFunction fun) { _primspec_fun = fun; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Base filesystem directory to search asset files.
|
/// Base filesystem directory to search asset files.
|
||||||
///
|
///
|
||||||
@@ -307,30 +285,35 @@ class AsciiParser {
|
|||||||
///
|
///
|
||||||
/// Parser entry point
|
/// Parser entry point
|
||||||
///
|
///
|
||||||
bool Parse(LoadState state = LoadState::TOPLEVEL);
|
bool Parse(LoadState state = LoadState::Toplevel);
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Parse TimeSample value with specified array type of `type_id`(value::TypeId)
|
/// Parse TimeSample value with specified array type of
|
||||||
/// (You can obrain type_id from string using value::GetTypeId())
|
/// `type_id`(value::TypeId) (You can obrain type_id from string using
|
||||||
|
/// value::GetTypeId())
|
||||||
///
|
///
|
||||||
bool ParseTimeSampleValue(const uint32_t type_id, value::Value *result);
|
bool ParseTimeSampleValue(const uint32_t type_id, value::Value *result);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Parse TimeSample value with specified `type_name`(Appears in USDA. .e.g. "float", "matrix2d")
|
/// Parse TimeSample value with specified `type_name`(Appears in USDA. .e.g.
|
||||||
|
/// "float", "matrix2d")
|
||||||
///
|
///
|
||||||
bool ParseTimeSampleValue(const std::string &type_name, value::Value *result);
|
bool ParseTimeSampleValue(const std::string &type_name, value::Value *result);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Parse TimeSample value with specified base type of `type_id`(value::TypeId)
|
/// Parse TimeSample value with specified base type of
|
||||||
/// (You can obrain type_id from string using value::GetTypeId())
|
/// `type_id`(value::TypeId) (You can obrain type_id from string using
|
||||||
|
/// value::GetTypeId())
|
||||||
///
|
///
|
||||||
bool ParseTimeSampleValueOfArrayType(const uint32_t base_type_id, value::Value *result);
|
bool ParseTimeSampleValueOfArrayType(const uint32_t base_type_id,
|
||||||
|
value::Value *result);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Parse TimeSample value with specified array type of `type_name`("[]" omiotted. .e.g. "float" for "float[]")
|
/// Parse TimeSample value with specified array type of `type_name`("[]"
|
||||||
|
/// omiotted. .e.g. "float" for "float[]")
|
||||||
///
|
///
|
||||||
bool ParseTimeSampleValueOfArrayType(const std::string &type_name, value::Value *result);
|
bool ParseTimeSampleValueOfArrayType(const std::string &type_name,
|
||||||
|
value::Value *result);
|
||||||
|
|
||||||
// TODO: ParseBasicType?
|
// TODO: ParseBasicType?
|
||||||
bool ParsePurpose(Purpose *result);
|
bool ParsePurpose(Purpose *result);
|
||||||
@@ -740,8 +723,8 @@ class AsciiParser {
|
|||||||
|
|
||||||
// -- [TimeSamples] -------------------
|
// -- [TimeSamples] -------------------
|
||||||
|
|
||||||
//template <typename T>
|
// template <typename T>
|
||||||
//using TimeSampleData = std::vector<std::pair<double, nonstd::optional<T>>>;
|
// using TimeSampleData = std::vector<std::pair<double, nonstd::optional<T>>>;
|
||||||
|
|
||||||
// template <typename T>
|
// template <typename T>
|
||||||
// using TimeSampleDataArray = std::vector<std::pair<double,
|
// using TimeSampleDataArray = std::vector<std::pair<double,
|
||||||
@@ -751,19 +734,20 @@ class AsciiParser {
|
|||||||
/// Convert TimeSampleData<T> to TimeSamples(type-erased TimeSample Sdata
|
/// Convert TimeSampleData<T> to TimeSamples(type-erased TimeSample Sdata
|
||||||
/// struct)
|
/// struct)
|
||||||
///
|
///
|
||||||
//template <typename T>
|
// template <typename T>
|
||||||
//value::TimeSamples ConvertToTimeSamples(const TimeSampleData<T> &in);
|
// value::TimeSamples ConvertToTimeSamples(const TimeSampleData<T> &in);
|
||||||
|
|
||||||
//template <typename T>
|
// template <typename T>
|
||||||
//value::TimeSamples ConvertToTimeSamples(
|
// value::TimeSamples ConvertToTimeSamples(
|
||||||
// const TimeSampleData<std::vector<T>> &in);
|
// const TimeSampleData<std::vector<T>> &in);
|
||||||
|
|
||||||
//// T = scalar(e.g. `float`)
|
//// T = scalar(e.g. `float`)
|
||||||
//template <typename T>
|
// template <typename T>
|
||||||
//nonstd::optional<TimeSampleData<T>> TryParseTimeSamples();
|
// nonstd::optional<TimeSampleData<T>> TryParseTimeSamples();
|
||||||
|
|
||||||
//template <typename T>
|
// template <typename T>
|
||||||
//nonstd::optional<TimeSampleData<std::vector<T>>> TryParseTimeSamplesOfArray();
|
// nonstd::optional<TimeSampleData<std::vector<T>>>
|
||||||
|
// TryParseTimeSamplesOfArray();
|
||||||
|
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
|
|
||||||
@@ -847,8 +831,8 @@ class AsciiParser {
|
|||||||
std::map<std::string, PrimConstructFunction> _prim_construct_fun_map;
|
std::map<std::string, PrimConstructFunction> _prim_construct_fun_map;
|
||||||
std::map<std::string, PostPrimConstructFunction> _post_prim_construct_fun_map;
|
std::map<std::string, PostPrimConstructFunction> _post_prim_construct_fun_map;
|
||||||
|
|
||||||
// class Impl;
|
// For composition. PrimSpec is typeless so single callback function only.
|
||||||
// Impl *_impl;
|
PrimSpecFunction _primspec_fun{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ascii
|
} // namespace ascii
|
||||||
|
|||||||
21
src/composition.hh
Normal file
21
src/composition.hh
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-License-Identifier: Apache 2.0
|
||||||
|
// Copyright 2022-Present Light Transport Entertainment Inc.
|
||||||
|
//
|
||||||
|
// Layer and Prim composition features.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "prim-types.hh"
|
||||||
|
|
||||||
|
namespace tinyusdz {
|
||||||
|
|
||||||
|
// USD asset loading state.
|
||||||
|
enum class LoadState
|
||||||
|
{
|
||||||
|
Toplevel, // load initial .usd(default)
|
||||||
|
Sublayer, // load USD from Stage meta sublayer
|
||||||
|
Reference, // load USD from Prim meta reference
|
||||||
|
Payload // load USD from Prim meta payload
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tinyusdz
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: Apache 2.0
|
// SPDX-License-Identifier: Apache 2.0
|
||||||
// Copyright 2022-Present Light Transport Entertainment Inc.
|
// Copyright 2022-Present Light Transport Entertainment Inc.
|
||||||
#include "prim-composition.hh"
|
#include "composition.hh"
|
||||||
|
|
||||||
namespace tinyusdz {
|
namespace tinyusdz {
|
||||||
namespace prim {
|
namespace prim {
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache 2.0
|
|
||||||
// Copyright 2022-Present Light Transport Entertainment Inc.
|
|
||||||
//
|
|
||||||
// Prim composition features.
|
|
||||||
//
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "prim-types.hh"
|
|
||||||
|
|
||||||
namespace tinyusdz {
|
|
||||||
namespace prim {
|
|
||||||
|
|
||||||
class LayerStack
|
|
||||||
{
|
|
||||||
std::vector<Layer> layers;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace prim
|
|
||||||
} // namespace tinyusdz
|
|
||||||
10
src/stage.cc
10
src/stage.cc
@@ -293,15 +293,17 @@ bool Stage::find_prim_from_relative_path(const Prim &root,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stage::LoadLayerFromMemory(const uint8_t *addr, const size_t nbytes, const std::string &asset_name, Layer *layer) {
|
bool Stage::LoadLayerFromMemory(const uint8_t *addr, const size_t nbytes, const std::string &asset_name, const LoadState load_state, Layer *layer) {
|
||||||
|
|
||||||
|
// TODO: USDC/USDZ support.
|
||||||
|
|
||||||
tinyusdz::StreamReader sr(addr, nbytes, /* swap endian */ false);
|
tinyusdz::StreamReader sr(addr, nbytes, /* swap endian */ false);
|
||||||
tinyusdz::usda::USDAReader reader(&sr);
|
tinyusdz::usda::USDAReader reader(&sr);
|
||||||
|
|
||||||
// TODO: Uase AssetResolver
|
// TODO: Uase AssetResolver
|
||||||
//reader.SetBaseDir(base_dir);
|
//reader.SetBaseDir(base_dir);
|
||||||
|
|
||||||
if (!reader.Read(ascii::LoadState::REFERENCE)) {
|
if (!reader.Read(load_state)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +314,7 @@ bool Stage::LoadLayerFromMemory(const uint8_t *addr, const size_t nbytes, const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stage::LoadLayerFromFile(const std::string &_filename, Layer *layer) {
|
bool Stage::LoadLayerFromFile(const std::string &_filename, const LoadState load_state, Layer *layer) {
|
||||||
// TODO: Setup AssetResolver.
|
// TODO: Setup AssetResolver.
|
||||||
|
|
||||||
std::string filepath = io::ExpandFilePath(_filename, /* userdata */ nullptr);
|
std::string filepath = io::ExpandFilePath(_filename, /* userdata */ nullptr);
|
||||||
@@ -328,7 +330,7 @@ bool Stage::LoadLayerFromFile(const std::string &_filename, Layer *layer) {
|
|||||||
PUSH_ERROR_AND_RETURN("Read file failed: " + err);
|
PUSH_ERROR_AND_RETURN("Read file failed: " + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoadLayerFromMemory(data.data(), data.size(), filepath, layer);
|
return LoadLayerFromMemory(data.data(), data.size(), filepath, load_state, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stage::LoadSubLayers(std::vector<Layer> *sublayers) {
|
bool Stage::LoadSubLayers(std::vector<Layer> *sublayers) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "prim-types.hh"
|
#include "prim-types.hh"
|
||||||
|
#include "composition.hh"
|
||||||
|
|
||||||
namespace tinyusdz {
|
namespace tinyusdz {
|
||||||
|
|
||||||
@@ -129,11 +130,11 @@ class Stage {
|
|||||||
///
|
///
|
||||||
/// Loads USD from and return it as Layer
|
/// Loads USD from and return it as Layer
|
||||||
///
|
///
|
||||||
bool LoadLayerFromFile(const std::string &filename, Layer *layer);
|
bool LoadLayerFromFile(const std::string &filename, const LoadState load_state, Layer *layer);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Loads USD asset from memory and return it as Layer
|
/// Loads USD asset from memory and return it as Layer
|
||||||
bool LoadLayerFromMemory(const uint8_t *addr, const size_t nbytes, const std::string &asset_name, Layer *layer);
|
bool LoadLayerFromMemory(const uint8_t *addr, const size_t nbytes, const std::string &asset_name, const LoadState load_state, Layer *dest);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Loads `reference` USD asset and return it as Layer
|
/// Loads `reference` USD asset and return it as Layer
|
||||||
|
|||||||
@@ -518,6 +518,76 @@ class USDAReader::Impl {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterPrimSpecHandler() {
|
||||||
|
_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,
|
||||||
|
const prim::PropertyMap &properties,
|
||||||
|
const ascii::AsciiParser::PrimMetaMap &in_meta)
|
||||||
|
-> nonstd::expected<bool, std::string> {
|
||||||
|
|
||||||
|
if (!prim_name.is_valid()) {
|
||||||
|
return nonstd::make_unexpected("Invalid Prim name: " +
|
||||||
|
prim_name.full_path_name());
|
||||||
|
}
|
||||||
|
if (prim_name.is_absolute_path() || prim_name.is_root_path()) {
|
||||||
|
return nonstd::make_unexpected(
|
||||||
|
"Prim name should not starts with '/' or contain `/`: Prim "
|
||||||
|
"name = " +
|
||||||
|
prim_name.full_path_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prim_name.prop_part().empty()) {
|
||||||
|
return nonstd::make_unexpected(
|
||||||
|
"Prim path should not contain property part(`.`): Prim name "
|
||||||
|
"= " +
|
||||||
|
prim_name.full_path_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primIdx < 0) {
|
||||||
|
return nonstd::make_unexpected(
|
||||||
|
"Unexpected primIdx value. primIdx must be positive.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prim_name.prim_part().empty()) {
|
||||||
|
return nonstd::make_unexpected("Prim's name should not be empty ");
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimSpec primspec;
|
||||||
|
primspec.name() = prim_name.prim_part();
|
||||||
|
primspec.specifier() = spec;
|
||||||
|
primspec.typeName() = typeName;
|
||||||
|
|
||||||
|
DCOUT("primspec name, primType = " << prim_name.prim_part() << ", " << typeName);
|
||||||
|
|
||||||
|
// Assign index for PrimSpec
|
||||||
|
// TODO: Use sample id table(= _prim_nodes)
|
||||||
|
|
||||||
|
if (size_t(primIdx) >= _primspec_nodes.size()) {
|
||||||
|
_primspec_nodes.resize(size_t(primIdx) + 1);
|
||||||
|
}
|
||||||
|
DCOUT("sz " << std::to_string(_primspec_nodes.size())
|
||||||
|
<< ", primIdx = " << primIdx);
|
||||||
|
|
||||||
|
_primspec_nodes[size_t(primIdx)].primSpec = std::move(primspec);
|
||||||
|
DCOUT("primspec[" << primIdx << "].ty = "
|
||||||
|
<< _primspec_nodes[size_t(primIdx)].primSpec.typeName());
|
||||||
|
_primspec_nodes[size_t(primIdx)].parent = parentPrimIdx;
|
||||||
|
|
||||||
|
if (parentPrimIdx == -1) {
|
||||||
|
_toplevel_primspecs.push_back(size_t(primIdx));
|
||||||
|
} else {
|
||||||
|
_primspec_nodes[size_t(parentPrimIdx)].children.push_back(
|
||||||
|
size_t(primIdx));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ImportScene(tinyusdz::Stage &scene) { _imported_scene = scene; }
|
void ImportScene(tinyusdz::Stage &scene) { _imported_scene = scene; }
|
||||||
|
|
||||||
bool HasPath(const std::string &path) {
|
bool HasPath(const std::string &path) {
|
||||||
@@ -937,7 +1007,7 @@ class USDAReader::Impl {
|
|||||||
/// TODO: Use callback function(visitor) so that Reconstruct**** function is
|
/// TODO: Use callback function(visitor) so that Reconstruct**** function is
|
||||||
/// invoked in the Parser context.
|
/// invoked in the Parser context.
|
||||||
///
|
///
|
||||||
bool Read(ascii::LoadState state = ascii::LoadState::TOPLEVEL);
|
bool Read(LoadState state = LoadState::Toplevel);
|
||||||
|
|
||||||
// std::vector<GPrim> GetGPrims() { return _gprims; }
|
// std::vector<GPrim> GetGPrims() { return _gprims; }
|
||||||
|
|
||||||
@@ -1551,7 +1621,7 @@ bool USDAReader::Impl::ReconstructPrim(
|
|||||||
/// -- Impl Read
|
/// -- Impl Read
|
||||||
///
|
///
|
||||||
|
|
||||||
bool USDAReader::Impl::Read(ascii::LoadState state) {
|
bool USDAReader::Impl::Read(LoadState state) {
|
||||||
///
|
///
|
||||||
/// Setup callbacks.
|
/// Setup callbacks.
|
||||||
///
|
///
|
||||||
@@ -1559,6 +1629,10 @@ bool USDAReader::Impl::Read(ascii::LoadState state) {
|
|||||||
|
|
||||||
RegisterPrimIdxAssignCallback();
|
RegisterPrimIdxAssignCallback();
|
||||||
|
|
||||||
|
// For composition(load state = !Toplevel)
|
||||||
|
RegisterPrimSpecHandler();
|
||||||
|
|
||||||
|
// For direct Prim reconstruction(load state = Toplevel)
|
||||||
RegisterReconstructCallback<Model>(); // Generic prim.
|
RegisterReconstructCallback<Model>(); // Generic prim.
|
||||||
|
|
||||||
RegisterReconstructCallback<GPrim>(); // Geometric prim
|
RegisterReconstructCallback<GPrim>(); // Geometric prim
|
||||||
@@ -1600,80 +1674,6 @@ bool USDAReader::Impl::Read(ascii::LoadState state) {
|
|||||||
PUSH_ERROR_AND_RETURN("Parse failed:" + _parser.GetError());
|
PUSH_ERROR_AND_RETURN("Parse failed:" + _parser.GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
DCOUT("# of toplevel prims = " << std::to_string(PrimSize()));
|
|
||||||
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
for (auto it = PrimBegin(); it != PrimEnd(); ++it, i++) {
|
|
||||||
DCOUT("Prim[" << std::to_string(i) << "].type = " << (*it).type_name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//_sub_layered = (state == LOAD_STATE_SUBLAYER);
|
|
||||||
//_referenced = (state == LOAD_STATE_REFERENCE);
|
|
||||||
//_payloaded = (state == LOAD_STATE_PAYLOAD);
|
|
||||||
|
|
||||||
// Stage meta.
|
|
||||||
if (!_parser.ParseStageMetas()) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DCOUT("Done parsing Stage metas");
|
|
||||||
|
|
||||||
// parse blocks
|
|
||||||
while (!_parser.Eof()) {
|
|
||||||
if (!_parser.SkipCommentAndWhitespaceAndNewline()) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_parser.Eof()) {
|
|
||||||
// Whitespaces in the end of line.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look ahead token
|
|
||||||
auto curr_loc = _parser.CurrLoc();
|
|
||||||
DCOUT("loc = " << curr_loc);
|
|
||||||
|
|
||||||
std::string tok;
|
|
||||||
if (!_parser.ReadIdentifier(&tok)) {
|
|
||||||
DCOUT("Failed to read identifier");
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
DCOUT("tok = " << tok);
|
|
||||||
|
|
||||||
// Rewind
|
|
||||||
if (!_parser.SeekTo(curr_loc)) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok == "def") {
|
|
||||||
DCOUT("`def` block");
|
|
||||||
bool block_ok = _parser.ParseDefBlock();
|
|
||||||
if (!block_ok) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
} else if (tok == "over") {
|
|
||||||
DCOUT("`over` block");
|
|
||||||
bool block_ok = _parser.ParseOverBlock();
|
|
||||||
if (!block_ok) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
} else if (tok == "class") {
|
|
||||||
DCOUT("`class` block");
|
|
||||||
bool block_ok = _parser.ParseClassBlock();
|
|
||||||
if (!block_ok) {
|
|
||||||
PUSH_PARSER_ERROR_AND_RETURN();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PUSH_ERROR_AND_RETURN("Unknown identifier '" + tok + "' for Prim block statement.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1703,7 +1703,7 @@ USDAReader::USDAReader(StreamReader *sr) { _impl = new Impl(sr); }
|
|||||||
|
|
||||||
USDAReader::~USDAReader() { delete _impl; }
|
USDAReader::~USDAReader() { delete _impl; }
|
||||||
|
|
||||||
bool USDAReader::Read(ascii::LoadState state) { return _impl->Read(state); }
|
bool USDAReader::Read(const LoadState state) { return _impl->Read(state); }
|
||||||
|
|
||||||
void USDAReader::SetBaseDir(const std::string &dir) {
|
void USDAReader::SetBaseDir(const std::string &dir) {
|
||||||
return _impl->SetBaseDir(dir);
|
return _impl->SetBaseDir(dir);
|
||||||
@@ -1744,7 +1744,7 @@ USDAReader::~USDAReader() {
|
|||||||
|
|
||||||
bool USDAReader::CheckHeader() { return false; }
|
bool USDAReader::CheckHeader() { return false; }
|
||||||
|
|
||||||
bool USDAReader::Read(ascii::LoadState state) {
|
bool USDAReader::Read(const LoadState state) {
|
||||||
(void)state;
|
(void)state;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class USDAReader {
|
|||||||
///
|
///
|
||||||
/// Reader entry point
|
/// Reader entry point
|
||||||
///
|
///
|
||||||
bool Read(ascii::LoadState state = ascii::LoadState::TOPLEVEL);
|
bool Read(LoadState state = LoadState::Toplevel);
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user