tinyusdz.hh 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824
  1. /*
  2. Copyright (c) 2019 - 2020, Syoyo Fujita.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * Neither the name of the Syoyo Fujita nor the
  12. names of its contributors may be used to endorse or promote products
  13. derived from this software without specific prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  18. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef TINYUSDZ_HH_
  26. #define TINYUSDZ_HH_
  27. #include <array>
  28. #include <cstring>
  29. #include <limits>
  30. #include <map>
  31. #include <string>
  32. #include <utility>
  33. #include <vector>
  34. #define TINYUSDZ_LOCAL_DEBUG_PRINT (0) ////
  35. // #if TINYUSDZ_LOCAL_DEBUG_PRINT ////
  36. #include <iostream> // dbg
  37. // #endif ////
  38. namespace tinyusdz {
  39. // Simple image class.
  40. // No colorspace conversion will be applied when decoding image data(e.g. from
  41. // .jpg, .png).
  42. // TODO(syoyo): Add option to decode image into linear space.
  43. struct Image {
  44. std::string uri; // filename or uri;
  45. int width{-1}; // -1 = invalid
  46. int height{-1}; // -1 = invalid
  47. int channels{-1}; // Image channels. 3=RGB, 4=RGBA. -1 = invalid
  48. int bpp{-1}; // bits per pixel. 8=LDR, 16=HDR
  49. std::vector<uint8_t> data;
  50. };
  51. // TODO(syoyo): Support Big Endian
  52. // https://gist.github.com/rygorous/2156668
  53. union FP32 {
  54. unsigned int u;
  55. float f;
  56. struct {
  57. #if 1
  58. unsigned int Mantissa : 23;
  59. unsigned int Exponent : 8;
  60. unsigned int Sign : 1;
  61. #else
  62. unsigned int Sign : 1;
  63. unsigned int Exponent : 8;
  64. unsigned int Mantissa : 23;
  65. #endif
  66. } s;
  67. };
  68. #ifdef __clang__
  69. #pragma clang diagnostic push
  70. #pragma clang diagnostic ignored "-Wpadded"
  71. #endif
  72. // NOTE: usually sizeof(float16) == 4, not 2
  73. union float16 {
  74. unsigned short u;
  75. struct {
  76. #if 1
  77. unsigned int Mantissa : 10;
  78. unsigned int Exponent : 5;
  79. unsigned int Sign : 1;
  80. #else
  81. unsigned int Sign : 1;
  82. unsigned int Exponent : 5;
  83. unsigned int Mantissa : 10;
  84. #endif
  85. } s;
  86. };
  87. float half_to_float(float16 h);
  88. float16 float_to_half_full(float f);
  89. template <typename T, size_t N>
  90. struct Matrix {
  91. T m[N][N];
  92. constexpr static uint32_t n = N;
  93. };
  94. using Matrix2f = Matrix<float, 2>;
  95. using Matrix2d = Matrix<double, 2>;
  96. using Matrix3f = Matrix<float, 3>;
  97. using Matrix3d = Matrix<double, 3>;
  98. using Matrix4f = Matrix<float, 4>;
  99. using Matrix4d = Matrix<double, 4>;
  100. using Vec4i = std::array<int32_t, 4>;
  101. using Vec3i = std::array<int32_t, 3>;
  102. using Vec2i = std::array<int32_t, 2>;
  103. // Use uint16_t for storage of half type.
  104. // Need to decode/encode value through half converter functions
  105. using Vec4h = std::array<uint16_t, 4>;
  106. using Vec3h = std::array<uint16_t, 3>;
  107. using Vec2h = std::array<uint16_t, 2>;
  108. using Vec4f = std::array<float, 4>;
  109. using Vec3f = std::array<float, 3>;
  110. using Vec2f = std::array<float, 2>;
  111. using Vec4d = std::array<double, 4>;
  112. using Vec3d = std::array<double, 3>;
  113. using Vec2d = std::array<double, 2>;
  114. using Quath = std::array<uint16_t, 4>;
  115. using Quatf = std::array<float, 4>;
  116. using Quatd = std::array<double, 4>;
  117. using Quaternion = std::array<double, 4>; // Storage layout is same with Quadd,
  118. // so we can delete this
  119. // TODO(syoyo): Range, Interval, Rect2i, Frustum, MultiInterval
  120. /*
  121. #define VT_GFRANGE_VALUE_TYPES \
  122. (( GfRange3f, Range3f )) \
  123. (( GfRange3d, Range3d )) \
  124. (( GfRange2f, Range2f )) \
  125. (( GfRange2d, Range2d )) \
  126. (( GfRange1f, Range1f )) \
  127. (( GfRange1d, Range1d ))
  128. #define VT_RANGE_VALUE_TYPES \
  129. VT_GFRANGE_VALUE_TYPES \
  130. (( GfInterval, Interval )) \
  131. (( GfRect2i, Rect2i ))
  132. #define VT_STRING_VALUE_TYPES \
  133. (( std::string, String )) \
  134. (( TfToken, Token ))
  135. #define VT_QUATERNION_VALUE_TYPES \
  136. (( GfQuath, Quath )) \
  137. (( GfQuatf, Quatf )) \
  138. (( GfQuatd, Quatd )) \
  139. (( GfQuaternion, Quaternion ))
  140. #define VT_NONARRAY_VALUE_TYPES \
  141. (( GfFrustum, Frustum)) \
  142. (( GfMultiInterval, MultiInterval))
  143. */
  144. template <typename T>
  145. class ListOp {
  146. public:
  147. ListOp() : is_explicit(false) {}
  148. void ClearAndMakeExplicit() {
  149. explicit_items.clear();
  150. added_items.clear();
  151. prepended_items.clear();
  152. appended_items.clear();
  153. deleted_items.clear();
  154. ordered_items.clear();
  155. is_explicit = true;
  156. }
  157. bool HasExplicitItems() const { return explicit_items.size(); }
  158. bool HasAddedItems() const { return added_items.size(); }
  159. bool HasPrependedItems() const { return prepended_items.size(); }
  160. bool HasAppendedItems() const { return appended_items.size(); }
  161. bool HasDeletedItems() const { return deleted_items.size(); }
  162. bool HasOrderedItems() const { return deleted_items.size(); }
  163. const std::vector<T> &GetExplicitItems() const { return explicit_items; }
  164. const std::vector<T> &GetAddedItems() const { return added_items; }
  165. const std::vector<T> &GetPrependedItems() const { return prepended_items; }
  166. const std::vector<T> &GetAppendedItems() const { return appended_items; }
  167. const std::vector<T> &GetDeletedItems() const { return deleted_items; }
  168. const std::vector<T> &GetOrderedItems() const { return ordered_items; }
  169. void SetExplicitItems(const std::vector<T> &v) { explicit_items = v; }
  170. void SetAddedItems(const std::vector<T> &v) { added_items = v; }
  171. void SetPrependedItems(const std::vector<T> &v) { prepended_items = v; }
  172. void SetAppendedItems(const std::vector<T> &v) { appended_items = v; }
  173. void SetDeletedItems(const std::vector<T> &v) { deleted_items = v; }
  174. void SetOrderedItems(const std::vector<T> &v) { ordered_items = v; }
  175. #if TINYUSDZ_LOCAL_DEBUG_PRINT
  176. void Print() const {
  177. std::cout << "is_explicit:" << is_explicit << "\n";
  178. std::cout << "# of explicit_items" << explicit_items.size() << "\n";
  179. std::cout << "# of added_items" << added_items.size() << "\n";
  180. std::cout << "# of prepended_items" << prepended_items.size() << "\n";
  181. std::cout << "# of deleted_items" << deleted_items.size() << "\n";
  182. std::cout << "# of ordered_items" << ordered_items.size() << "\n";
  183. }
  184. #endif
  185. private:
  186. bool is_explicit{false};
  187. std::vector<T> explicit_items;
  188. std::vector<T> added_items;
  189. std::vector<T> prepended_items;
  190. std::vector<T> appended_items;
  191. std::vector<T> deleted_items;
  192. std::vector<T> ordered_items;
  193. };
  194. struct ListOpHeader {
  195. enum Bits {
  196. IsExplicitBit = 1 << 0,
  197. HasExplicitItemsBit = 1 << 1,
  198. HasAddedItemsBit = 1 << 2,
  199. HasDeletedItemsBit = 1 << 3,
  200. HasOrderedItemsBit = 1 << 4,
  201. HasPrependedItemsBit = 1 << 5,
  202. HasAppendedItemsBit = 1 << 6
  203. };
  204. ListOpHeader() : bits(0) {}
  205. explicit ListOpHeader(uint8_t b) : bits(b) {}
  206. explicit ListOpHeader(ListOpHeader const &op) : bits(0) {
  207. bits |= op.IsExplicit() ? IsExplicitBit : 0;
  208. bits |= op.HasExplicitItems() ? HasExplicitItemsBit : 0;
  209. bits |= op.HasAddedItems() ? HasAddedItemsBit : 0;
  210. bits |= op.HasPrependedItems() ? HasPrependedItemsBit : 0;
  211. bits |= op.HasAppendedItems() ? HasAppendedItemsBit : 0;
  212. bits |= op.HasDeletedItems() ? HasDeletedItemsBit : 0;
  213. bits |= op.HasOrderedItems() ? HasOrderedItemsBit : 0;
  214. }
  215. bool IsExplicit() const { return bits & IsExplicitBit; }
  216. bool HasExplicitItems() const { return bits & HasExplicitItemsBit; }
  217. bool HasAddedItems() const { return bits & HasAddedItemsBit; }
  218. bool HasPrependedItems() const { return bits & HasPrependedItemsBit; }
  219. bool HasAppendedItems() const { return bits & HasAppendedItemsBit; }
  220. bool HasDeletedItems() const { return bits & HasDeletedItemsBit; }
  221. bool HasOrderedItems() const { return bits & HasOrderedItemsBit; }
  222. uint8_t bits;
  223. };
  224. ///
  225. /// We don't need the performance for USDZ, so use naiive implementation
  226. /// to represent Path.
  227. /// Path is something like Unix path, delimited by `/`, ':' and '.'
  228. ///
  229. /// Example:
  230. ///
  231. /// `/muda/bora.dora` : prim_part is `/muda/bora`, prop_part is `.dora`.
  232. ///
  233. /// ':' is a namespce delimiter(example `input:muda`).
  234. ///
  235. /// Limitations:
  236. ///
  237. /// Relational attribute path(`[` `]`. e.g. `/muda/bora[/ari].dora`) is not
  238. /// supported.
  239. ///
  240. /// variant chars('{' '}') is not supported.
  241. /// '..' is not supported
  242. ///
  243. /// and have more limitatons.
  244. ///
  245. class Path {
  246. public:
  247. Path() : valid(false) {}
  248. Path(const std::string &prim)
  249. : prim_part(prim), local_part(prim), valid(true) {}
  250. // Path(const std::string &prim, const std::string &prop)
  251. // : prim_part(prim), prop_part(prop) {}
  252. Path(const Path &rhs) = default;
  253. Path &operator=(const Path &rhs) {
  254. this->valid = rhs.valid;
  255. this->prim_part = rhs.prim_part;
  256. this->prop_part = rhs.prop_part;
  257. this->local_part = rhs.local_part;
  258. return (*this);
  259. }
  260. std::string full_path_name() const {
  261. std::string s;
  262. if (!valid) {
  263. s += "INVALID#";
  264. }
  265. s += prim_part;
  266. if (prop_part.empty()) {
  267. return s;
  268. }
  269. s += "." + prop_part;
  270. return s;
  271. }
  272. std::string local_path_name() const {
  273. std::string s;
  274. if (!valid) {
  275. s += "INVALID#";
  276. }
  277. s += local_part;
  278. return s;
  279. }
  280. std::string GetPrimPart() const { return prim_part; }
  281. std::string GetPropPart() const { return prop_part; }
  282. bool IsEmpty() { return (prim_part.empty() && prop_part.empty()); }
  283. static Path AbsoluteRootPath() { return Path("/"); }
  284. void SetLocalPath(const Path &rhs) {
  285. // assert(rhs.valid == true);
  286. this->local_part = rhs.local_part;
  287. this->valid = rhs.valid;
  288. }
  289. Path AppendProperty(const std::string &elem) {
  290. Path p = (*this);
  291. if (elem.empty()) {
  292. p.valid = false;
  293. return p;
  294. }
  295. if (elem[0] == '{') {
  296. // variant chars are not supported
  297. p.valid = false;
  298. return p;
  299. } else if (elem[0] == '[') {
  300. // relational attrib are not supported
  301. p.valid = false;
  302. return p;
  303. } else if (elem[0] == '.') {
  304. // std::cerr << "???. elem[0] is '.'\n";
  305. // For a while, make this valid.
  306. p.valid = false;
  307. return p;
  308. } else {
  309. p.prop_part = elem;
  310. return p;
  311. }
  312. }
  313. Path AppendElement(const std::string &elem) {
  314. Path p = (*this);
  315. if (elem.empty()) {
  316. p.valid = false;
  317. return p;
  318. }
  319. if (elem[0] == '{') {
  320. // variant chars are not supported
  321. p.valid = false;
  322. return p;
  323. } else if (elem[0] == '[') {
  324. // relational attrib are not supported
  325. p.valid = false;
  326. return p;
  327. } else if (elem[0] == '.') {
  328. // std::cerr << "???. elem[0] is '.'\n";
  329. // For a while, make this valid.
  330. p.valid = false;
  331. return p;
  332. } else {
  333. // std::cout << "elem " << elem << "\n";
  334. if ((p.prim_part.size() == 1) && (p.prim_part[0] == '/')) {
  335. p.prim_part += elem;
  336. } else {
  337. p.prim_part += '/' + elem;
  338. }
  339. return p;
  340. }
  341. }
  342. bool IsValid() const { return valid; }
  343. private:
  344. std::string prim_part; // full path
  345. std::string prop_part; // full path
  346. std::string local_part;
  347. bool valid{false};
  348. };
  349. enum ValueTypeId {
  350. VALUE_TYPE_INVALID = 0,
  351. VALUE_TYPE_BOOL = 1,
  352. VALUE_TYPE_UCHAR = 2,
  353. VALUE_TYPE_INT = 3,
  354. VALUE_TYPE_UINT = 4,
  355. VALUE_TYPE_INT64 = 5,
  356. VALUE_TYPE_UINT64 = 6,
  357. VALUE_TYPE_HALF = 7,
  358. VALUE_TYPE_FLOAT = 8,
  359. VALUE_TYPE_DOUBLE = 9,
  360. VALUE_TYPE_STRING = 10,
  361. VALUE_TYPE_TOKEN = 11,
  362. VALUE_TYPE_ASSET_PATH = 12,
  363. VALUE_TYPE_MATRIX2D = 13,
  364. VALUE_TYPE_MATRIX3D = 14,
  365. VALUE_TYPE_MATRIX4D = 15,
  366. VALUE_TYPE_QUATD = 16,
  367. VALUE_TYPE_QUATF = 17,
  368. VALUE_TYPE_QUATH = 18,
  369. VALUE_TYPE_VEC2D = 19,
  370. VALUE_TYPE_VEC2F = 20,
  371. VALUE_TYPE_VEC2H = 21,
  372. VALUE_TYPE_VEC2I = 22,
  373. VALUE_TYPE_VEC3D = 23,
  374. VALUE_TYPE_VEC3F = 24,
  375. VALUE_TYPE_VEC3H = 25,
  376. VALUE_TYPE_VEC3I = 26,
  377. VALUE_TYPE_VEC4D = 27,
  378. VALUE_TYPE_VEC4F = 28,
  379. VALUE_TYPE_VEC4H = 29,
  380. VALUE_TYPE_VEC4I = 30,
  381. VALUE_TYPE_DICTIONARY = 31,
  382. VALUE_TYPE_TOKEN_LIST_OP = 32,
  383. VALUE_TYPE_STRING_LIST_OP = 33,
  384. VALUE_TYPE_PATH_LIST_OP = 34,
  385. VALUE_TYPE_REFERENCE_LIST_OP = 35,
  386. VALUE_TYPE_INT_LIST_OP = 36,
  387. VALUE_TYPE_INT64_LIST_OP = 37,
  388. VALUE_TYPE_UINT_LIST_OP = 38,
  389. VALUE_TYPE_UINT64_LIST_OP = 39,
  390. VALUE_TYPE_PATH_VECTOR = 40,
  391. VALUE_TYPE_TOKEN_VECTOR = 41,
  392. VALUE_TYPE_SPECIFIER = 42,
  393. VALUE_TYPE_PERMISSION = 43,
  394. VALUE_TYPE_VARIABILITY = 44,
  395. VALUE_TYPE_VARIANT_SELECTION_MAP = 45,
  396. VALUE_TYPE_TIME_SAMPLES = 46,
  397. VALUE_TYPE_PAYLOAD = 47,
  398. VALUE_TYPE_DOUBLE_VECTOR = 48,
  399. VALUE_TYPE_LAYER_OFFSET_VECTOR = 49,
  400. VALUE_TYPE_STRING_VECTOR = 50,
  401. VALUE_TYPE_VALUE_BLOCK = 51,
  402. VALUE_TYPE_VALUE = 52,
  403. VALUE_TYPE_UNREGISTERED_VALUE = 53,
  404. VALUE_TYPE_UNREGISTERED_VALUE_LIST_OP = 54,
  405. VALUE_TYPE_PAYLOAD_LIST_OP = 55,
  406. VALUE_TYPE_TIME_CODE = 56,
  407. };
  408. struct ValueType {
  409. ValueType()
  410. : name("Invalid"), id(VALUE_TYPE_INVALID), supports_array(false) {}
  411. ValueType(const std::string &n, uint32_t i, bool a)
  412. : name(n), id(ValueTypeId(i)), supports_array(a) {}
  413. std::string name;
  414. ValueTypeId id{VALUE_TYPE_INVALID};
  415. bool supports_array{false};
  416. };
  417. enum SpecType {
  418. SpecTypeUnknown = 0,
  419. SpecTypeAttribute,
  420. SpecTypeConnection,
  421. SpecTypeExpression,
  422. SpecTypeMapper,
  423. SpecTypeMapperArg,
  424. SpecTypePrim,
  425. SpecTypePseudoRoot,
  426. SpecTypeRelationship,
  427. SpecTypeRelationshipTarget,
  428. SpecTypeVariant,
  429. SpecTypeVariantSet,
  430. NumSpecTypes
  431. };
  432. enum Orientation {
  433. OrientationRightHanded, // 0
  434. OrientationLeftHanded,
  435. };
  436. enum Visibility {
  437. VisibilityInherited, // 0
  438. VisibilityInvisible,
  439. };
  440. enum Purpose {
  441. PurposeDefault, // 0
  442. PurposeRender,
  443. PurposeProxy,
  444. PurposeGuide,
  445. };
  446. enum SubdivisionScheme {
  447. SubdivisionSchemeCatmullClark, // 0
  448. SubdivisionSchemeLoop,
  449. SubdivisionSchemeBilinear,
  450. SubdivisionSchemeNone,
  451. };
  452. // For PrimSpec
  453. enum Specifier {
  454. SpecifierDef, // 0
  455. SpecifierOver,
  456. SpecifierClass,
  457. NumSpecifiers
  458. };
  459. enum Permission {
  460. PermissionPublic, // 0
  461. PermissionPrivate,
  462. NumPermissions
  463. };
  464. enum Variability {
  465. VariabilityVarying, // 0
  466. VariabilityUniform,
  467. VariabilityConfig,
  468. NumVariabilities
  469. };
  470. // forward decl
  471. class Value;
  472. struct TimeSamples {
  473. std::vector<double> times;
  474. std::vector<Value> values;
  475. };
  476. ///
  477. /// Represent value.
  478. /// multi-dimensional type is not supported(e.g. float[][])
  479. ///
  480. class Value {
  481. public:
  482. typedef std::map<std::string, Value> Dictionary;
  483. Value() = default;
  484. Value(const ValueType &_dtype, const std::vector<uint8_t> &_data)
  485. : dtype(_dtype), data(_data), array_length(-1) {}
  486. Value(const ValueType &_dtype, const std::vector<uint8_t> &_data,
  487. uint64_t _array_length)
  488. : dtype(_dtype), data(_data), array_length(int64_t(_array_length)) {}
  489. bool IsArray() const {
  490. if ((array_length > 0) || string_array.size() ||
  491. (dtype.id == VALUE_TYPE_PATH_LIST_OP)) {
  492. return true;
  493. }
  494. return false;
  495. }
  496. // Setter for primitive types.
  497. void SetBool(const bool d) {
  498. dtype.name = "Bool";
  499. dtype.id = VALUE_TYPE_BOOL;
  500. uint8_t value = d ? 1 : 0;
  501. data.resize(1);
  502. data[0] = value;
  503. }
  504. void SetUChar(const unsigned char d) {
  505. dtype.name = "UChar";
  506. dtype.id = VALUE_TYPE_UCHAR;
  507. data.resize(1);
  508. data[0] = d;
  509. }
  510. void SetInt(const int32_t i) {
  511. static_assert(sizeof(int32_t) == 4, "");
  512. dtype.name = "Int";
  513. dtype.id = VALUE_TYPE_INT;
  514. data.resize(sizeof(int32_t));
  515. memcpy(data.data(), reinterpret_cast<const void *>(&i), sizeof(int32_t));
  516. }
  517. void SetUInt(const uint32_t i) {
  518. static_assert(sizeof(uint32_t) == 4, "");
  519. dtype.name = "UInt";
  520. dtype.id = VALUE_TYPE_UINT;
  521. data.resize(sizeof(uint32_t));
  522. memcpy(data.data(), reinterpret_cast<const void *>(&i), sizeof(uint32_t));
  523. }
  524. void SetInt64(const int64_t i) {
  525. static_assert(sizeof(int64_t) == 8, "");
  526. dtype.name = "Int64";
  527. dtype.id = VALUE_TYPE_INT64;
  528. data.resize(sizeof(int64_t));
  529. memcpy(data.data(), reinterpret_cast<const void *>(&i), sizeof(int64_t));
  530. }
  531. void SetUInt64(const uint64_t i) {
  532. static_assert(sizeof(uint64_t) == 8, "");
  533. dtype.name = "UInt64";
  534. dtype.id = VALUE_TYPE_UINT64;
  535. data.resize(sizeof(uint64_t));
  536. memcpy(data.data(), reinterpret_cast<const void *>(&i), sizeof(uint64_t));
  537. }
  538. void SetDouble(const double d) {
  539. static_assert(sizeof(double) == 8, "");
  540. dtype.name = "Double";
  541. dtype.id = VALUE_TYPE_DOUBLE;
  542. data.resize(sizeof(double));
  543. memcpy(data.data(), reinterpret_cast<const void *>(&d), sizeof(double));
  544. }
  545. void SetFloat(const float d) {
  546. static_assert(sizeof(float) == 4, "");
  547. dtype.name = "Float";
  548. dtype.id = VALUE_TYPE_FLOAT;
  549. data.resize(sizeof(float));
  550. memcpy(data.data(), reinterpret_cast<const void *>(&d), sizeof(float));
  551. }
  552. void SetHalf(const float16 d) {
  553. dtype.name = "Half";
  554. dtype.id = VALUE_TYPE_HALF;
  555. data.resize(sizeof(uint16_t));
  556. memcpy(data.data(), reinterpret_cast<const void *>(&d.u), sizeof(uint16_t));
  557. }
  558. void SetVec2i(const Vec2i v) {
  559. static_assert(sizeof(Vec2i) == 8, "");
  560. dtype.name = "Vec2i";
  561. dtype.id = VALUE_TYPE_VEC2I;
  562. data.resize(sizeof(Vec2i));
  563. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec2i));
  564. }
  565. void SetVec2f(const Vec2f v) {
  566. static_assert(sizeof(Vec2f) == 8, "");
  567. dtype.name = "Vec2f";
  568. dtype.id = VALUE_TYPE_VEC2F;
  569. data.resize(sizeof(Vec2f));
  570. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec2f));
  571. }
  572. void SetVec2d(const Vec2d v) {
  573. static_assert(sizeof(Vec2d) == 16, "");
  574. dtype.name = "Vec2d";
  575. dtype.id = VALUE_TYPE_VEC2D;
  576. data.resize(sizeof(Vec2d));
  577. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec2d));
  578. }
  579. void SetVec2h(const Vec2h v) {
  580. static_assert(sizeof(Vec2h) == 4, "");
  581. dtype.name = "Vec2h";
  582. dtype.id = VALUE_TYPE_VEC2H;
  583. data.resize(sizeof(Vec2h));
  584. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec2h));
  585. }
  586. void SetVec3i(const Vec3i v) {
  587. static_assert(sizeof(Vec3i) == 12, "");
  588. dtype.name = "Vec3i";
  589. dtype.id = VALUE_TYPE_VEC3I;
  590. data.resize(sizeof(Vec3i));
  591. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec3i));
  592. }
  593. void SetVec3f(const Vec3f v) {
  594. static_assert(sizeof(Vec3f) == 12, "");
  595. dtype.name = "Vec3f";
  596. dtype.id = VALUE_TYPE_VEC3F;
  597. data.resize(sizeof(Vec3f));
  598. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec3f));
  599. }
  600. void SetVec3d(const Vec3d v) {
  601. static_assert(sizeof(Vec3d) == 24, "");
  602. dtype.name = "Vec3d";
  603. dtype.id = VALUE_TYPE_VEC3D;
  604. data.resize(sizeof(Vec3d));
  605. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec3d));
  606. }
  607. void SetVec3h(const Vec3h v) {
  608. static_assert(sizeof(Vec3h) == 6, "");
  609. dtype.name = "Vec3h";
  610. dtype.id = VALUE_TYPE_VEC3H;
  611. data.resize(sizeof(Vec3h));
  612. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec3h));
  613. }
  614. void SetVec4i(const Vec4i v) {
  615. static_assert(sizeof(Vec4i) == 16, "");
  616. dtype.name = "Vec4i";
  617. dtype.id = VALUE_TYPE_VEC4I;
  618. data.resize(sizeof(Vec4i));
  619. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec4i));
  620. }
  621. void SetVec4f(const Vec4f v) {
  622. static_assert(sizeof(Vec4f) == 16, "");
  623. dtype.name = "Vec4f";
  624. dtype.id = VALUE_TYPE_VEC4F;
  625. data.resize(sizeof(Vec4f));
  626. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec4f));
  627. }
  628. void SetVec4d(const Vec4d v) {
  629. static_assert(sizeof(Vec4d) == 32, "");
  630. dtype.name = "Vec4d";
  631. dtype.id = VALUE_TYPE_VEC4D;
  632. data.resize(sizeof(Vec4d));
  633. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec4d));
  634. }
  635. void SetVec4h(const Vec4h v) {
  636. static_assert(sizeof(Vec4h) == 8, "");
  637. dtype.name = "Vec4h";
  638. dtype.id = VALUE_TYPE_VEC4H;
  639. data.resize(sizeof(Vec4h));
  640. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Vec3h));
  641. }
  642. void SetQuath(const Quath v) {
  643. static_assert(sizeof(Quath) == (2 * 4), "");
  644. dtype.name = "Quath";
  645. dtype.id = VALUE_TYPE_QUATH;
  646. data.resize(sizeof(Quath));
  647. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Quath));
  648. }
  649. void SetQuatf(const Quatf v) {
  650. static_assert(sizeof(Quatf) == (4 * 4), "");
  651. dtype.name = "Quatf";
  652. dtype.id = VALUE_TYPE_QUATF;
  653. data.resize(sizeof(Quatf));
  654. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Quatf));
  655. }
  656. void SetQuatd(const Quatd v) {
  657. static_assert(sizeof(Quatd) == (8 * 4), "");
  658. dtype.name = "Quatd";
  659. dtype.id = VALUE_TYPE_QUATD;
  660. data.resize(sizeof(Quatd));
  661. memcpy(data.data(), reinterpret_cast<const void *>(&v), sizeof(Quatd));
  662. }
  663. void SetMatrix2d(const Matrix2d v) {
  664. static_assert(sizeof(Matrix2d) == (2 * 2 * 8), "");
  665. dtype.name = "Matrix2d";
  666. dtype.id = VALUE_TYPE_MATRIX2D;
  667. data.resize(sizeof(Matrix2d));
  668. memcpy(data.data(), reinterpret_cast<const void *>(v.m), sizeof(Matrix2d));
  669. }
  670. void SetMatrix3d(const Matrix3d v) {
  671. static_assert(sizeof(Matrix3d) == (3 * 3 * 8), "");
  672. dtype.name = "Matrix3d";
  673. dtype.id = VALUE_TYPE_MATRIX3D;
  674. data.resize(sizeof(Matrix3d));
  675. memcpy(data.data(), reinterpret_cast<const void *>(v.m), sizeof(Matrix3d));
  676. }
  677. void SetMatrix4d(const Matrix4d v) {
  678. static_assert(sizeof(Matrix4d) == (4 * 4 * 8), "");
  679. dtype.name = "Matrix4d";
  680. dtype.id = VALUE_TYPE_MATRIX4D;
  681. data.resize(sizeof(Matrix4d));
  682. memcpy(data.data(), reinterpret_cast<const void *>(v.m), sizeof(Matrix4d));
  683. }
  684. void SetToken(const std::string &s) {
  685. dtype.name = "Token";
  686. dtype.id = VALUE_TYPE_TOKEN;
  687. data.resize(s.size()); // No '\0'
  688. memcpy(data.data(), reinterpret_cast<const void *>(&s[0]), s.size());
  689. }
  690. void SetString(const std::string &s) {
  691. dtype.name = "String";
  692. dtype.id =
  693. VALUE_TYPE_STRING; // we treat String as std::string, not StringIndex
  694. data.resize(s.size()); // No '\0'
  695. memcpy(data.data(), reinterpret_cast<const void *>(&s[0]), s.size());
  696. }
  697. void SetAssetPath(const std::string &s) {
  698. dtype.name = "AssetPath";
  699. dtype.id = VALUE_TYPE_ASSET_PATH; // we treat AssetPath as std::string, not
  700. // TokenIndex
  701. data.resize(s.size()); // No '\0'
  702. memcpy(data.data(), reinterpret_cast<const void *>(&s[0]), s.size());
  703. }
  704. void SetPermission(const uint32_t d) {
  705. // TODO(syoyo): range check
  706. dtype.name = "Permission";
  707. dtype.id = VALUE_TYPE_PERMISSION;
  708. data.resize(sizeof(uint32_t));
  709. memcpy(data.data(), reinterpret_cast<const void *>(&d), sizeof(uint32_t));
  710. }
  711. void SetSpecifier(const uint32_t d) {
  712. // TODO(syoyo): range check
  713. dtype.name = "Specifier";
  714. dtype.id = VALUE_TYPE_SPECIFIER;
  715. data.resize(sizeof(uint32_t));
  716. memcpy(data.data(), reinterpret_cast<const void *>(&d), sizeof(uint32_t));
  717. }
  718. void SetVariability(const uint32_t d) {
  719. // TODO(syoyo): range check
  720. dtype.name = "Variability";
  721. dtype.id = VALUE_TYPE_VARIABILITY;
  722. data.resize(sizeof(uint32_t));
  723. memcpy(data.data(), reinterpret_cast<const void *>(&d), sizeof(uint32_t));
  724. }
  725. void SetIntArray(const int *d, const size_t n) {
  726. dtype.name = "IntArray";
  727. dtype.id = VALUE_TYPE_INT;
  728. array_length = int64_t(n);
  729. data.resize(n * sizeof(uint32_t));
  730. memcpy(data.data(), reinterpret_cast<const void *>(d),
  731. n * sizeof(uint32_t));
  732. }
  733. void SetHalfArray(const uint16_t *d, const size_t n) {
  734. dtype.name = "HalfArray";
  735. dtype.id = VALUE_TYPE_HALF;
  736. array_length = int64_t(n);
  737. data.resize(n * sizeof(uint16_t));
  738. memcpy(data.data(), reinterpret_cast<const void *>(d),
  739. n * sizeof(uint16_t));
  740. }
  741. void SetFloatArray(const float *d, const size_t n) {
  742. dtype.name = "FloatArray";
  743. dtype.id = VALUE_TYPE_FLOAT;
  744. array_length = int64_t(n);
  745. data.resize(n * sizeof(float));
  746. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(float));
  747. }
  748. void SetDoubleArray(const double *d, const size_t n) {
  749. dtype.name = "DoubleArray";
  750. dtype.id = VALUE_TYPE_DOUBLE;
  751. array_length = int64_t(n);
  752. data.resize(n * sizeof(double));
  753. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(double));
  754. }
  755. void SetVec2fArray(const Vec2f *d, const size_t n) {
  756. static_assert(sizeof(Vec2f) == 8, "");
  757. dtype.name = "Vec2fArray";
  758. dtype.id = VALUE_TYPE_VEC2F;
  759. array_length = int64_t(n);
  760. data.resize(n * sizeof(Vec2f));
  761. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec2f));
  762. }
  763. void SetVec3fArray(const Vec3f *d, const size_t n) {
  764. static_assert(sizeof(Vec3f) == 12, "");
  765. dtype.name = "Vec3fArray";
  766. dtype.id = VALUE_TYPE_VEC3F;
  767. array_length = int64_t(n);
  768. data.resize(n * sizeof(Vec3f));
  769. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec3f));
  770. }
  771. void SetVec4fArray(const Vec4f *d, const size_t n) {
  772. static_assert(sizeof(Vec4f) == 16, "");
  773. dtype.name = "Vec4fArray";
  774. dtype.id = VALUE_TYPE_VEC4F;
  775. array_length = int64_t(n);
  776. data.resize(n * sizeof(Vec4f));
  777. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec4f));
  778. }
  779. void SetVec2dArray(const Vec2d *d, const size_t n) {
  780. static_assert(sizeof(Vec2d) == 16, "");
  781. dtype.name = "Vec2dArray";
  782. dtype.id = VALUE_TYPE_VEC2D;
  783. array_length = int64_t(n);
  784. data.resize(n * sizeof(Vec2d));
  785. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec2d));
  786. }
  787. void SetVec3dArray(const Vec3d *d, const size_t n) {
  788. static_assert(sizeof(Vec3d) == 24, "");
  789. dtype.name = "Vec3dArray";
  790. dtype.id = VALUE_TYPE_VEC3D;
  791. array_length = int64_t(n);
  792. data.resize(n * sizeof(Vec3d));
  793. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec3d));
  794. }
  795. void SetVec4dArray(const Vec4d *d, const size_t n) {
  796. static_assert(sizeof(Vec4d) == 32, "");
  797. dtype.name = "Vec4dArray";
  798. dtype.id = VALUE_TYPE_VEC4D;
  799. array_length = int64_t(n);
  800. data.resize(n * sizeof(Vec4d));
  801. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Vec4d));
  802. }
  803. void SetQuathArray(const Quath *d, const size_t n) {
  804. static_assert(sizeof(Quath) == 8, "");
  805. dtype.name = "QuathArray";
  806. dtype.id = VALUE_TYPE_QUATH;
  807. array_length = int64_t(n);
  808. data.resize(n * sizeof(Quath));
  809. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Quath));
  810. }
  811. void SetQuatfArray(const Quatf *d, const size_t n) {
  812. static_assert(sizeof(Quatf) == 16, "");
  813. dtype.name = "QuatfArray";
  814. dtype.id = VALUE_TYPE_QUATF;
  815. array_length = int64_t(n);
  816. data.resize(n * sizeof(Quatf));
  817. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Quatf));
  818. }
  819. void SetQuatdArray(const Quatd *d, const size_t n) {
  820. static_assert(sizeof(Quatd) == 32, "");
  821. dtype.name = "QuatdArray";
  822. dtype.id = VALUE_TYPE_QUATD;
  823. array_length = int64_t(n);
  824. data.resize(n * sizeof(Quatd));
  825. memcpy(data.data(), reinterpret_cast<const void *>(d), n * sizeof(Quatd));
  826. }
  827. void SetTokenArray(const std::vector<std::string> &d) {
  828. dtype.name = "TokenArray";
  829. dtype.id = VALUE_TYPE_TOKEN_VECTOR;
  830. array_length = int64_t(d.size());
  831. string_array = d;
  832. }
  833. void SetPathListOp(const ListOp<Path> &d) {
  834. dtype.name = "PathListOp";
  835. dtype.id = VALUE_TYPE_PATH_LIST_OP;
  836. // FIXME(syoyo): How to determine array length?
  837. // array_length = int64_t(d.size());
  838. path_list_op = d;
  839. }
  840. void SetTimeSamples(const TimeSamples &d) {
  841. dtype.name = "TimeSamples";
  842. dtype.id = VALUE_TYPE_TIME_SAMPLES;
  843. // FIXME(syoyo): How to determine array length?
  844. // array_length = int64_t(d.size());
  845. time_samples = d;
  846. }
  847. const ListOp<Path> &GetPathListOp() const { return path_list_op; }
  848. // Getter for frequently used types.
  849. Specifier GetSpecifier() const {
  850. if (dtype.id == VALUE_TYPE_SPECIFIER) {
  851. uint32_t d = *reinterpret_cast<const uint32_t *>(data.data());
  852. return static_cast<Specifier>(d);
  853. }
  854. return NumSpecifiers; // invalid
  855. }
  856. Variability GetVariability() const {
  857. if (dtype.id == VALUE_TYPE_VARIABILITY) {
  858. uint32_t d = *reinterpret_cast<const uint32_t *>(data.data());
  859. return static_cast<Variability>(d);
  860. }
  861. return NumVariabilities; // invalid
  862. }
  863. bool GetBool(bool *ret) const {
  864. if (ret == nullptr) {
  865. return false;
  866. }
  867. if (dtype.id == VALUE_TYPE_BOOL) {
  868. uint8_t d = *reinterpret_cast<const uint8_t *>(data.data());
  869. (*ret) = bool(d);
  870. return true;
  871. }
  872. return false;
  873. }
  874. double GetDouble() const {
  875. if (dtype.id == VALUE_TYPE_DOUBLE) {
  876. double d = *reinterpret_cast<const double *>(data.data());
  877. return static_cast<double>(d);
  878. } else if (dtype.id == VALUE_TYPE_FLOAT) {
  879. float d = *reinterpret_cast<const float *>(data.data());
  880. return static_cast<double>(d);
  881. }
  882. return std::numeric_limits<double>::quiet_NaN(); // invalid
  883. }
  884. bool GetInt(int *ret) const {
  885. if (ret == nullptr) {
  886. return false;
  887. }
  888. if (dtype.id == VALUE_TYPE_INT) {
  889. int d = *reinterpret_cast<const int *>(data.data());
  890. (*ret) = d;
  891. return true;
  892. }
  893. return false;
  894. }
  895. float GetFloat() const {
  896. if (dtype.id == VALUE_TYPE_FLOAT) {
  897. float d = *reinterpret_cast<const float *>(data.data());
  898. return d;
  899. }
  900. return std::numeric_limits<double>::quiet_NaN(); // invalid
  901. }
  902. std::string GetToken() const {
  903. if (dtype.id == VALUE_TYPE_TOKEN) {
  904. std::string s(reinterpret_cast<const char *>(data.data()), data.size());
  905. return s;
  906. }
  907. return std::string();
  908. }
  909. std::string GetString() const {
  910. if (dtype.id == VALUE_TYPE_STRING) {
  911. std::string s(reinterpret_cast<const char *>(data.data()), data.size());
  912. return s;
  913. }
  914. return std::string();
  915. }
  916. size_t GetArrayLength() const { return size_t(array_length); }
  917. const std::vector<std::string> &GetStringArray() const {
  918. return string_array;
  919. }
  920. const std::vector<uint8_t> &GetData() const {
  921. // TODO(syoyo): Report error for Dictionary type.
  922. return data;
  923. }
  924. const std::string &GetTypeName() const { return dtype.name; }
  925. const ValueTypeId &GetTypeId() const { return dtype.id; }
  926. bool IsDictionary() const { return dtype.id == VALUE_TYPE_DICTIONARY; }
  927. void SetDictionary(const Dictionary &d) {
  928. // Dictonary has separated storage
  929. dict = d;
  930. }
  931. const Dictionary &GetDictionary() const { return dict; }
  932. private:
  933. ValueType dtype;
  934. std::string string_value;
  935. std::vector<uint8_t> data; // value as opaque binary data.
  936. int64_t array_length{-1};
  937. // Dictonary, ListOp and array of string has separated storage
  938. std::vector<std::string> string_array;
  939. Dictionary dict;
  940. ListOp<Path> path_list_op;
  941. ListOp<std::string> token_list_op;
  942. // TODO(syoyo): Reference
  943. // TODO(syoyo): Use single representation for integral types
  944. ListOp<int32_t> int_list_op;
  945. ListOp<uint32_t> int64_list_op;
  946. ListOp<int64_t> uint_list_op;
  947. ListOp<uint64_t> uint64_list_op;
  948. TimeSamples time_samples;
  949. };
  950. //
  951. // Data structure for rendering pipeline.
  952. //
  953. // Similar to OpenGL BufferData
  954. //
  955. //
  956. struct BufferData {
  957. enum DataType {
  958. BUFFER_DATA_TYPE_INVALID,
  959. BUFFER_DATA_TYPE_UNSIGNED_BYTE,
  960. BUFFER_DATA_TYPE_UNSIGNED_SHORT,
  961. BUFFER_DATA_TYPE_UNSIGNED_INT,
  962. BUFFER_DATA_TYPE_UNSIGNED_INT64,
  963. BUFFER_DATA_TYPE_BYTE,
  964. BUFFER_DATA_TYPE_SHORT,
  965. BUFFER_DATA_TYPE_INT,
  966. BUFFER_DATA_TYPE_INT64,
  967. BUFFER_DATA_TYPE_HALF,
  968. BUFFER_DATA_TYPE_FLOAT,
  969. BUFFER_DATA_TYPE_DOUBLE,
  970. };
  971. std::vector<uint8_t> data; // Opaque byte data.
  972. size_t stride{
  973. 0}; // byte stride for each element. e.g. 12 for XYZXYZXYZ... data. 0 =
  974. // app should calculate byte stride from type and `num_coords`.
  975. int32_t num_coords{-1}; // The number of coordinates. e.g. 3 for XYZ, RGB
  976. // data, 4 for RGBA. -1 = invalid
  977. DataType data_type{BUFFER_DATA_TYPE_INVALID};
  978. void Set(DataType ty, int32_t c, size_t _stride,
  979. const std::vector<uint8_t> &_data) {
  980. data_type = ty;
  981. num_coords = c;
  982. stride = _stride;
  983. data = _data;
  984. }
  985. bool Valid() {
  986. if (data_type == BUFFER_DATA_TYPE_INVALID) {
  987. return false;
  988. }
  989. return (data.size() > 0) && (num_coords > 0);
  990. }
  991. size_t GetDataTypeByteSize(DataType ty) const {
  992. switch (ty) {
  993. case BUFFER_DATA_TYPE_INVALID:
  994. return 0;
  995. case BUFFER_DATA_TYPE_BYTE:
  996. return 1;
  997. case BUFFER_DATA_TYPE_UNSIGNED_BYTE:
  998. return 1;
  999. case BUFFER_DATA_TYPE_SHORT:
  1000. return 2;
  1001. case BUFFER_DATA_TYPE_UNSIGNED_SHORT:
  1002. return 2;
  1003. case BUFFER_DATA_TYPE_INT:
  1004. return 4;
  1005. case BUFFER_DATA_TYPE_UNSIGNED_INT:
  1006. return 4;
  1007. case BUFFER_DATA_TYPE_INT64:
  1008. return 8;
  1009. case BUFFER_DATA_TYPE_UNSIGNED_INT64:
  1010. return 8;
  1011. case BUFFER_DATA_TYPE_HALF:
  1012. return 2;
  1013. case BUFFER_DATA_TYPE_FLOAT:
  1014. return 4;
  1015. case BUFFER_DATA_TYPE_DOUBLE:
  1016. return 8;
  1017. }
  1018. return 0; // Should not reach here.
  1019. }
  1020. size_t GetElementByteSize() const {
  1021. if (num_coords <= 0) {
  1022. // TODO(syoyo): Report error
  1023. return 0;
  1024. }
  1025. return GetDataTypeByteSize(data_type) * size_t(num_coords);
  1026. }
  1027. size_t GetNumElements() const {
  1028. if (num_coords <= 0) {
  1029. // TODO(syoyo): Report error
  1030. return 0;
  1031. }
  1032. size_t n = data.size() / GetElementByteSize();
  1033. #if TINYUSDZ_LOCAL_DEBUG_PRINT
  1034. std::cout << "num_coords = " << num_coords << "\n";
  1035. std::cout << "ccc: num_elements = " << n << "\n";
  1036. #endif
  1037. return n;
  1038. }
  1039. int32_t GetNumCoords() const { return num_coords; }
  1040. DataType GetDataType() const { return data_type; }
  1041. size_t GetStride() const { return stride; }
  1042. //
  1043. // Utility functions
  1044. //
  1045. float GetAsFloat() const {
  1046. if (((GetStride() == 0) || (GetStride() == sizeof(float))) &&
  1047. (GetNumCoords() == 1) && (GetDataType() == BUFFER_DATA_TYPE_FLOAT) &&
  1048. (GetNumElements() == 1)) {
  1049. return *(reinterpret_cast<const float *>(data.data()));
  1050. }
  1051. return std::numeric_limits<float>::quiet_NaN();
  1052. }
  1053. std::array<float, 3> GetAsColor3f() const {
  1054. std::array<float, 3> buf;
  1055. if (((GetStride() == 0) || (GetStride() == 3 * sizeof(float))) &&
  1056. (GetNumCoords() == 3) && (GetDataType() == BUFFER_DATA_TYPE_FLOAT)) {
  1057. memcpy(buf.data(), data.data(), buf.size() * sizeof(float));
  1058. }
  1059. return buf;
  1060. }
  1061. // Return empty array when required type mismatches.
  1062. //
  1063. std::vector<uint32_t> GetAsUInt32Array() const {
  1064. std::vector<uint32_t> buf;
  1065. if (((GetStride() == 0) || (GetStride() == sizeof(uint32_t))) &&
  1066. (GetDataType() == BUFFER_DATA_TYPE_UNSIGNED_INT)) {
  1067. buf.resize(GetNumElements() * size_t(GetNumCoords()));
  1068. #if TINYUSDZ_LOCAL_DEBUG_PRINT
  1069. std::cout << "buf.size = " << buf.size() << "\n";
  1070. #endif
  1071. memcpy(buf.data(), data.data(), buf.size() * sizeof(uint32_t));
  1072. }
  1073. return buf;
  1074. }
  1075. std::vector<int32_t> GetAsInt32Array() const {
  1076. std::vector<int32_t> buf;
  1077. if (((GetStride() == 0) || (GetStride() == sizeof(int32_t))) &&
  1078. (GetDataType() == BUFFER_DATA_TYPE_INT)) {
  1079. buf.resize(GetNumElements() * size_t(GetNumCoords()));
  1080. #if TINYUSDZ_LOCAL_DEBUG_PRINT
  1081. std::cout << "buf.size = " << buf.size() << "\n";
  1082. #endif
  1083. memcpy(buf.data(), data.data(), buf.size() * sizeof(int32_t));
  1084. }
  1085. return buf;
  1086. }
  1087. std::vector<float> GetAsFloatArray() const {
  1088. std::vector<float> buf;
  1089. if (((GetStride() == 0) || (GetStride() == sizeof(float))) &&
  1090. (GetDataType() == BUFFER_DATA_TYPE_FLOAT)) {
  1091. buf.resize(GetNumElements() * size_t(GetNumCoords()));
  1092. memcpy(buf.data(), data.data(), buf.size() * sizeof(float));
  1093. }
  1094. return buf;
  1095. }
  1096. std::vector<float> GetAsVec2fArray() const {
  1097. std::vector<float> buf;
  1098. if (((GetStride() == 0) || (GetStride() == 2 * sizeof(float))) &&
  1099. (GetNumCoords() == 2) && (GetDataType() == BUFFER_DATA_TYPE_FLOAT)) {
  1100. buf.resize(GetNumElements() * 2);
  1101. memcpy(buf.data(), data.data(), buf.size() * sizeof(float));
  1102. }
  1103. return buf;
  1104. }
  1105. std::vector<float> GetAsVec3fArray() const {
  1106. std::vector<float> buf;
  1107. // std::cout << "stride = " << GetStride() << ", num_coords = " <<
  1108. // GetNumCoords() << ", dtype = " << GetDataType() << ", num_elements = " <<
  1109. // GetNumElements() << "\n";
  1110. if (((GetStride() == 0) || (GetStride() == 3 * sizeof(float))) &&
  1111. (GetNumCoords() == 3) && (GetDataType() == BUFFER_DATA_TYPE_FLOAT)) {
  1112. buf.resize(GetNumElements() * 3);
  1113. memcpy(buf.data(), data.data(), buf.size() * sizeof(float));
  1114. }
  1115. return buf;
  1116. }
  1117. std::vector<float> GetAsVec4fArray() const {
  1118. std::vector<float> buf;
  1119. if (((GetStride() == 0) || (GetStride() == 4 * sizeof(float))) &&
  1120. (GetNumCoords() == 4) && (GetDataType() == BUFFER_DATA_TYPE_FLOAT)) {
  1121. buf.resize(GetNumElements());
  1122. memcpy(buf.data(), data.data(), buf.size() * 4 * sizeof(float));
  1123. }
  1124. return buf;
  1125. }
  1126. };
  1127. struct ConnectionPath {
  1128. bool input{false}; // true: Input connection. false: Ouput connection.
  1129. Path path; // original Path information in USD
  1130. std::string token; // token(or string) in USD
  1131. int64_t index{-1}; // corresponding array index(e.g. the array index to
  1132. // `Scene.shaders`)
  1133. };
  1134. // PrimAttrib is a struct to hold attributes of the object.
  1135. // (e.g. property, PrimVar).
  1136. // We treat PrimVar as PrimAttrib(attributes) at the moment.
  1137. struct PrimAttrib {
  1138. std::string name; // attrib name
  1139. std::string type_name; // name of attrib type(e.g. "float', "color3f")
  1140. // For array data types(e.g. FloatArray)
  1141. BufferData buffer; // raw buffer data
  1142. Variability variability;
  1143. bool facevarying{false};
  1144. // For basic types(e.g. Bool, Float).
  1145. // "bool", "string", "float", "int", "uint", "int64", "uint64", "double" or
  1146. // "path" empty = array data type
  1147. std::string basic_type;
  1148. // TODO: Use union struct
  1149. bool boolVal;
  1150. int intVal;
  1151. uint32_t uintVal;
  1152. int64_t int64Val;
  1153. uint64_t uint64Val;
  1154. float floatVal;
  1155. double doubleVal;
  1156. std::string stringVal; // token, string
  1157. Path path;
  1158. };
  1159. // UsdPrimvarReader_float2.
  1160. // Currently for UV texture coordinate
  1161. struct PrimvarReader {
  1162. std::string output_type = "float2"; // currently "float2" only.
  1163. std::array<float, 2> fallback{0.0f, 0.0f}; // fallback value
  1164. ConnectionPath
  1165. varname; // Name of the primvar to be fetched from the geometry.
  1166. };
  1167. // Predefined node class
  1168. struct Xform {
  1169. int64_t parent_id{-1}; // Index to xform node
  1170. Matrix4d matrix;
  1171. // double world_bbox; // bounding box in world coordinate.
  1172. Orientation orientation{OrientationRightHanded};
  1173. Visibility visibility{VisibilityInherited};
  1174. Purpose purpose{PurposeDefault};
  1175. // std::vector<int32_t> xformOpOrder; // T.B.D.
  1176. };
  1177. struct UVCoords {
  1178. std::string name;
  1179. BufferData buffer;
  1180. Variability variability;
  1181. // non-empty when UV has its own indices.
  1182. std::vector<uint32_t> indices; // UV indices. Usually varying
  1183. };
  1184. struct Extent {
  1185. Vec3f lower{std::numeric_limits<float>::infinity(),
  1186. std::numeric_limits<float>::infinity(),
  1187. std::numeric_limits<float>::infinity()};
  1188. Vec3f upper{-std::numeric_limits<float>::infinity(),
  1189. -std::numeric_limits<float>::infinity(),
  1190. -std::numeric_limits<float>::infinity()};
  1191. };
  1192. // Polygon mesh geometry
  1193. // TODO(syoyo): Points, Curves, Volumes, ...
  1194. struct GeomMesh {
  1195. std::string name;
  1196. int64_t parent_id{-1}; // Index to xform node
  1197. //
  1198. // Predefined attribs.
  1199. //
  1200. // Vertex data would use various data types, byte strides, etc, so use
  1201. // PrimAttrib to represent it.
  1202. PrimAttrib points; // Usually float3[]
  1203. PrimAttrib normals; // Usually float3[], varying
  1204. //
  1205. // Utility functions
  1206. //
  1207. size_t GetNumPoints() const;
  1208. size_t GetNumFacevaryingNormals() const;
  1209. // Get `points` as float3 array
  1210. // Return false if `points` is not float3[] type
  1211. bool GetPoints(std::vector<float> *v) const;
  1212. // Get `normals` as float3 array + facevarying
  1213. // Return false if `normals` is neither float3[] type nor `varying`
  1214. bool GetFacevaryingNormals(std::vector<float> *v) const;
  1215. // Get `texcoords` as float2 array + facevarying
  1216. // Return false if `texcoords` is neither float2[] type nor `varying`
  1217. bool GetFacevaryingTexcoords(std::vector<float> *v) const;
  1218. // PrimVar(TODO: Remove)
  1219. UVCoords st;
  1220. PrimAttrib velocitiess; // Usually float3[], varying
  1221. std::vector<int32_t> faceVertexCounts;
  1222. std::vector<int32_t> faceVertexIndices;
  1223. //
  1224. // Properties
  1225. //
  1226. Extent extent; // bounding extent(in local coord?).
  1227. std::string facevaryingLinearInterpolation = "cornerPlus1";
  1228. bool doubleSided{true};
  1229. Orientation orientation{OrientationRightHanded};
  1230. Visibility visibility{VisibilityInherited};
  1231. Purpose purpose{PurposeDefault};
  1232. //
  1233. // SubD attribs.
  1234. //
  1235. std::vector<int32_t> cornerIndices;
  1236. std::vector<float> cornerSharpnesses;
  1237. std::vector<int32_t> creaseIndices;
  1238. std::vector<int32_t> creaseLengths;
  1239. std::vector<float> creaseSharpnesses;
  1240. std::vector<int32_t> holeIndices;
  1241. std::string interpolateBoundary =
  1242. "edgeAndCorner"; // "none", "edgeAndCorner" or "edgeOnly"
  1243. SubdivisionScheme subdivisionScheme;
  1244. // List of Primitive attributes(primvars)
  1245. std::map<std::string, PrimAttrib> attribs;
  1246. };
  1247. //
  1248. // Similar to Maya's ShadingGroup
  1249. //
  1250. struct Material {
  1251. std::string name;
  1252. int64_t parent_id{-1};
  1253. int64_t surface_shader_id{-1}; // Index to `Scene::shaders`
  1254. int64_t volume_shader_id{-1}; // Index to `Scene::shaders`
  1255. // int64_t displacement_shader_id{-1}; // Index to shader object. TODO(syoyo)
  1256. };
  1257. // result = (texture_id == -1) ? use color : lookup texture
  1258. struct Color3OrTexture {
  1259. Color3OrTexture(float x, float y, float z) {
  1260. color[0] = x;
  1261. color[1] = y;
  1262. color[2] = z;
  1263. }
  1264. std::array<float, 3> color{{0.0f, 0.0f, 0.0f}};
  1265. std::string path; // path to .connect(We only support texture file connection
  1266. // at the moment)
  1267. int64_t texture_id{-1};
  1268. bool HasTexture() const { return texture_id > -1; }
  1269. };
  1270. struct FloatOrTexture {
  1271. FloatOrTexture(float x) { value = x; }
  1272. float value{0.0f};
  1273. std::string path; // path to .connect(We only support texture file connection
  1274. // at the moment)
  1275. int64_t texture_id{-1};
  1276. bool HasTexture() const { return texture_id > -1; }
  1277. };
  1278. enum TextureWrap {
  1279. TextureWrapUseMetadata, // look for wrapS and wrapT metadata in the texture
  1280. // file itself
  1281. TextureWrapBlack,
  1282. TextureWrapClamp,
  1283. TextureWrapRepeat,
  1284. TextureWrapMirror,
  1285. };
  1286. // For texture transform
  1287. // result = in * scale * rotate * translation
  1288. struct UsdTranform2d {
  1289. float rotation =
  1290. 0.0f; // counter-clockwise rotation in degrees around the origin.
  1291. std::array<float, 2> scale{{1.0f, 1.0f}};
  1292. std::array<float, 2> translation{{0.0f, 0.0f}};
  1293. };
  1294. // UsdUvTexture
  1295. struct UVTexture {
  1296. std::string asset; // asset name(usually file path)
  1297. int64_t image_id{
  1298. -1}; // TODO(syoyo): Consider UDIM `@textures/occlusion.<UDIM>.tex@`
  1299. TextureWrap wrapS;
  1300. TextureWrap wrapT;
  1301. std::array<float, 4> fallback{
  1302. {0.0f, 0.0f, 0.0f,
  1303. 1.0f}}; // fallback color used when texture cannot be read.
  1304. std::array<float, 4> scale{
  1305. {1.0f, 1.0f, 1.0f, 1.0f}}; // scale to be applied to output texture value
  1306. std::array<float, 4> bias{
  1307. {0.0f, 0.0f, 0.0f, 0.0f}}; // bias to be applied to output texture value
  1308. UsdTranform2d texture_transfom; // texture coordinate orientation.
  1309. // key = connection name: e.g. "outputs:rgb"
  1310. // item = pair<type, name> : example: <"float3", "outputs:rgb">
  1311. std::map<std::string, std::pair<std::string, std::string>> outputs;
  1312. PrimvarReader st; // texture coordinate(`inputs:st`). We assume there is a
  1313. // connection to this.
  1314. // TODO: orientation?
  1315. // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html#UsdPreviewSurfaceProposal-TextureCoordinateOrientationinUSD
  1316. };
  1317. // USD's default? PBR shader
  1318. // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
  1319. struct PreviewSurface {
  1320. std::string doc;
  1321. //
  1322. // Inputs
  1323. //
  1324. // Currently we don't support nested shader description.
  1325. //
  1326. Color3OrTexture diffuseColor{0.18f, 0.18f, 0.18f};
  1327. Color3OrTexture emissiveColor{0.0f, 0.0f, 0.0f};
  1328. int usdSpecularWorkflow{0}; // 0 = metalness workflow, 1 = specular workflow
  1329. // specular workflow
  1330. Color3OrTexture specularColor{0.0f, 0.0f, 0.0f};
  1331. // metalness workflow
  1332. FloatOrTexture metallic{0.0f};
  1333. FloatOrTexture roughness{0.5f};
  1334. FloatOrTexture clearcoat{0.0f};
  1335. FloatOrTexture clearcoatRoughness{0.01f};
  1336. FloatOrTexture opacity{1.0f};
  1337. FloatOrTexture opacityThreshold{0.0f};
  1338. FloatOrTexture ior{1.5f};
  1339. Color3OrTexture normal{0.0f, 0.0f, 1.0f};
  1340. FloatOrTexture displacement{0.0f};
  1341. FloatOrTexture occlusion{0.0f};
  1342. //
  1343. // Outputs
  1344. //
  1345. int64_t surface_id{-1}; // index to `Scene::shaders`
  1346. int64_t displacement_id{-1}; // index to `Scene::shaders`
  1347. };
  1348. using StringOrId = std::pair<std::string, int32_t>;
  1349. // Simple bidirectional Path(string) <-> index lookup
  1350. struct StringAndIdMap {
  1351. void add(int32_t key, const std::string &val) {
  1352. _i_to_s[key] = val;
  1353. _s_to_i[val] = key;
  1354. }
  1355. void add(const std::string &key, int32_t val) {
  1356. _s_to_i[key] = val;
  1357. _i_to_s[val] = key;
  1358. }
  1359. size_t count(int32_t i) const { return _i_to_s.count(i); }
  1360. size_t count(const std::string &s) const { return _s_to_i.count(s); }
  1361. std::string at(int32_t i) const { return _i_to_s.at(i); }
  1362. int32_t at(std::string s) const { return _s_to_i.at(s); }
  1363. std::map<int32_t, std::string> _i_to_s; // index -> string
  1364. std::map<std::string, int32_t> _s_to_i; // string -> index
  1365. };
  1366. // Corresponds to USD's Scope.
  1367. // `Scope` is uncommon term in graphics community, so we use `Group`.
  1368. // From USD doc: Scope is the simplest grouping primitive, and does not carry
  1369. // the baggage of transformability.
  1370. struct Group {
  1371. std::string name;
  1372. int64_t parent_id{-1};
  1373. Visibility visibility{VisibilityInherited};
  1374. Purpose purpose{PurposeDefault};
  1375. };
  1376. enum NodeType {
  1377. NODE_TYPE_NULL = 0,
  1378. NODE_TYPE_XFORM,
  1379. NODE_TYPE_GROUP,
  1380. NODE_TYPE_GEOM_MESH,
  1381. NODE_TYPE_MATERIAL,
  1382. NODE_TYPE_SHADER,
  1383. NODE_TYPE_CUSTOM, // Uer defined custom node
  1384. };
  1385. struct Node {
  1386. std::string name;
  1387. NodeType type{NODE_TYPE_NULL};
  1388. //
  1389. // index to a scene object.
  1390. // For example, Lookup `xforms[node_idx]` When node type is XFORM
  1391. //
  1392. int64_t index{-1};
  1393. int64_t parent; // parent node index. Example: `nodes[parent]`
  1394. std::vector<int64_t> children; // child node indices.
  1395. };
  1396. struct Scene {
  1397. std::string name; // Scene name
  1398. int64_t root_node{-1}; // index to `xforms`(root Xform node)
  1399. std::vector<Node> nodes; // Node hierarchies
  1400. // Scene global setting
  1401. std::string upAxis = "Y";
  1402. std::string defaultPrim; // prim node name
  1403. double metersPerUnit = 1.0; // default [m]
  1404. double timeCodesPerSecond = 24.0; // default 24 fps
  1405. //
  1406. // glTF-like scene objects
  1407. // TODO(syoyo): Use std::variant(C++17) like static polymorphism
  1408. //
  1409. std::vector<Xform> xforms;
  1410. std::vector<GeomMesh> geom_meshes;
  1411. std::vector<Material> materials;
  1412. std::vector<PreviewSurface> shaders; // TODO(syoyo): Support othre shaders
  1413. std::vector<Group> groups;
  1414. StringAndIdMap geom_meshes_map; // Path <-> array index map
  1415. StringAndIdMap materials_map; // Path <-> array index map
  1416. // TODO(syoyo): User defined custom layer data
  1417. // "customLayerData"
  1418. };
  1419. struct USDLoadOptions {
  1420. ///
  1421. /// Set the number of threads to use when parsing USD scene.
  1422. /// -1 = use # of system threads(CPU cores/threads).
  1423. ///
  1424. int num_threads{-1};
  1425. // Set the maximum memory limit advisorily(including image data).
  1426. // This feature would be helpful if you want to load USDZ model in mobile
  1427. // device.
  1428. int32_t max_memory_limit_in_mb{10000}; // in [mb] Default 10GB
  1429. ///
  1430. /// Loads asset data(e.g. texture image, audio). Default is true.
  1431. /// If you want to load asset data in your own way or don't need asset data to
  1432. /// be loaded, Set this false.
  1433. ///
  1434. bool load_assets{true};
  1435. };
  1436. #if 0 // TODO
  1437. //struct USDWriteOptions
  1438. //{
  1439. //
  1440. //
  1441. //};
  1442. #endif
  1443. ///
  1444. /// Load USDZ(zip) from a file.
  1445. ///
  1446. /// @param[in] filename USDZ filename
  1447. /// @param[out] scene USD scene.
  1448. /// @param[out] warn Warning message.
  1449. /// @param[out] err Error message(filled when the function returns false)
  1450. /// @param[in] options Load options(optional)
  1451. ///
  1452. /// @return true upon success
  1453. ///
  1454. bool LoadUSDZFromFile(const std::string &filename, Scene *scene,
  1455. std::string *warn, std::string *err,
  1456. const USDLoadOptions &options = USDLoadOptions());
  1457. ///
  1458. /// Load USDC(binary) from a file.
  1459. ///
  1460. /// @param[in] filename USDC filename
  1461. /// @param[out] scene USD scene.
  1462. /// @param[out] warn Warning message.
  1463. /// @param[out] err Error message(filled when the function returns false)
  1464. /// @param[in] options Load options(optional)
  1465. ///
  1466. /// @return true upon success
  1467. ///
  1468. bool LoadUSDCFromFile(const std::string &filename, Scene *scene,
  1469. std::string *warn, std::string *err,
  1470. const USDLoadOptions &options = USDLoadOptions());
  1471. ///
  1472. /// Load USDC(binary) from a memory.
  1473. ///
  1474. /// @param[in] addr Memory address of USDC data
  1475. /// @param[in] length Byte length of USDC data
  1476. /// @param[out] scene USD scene.
  1477. /// @param[out] warn Warning message.
  1478. /// @param[out] err Error message(filled when the function returns false)
  1479. /// @param[in] options Load options(optional)
  1480. ///
  1481. /// @return true upon success
  1482. ///
  1483. bool LoadUSDCFromMemory(const uint8_t *addr, const size_t length, Scene *scene,
  1484. std::string *warn, std::string *err,
  1485. const USDLoadOptions &options = USDLoadOptions());
  1486. #if 0 // TODO
  1487. ///
  1488. /// Write scene as USDC to a file.
  1489. ///
  1490. /// @param[in] filename USDC filename
  1491. /// @param[out] err Error message(filled when the function returns false)
  1492. /// @param[in] options Write options(optional)
  1493. ///
  1494. /// @return true upon success
  1495. ///
  1496. bool WriteAsUSDCToFile(const std::string &filename, std::string *err, const USDCWriteOptions &options = USDCWriteOptions());
  1497. #endif
  1498. } // namespace tinyusdz
  1499. #endif // TINYUSDZ_HH_