tiniergltf.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. #pragma once
  2. #include <json/json.h>
  3. #include "util/base64.h"
  4. #include <cstdint>
  5. #include <functional>
  6. #include <stack>
  7. #include <string>
  8. #include <string_view>
  9. #include <variant>
  10. #include <vector>
  11. #include <array>
  12. #include <optional>
  13. #include <limits>
  14. #include <stdexcept>
  15. #include <unordered_map>
  16. #include <unordered_set>
  17. namespace tiniergltf {
  18. static inline void check(bool cond) {
  19. if (!cond)
  20. throw std::runtime_error("invalid glTF");
  21. }
  22. template <typename T>
  23. static inline void checkIndex(const std::optional<std::vector<T>> &vec,
  24. const std::optional<std::size_t> &i) {
  25. if (!i.has_value()) return;
  26. check(vec.has_value());
  27. check(i < vec->size());
  28. }
  29. template <typename T>
  30. static inline void checkIndex(const std::vector<T> &vec,
  31. const std::optional<std::size_t> &i) {
  32. if (!i.has_value()) return;
  33. check(i < vec.size());
  34. }
  35. template <typename T, typename F>
  36. static inline void checkForall(const std::optional<std::vector<T>> &vec, const F &cond) {
  37. if (!vec.has_value())
  38. return;
  39. for (const T &v : vec.value())
  40. cond(v);
  41. }
  42. template <typename T>
  43. static inline void checkDuplicateFree(const std::vector<T> &vec) {
  44. check(std::unordered_set<T>(vec.begin(), vec.end()).size() == vec.size());
  45. }
  46. template <typename T>
  47. static inline T as(const Json::Value &o);
  48. template<>
  49. bool as(const Json::Value &o) {
  50. check(o.isBool());
  51. return o.asBool();
  52. }
  53. template<>
  54. double as (const Json::Value &o) {
  55. check(o.isDouble());
  56. return o.asDouble();
  57. }
  58. template<>
  59. std::size_t as(const Json::Value &o) {
  60. check(o.isUInt64());
  61. auto u = o.asUInt64();
  62. check(u <= std::numeric_limits<std::size_t>::max());
  63. return u;
  64. }
  65. template<>
  66. std::string as(const Json::Value &o) {
  67. check(o.isString());
  68. return o.asString();
  69. }
  70. template<typename U>
  71. std::vector<U> asVec(const Json::Value &o) {
  72. check(o.isArray());
  73. std::vector<U> res;
  74. res.reserve(o.size());
  75. for (Json::ArrayIndex i = 0; i < o.size(); ++i) {
  76. res.push_back(as<U>(o[i]));
  77. }
  78. return res;
  79. }
  80. template<typename U, std::size_t n>
  81. std::array<U, n> asArr(const Json::Value &o) {
  82. check(o.isArray());
  83. check(o.size() == n);
  84. std::array<U, n> res;
  85. for (Json::ArrayIndex i = 0; i < n; ++i) {
  86. res[i] = as<U>(o[i]);
  87. }
  88. return res;
  89. }
  90. struct AccessorSparseIndices {
  91. std::size_t bufferView;
  92. std::size_t byteOffset;
  93. // as defined in the glTF specification
  94. enum class ComponentType {
  95. UNSIGNED_BYTE,
  96. UNSIGNED_SHORT,
  97. UNSIGNED_INT,
  98. };
  99. ComponentType componentType;
  100. std::size_t componentSize() const {
  101. switch (componentType) {
  102. case ComponentType::UNSIGNED_BYTE:
  103. return 1;
  104. case ComponentType::UNSIGNED_SHORT:
  105. return 2;
  106. case ComponentType::UNSIGNED_INT:
  107. return 4;
  108. }
  109. throw std::logic_error("invalid component type");
  110. }
  111. std::size_t elementSize() const {
  112. return componentSize();
  113. }
  114. AccessorSparseIndices(const Json::Value &o)
  115. : bufferView(as<std::size_t>(o["bufferView"]))
  116. , byteOffset(0)
  117. {
  118. check(o.isObject());
  119. if (o.isMember("byteOffset")) {
  120. byteOffset = as<std::size_t>(o["byteOffset"]);
  121. check(byteOffset >= 0);
  122. }
  123. {
  124. static std::unordered_map<Json::UInt64, ComponentType> map = {
  125. {5121, ComponentType::UNSIGNED_BYTE},
  126. {5123, ComponentType::UNSIGNED_SHORT},
  127. {5125, ComponentType::UNSIGNED_INT},
  128. };
  129. const auto &v = o["componentType"]; check(v.isUInt64());
  130. componentType = map.at(v.asUInt64());
  131. }
  132. }
  133. };
  134. template<> AccessorSparseIndices as(const Json::Value &o) { return o; }
  135. struct AccessorSparseValues {
  136. std::size_t bufferView;
  137. std::size_t byteOffset;
  138. AccessorSparseValues(const Json::Value &o)
  139. : bufferView(as<std::size_t>(o["bufferView"]))
  140. , byteOffset(0)
  141. {
  142. check(o.isObject());
  143. if (o.isMember("byteOffset")) {
  144. byteOffset = as<std::size_t>(o["byteOffset"]);
  145. check(byteOffset >= 0);
  146. }
  147. }
  148. };
  149. template<> AccessorSparseValues as(const Json::Value &o) { return o; }
  150. struct AccessorSparse {
  151. std::size_t count;
  152. AccessorSparseIndices indices;
  153. AccessorSparseValues values;
  154. AccessorSparse(const Json::Value &o)
  155. : count(as<std::size_t>(o["count"]))
  156. , indices(as<AccessorSparseIndices>(o["indices"]))
  157. , values(as<AccessorSparseValues>(o["values"]))
  158. {
  159. check(o.isObject());
  160. check(count >= 1);
  161. }
  162. };
  163. template<> AccessorSparse as(const Json::Value &o) { return o; }
  164. struct Accessor {
  165. std::optional<std::size_t> bufferView;
  166. std::size_t byteOffset;
  167. // as defined in the glTF specification
  168. enum class ComponentType {
  169. BYTE,
  170. UNSIGNED_BYTE,
  171. SHORT,
  172. UNSIGNED_SHORT,
  173. UNSIGNED_INT,
  174. FLOAT,
  175. };
  176. ComponentType componentType;
  177. std::size_t componentSize() const {
  178. switch (componentType) {
  179. case ComponentType::BYTE:
  180. case ComponentType::UNSIGNED_BYTE:
  181. return 1;
  182. case ComponentType::SHORT:
  183. case ComponentType::UNSIGNED_SHORT:
  184. return 2;
  185. case ComponentType::UNSIGNED_INT:
  186. case ComponentType::FLOAT:
  187. return 4;
  188. }
  189. throw std::logic_error("invalid component type");
  190. }
  191. std::size_t count;
  192. std::optional<std::vector<double>> max;
  193. std::optional<std::vector<double>> min;
  194. std::optional<std::string> name;
  195. bool normalized;
  196. std::optional<AccessorSparse> sparse;
  197. enum class Type {
  198. MAT2,
  199. MAT3,
  200. MAT4,
  201. SCALAR,
  202. VEC2,
  203. VEC3,
  204. VEC4,
  205. };
  206. std::size_t typeCount() const {
  207. switch (type) {
  208. case Type::SCALAR:
  209. return 1;
  210. case Type::VEC2:
  211. return 2;
  212. case Type::VEC3:
  213. return 3;
  214. case Type::MAT2:
  215. case Type::VEC4:
  216. return 4;
  217. case Type::MAT3:
  218. return 9;
  219. case Type::MAT4:
  220. return 16;
  221. }
  222. throw std::logic_error("invalid type");
  223. }
  224. Type type;
  225. std::size_t elementSize() const {
  226. return componentSize() * typeCount();
  227. }
  228. Accessor(const Json::Value &o)
  229. : byteOffset(0)
  230. , count(as<std::size_t>(o["count"]))
  231. , normalized(false)
  232. {
  233. check(o.isObject());
  234. if (o.isMember("bufferView")) {
  235. bufferView = as<std::size_t>(o["bufferView"]);
  236. }
  237. {
  238. static std::unordered_map<Json::UInt64, ComponentType> map = {
  239. {5120, ComponentType::BYTE},
  240. {5121, ComponentType::UNSIGNED_BYTE},
  241. {5122, ComponentType::SHORT},
  242. {5123, ComponentType::UNSIGNED_SHORT},
  243. {5125, ComponentType::UNSIGNED_INT},
  244. {5126, ComponentType::FLOAT},
  245. };
  246. const auto &v = o["componentType"]; check(v.isUInt64());
  247. componentType = map.at(v.asUInt64());
  248. }
  249. if (o.isMember("byteOffset")) {
  250. byteOffset = as<std::size_t>(o["byteOffset"]);
  251. check(byteOffset >= 0);
  252. check(byteOffset % componentSize() == 0);
  253. }
  254. check(count >= 1);
  255. if (o.isMember("name")) {
  256. name = as<std::string>(o["name"]);
  257. }
  258. if (o.isMember("normalized")) {
  259. normalized = as<bool>(o["normalized"]);
  260. }
  261. if (o.isMember("sparse")) {
  262. sparse = as<AccessorSparse>(o["sparse"]);
  263. }
  264. {
  265. static std::unordered_map<Json::String, Type> map = {
  266. {"MAT2", Type::MAT2},
  267. {"MAT3", Type::MAT3},
  268. {"MAT4", Type::MAT4},
  269. {"SCALAR", Type::SCALAR},
  270. {"VEC2", Type::VEC2},
  271. {"VEC3", Type::VEC3},
  272. {"VEC4", Type::VEC4},
  273. };
  274. const auto &v = o["type"]; check(v.isString());
  275. type = map.at(v.asString());
  276. }
  277. if (o.isMember("max")) {
  278. max = asVec<double>(o["max"]);
  279. check(max->size() == typeCount());
  280. }
  281. if (o.isMember("min")) {
  282. min = asVec<double>(o["min"]);
  283. check(min->size() == typeCount());
  284. }
  285. }
  286. };
  287. template<> Accessor as(const Json::Value &o) { return o; }
  288. struct AnimationChannelTarget {
  289. std::optional<std::size_t> node;
  290. enum class Path {
  291. ROTATION,
  292. SCALE,
  293. TRANSLATION,
  294. WEIGHTS,
  295. };
  296. Path path;
  297. AnimationChannelTarget(const Json::Value &o)
  298. {
  299. check(o.isObject());
  300. if (o.isMember("node")) {
  301. node = as<std::size_t>(o["node"]);
  302. }
  303. {
  304. static std::unordered_map<Json::String, Path> map = {
  305. {"rotation", Path::ROTATION},
  306. {"scale", Path::SCALE},
  307. {"translation", Path::TRANSLATION},
  308. {"weights", Path::WEIGHTS},
  309. };
  310. const auto &v = o["path"]; check(v.isString());
  311. path = map.at(v.asString());
  312. }
  313. }
  314. };
  315. template<> AnimationChannelTarget as(const Json::Value &o) { return o; }
  316. struct AnimationChannel {
  317. std::size_t sampler;
  318. AnimationChannelTarget target;
  319. AnimationChannel(const Json::Value &o)
  320. : sampler(as<std::size_t>(o["sampler"]))
  321. , target(as<AnimationChannelTarget>(o["target"]))
  322. {
  323. check(o.isObject());
  324. }
  325. };
  326. template<> AnimationChannel as(const Json::Value &o) { return o; }
  327. struct AnimationSampler {
  328. std::size_t input;
  329. enum class Interpolation {
  330. CUBICSPLINE,
  331. LINEAR,
  332. STEP,
  333. };
  334. Interpolation interpolation;
  335. std::size_t output;
  336. AnimationSampler(const Json::Value &o)
  337. : input(as<std::size_t>(o["input"]))
  338. , interpolation(Interpolation::LINEAR)
  339. , output(as<std::size_t>(o["output"]))
  340. {
  341. check(o.isObject());
  342. if (o.isMember("interpolation")) {
  343. static std::unordered_map<Json::String, Interpolation> map = {
  344. {"CUBICSPLINE", Interpolation::CUBICSPLINE},
  345. {"LINEAR", Interpolation::LINEAR},
  346. {"STEP", Interpolation::STEP},
  347. };
  348. const auto &v = o["interpolation"]; check(v.isString());
  349. interpolation = map.at(v.asString());
  350. }
  351. }
  352. };
  353. template<> AnimationSampler as(const Json::Value &o) { return o; }
  354. struct Animation {
  355. std::vector<AnimationChannel> channels;
  356. std::optional<std::string> name;
  357. std::vector<AnimationSampler> samplers;
  358. Animation(const Json::Value &o)
  359. : channels(asVec<AnimationChannel>(o["channels"]))
  360. , samplers(asVec<AnimationSampler>(o["samplers"]))
  361. {
  362. check(o.isObject());
  363. check(channels.size() >= 1);
  364. if (o.isMember("name")) {
  365. name = as<std::string>(o["name"]);
  366. }
  367. check(samplers.size() >= 1);
  368. }
  369. };
  370. template<> Animation as(const Json::Value &o) { return o; }
  371. struct Asset {
  372. std::optional<std::string> copyright;
  373. std::optional<std::string> generator;
  374. std::optional<std::string> minVersion;
  375. std::string version;
  376. Asset(const Json::Value &o)
  377. : version(as<std::string>(o["version"]))
  378. {
  379. check(o.isObject());
  380. if (o.isMember("copyright")) {
  381. copyright = as<std::string>(o["copyright"]);
  382. }
  383. if (o.isMember("generator")) {
  384. generator = as<std::string>(o["generator"]);
  385. }
  386. if (o.isMember("minVersion")) {
  387. minVersion = as<std::string>(o["minVersion"]);
  388. }
  389. }
  390. };
  391. template<> Asset as(const Json::Value &o) { return o; }
  392. struct BufferView {
  393. std::size_t buffer;
  394. std::size_t byteLength;
  395. std::size_t byteOffset;
  396. std::optional<std::size_t> byteStride;
  397. std::optional<std::string> name;
  398. enum class Target {
  399. ARRAY_BUFFER,
  400. ELEMENT_ARRAY_BUFFER,
  401. };
  402. std::optional<Target> target;
  403. BufferView(const Json::Value &o)
  404. : buffer(as<std::size_t>(o["buffer"]))
  405. , byteLength(as<std::size_t>(o["byteLength"]))
  406. , byteOffset(0)
  407. {
  408. check(o.isObject());
  409. check(byteLength >= 1);
  410. if (o.isMember("byteOffset")) {
  411. byteOffset = as<std::size_t>(o["byteOffset"]);
  412. check(byteOffset >= 0);
  413. }
  414. if (o.isMember("byteStride")) {
  415. byteStride = as<std::size_t>(o["byteStride"]);
  416. check(byteStride.value() >= 4);
  417. check(byteStride.value() <= 252);
  418. check(byteStride.value() % 4 == 0);
  419. }
  420. if (o.isMember("name")) {
  421. name = as<std::string>(o["name"]);
  422. }
  423. if (o.isMember("target")) {
  424. static std::unordered_map<Json::UInt64, Target> map = {
  425. {34962, Target::ARRAY_BUFFER},
  426. {34963, Target::ELEMENT_ARRAY_BUFFER},
  427. };
  428. const auto &v = o["target"]; check(v.isUInt64());
  429. target = map.at(v.asUInt64());
  430. }
  431. }
  432. };
  433. template<> BufferView as(const Json::Value &o) { return o; }
  434. struct Buffer {
  435. std::size_t byteLength;
  436. std::optional<std::string> name;
  437. std::string data;
  438. Buffer(const Json::Value &o,
  439. const std::function<std::string(const std::string &uri)> &resolveURI,
  440. std::optional<std::string> &&glbData = std::nullopt)
  441. : byteLength(as<std::size_t>(o["byteLength"]))
  442. {
  443. check(o.isObject());
  444. check(byteLength >= 1);
  445. if (o.isMember("name")) {
  446. name = as<std::string>(o["name"]);
  447. }
  448. if (glbData.has_value()) {
  449. check(!o.isMember("uri"));
  450. data = *std::move(glbData);
  451. // GLB allows padding, which need not be reflected in the JSON
  452. check(byteLength + 3 >= data.size());
  453. check(data.size() >= byteLength);
  454. } else {
  455. check(o.isMember("uri"));
  456. bool dataURI = false;
  457. const std::string uri = as<std::string>(o["uri"]);
  458. for (auto &prefix : std::array<std::string, 2> {
  459. "data:application/octet-stream;base64,",
  460. "data:application/gltf-buffer;base64,"
  461. }) {
  462. if (std::string_view(uri).substr(0, prefix.length()) == prefix) {
  463. auto view = std::string_view(uri).substr(prefix.length());
  464. check(base64_is_valid(view));
  465. data = base64_decode(view);
  466. dataURI = true;
  467. break;
  468. }
  469. }
  470. if (!dataURI)
  471. data = resolveURI(uri);
  472. check(data.size() >= byteLength);
  473. }
  474. data.resize(byteLength);
  475. }
  476. };
  477. struct CameraOrthographic {
  478. double xmag;
  479. double ymag;
  480. double zfar;
  481. double znear;
  482. CameraOrthographic(const Json::Value &o)
  483. : xmag(as<double>(o["xmag"]))
  484. , ymag(as<double>(o["ymag"]))
  485. , zfar(as<double>(o["zfar"]))
  486. , znear(as<double>(o["znear"]))
  487. {
  488. check(o.isObject());
  489. check(zfar > 0);
  490. check(znear >= 0);
  491. }
  492. };
  493. template<> CameraOrthographic as(const Json::Value &o) { return o; }
  494. struct CameraPerspective {
  495. std::optional<double> aspectRatio;
  496. double yfov;
  497. std::optional<double> zfar;
  498. double znear;
  499. CameraPerspective(const Json::Value &o)
  500. : yfov(as<double>(o["yfov"]))
  501. , znear(as<double>(o["znear"]))
  502. {
  503. check(o.isObject());
  504. if (o.isMember("aspectRatio")) {
  505. aspectRatio = as<double>(o["aspectRatio"]);
  506. check(aspectRatio.value() > 0);
  507. }
  508. check(yfov > 0);
  509. if (o.isMember("zfar")) {
  510. zfar = as<double>(o["zfar"]);
  511. check(zfar.value() > 0);
  512. }
  513. check(znear > 0);
  514. }
  515. };
  516. template<> CameraPerspective as(const Json::Value &o) { return o; }
  517. struct Camera {
  518. std::optional<std::string> name;
  519. std::optional<CameraOrthographic> orthographic;
  520. std::optional<CameraPerspective> perspective;
  521. enum class Type {
  522. ORTHOGRAPHIC,
  523. PERSPECTIVE,
  524. };
  525. Type type;
  526. Camera(const Json::Value &o)
  527. {
  528. check(o.isObject());
  529. if (o.isMember("name")) {
  530. name = as<std::string>(o["name"]);
  531. }
  532. if (o.isMember("orthographic")) {
  533. orthographic = as<CameraOrthographic>(o["orthographic"]);
  534. }
  535. if (o.isMember("perspective")) {
  536. perspective = as<CameraPerspective>(o["perspective"]);
  537. }
  538. {
  539. static std::unordered_map<Json::String, Type> map = {
  540. {"orthographic", Type::ORTHOGRAPHIC},
  541. {"perspective", Type::PERSPECTIVE},
  542. };
  543. const auto &v = o["type"]; check(v.isString());
  544. type = map.at(v.asString());
  545. }
  546. }
  547. };
  548. template<> Camera as(const Json::Value &o) { return o; }
  549. struct Image {
  550. std::optional<std::size_t> bufferView;
  551. enum class MimeType {
  552. IMAGE_JPEG,
  553. IMAGE_PNG,
  554. };
  555. std::optional<MimeType> mimeType;
  556. std::optional<std::string> name;
  557. std::optional<std::string> uri;
  558. Image(const Json::Value &o)
  559. {
  560. check(o.isObject());
  561. if (o.isMember("bufferView")) {
  562. bufferView = as<std::size_t>(o["bufferView"]);
  563. }
  564. if (o.isMember("mimeType")) {
  565. static std::unordered_map<Json::String, MimeType> map = {
  566. {"image/jpeg", MimeType::IMAGE_JPEG},
  567. {"image/png", MimeType::IMAGE_PNG},
  568. };
  569. const auto &v = o["mimeType"]; check(v.isString());
  570. mimeType = map.at(v.asString());
  571. }
  572. if (o.isMember("name")) {
  573. name = as<std::string>(o["name"]);
  574. }
  575. if (o.isMember("uri")) {
  576. uri = as<std::string>(o["uri"]);
  577. }
  578. }
  579. };
  580. template<> Image as(const Json::Value &o) { return o; }
  581. struct TextureInfo {
  582. std::size_t index;
  583. std::size_t texCoord;
  584. TextureInfo(const Json::Value &o)
  585. : index(as<std::size_t>(o["index"]))
  586. , texCoord(0)
  587. {
  588. check(o.isObject());
  589. if (o.isMember("texCoord")) {
  590. texCoord = as<std::size_t>(o["texCoord"]);
  591. check(texCoord >= 0);
  592. }
  593. }
  594. };
  595. template<> TextureInfo as(const Json::Value &o) { return o; }
  596. struct MaterialNormalTextureInfo {
  597. std::size_t index;
  598. double scale;
  599. std::size_t texCoord;
  600. MaterialNormalTextureInfo(const Json::Value &o)
  601. : index(as<std::size_t>(o["index"]))
  602. , scale(1)
  603. , texCoord(0)
  604. {
  605. check(o.isObject());
  606. if (o.isMember("scale")) {
  607. scale = as<double>(o["scale"]);
  608. }
  609. if (o.isMember("texCoord")) {
  610. texCoord = as<std::size_t>(o["texCoord"]);
  611. }
  612. }
  613. };
  614. template<> MaterialNormalTextureInfo as(const Json::Value &o) { return o; }
  615. struct MaterialOcclusionTextureInfo {
  616. std::size_t index;
  617. double strength;
  618. std::size_t texCoord;
  619. MaterialOcclusionTextureInfo(const Json::Value &o)
  620. : index(as<std::size_t>(o["index"]))
  621. , strength(1)
  622. , texCoord(0)
  623. {
  624. check(o.isObject());
  625. if (o.isMember("strength")) {
  626. strength = as<double>(o["strength"]);
  627. check(strength >= 0);
  628. check(strength <= 1);
  629. }
  630. if (o.isMember("texCoord")) {
  631. texCoord = as<std::size_t>(o["texCoord"]);
  632. }
  633. }
  634. };
  635. template<> MaterialOcclusionTextureInfo as(const Json::Value &o) { return o; }
  636. struct MaterialPbrMetallicRoughness {
  637. std::array<double, 4> baseColorFactor;
  638. std::optional<TextureInfo> baseColorTexture;
  639. double metallicFactor;
  640. std::optional<TextureInfo> metallicRoughnessTexture;
  641. double roughnessFactor;
  642. MaterialPbrMetallicRoughness(const Json::Value &o)
  643. : baseColorFactor{1, 1, 1, 1}
  644. , metallicFactor(1)
  645. , roughnessFactor(1)
  646. {
  647. check(o.isObject());
  648. if (o.isMember("baseColorFactor")) {
  649. baseColorFactor = asArr<double, 4>(o["baseColorFactor"]);
  650. for (auto v: baseColorFactor) {
  651. check(v >= 0);
  652. check(v <= 1);
  653. }
  654. }
  655. if (o.isMember("baseColorTexture")) {
  656. baseColorTexture = as<TextureInfo>(o["baseColorTexture"]);
  657. }
  658. if (o.isMember("metallicFactor")) {
  659. metallicFactor = as<double>(o["metallicFactor"]);
  660. check(metallicFactor >= 0);
  661. check(metallicFactor <= 1);
  662. }
  663. if (o.isMember("metallicRoughnessTexture")) {
  664. metallicRoughnessTexture = as<TextureInfo>(o["metallicRoughnessTexture"]);
  665. }
  666. if (o.isMember("roughnessFactor")) {
  667. roughnessFactor = as<double>(o["roughnessFactor"]);
  668. check(roughnessFactor >= 0);
  669. check(roughnessFactor <= 1);
  670. }
  671. }
  672. };
  673. template<> MaterialPbrMetallicRoughness as(const Json::Value &o) { return o; }
  674. struct Material {
  675. double alphaCutoff;
  676. enum class AlphaMode {
  677. BLEND,
  678. MASK,
  679. OPAQUE,
  680. };
  681. AlphaMode alphaMode;
  682. bool doubleSided;
  683. std::array<double, 3> emissiveFactor;
  684. std::optional<TextureInfo> emissiveTexture;
  685. std::optional<std::string> name;
  686. std::optional<MaterialNormalTextureInfo> normalTexture;
  687. std::optional<MaterialOcclusionTextureInfo> occlusionTexture;
  688. std::optional<MaterialPbrMetallicRoughness> pbrMetallicRoughness;
  689. Material(const Json::Value &o)
  690. : alphaCutoff(0.5)
  691. , alphaMode(AlphaMode::OPAQUE)
  692. , doubleSided(false)
  693. , emissiveFactor{0, 0, 0}
  694. {
  695. check(o.isObject());
  696. if (o.isMember("alphaCutoff")) {
  697. alphaCutoff = as<double>(o["alphaCutoff"]);
  698. check(alphaCutoff >= 0);
  699. }
  700. if (o.isMember("alphaMode")){
  701. static std::unordered_map<Json::String, AlphaMode> map = {
  702. {"BLEND", AlphaMode::BLEND},
  703. {"MASK", AlphaMode::MASK},
  704. {"OPAQUE", AlphaMode::OPAQUE},
  705. };
  706. const auto &v = o["alphaMode"]; check(v.isString());
  707. alphaMode = map.at(v.asString());
  708. }
  709. if (o.isMember("doubleSided")) {
  710. doubleSided = as<bool>(o["doubleSided"]);
  711. }
  712. if (o.isMember("emissiveFactor")) {
  713. emissiveFactor = asArr<double, 3>(o["emissiveFactor"]);
  714. for (const auto &v: emissiveFactor) {
  715. check(v >= 0);
  716. check(v <= 1);
  717. }
  718. }
  719. if (o.isMember("emissiveTexture")) {
  720. emissiveTexture = as<TextureInfo>(o["emissiveTexture"]);
  721. }
  722. if (o.isMember("name")) {
  723. name = as<std::string>(o["name"]);
  724. }
  725. if (o.isMember("normalTexture")) {
  726. normalTexture = as<MaterialNormalTextureInfo>(o["normalTexture"]);
  727. }
  728. if (o.isMember("occlusionTexture")) {
  729. occlusionTexture = as<MaterialOcclusionTextureInfo>(o["occlusionTexture"]);
  730. }
  731. if (o.isMember("pbrMetallicRoughness")) {
  732. pbrMetallicRoughness = as<MaterialPbrMetallicRoughness>(o["pbrMetallicRoughness"]);
  733. }
  734. }
  735. };
  736. template<> Material as(const Json::Value &o) { return o; }
  737. struct MeshPrimitive {
  738. static void enumeratedProps(const Json::Value &o, const std::string &name, std::optional<std::vector<std::size_t>> &attr) {
  739. for (std::size_t i = 0;; ++i) {
  740. const std::string s = name + "_" + std::to_string(i);
  741. if (!o.isMember(s)) break;
  742. if (i == 0) {
  743. attr = std::vector<std::size_t>();
  744. }
  745. attr->push_back(as<std::size_t>(o[s]));
  746. }
  747. }
  748. struct Attributes {
  749. std::optional<std::size_t> position, normal, tangent;
  750. std::optional<std::vector<std::size_t>> texcoord, color, joints, weights;
  751. Attributes(const Json::Value &o) {
  752. if (o.isMember("POSITION"))
  753. position = as<std::size_t>(o["POSITION"]);
  754. if (o.isMember("NORMAL"))
  755. normal = as<std::size_t>(o["NORMAL"]);
  756. if (o.isMember("TANGENT"))
  757. tangent = as<std::size_t>(o["TANGENT"]);
  758. enumeratedProps(o, "TEXCOORD", texcoord);
  759. enumeratedProps(o, "COLOR", color);
  760. enumeratedProps(o, "JOINTS", joints);
  761. enumeratedProps(o, "WEIGHTS", weights);
  762. check(joints.has_value() == weights.has_value());
  763. if (joints.has_value()) {
  764. check(joints->size() == weights->size());
  765. }
  766. check(position.has_value()
  767. || normal.has_value()
  768. || tangent.has_value()
  769. || texcoord.has_value()
  770. || color.has_value()
  771. || joints.has_value()
  772. || weights.has_value());
  773. }
  774. };
  775. Attributes attributes;
  776. std::optional<std::size_t> indices;
  777. std::optional<std::size_t> material;
  778. enum class Mode {
  779. POINTS,
  780. LINES,
  781. LINE_LOOP,
  782. LINE_STRIP,
  783. TRIANGLES,
  784. TRIANGLE_STRIP,
  785. TRIANGLE_FAN,
  786. };
  787. Mode mode;
  788. struct MorphTargets {
  789. std::optional<std::size_t> position, normal, tangent;
  790. std::optional<std::vector<std::size_t>> texcoord, color;
  791. MorphTargets(const Json::Value &o) {
  792. if (o.isMember("POSITION"))
  793. position = as<std::size_t>(o["POSITION"]);
  794. if (o.isMember("NORMAL"))
  795. normal = as<std::size_t>(o["NORMAL"]);
  796. if (o.isMember("TANGENT"))
  797. tangent = as<std::size_t>(o["TANGENT"]);
  798. enumeratedProps(o, "TEXCOORD", texcoord);
  799. enumeratedProps(o, "COLOR", color);
  800. check(position.has_value()
  801. || normal.has_value()
  802. || tangent.has_value()
  803. || texcoord.has_value()
  804. || color.has_value());
  805. }
  806. };
  807. std::optional<std::vector<MorphTargets>> targets;
  808. MeshPrimitive(const Json::Value &o)
  809. : attributes(Attributes(o["attributes"]))
  810. , mode(Mode::TRIANGLES)
  811. {
  812. check(o.isObject());
  813. if (o.isMember("indices")) {
  814. indices = as<std::size_t>(o["indices"]);
  815. }
  816. if (o.isMember("material")) {
  817. material = as<std::size_t>(o["material"]);
  818. }
  819. if (o.isMember("mode")) {
  820. static std::unordered_map<Json::UInt64, Mode> map = {
  821. {0, Mode::POINTS},
  822. {1, Mode::LINES},
  823. {2, Mode::LINE_LOOP},
  824. {3, Mode::LINE_STRIP},
  825. {4, Mode::TRIANGLES},
  826. {5, Mode::TRIANGLE_STRIP},
  827. {6, Mode::TRIANGLE_FAN},
  828. };
  829. const auto &v = o["mode"]; check(v.isUInt64());
  830. mode = map.at(v.asUInt64());
  831. }
  832. if (o.isMember("targets")) {
  833. targets = asVec<MorphTargets>(o["targets"]);
  834. check(targets->size() >= 1);
  835. }
  836. }
  837. };
  838. template<> MeshPrimitive::MorphTargets as(const Json::Value &o) { return o; }
  839. template<> MeshPrimitive as(const Json::Value &o) { return o; }
  840. struct Mesh {
  841. std::optional<std::string> name;
  842. std::vector<MeshPrimitive> primitives;
  843. std::optional<std::vector<double>> weights;
  844. Mesh(const Json::Value &o)
  845. : primitives(asVec<MeshPrimitive>(o["primitives"]))
  846. {
  847. check(o.isObject());
  848. if (o.isMember("name")) {
  849. name = as<std::string>(o["name"]);
  850. }
  851. check(primitives.size() >= 1);
  852. if (o.isMember("weights")) {
  853. weights = asVec<double>(o["weights"]);
  854. check(weights->size() >= 1);
  855. }
  856. }
  857. };
  858. template<> Mesh as(const Json::Value &o) { return o; }
  859. struct Node {
  860. std::optional<std::size_t> camera;
  861. std::optional<std::vector<std::size_t>> children;
  862. typedef std::array<double, 16> Matrix;
  863. struct TRS {
  864. std::array<double, 3> translation = {0, 0, 0};
  865. std::array<double, 4> rotation = {0, 0, 0, 1};
  866. std::array<double, 3> scale = {1, 1, 1};
  867. };
  868. std::variant<Matrix, TRS> transform;
  869. std::optional<std::size_t> mesh;
  870. std::optional<std::string> name;
  871. std::optional<std::size_t> skin;
  872. std::optional<std::vector<double>> weights;
  873. Node(const Json::Value &o)
  874. : transform(Matrix {
  875. 1, 0, 0, 0,
  876. 0, 1, 0, 0,
  877. 0, 0, 1, 0,
  878. 0, 0, 0, 1
  879. })
  880. {
  881. check(o.isObject());
  882. if (o.isMember("camera")) {
  883. camera = as<std::size_t>(o["camera"]);
  884. }
  885. if (o.isMember("children")) {
  886. children = asVec<std::size_t>(o["children"]);
  887. check(children->size() >= 1);
  888. checkDuplicateFree(*children);
  889. }
  890. bool hasTRS = o.isMember("translation") || o.isMember("rotation") || o.isMember("scale");
  891. if (o.isMember("matrix")) {
  892. check(!hasTRS);
  893. transform = asArr<double, 16>(o["matrix"]);
  894. } else if (hasTRS) {
  895. TRS trs;
  896. if (o.isMember("translation")) {
  897. trs.translation = asArr<double, 3>(o["translation"]);
  898. }
  899. if (o.isMember("rotation")) {
  900. trs.rotation = asArr<double, 4>(o["rotation"]);
  901. for (auto v: trs.rotation) {
  902. check(v >= -1);
  903. check(v <= 1);
  904. }
  905. }
  906. if (o.isMember("scale")) {
  907. trs.scale = asArr<double, 3>(o["scale"]);
  908. }
  909. transform = trs;
  910. }
  911. if (o.isMember("mesh")) {
  912. mesh = as<std::size_t>(o["mesh"]);
  913. }
  914. if (o.isMember("name")) {
  915. name = as<std::string>(o["name"]);
  916. }
  917. if (o.isMember("skin")) {
  918. check(mesh.has_value());
  919. skin = as<std::size_t>(o["skin"]);
  920. }
  921. if (o.isMember("weights")) {
  922. weights = asVec<double>(o["weights"]);
  923. check(weights->size() >= 1);
  924. }
  925. }
  926. };
  927. template<> Node as(const Json::Value &o) { return o; }
  928. struct Sampler {
  929. enum class MagFilter {
  930. NEAREST,
  931. LINEAR,
  932. };
  933. std::optional<MagFilter> magFilter;
  934. enum class MinFilter {
  935. NEAREST,
  936. LINEAR,
  937. NEAREST_MIPMAP_NEAREST,
  938. LINEAR_MIPMAP_NEAREST,
  939. NEAREST_MIPMAP_LINEAR,
  940. LINEAR_MIPMAP_LINEAR,
  941. };
  942. std::optional<MinFilter> minFilter;
  943. std::optional<std::string> name;
  944. enum class Wrap {
  945. REPEAT,
  946. CLAMP_TO_EDGE,
  947. MIRRORED_REPEAT,
  948. };
  949. Wrap wrapS;
  950. Wrap wrapT;
  951. Sampler(const Json::Value &o)
  952. : wrapS(Wrap::REPEAT)
  953. , wrapT(Wrap::REPEAT)
  954. {
  955. check(o.isObject());
  956. if (o.isMember("magFilter")) {
  957. static std::unordered_map<Json::UInt64, MagFilter> map = {
  958. {9728, MagFilter::NEAREST},
  959. {9729, MagFilter::LINEAR},
  960. };
  961. const auto &v = o["magFilter"]; check(v.isUInt64());
  962. magFilter = map.at(v.asUInt64());
  963. }
  964. if (o.isMember("minFilter")) {
  965. static std::unordered_map<Json::UInt64, MinFilter> map = {
  966. {9728, MinFilter::NEAREST},
  967. {9729, MinFilter::LINEAR},
  968. {9984, MinFilter::NEAREST_MIPMAP_NEAREST},
  969. {9985, MinFilter::LINEAR_MIPMAP_NEAREST},
  970. {9986, MinFilter::NEAREST_MIPMAP_LINEAR},
  971. {9987, MinFilter::LINEAR_MIPMAP_LINEAR},
  972. };
  973. const auto &v = o["minFilter"]; check(v.isUInt64());
  974. minFilter = map.at(v.asUInt64());
  975. }
  976. if (o.isMember("name")) {
  977. name = as<std::string>(o["name"]);
  978. }
  979. static std::unordered_map<Json::UInt64, Wrap> map = {
  980. {10497, Wrap::REPEAT},
  981. {33071, Wrap::CLAMP_TO_EDGE},
  982. {33648, Wrap::MIRRORED_REPEAT},
  983. };
  984. if (o.isMember("wrapS")) {
  985. const auto &v = o["wrapS"]; check(v.isUInt64());
  986. wrapS = map.at(v.asUInt64());
  987. }
  988. if (o.isMember("wrapT")) {
  989. const auto &v = o["wrapT"]; check(v.isUInt64());
  990. wrapT = map.at(v.asUInt64());
  991. }
  992. }
  993. };
  994. template<> Sampler as(const Json::Value &o) { return o; }
  995. struct Scene {
  996. std::optional<std::string> name;
  997. std::optional<std::vector<std::size_t>> nodes;
  998. Scene(const Json::Value &o)
  999. {
  1000. check(o.isObject());
  1001. if (o.isMember("name")) {
  1002. name = as<std::string>(o["name"]);
  1003. }
  1004. if (o.isMember("nodes")) {
  1005. nodes = asVec<std::size_t>(o["nodes"]);
  1006. check(nodes->size() >= 1);
  1007. checkDuplicateFree(*nodes);
  1008. }
  1009. }
  1010. };
  1011. template<> Scene as(const Json::Value &o) { return o; }
  1012. struct Skin {
  1013. std::optional<std::size_t> inverseBindMatrices;
  1014. std::vector<std::size_t> joints;
  1015. std::optional<std::string> name;
  1016. std::optional<std::size_t> skeleton;
  1017. Skin(const Json::Value &o)
  1018. : joints(asVec<std::size_t>(o["joints"]))
  1019. {
  1020. check(o.isObject());
  1021. if (o.isMember("inverseBindMatrices")) {
  1022. inverseBindMatrices = as<std::size_t>(o["inverseBindMatrices"]);
  1023. }
  1024. check(joints.size() >= 1);
  1025. checkDuplicateFree(joints);
  1026. if (o.isMember("name")) {
  1027. name = as<std::string>(o["name"]);
  1028. }
  1029. if (o.isMember("skeleton")) {
  1030. skeleton = as<std::size_t>(o["skeleton"]);
  1031. }
  1032. }
  1033. };
  1034. template<> Skin as(const Json::Value &o) { return o; }
  1035. struct Texture {
  1036. std::optional<std::string> name;
  1037. std::optional<std::size_t> sampler;
  1038. std::optional<std::size_t> source;
  1039. Texture(const Json::Value &o)
  1040. {
  1041. check(o.isObject());
  1042. if (o.isMember("name")) {
  1043. name = as<std::string>(o["name"]);
  1044. }
  1045. if (o.isMember("sampler")) {
  1046. sampler = as<std::size_t>(o["sampler"]);
  1047. }
  1048. if (o.isMember("source")) {
  1049. source = as<std::size_t>(o["source"]);
  1050. }
  1051. }
  1052. };
  1053. template<> Texture as(const Json::Value &o) { return o; }
  1054. using UriResolver = std::function<std::string(const std::string &uri)>;
  1055. static inline std::string uriError(const std::string &uri) {
  1056. // only base64 data URI support by default
  1057. throw std::runtime_error("unsupported URI: " + uri);
  1058. }
  1059. struct GlTF {
  1060. std::optional<std::vector<Accessor>> accessors;
  1061. std::optional<std::vector<Animation>> animations;
  1062. Asset asset;
  1063. std::optional<std::vector<BufferView>> bufferViews;
  1064. std::optional<std::vector<Buffer>> buffers;
  1065. std::optional<std::vector<Camera>> cameras;
  1066. std::optional<std::vector<std::string>> extensionsRequired;
  1067. std::optional<std::vector<std::string>> extensionsUsed;
  1068. std::optional<std::vector<Image>> images;
  1069. std::optional<std::vector<Material>> materials;
  1070. std::optional<std::vector<Mesh>> meshes;
  1071. std::optional<std::vector<Node>> nodes;
  1072. std::optional<std::vector<Sampler>> samplers;
  1073. std::optional<std::size_t> scene;
  1074. std::optional<std::vector<Scene>> scenes;
  1075. std::optional<std::vector<Skin>> skins;
  1076. std::optional<std::vector<Texture>> textures;
  1077. GlTF(const Json::Value &o,
  1078. const UriResolver &resolveUri = uriError,
  1079. std::optional<std::string> &&glbData = std::nullopt)
  1080. : asset(as<Asset>(o["asset"]))
  1081. {
  1082. check(o.isObject());
  1083. if (o.isMember("accessors")) {
  1084. accessors = asVec<Accessor>(o["accessors"]);
  1085. check(accessors->size() >= 1);
  1086. }
  1087. if (o.isMember("animations")) {
  1088. animations = asVec<Animation>(o["animations"]);
  1089. check(animations->size() >= 1);
  1090. }
  1091. if (o.isMember("bufferViews")) {
  1092. bufferViews = asVec<BufferView>(o["bufferViews"]);
  1093. check(bufferViews->size() >= 1);
  1094. }
  1095. if (o.isMember("buffers")) {
  1096. auto b = o["buffers"];
  1097. check(b.isArray());
  1098. std::vector<Buffer> bufs;
  1099. bufs.reserve(b.size());
  1100. for (Json::ArrayIndex i = 0; i < b.size(); ++i) {
  1101. bufs.emplace_back(b[i], resolveUri,
  1102. i == 0 ? std::move(glbData) : std::nullopt);
  1103. }
  1104. check(bufs.size() >= 1);
  1105. buffers = std::move(bufs);
  1106. }
  1107. if (o.isMember("cameras")) {
  1108. cameras = asVec<Camera>(o["cameras"]);
  1109. check(cameras->size() >= 1);
  1110. }
  1111. if (o.isMember("extensionsRequired")) {
  1112. extensionsRequired = asVec<std::string>(o["extensionsRequired"]);
  1113. check(extensionsRequired->size() >= 1);
  1114. checkDuplicateFree(*extensionsRequired);
  1115. }
  1116. if (o.isMember("extensionsUsed")) {
  1117. extensionsUsed = asVec<std::string>(o["extensionsUsed"]);
  1118. check(extensionsUsed->size() >= 1);
  1119. checkDuplicateFree(*extensionsUsed);
  1120. }
  1121. if (o.isMember("images")) {
  1122. images = asVec<Image>(o["images"]);
  1123. check(images->size() >= 1);
  1124. }
  1125. if (o.isMember("materials")) {
  1126. materials = asVec<Material>(o["materials"]);
  1127. check(materials->size() >= 1);
  1128. }
  1129. if (o.isMember("meshes")) {
  1130. meshes = asVec<Mesh>(o["meshes"]);
  1131. check(meshes->size() >= 1);
  1132. }
  1133. if (o.isMember("nodes")) {
  1134. nodes = asVec<Node>(o["nodes"]);
  1135. check(nodes->size() >= 1);
  1136. // Nodes must be a forest:
  1137. // 1. Each node should have indegree 0 or 1:
  1138. std::vector<std::size_t> indeg(nodes->size());
  1139. for (std::size_t i = 0; i < nodes->size(); ++i) {
  1140. auto children = nodes->at(i).children;
  1141. if (!children.has_value()) continue;
  1142. for (auto child : children.value()) {
  1143. ++indeg.at(child);
  1144. }
  1145. }
  1146. for (const auto deg : indeg) {
  1147. check(deg <= 1);
  1148. }
  1149. // 2. There should be no cycles:
  1150. std::vector<bool> visited(nodes->size());
  1151. std::stack<std::size_t, std::vector<std::size_t>> toVisit;
  1152. for (std::size_t i = 0; i < nodes->size(); ++i) {
  1153. // Only start DFS in roots.
  1154. if (indeg[i] > 0)
  1155. continue;
  1156. toVisit.push(i);
  1157. do {
  1158. std::size_t j = toVisit.top();
  1159. check(!visited.at(j));
  1160. visited[j] = true;
  1161. toVisit.pop();
  1162. auto children = nodes->at(j).children;
  1163. if (!children.has_value())
  1164. continue;
  1165. for (auto child : *children) {
  1166. toVisit.push(child);
  1167. }
  1168. } while (!toVisit.empty());
  1169. }
  1170. }
  1171. if (o.isMember("samplers")) {
  1172. samplers = asVec<Sampler>(o["samplers"]);
  1173. check(samplers->size() >= 1);
  1174. }
  1175. if (o.isMember("scene")) {
  1176. scene = as<std::size_t>(o["scene"]);
  1177. }
  1178. if (o.isMember("scenes")) {
  1179. scenes = asVec<Scene>(o["scenes"]);
  1180. check(scenes->size() >= 1);
  1181. }
  1182. if (o.isMember("skins")) {
  1183. skins = asVec<Skin>(o["skins"]);
  1184. check(skins->size() >= 1);
  1185. }
  1186. if (o.isMember("textures")) {
  1187. textures = asVec<Texture>(o["textures"]);
  1188. check(textures->size() >= 1);
  1189. }
  1190. // Validation
  1191. checkForall(bufferViews, [&](const BufferView &view) {
  1192. check(buffers.has_value());
  1193. const Buffer &buf = buffers->at(view.buffer);
  1194. // Be careful because of possible integer overflows.
  1195. check(view.byteOffset < buf.byteLength);
  1196. check(view.byteLength <= buf.byteLength);
  1197. check(view.byteOffset <= buf.byteLength - view.byteLength);
  1198. });
  1199. const auto checkAccessor = [&](const auto &accessor,
  1200. std::size_t bufferView, std::size_t byteOffset, std::size_t count) {
  1201. const BufferView &view = bufferViews->at(bufferView);
  1202. if (view.byteStride.has_value())
  1203. check(*view.byteStride % accessor.componentSize() == 0);
  1204. check(byteOffset < view.byteLength);
  1205. // Use division to avoid overflows.
  1206. const auto effective_byte_stride = view.byteStride.value_or(accessor.elementSize());
  1207. check(count <= (view.byteLength - byteOffset) / effective_byte_stride);
  1208. };
  1209. checkForall(accessors, [&](const Accessor &accessor) {
  1210. if (accessor.bufferView.has_value())
  1211. checkAccessor(accessor, *accessor.bufferView, accessor.byteOffset, accessor.count);
  1212. if (accessor.sparse.has_value()) {
  1213. const auto &indices = accessor.sparse->indices;
  1214. checkAccessor(indices, indices.bufferView, indices.byteOffset, accessor.sparse->count);
  1215. const auto &values = accessor.sparse->values;
  1216. checkAccessor(accessor, values.bufferView, values.byteOffset, accessor.sparse->count);
  1217. }
  1218. });
  1219. checkForall(images, [&](const Image &image) {
  1220. checkIndex(bufferViews, image.bufferView);
  1221. });
  1222. checkForall(meshes, [&](const Mesh &mesh) {
  1223. for (const auto &primitive : mesh.primitives) {
  1224. checkIndex(accessors, primitive.indices);
  1225. checkIndex(materials, primitive.material);
  1226. checkIndex(accessors, primitive.attributes.normal);
  1227. checkIndex(accessors, primitive.attributes.position);
  1228. checkIndex(accessors, primitive.attributes.tangent);
  1229. checkForall(primitive.attributes.texcoord, [&](const std::size_t &i) {
  1230. checkIndex(accessors, i);
  1231. });
  1232. checkForall(primitive.attributes.color, [&](const std::size_t &i) {
  1233. checkIndex(accessors, i);
  1234. });
  1235. checkForall(primitive.attributes.joints, [&](const std::size_t &i) {
  1236. checkIndex(accessors, i);
  1237. });
  1238. checkForall(primitive.attributes.weights, [&](const std::size_t &i) {
  1239. checkIndex(accessors, i);
  1240. });
  1241. if (primitive.material.has_value()) {
  1242. const Material &material = materials->at(primitive.material.value());
  1243. if (material.emissiveTexture.has_value()) {
  1244. check(primitive.attributes.texcoord.has_value());
  1245. check(material.emissiveTexture->texCoord < primitive.attributes.texcoord->size());
  1246. }
  1247. if (material.normalTexture.has_value()) {
  1248. check(primitive.attributes.texcoord.has_value());
  1249. check(material.normalTexture->texCoord < primitive.attributes.texcoord->size());
  1250. }
  1251. if (material.occlusionTexture.has_value()) {
  1252. check(primitive.attributes.texcoord.has_value());
  1253. check(material.occlusionTexture->texCoord < primitive.attributes.texcoord->size());
  1254. }
  1255. }
  1256. checkForall(primitive.targets, [&](const MeshPrimitive::MorphTargets &target) {
  1257. checkIndex(accessors, target.normal);
  1258. checkIndex(accessors, target.position);
  1259. checkIndex(accessors, target.tangent);
  1260. checkForall(target.texcoord, [&](const std::size_t &i) {
  1261. checkIndex(accessors, i);
  1262. });
  1263. checkForall(target.color, [&](const std::size_t &i) {
  1264. checkIndex(accessors, i);
  1265. });
  1266. });
  1267. }
  1268. });
  1269. checkForall(nodes, [&](const Node &node) {
  1270. checkIndex(cameras, node.camera);
  1271. checkIndex(meshes, node.mesh);
  1272. checkIndex(skins, node.skin);
  1273. });
  1274. checkForall(scenes, [&](const Scene &scene) {
  1275. checkForall(scene.nodes, [&](const size_t &i) {
  1276. checkIndex(nodes, i);
  1277. });
  1278. });
  1279. checkForall(skins, [&](const Skin &skin) {
  1280. checkIndex(accessors, skin.inverseBindMatrices);
  1281. for (const std::size_t &i : skin.joints)
  1282. checkIndex(nodes, i);
  1283. checkIndex(nodes, skin.skeleton);
  1284. });
  1285. checkForall(textures, [&](const Texture &texture) {
  1286. checkIndex(samplers, texture.sampler);
  1287. checkIndex(images, texture.source);
  1288. });
  1289. checkForall(animations, [&](const Animation &animation) {
  1290. for (const auto &sampler : animation.samplers) {
  1291. checkIndex(accessors, sampler.input);
  1292. const auto &accessor = accessors->at(sampler.input);
  1293. check(accessor.type == Accessor::Type::SCALAR);
  1294. check(accessor.componentType == Accessor::ComponentType::FLOAT);
  1295. checkIndex(accessors, sampler.output);
  1296. }
  1297. for (const auto &channel : animation.channels) {
  1298. checkIndex(nodes, channel.target.node);
  1299. checkIndex(animation.samplers, channel.sampler);
  1300. }
  1301. });
  1302. checkIndex(scenes, scene);
  1303. }
  1304. };
  1305. // std::span is C++ 20, so we roll our own little struct here.
  1306. template <typename T>
  1307. struct Span {
  1308. T *ptr;
  1309. uint32_t len;
  1310. bool empty() const {
  1311. return len == 0;
  1312. }
  1313. T *end() const {
  1314. return ptr + len;
  1315. }
  1316. template <typename U>
  1317. Span<U> cast() const {
  1318. return {(U *) ptr, len};
  1319. }
  1320. };
  1321. static Json::Value readJson(Span<const char> span) {
  1322. Json::CharReaderBuilder builder;
  1323. const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
  1324. Json::Value json;
  1325. JSONCPP_STRING err;
  1326. if (!reader->parse(span.ptr, span.end(), &json, &err))
  1327. throw std::runtime_error(std::string("invalid JSON: ") + err);
  1328. return json;
  1329. }
  1330. inline GlTF readGlb(const char *data, std::size_t len, const UriResolver &resolveUri = uriError) {
  1331. struct Chunk {
  1332. uint32_t type;
  1333. Span<const uint8_t> span;
  1334. };
  1335. struct Stream {
  1336. Span<const uint8_t> span;
  1337. bool eof() const {
  1338. return span.empty();
  1339. }
  1340. void advance(uint32_t n) {
  1341. span.len -= n;
  1342. span.ptr += n;
  1343. }
  1344. uint32_t readUint32() {
  1345. if (span.len < 4)
  1346. throw std::runtime_error("premature EOF");
  1347. uint32_t res = 0;
  1348. for (int i = 0; i < 4; ++i)
  1349. res += span.ptr[i] << (i * 8);
  1350. advance(4);
  1351. return res;
  1352. }
  1353. Chunk readChunk() {
  1354. const auto chunkLen = readUint32();
  1355. if (chunkLen % 4 != 0)
  1356. throw std::runtime_error("chunk length must be multiple of 4");
  1357. const auto chunkType = readUint32();
  1358. auto chunkPtr = span.ptr;
  1359. if (span.len < chunkLen)
  1360. throw std::runtime_error("premature EOF");
  1361. advance(chunkLen);
  1362. return {chunkType, {chunkPtr, chunkLen}};
  1363. }
  1364. };
  1365. constexpr uint32_t MAGIC_GLTF = 0x46546C67;
  1366. constexpr uint32_t MAGIC_JSON = 0x4E4F534A;
  1367. constexpr uint32_t MAGIC_BIN = 0x004E4942;
  1368. if (len > std::numeric_limits<uint32_t>::max())
  1369. throw std::runtime_error("too large");
  1370. Stream is{{(const uint8_t *) data, static_cast<uint32_t>(len)}};
  1371. const auto magic = is.readUint32();
  1372. if (magic != MAGIC_GLTF)
  1373. throw std::runtime_error("wrong magic number");
  1374. const auto version = is.readUint32();
  1375. if (version != 2)
  1376. throw std::runtime_error("wrong version");
  1377. const auto length = is.readUint32();
  1378. if (length != len)
  1379. throw std::runtime_error("wrong length");
  1380. const auto json = is.readChunk();
  1381. if (json.type != MAGIC_JSON)
  1382. throw std::runtime_error("expected JSON chunk");
  1383. std::optional<std::string> buffer;
  1384. if (!is.eof()) {
  1385. const auto chunk = is.readChunk();
  1386. if (chunk.type == MAGIC_BIN)
  1387. buffer = std::string((const char *) chunk.span.ptr, chunk.span.len);
  1388. else if (chunk.type == MAGIC_JSON)
  1389. throw std::runtime_error("unexpected chunk");
  1390. // Ignore all other chunks. We still want to validate that
  1391. // 1. These chunks are valid;
  1392. // 2. These chunks are *not* JSON or BIN chunks
  1393. while (!is.eof()) {
  1394. const auto type = is.readChunk().type;
  1395. if (type == MAGIC_JSON || type == MAGIC_BIN)
  1396. throw std::runtime_error("unexpected chunk");
  1397. }
  1398. }
  1399. return GlTF(readJson(json.span.cast<const char>()), resolveUri, std::move(buffer));
  1400. }
  1401. inline GlTF readGlTF(const char *data, std::size_t len, const UriResolver &resolveUri = uriError) {
  1402. if (len > std::numeric_limits<uint32_t>::max())
  1403. throw std::runtime_error("too large");
  1404. return GlTF(readJson({data, static_cast<uint32_t>(len)}), resolveUri);
  1405. }
  1406. }