Expose FromMemory loader API.

Fix wasi build.
This commit is contained in:
Syoyo Fujita
2022-09-16 04:43:58 +09:00
parent b0f660f049
commit 1d25f1ce52
7 changed files with 360 additions and 129 deletions

View File

@@ -19,17 +19,30 @@ list(
../../src/io-util.cc
../../src/prim-types.cc
../../src/pprinter.cc
../../src/value-pprint.cc
../../src/value-types.cc
../../src/primvar.cc
../../src/prim-types.cc
../../src/crate-format.cc
../../src/crate-reader.cc
../../src/crate-writer.cc
../../src/crate-pprint.cc
../../src/ascii-parser.cc
../../src/usda-reader.cc
../../src/usda-writer.cc
../../src/usdc-reader.cc
../../src/usdc-writer.cc
../../src/image-loader.cc
../../src/prim-reconstruct.cc
../../src/tiny-format.cc
../../src/xform.cc
../../src/usdGeom.cc
../../src/usdLux.cc
../../src/usdShade.cc
../../src/usdSkel.cc
../../src/usdMtlx.cc
../../src/usdObj.cc
../../src/tydra/render-data.cc
)
set(TINYUSDZ_DEP_SOURCES
@@ -37,6 +50,9 @@ set(TINYUSDZ_DEP_SOURCES
../../src/lz4-compression.cc
../../src/lz4/lz4.c
../../src/external/fpng.cpp
../../src/external/string_id/string_id.cpp
../../src/external/string_id/error.cpp
../../src/external/string_id/database.cpp
../../src/external/staticstruct.cc
../../src/external/tinyxml2/tinyxml2.cpp
)

View File

@@ -13,13 +13,23 @@ $ cd build
$ make
```
## Note
### Binary size
Currently is less than 4MB when compiled with `-DCMAKE_BUILD_TYPE=MinSizeRel`.
## Run
Currently tested by running app with `wasmtime`.
https://github.com/bytecodealliance/wasmtime
https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md
```
$ wasmtime tinyusdz_wasi
Install `wasmtime`, then copy example USD file to `build` folder(where `tinyusdz_wasi` is located. Otherwise add path using `--dir` option)
```bash
$ cp ../../../models/cube-previewsurface.usda .
$ wasmtime --dir=. tinyusdz_wasi cube-previewsurface.usda
```

View File

@@ -6,4 +6,4 @@ WASI_VERSION_FULL=${WASI_VERSION}.0
WASI_SDK_PATH=$HOME/local/wasi-sdk-${WASI_VERSION_FULL}
CC=${WASI_SDK_PATH}/bin/clang CXX=${WASI_SDK_PATH}/bin/clang++ cmake -DWASI_SDK_PATH=${WASI_SDK_PATH} -Bbuild -H.
CC=${WASI_SDK_PATH}/bin/clang CXX=${WASI_SDK_PATH}/bin/clang++ cmake -DWASI_SDK_PATH=${WASI_SDK_PATH} -Bbuild -DCMAKE_BUILD_TYPE=MinSizeRel -S.

View File

@@ -1,12 +1,137 @@
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include "tinyusdz.hh"
int main(int argc, char **argv)
{
static std::string GetFileExtension(const std::string &filename) {
if (filename.find_last_of(".") != std::string::npos)
return filename.substr(filename.find_last_of(".") + 1);
return "";
}
static std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c) { return std::tolower(c); } // correct
);
return s;
}
bool LoadModelFromString(const std::vector<uint8_t> &content,
const std::string &filename, tinyusdz::Stage *stage) {
std::string ext = str_tolower(GetFileExtension(filename));
std::string warn;
std::string err;
if (ext.compare("usdz") == 0) {
std::cout << "usdz\n";
bool ret = tinyusdz::LoadUSDZFromMemory(content.data(), content.size(), filename, stage, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
}
if (!ret) {
std::cerr << "Failed to load USDZ file: " << filename << "\n";
return false;
}
} else if (ext.compare("usda") == 0) {
std::cout << "usda\n";
bool ret = tinyusdz::LoadUSDAFromMemory(content.data(), content.size(), filename, stage, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
}
if (!ret) {
std::cerr << "Failed to load USDA file: " << filename << "\n";
return false;
}
} else { // assume usdc
bool ret = tinyusdz::LoadUSDCFromMemory(content.data(), content.size(), filename, stage, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
}
if (!ret) {
std::cerr << "Failed to load USDC file: " << filename << "\n";
return false;
}
}
return false;
}
// It looks WASI does not provide fopen(), so use open() to read file content.
std::vector<uint8_t> ReadFile(const char *arg) {
std::ostringstream ss;
ssize_t n;
char buf[BUFSIZ];
int in = open(arg, O_RDONLY);
if (in < 0) {
fprintf(stderr, "error opening input %s: %s\n", arg, strerror(errno));
exit(1);
}
while ((n = read(in, buf, BUFSIZ)) > 0) {
char *ptr = buf;
ss.write(ptr, n);
}
std::string s = ss.str();
size_t len = s.size();
std::vector<uint8_t> dst;
dst.resize(len);
std::cout << "input = " << s << "\n";
memcpy(dst.data(), s.data(), len);
return dst;
}
int main(int argc, char **argv) {
std::cout << "bora\n";
printf("sz = %d\n", sizeof(size_t));
if (argc > 1) {
std::string filename = argv[1];
std::vector<uint8_t> content = ReadFile(filename.c_str());
if (content.empty()) {
std::cerr << "File is empty or failed to read: " << filename << "\n";
}
tinyusdz::Stage stage;
bool ret = LoadModelFromString(content, filename, &stage);
if (!ret) {
return EXIT_FAILURE;
}
std::cout << "Load oK\n";
std::string outs = stage.ExportToString();
std::cout << outs;
} else {
std::cout << "Need input USD filename(.usda/.usdc/.usdz)\n";
}
return 0;
}

View File

@@ -194,7 +194,7 @@ inline void hash_combine_impl32(std::size_t &seed, const T &v)
template <class T>
inline void hash_combine(std::size_t &seed, const T &v) {
#if defined(__wasi__) // 32bit platform
hash_compbine_impl32(seed, v);
hash_combine_impl32(seed, v);
#else
if (sizeof(std::size_t) == 4) {
hash_combine_impl32(seed, v);

View File

@@ -43,19 +43,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_set>
#include <vector>
#include "image-loader.hh"
#include "integerCoding.h"
#include "io-util.hh"
#include "lz4-compression.hh"
#include "pprinter.hh"
#include "str-util.hh"
#include "stream-reader.hh"
#include "tinyusdz.hh"
#include "io-util.hh"
#include "pprinter.hh"
#include "usdShade.hh"
#include "usda-reader.hh"
#include "usdc-reader.hh"
#include "image-loader.hh"
#include "usdShade.hh"
#include "value-pprint.hh"
#include "str-util.hh"
#if 0
#if defined(TINYUSDZ_WITH_AUDIO)
@@ -128,15 +127,13 @@ class Node {
const Path &GetPath() const { return _path; }
//NodeType GetNodeType() const { return _node_type; }
// NodeType GetNodeType() const { return _node_type; }
const std::unordered_set<std::string> &GetPrimChildren() const {
return _primChildren;
}
void SetAssetInfo(const value::dict &dict) {
_assetInfo = dict;
}
void SetAssetInfo(const value::dict &dict) { _assetInfo = dict; }
const value::dict &GetAssetInfo() const { return _assetInfo; }
@@ -149,13 +146,13 @@ class Node {
Path _path; // local path
value::dict _assetInfo;
//NodeType _node_type;
// NodeType _node_type;
};
} // namespace
bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Stage *stage,
bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length,
const std::string &filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
if (stage == nullptr) {
@@ -169,7 +166,8 @@ bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Stage *stage,
if (length > size_t(1024 * 1024 * options.max_memory_limit_in_mb)) {
if (err) {
(*err) += "USDZ data is too large(size = " + std::to_string(length) +
(*err) += "USDC data [" + filename +
"] is too large(size = " + std::to_string(length) +
", which exceeds memory limit " +
std::to_string(options.max_memory_limit_in_mb) + " [mb]).\n";
}
@@ -194,12 +192,12 @@ bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Stage *stage,
return false;
}
//DCOUT("# of paths: " << reader.NumPaths());
//DCOUT("num_paths: " << std::to_string(parser.NumPaths()));
// DCOUT("# of paths: " << reader.NumPaths());
// DCOUT("num_paths: " << std::to_string(parser.NumPaths()));
//for (size_t i = 0; i < parser.NumPaths(); i++) {
//Path path = parser.GetPath(crate::Index(uint32_t(i)));
//DCOUT("path[" << i << "].name = " << path.full_path_name());
// for (size_t i = 0; i < parser.NumPaths(); i++) {
// Path path = parser.GetPath(crate::Index(uint32_t(i)));
// DCOUT("path[" << i << "].name = " << path.full_path_name());
//}
// Create `Stage` object
@@ -235,11 +233,12 @@ bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Stage *stage,
bool LoadUSDCFromFile(const std::string &_filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
std::string filepath = io::ExpandFilePath(_filename, /* userdata */nullptr);
std::string filepath = io::ExpandFilePath(_filename, /* userdata */ nullptr);
std::vector<uint8_t> data;
size_t max_bytes = size_t(1024 * 1024 * options.max_memory_limit_in_mb);
if (!io::ReadWholeFile(&data, err, filepath, max_bytes, /* userdata */nullptr)) {
if (!io::ReadWholeFile(&data, err, filepath, max_bytes,
/* userdata */ nullptr)) {
return false;
}
@@ -248,15 +247,14 @@ bool LoadUSDCFromFile(const std::string &_filename, Stage *stage,
if (data.size() < (11 * 8)) {
// ???
if (err) {
(*err) +=
"File size too short. Looks like this file is not a USDC : \"" +
filepath + "\"\n";
(*err) += "File size too short. Looks like this file is not a USDC : \"" +
filepath + "\"\n";
}
return false;
}
return LoadUSDCFromMemory(data.data(), data.size(), stage, warn, err,
options);
return LoadUSDCFromMemory(data.data(), data.size(), filepath, stage, warn,
err, options);
}
namespace {
@@ -269,46 +267,43 @@ static std::string GetFileExtension(const std::string &filename) {
static std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::tolower(c); }
);
[](unsigned char c) { return std::tolower(c); });
return s;
}
} // namespace
bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
bool LoadUSDZFromMemory(const uint8_t *addr, const size_t length,
const std::string &filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
// <filename, byte_begin, byte_end>
std::vector<std::tuple<std::string, size_t, size_t>> assets;
std::string filepath = io::ExpandFilePath(_filename, /* userdata */nullptr);
std::vector<uint8_t> data;
size_t max_bytes = size_t(1024 * 1024 * options.max_memory_limit_in_mb);
if (!io::ReadWholeFile(&data, err, filepath, max_bytes, /* userdata */nullptr)) {
return false;
}
if (data.size() < (11 * 8) + 30) { // 88 for USDC header, 30 for ZIP header
// ???
if (!addr) {
if (err) {
(*err) +=
"File size too short. Looks like this file is not a USDZ : \"" +
filepath + "\"\n";
(*err) += "null for `addr` argument.\n";
}
return false;
}
if (length < (11 * 8) + 30) { // 88 for USDC header, 30 for ZIP header
// ???
if (err) {
(*err) += "File size too short. Looks like this file is not a USDZ : \"" +
filename + "\"\n";
}
return false;
}
size_t offset = 0;
while ((offset + 30) < data.size()) {
while ((offset + 30) < length) {
//
// PK zip format:
// https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
//
std::vector<char> local_header(30);
memcpy(local_header.data(), data.data() + offset, 30);
memcpy(local_header.data(), addr + offset, 30);
// if we've reached the global header, stop reading
if (local_header[2] != 0x03 || local_header[3] != 0x04) break;
@@ -318,7 +313,7 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
// read in the variable name
uint16_t name_len;
memcpy(&name_len, &local_header[26], sizeof(uint16_t));
if ((offset + name_len) > data.size()) {
if ((offset + name_len) > length) {
if (err) {
(*err) += "Invalid ZIP data\n";
}
@@ -326,7 +321,7 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
}
std::string varname(name_len, ' ');
memcpy(&varname[0], data.data() + offset, name_len);
memcpy(&varname[0], addr + offset, name_len);
offset += name_len;
@@ -334,7 +329,7 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
uint16_t extra_field_len;
memcpy(&extra_field_len, &local_header[28], sizeof(uint16_t));
if (extra_field_len > 0) {
if (offset + extra_field_len > data.size()) {
if (offset + extra_field_len > length) {
if (err) {
(*err) += "Invalid extra field length in ZIP data\n";
}
@@ -413,16 +408,16 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
}
{
const size_t start_addr = std::get<1>(assets[size_t(usdc_index)]);
const size_t end_addr = std::get<2>(assets[size_t(usdc_index)]);
const size_t usdc_size = end_addr - start_addr;
const uint8_t *usdc_addr = &data[start_addr];
bool ret =
LoadUSDCFromMemory(usdc_addr, usdc_size, stage, warn, err, options);
const size_t start_addr_offset = std::get<1>(assets[size_t(usdc_index)]);
const size_t end_addr_offset = std::get<2>(assets[size_t(usdc_index)]);
const size_t usdc_size = end_addr_offset - start_addr_offset;
const uint8_t *usdc_addr = addr + start_addr_offset;
bool ret = LoadUSDCFromMemory(usdc_addr, usdc_size, filename, stage, warn,
err, options);
if (!ret) {
if (err) {
(*err) += "Failed to load USDC.\n";
(*err) += "Failed to load USDZ: [" + filename + "].\n";
}
return false;
@@ -436,14 +431,16 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
if ((ext.compare("png") == 0) || (ext.compare("jpg") == 0) ||
(ext.compare("jpeg") == 0)) {
const size_t start_addr = std::get<1>(assets[i]);
const size_t end_addr = std::get<2>(assets[i]);
const size_t usdc_size = end_addr - start_addr;
const uint8_t *usdc_addr = &data[start_addr];
const size_t start_addr_offset = std::get<1>(assets[i]);
const size_t end_addr_offset = std::get<2>(assets[i]);
const size_t usdc_size = end_addr_offset - start_addr_offset;
const uint8_t *usdc_addr = addr + start_addr_offset;
Image image;
nonstd::expected<image::ImageResult, std::string> ret = image::LoadImageFromMemory(usdc_addr, usdc_size, uri);
//bool ret = DecodeImage(usdc_addr, usdc_size, uri, &image, &_warn, &_err);
nonstd::expected<image::ImageResult, std::string> ret =
image::LoadImageFromMemory(usdc_addr, usdc_size, uri);
// bool ret = DecodeImage(usdc_addr, usdc_size, uri, &image, &_warn,
// &_err);
if (!ret) {
(*err) += ret.error();
@@ -453,12 +450,42 @@ bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
(*warn) += (*ret).warning;
}
}
} else {
// TODO: Support other asserts(e.g. audio mp3)
}
}
return true;
}
bool LoadUSDZFromFile(const std::string &_filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
// <filename, byte_begin, byte_end>
std::vector<std::tuple<std::string, size_t, size_t>> assets;
std::string filepath = io::ExpandFilePath(_filename, /* userdata */ nullptr);
std::vector<uint8_t> data;
size_t max_bytes = size_t(1024 * 1024 * options.max_memory_limit_in_mb);
if (!io::ReadWholeFile(&data, err, filepath, max_bytes,
/* userdata */ nullptr)) {
return false;
}
if (data.size() < (11 * 8) + 30) { // 88 for USDC header, 30 for ZIP header
// ???
if (err) {
(*err) += "File size too short. Looks like this file is not a USDZ : \"" +
filepath + "\"\n";
}
return false;
}
return LoadUSDZFromMemory(data.data(), data.size(), filepath, stage, warn,
err, options);
}
#ifdef _WIN32
bool LoadUSDZFromFile(const std::wstring &_filename, Stage *stage,
std::string *warn, std::string *err,
@@ -468,7 +495,8 @@ bool LoadUSDZFromFile(const std::wstring &_filename, Stage *stage,
}
#endif
bool LoadUSDAFromMemory(const uint8_t *addr, const size_t length, const std::string &base_dir, Stage *stage,
bool LoadUSDAFromMemory(const uint8_t *addr, const size_t length,
const std::string &base_dir, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
(void)warn;
@@ -526,19 +554,18 @@ bool LoadUSDAFromMemory(const uint8_t *addr, const size_t length, const std::str
bool LoadUSDAFromFile(const std::string &_filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options) {
std::string filepath = io::ExpandFilePath(_filename, /* userdata */nullptr);
std::string filepath = io::ExpandFilePath(_filename, /* userdata */ nullptr);
std::string base_dir = io::GetBaseDir(_filename);
std::vector<uint8_t> data;
size_t max_bytes = size_t(1024 * 1024 * options.max_memory_limit_in_mb);
if (!io::ReadWholeFile(&data, err, filepath, max_bytes, /* userdata */nullptr)) {
if (!io::ReadWholeFile(&data, err, filepath, max_bytes,
/* userdata */ nullptr)) {
return false;
}
return LoadUSDAFromMemory(data.data(), data.size(), base_dir, stage, warn, err,
options);
return LoadUSDAFromMemory(data.data(), data.size(), base_dir, stage, warn,
err, options);
}
///
@@ -547,46 +574,79 @@ bool LoadUSDAFromFile(const std::string &_filename, Stage *stage,
namespace {
nonstd::optional<Path> GetPath(const value::Value &v)
{
nonstd::optional<Path> GetPath(const value::Value &v) {
//
// TODO: Find a better C++ way... use a std::function?
//
if (auto pv = v.get_value<Model>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<Scope>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<Xform>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GPrim>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomMesh>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomBasisCurves>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomSphere>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomCube>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomCylinder>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomCapsule>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomCone>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomSubset>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<GeomCamera>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<Model>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<Scope>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<Xform>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GPrim>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomMesh>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomBasisCurves>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomSphere>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomCube>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomCylinder>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomCapsule>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomCone>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomSubset>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<GeomCamera>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<LuxDomeLight>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<LuxSphereLight>()) { return Path(pv.value().name, ""); }
//if (auto pv = v.get_value<LuxCylinderLight>()) { return Path(pv.value().name); }
//if (auto pv = v.get_value<LuxDiskLight>()) { return Path(pv.value().name); }
if (auto pv = v.get_value<LuxDomeLight>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<LuxSphereLight>()) {
return Path(pv.value().name, "");
}
// if (auto pv = v.get_value<LuxCylinderLight>()) { return
// Path(pv.value().name); } if (auto pv = v.get_value<LuxDiskLight>()) {
// return Path(pv.value().name); }
if (auto pv = v.get_value<Material>()) { return Path(pv.value().name, ""); }
if (auto pv = v.get_value<Shader>()) { return Path(pv.value().name, ""); }
//if (auto pv = v.get_value<UVTexture>()) { return Path(pv.value().name); }
//if (auto pv = v.get_value<PrimvarReader()) { return Path(pv.value().name); }
if (auto pv = v.get_value<Material>()) {
return Path(pv.value().name, "");
}
if (auto pv = v.get_value<Shader>()) {
return Path(pv.value().name, "");
}
// if (auto pv = v.get_value<UVTexture>()) { return Path(pv.value().name); }
// if (auto pv = v.get_value<PrimvarReader()) { return Path(pv.value().name);
// }
return nonstd::nullopt;
}
} // namespace
} // namespace
Prim::Prim(const value::Value &rhs)
{
Prim::Prim(const value::Value &rhs) {
// Check if Prim type is Model(GPrim)
if ((value::TypeId::TYPE_ID_MODEL_BEGIN <= rhs.type_id()) &&
(value::TypeId::TYPE_ID_MODEL_END > rhs.type_id())) {
if (auto pv = GetPath(rhs)) {
path = pv.value();
}
@@ -597,12 +657,10 @@ Prim::Prim(const value::Value &rhs)
}
}
Prim::Prim(value::Value &&rhs)
{
Prim::Prim(value::Value &&rhs) {
// Check if Prim type is Model(GPrim)
if ((value::TypeId::TYPE_ID_MODEL_BEGIN <= rhs.type_id()) &&
(value::TypeId::TYPE_ID_MODEL_END > rhs.type_id())) {
data = std::move(rhs);
if (auto pv = GetPath(data)) {
@@ -616,10 +674,10 @@ Prim::Prim(value::Value &&rhs)
namespace {
nonstd::optional<const Prim*> GetPrimAtPathRec(const Prim *parent, const Path &path) {
nonstd::optional<const Prim *> GetPrimAtPathRec(const Prim *parent,
const Path &path) {
//// TODO: Find better way to get path name from any value.
//if (auto pv = parent.get_value<Xform>)
// if (auto pv = parent.get_value<Xform>)
if (auto pv = GetPath(parent->data)) {
if (path == pv.value()) {
return parent;
@@ -635,11 +693,10 @@ nonstd::optional<const Prim*> GetPrimAtPathRec(const Prim *parent, const Path &p
return nonstd::nullopt;
}
} // namespace
} // namespace
nonstd::expected<const Prim*, std::string> Stage::GetPrimAtPath(const Path &path)
{
nonstd::expected<const Prim *, std::string> Stage::GetPrimAtPath(
const Path &path) {
if (!path.IsValid()) {
return nonstd::make_unexpected("Path is invalid.\n");
}
@@ -650,7 +707,8 @@ nonstd::expected<const Prim*, std::string> Stage::GetPrimAtPath(const Path &path
}
if (!path.IsAbsolutePath()) {
return nonstd::make_unexpected("Path is not absolute. Non-absolute Path is TODO.\n");
return nonstd::make_unexpected(
"Path is not absolute. Non-absolute Path is TODO.\n");
}
// Brute-force search.
@@ -661,35 +719,35 @@ nonstd::expected<const Prim*, std::string> Stage::GetPrimAtPath(const Path &path
}
}
return nonstd::make_unexpected("Cannot find path <" + path.full_path_name() + "> int the Stage.\n");
return nonstd::make_unexpected("Cannot find path <" + path.full_path_name() +
"> int the Stage.\n");
}
namespace {
void PrimPrintRec(std::stringstream &ss, const Prim &prim, uint32_t indent)
{
void PrimPrintRec(std::stringstream &ss, const Prim &prim, uint32_t indent) {
ss << "\n";
ss << pprint_value(prim.data, indent, /* closing_brace */false);
ss << pprint_value(prim.data, indent, /* closing_brace */ false);
DCOUT("num_children = " << prim.children.size());
for (const auto &child : prim.children) {
PrimPrintRec(ss, child, indent+1);
PrimPrintRec(ss, child, indent + 1);
}
ss << pprint::Indent(indent) << "}\n";
}
} // namespace
} // namespace
std::string Stage::ExportToString() const {
std::stringstream ss;
ss << "#usda 1.0\n";
ss << "(\n";
if (stage_metas.doc.value.empty()) {
ss << " doc = \"Exporterd from TinyUSDZ v" << tinyusdz::version_major << "."
<< tinyusdz::version_minor << "." << tinyusdz::version_micro << "\"\n";
ss << " doc = \"Exporterd from TinyUSDZ v" << tinyusdz::version_major
<< "." << tinyusdz::version_minor << "." << tinyusdz::version_micro
<< "\"\n";
} else {
ss << " doc = " << to_string(stage_metas.doc) << "\n";
}
@@ -699,11 +757,13 @@ std::string Stage::ExportToString() const {
}
if (stage_metas.upAxis.authored()) {
ss << " upAxis = " << quote(to_string(stage_metas.upAxis.GetValue())) << "\n";
ss << " upAxis = " << quote(to_string(stage_metas.upAxis.GetValue()))
<< "\n";
}
if (stage_metas.timeCodesPerSecond.authored()) {
ss << " timeCodesPerSecond = " << stage_metas.timeCodesPerSecond.GetValue() << "\n";
ss << " timeCodesPerSecond = " << stage_metas.timeCodesPerSecond.GetValue()
<< "\n";
}
if (stage_metas.startTimeCode.authored()) {
@@ -715,14 +775,16 @@ std::string Stage::ExportToString() const {
}
if (stage_metas.defaultPrim.str().size()) {
ss << " defaultPrim = " << tinyusdz::quote(stage_metas.defaultPrim.str()) << "\n";
ss << " defaultPrim = " << tinyusdz::quote(stage_metas.defaultPrim.str())
<< "\n";
}
if (!stage_metas.comment.value.empty()) {
ss << " doc = " << to_string(stage_metas.comment) << "\n";
}
if (stage_metas.customLayerData.size()) {
ss << print_customData(stage_metas.customLayerData, "customLayerData", /* indent */1);
ss << print_customData(stage_metas.customLayerData, "customLayerData",
/* indent */ 1);
}
// TODO: Sort by line_no?(preserve appearance in read USDA)
@@ -739,7 +801,6 @@ std::string Stage::ExportToString() const {
}
return ss.str();
}
} // namespace tinyusdz

View File

@@ -570,6 +570,24 @@ bool LoadUSDZFromFile(const std::wstring &filename, Stage *stage,
const USDLoadOptions &options = USDLoadOptions());
#endif
///
/// Load USDZ(zip) from memory.
///
/// @param[in] addr Memory address of USDZ data
/// @param[in] length Byte length of USDZ data
/// @param[in] filename Filename(can be empty).
/// @param[out] stage USD stage(scene graph).
/// @param[out] warn Warning message.
/// @param[out] err Error message(filled when the function returns false)
/// @param[in] options Load options(optional)
///
/// @return true upon success
///
bool LoadUSDZFromMemory(const uint8_t *addr, const size_t length, const std::string &filename,
Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options = USDLoadOptions());
///
/// Load USDC(binary) from a file.
///
@@ -590,6 +608,7 @@ bool LoadUSDCFromFile(const std::string &filename, Stage *stage,
///
/// @param[in] addr Memory address of USDC data
/// @param[in] length Byte length of USDC data
/// @param[in] filename Filename(can be empty).
/// @param[out] stage USD stage.
/// @param[out] warn Warning message.
/// @param[out] err Error message(filled when the function returns false)
@@ -597,7 +616,7 @@ bool LoadUSDCFromFile(const std::string &filename, Stage *stage,
///
/// @return true upon success
///
bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Stage *stage,
bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, const std::string &filename, Stage *stage,
std::string *warn, std::string *err,
const USDLoadOptions &options = USDLoadOptions());