Open8
three.js 向けに USDZ loader を作るメモ

TinyUSDZ の JS binding(emscripten, wasm)作って, three.js で読めるようにしたい...

基本情報
まず Three.js でのローダは, core の機能ではなく addon として提供される.
たとえば wavefront .obj loader
ソースコードとしては, examples/jsm/loaders
にある.

emscripten デフォだと export されるのは Module
クラスになる模様?

-sMODULARIZE=1 -sEXPORT_ES6=1 -sEXPORT_NAME=tinyusdz
あたりを設定するとよいようだが...

wasm は非同期処理になるので,
基本的には module["onRuntimeInitialized"] でしかつかえない
-sMODULARIZE
で require で Promise が帰るようにすることはできる.

#include <emscripten/bind.h>
#include <vector>
using namespace emscripten;
///
/// Simple C++ wrapper class for Emscripten
///
class MyLoader {
public:
MyLoader(const std::string &binary) {
binary_ = binary;
}
~MyLoader() {}
bool ok() const { return binary_.size(); }
const std::string error() const { return error_; }
private:
std::string binary_;
std::string warn_;
std::string error_;
};
// Register STL
EMSCRIPTEN_BINDINGS(stl_wrappters) {
register_vector<float>("VectorFloat");
register_vector<int>("VectorInt");
register_vector<uint32_t>("VectorUInt");
}
EMSCRIPTEN_BINDINGS(myloader_module) {
class_<MyLoader>("MyLoader")
.constructor<const std::string &>()
.function("ok", &MyLoader::ok)
.function("error", &MyLoader::error);
}
でまずはテストしてみる.
コンパイルは以下
emcc --bind -Os simple.cc -sMODULARIZE -s ALLOW_MEMORY_GROWTH=1 -o myloader.js
とりあえずは以下のような感じにる
var factory = require('./myloader.js')
factory().then((instance) => {
let mystr = "aaaa";
loader = new instance.MyLoader(mystr);
console.log(loader.ok());
});
import Module from './myloader.js';
Module().then(function(mymod) {
let mystr = "aaaa";
const loader = new mymod.MyLoader(mystr);
console.log(loader.ok());
});
Jolt での例

より逐次的にしたい場合は, await を使うといいのだろうか...
(bun で実行確認)
import Module from './myloader.js';
const mymod = await Module();
let mystr = "aaaa";
const loader = new mymod.MyLoader(mystr);
console.log(loader.ok());

テクスチャは TinyUSDZ(Tydra) で読むことができる.
その場合はテクスチャデータを ImageData として, theejs TextureLoader に渡すとよいか?