mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Expose FromMemory loader API.
Fix wasi build.
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
303
src/tinyusdz.cc
303
src/tinyusdz.cc
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user