glTFAsset.inl 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. /*
  2. Open Asset Import Library (assimp)
  3. ----------------------------------------------------------------------
  4. Copyright (c) 2006-2020, assimp team
  5. All rights reserved.
  6. Redistribution and use of this software in source and binary forms,
  7. with or without modification, are permitted provided that the
  8. following conditions are met:
  9. * Redistributions of source code must retain the above
  10. copyright notice, this list of conditions and the
  11. following disclaimer.
  12. * Redistributions in binary form must reproduce the above
  13. copyright notice, this list of conditions and the
  14. following disclaimer in the documentation and/or other
  15. materials provided with the distribution.
  16. * Neither the name of the assimp team, nor the names of its
  17. contributors may be used to endorse or promote products
  18. derived from this software without specific prior
  19. written permission of the assimp team.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. ----------------------------------------------------------------------
  32. */
  33. #include <assimp/StringUtils.h>
  34. #include <iomanip>
  35. // Header files, Assimp
  36. #include <assimp/DefaultLogger.hpp>
  37. #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
  38. // Header files, Open3DGC.
  39. #include <Open3DGC/o3dgcSC3DMCDecoder.h>
  40. #endif
  41. using namespace Assimp;
  42. using namespace glTFCommon;
  43. namespace glTF {
  44. namespace {
  45. #if _MSC_VER
  46. # pragma warning(push)
  47. # pragma warning(disable : 4706)
  48. #endif // _MSC_VER
  49. //
  50. // JSON Value reading helpers
  51. //
  52. template <class T>
  53. struct ReadHelper {
  54. static bool Read(Value &val, T &out) {
  55. return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
  56. }
  57. };
  58. template <>
  59. struct ReadHelper<bool> {
  60. static bool Read(Value &val, bool &out) {
  61. return val.IsBool() ? out = val.GetBool(), true : false;
  62. }
  63. };
  64. template <>
  65. struct ReadHelper<float> {
  66. static bool Read(Value &val, float &out) {
  67. return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
  68. }
  69. };
  70. template <unsigned int N>
  71. struct ReadHelper<float[N]> {
  72. static bool Read(Value &val, float (&out)[N]) {
  73. if (!val.IsArray() || val.Size() != N) return false;
  74. for (unsigned int i = 0; i < N; ++i) {
  75. if (val[i].IsNumber())
  76. out[i] = static_cast<float>(val[i].GetDouble());
  77. }
  78. return true;
  79. }
  80. };
  81. template <>
  82. struct ReadHelper<const char *> {
  83. static bool Read(Value &val, const char *&out) {
  84. return val.IsString() ? (out = val.GetString(), true) : false;
  85. }
  86. };
  87. template <>
  88. struct ReadHelper<std::string> {
  89. static bool Read(Value &val, std::string &out) {
  90. return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
  91. }
  92. };
  93. template <class T>
  94. struct ReadHelper<Nullable<T>> {
  95. static bool Read(Value &val, Nullable<T> &out) {
  96. return out.isPresent = ReadHelper<T>::Read(val, out.value);
  97. }
  98. };
  99. template <>
  100. struct ReadHelper<uint64_t> {
  101. static bool Read(Value &val, uint64_t &out) {
  102. return val.IsUint64() ? out = val.GetUint64(), true : false;
  103. }
  104. };
  105. template <>
  106. struct ReadHelper<int64_t> {
  107. static bool Read(Value &val, int64_t &out) {
  108. return val.IsInt64() ? out = val.GetInt64(), true : false;
  109. }
  110. };
  111. template <class T>
  112. inline static bool ReadValue(Value &val, T &out) {
  113. return ReadHelper<T>::Read(val, out);
  114. }
  115. template <class T>
  116. inline static bool ReadMember(Value &obj, const char *id, T &out) {
  117. Value::MemberIterator it = obj.FindMember(id);
  118. if (it != obj.MemberEnd()) {
  119. return ReadHelper<T>::Read(it->value, out);
  120. }
  121. return false;
  122. }
  123. template <class T>
  124. inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
  125. T out;
  126. return ReadMember(obj, id, out) ? out : defaultValue;
  127. }
  128. inline Value *FindMember(Value &val, const char *id) {
  129. Value::MemberIterator it = val.FindMember(id);
  130. return (it != val.MemberEnd()) ? &it->value : 0;
  131. }
  132. inline Value *FindString(Value &val, const char *id) {
  133. Value::MemberIterator it = val.FindMember(id);
  134. return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
  135. }
  136. inline Value *FindNumber(Value &val, const char *id) {
  137. Value::MemberIterator it = val.FindMember(id);
  138. return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
  139. }
  140. inline Value *FindArray(Value &val, const char *id) {
  141. Value::MemberIterator it = val.FindMember(id);
  142. return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0;
  143. }
  144. inline Value *FindObject(Value &val, const char *id) {
  145. Value::MemberIterator it = val.FindMember(id);
  146. return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0;
  147. }
  148. } // namespace
  149. //
  150. // LazyDict methods
  151. //
  152. template <class T>
  153. inline LazyDict<T>::LazyDict(Asset &asset, const char *dictId, const char *extId) :
  154. mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset) {
  155. asset.mDicts.push_back(this); // register to the list of dictionaries
  156. }
  157. template <class T>
  158. inline LazyDict<T>::~LazyDict() {
  159. for (size_t i = 0; i < mObjs.size(); ++i) {
  160. delete mObjs[i];
  161. }
  162. }
  163. template <class T>
  164. inline void LazyDict<T>::AttachToDocument(Document &doc) {
  165. Value *container = 0;
  166. if (mExtId) {
  167. if (Value *exts = FindObject(doc, "extensions")) {
  168. container = FindObject(*exts, mExtId);
  169. }
  170. } else {
  171. container = &doc;
  172. }
  173. if (container) {
  174. mDict = FindObject(*container, mDictId);
  175. }
  176. }
  177. template <class T>
  178. inline void LazyDict<T>::DetachFromDocument() {
  179. mDict = 0;
  180. }
  181. template <class T>
  182. Ref<T> LazyDict<T>::Get(unsigned int i) {
  183. return Ref<T>(mObjs, i);
  184. }
  185. template <class T>
  186. Ref<T> LazyDict<T>::Get(const char *id) {
  187. id = T::TranslateId(mAsset, id);
  188. typename Dict::iterator it = mObjsById.find(id);
  189. if (it != mObjsById.end()) { // already created?
  190. return Ref<T>(mObjs, it->second);
  191. }
  192. // read it from the JSON object
  193. if (!mDict) {
  194. throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\"");
  195. }
  196. Value::MemberIterator obj = mDict->FindMember(id);
  197. if (obj == mDict->MemberEnd()) {
  198. throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\"");
  199. }
  200. if (!obj->value.IsObject()) {
  201. throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object");
  202. }
  203. // create an instance of the given type
  204. T *inst = new T();
  205. inst->id = id;
  206. ReadMember(obj->value, "name", inst->name);
  207. inst->Read(obj->value, mAsset);
  208. return Add(inst);
  209. }
  210. template <class T>
  211. Ref<T> LazyDict<T>::Add(T *obj) {
  212. unsigned int idx = unsigned(mObjs.size());
  213. mObjs.push_back(obj);
  214. mObjsById[obj->id] = idx;
  215. mAsset.mUsedIds[obj->id] = true;
  216. return Ref<T>(mObjs, idx);
  217. }
  218. template <class T>
  219. Ref<T> LazyDict<T>::Create(const char *id) {
  220. Asset::IdMap::iterator it = mAsset.mUsedIds.find(id);
  221. if (it != mAsset.mUsedIds.end()) {
  222. throw DeadlyImportError("GLTF: two objects with the same ID exist");
  223. }
  224. T *inst = new T();
  225. inst->id = id;
  226. return Add(inst);
  227. }
  228. //
  229. // glTF dictionary objects methods
  230. //
  231. inline Buffer::Buffer() :
  232. byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) {}
  233. inline Buffer::~Buffer() {
  234. for (SEncodedRegion *reg : EncodedRegion_List)
  235. delete reg;
  236. }
  237. inline const char *Buffer::TranslateId(Asset &r, const char *id) {
  238. // Compatibility with old spec
  239. if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) {
  240. return "binary_glTF";
  241. }
  242. return id;
  243. }
  244. inline void Buffer::Read(Value &obj, Asset &r) {
  245. size_t statedLength = MemberOrDefault<size_t>(obj, "byteLength", 0);
  246. byteLength = statedLength;
  247. Value *it = FindString(obj, "uri");
  248. if (!it) {
  249. if (statedLength > 0) {
  250. throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute");
  251. }
  252. return;
  253. }
  254. const char *uri = it->GetString();
  255. glTFCommon::Util::DataURI dataURI;
  256. if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
  257. if (dataURI.base64) {
  258. uint8_t *data = 0;
  259. this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
  260. this->mData.reset(data, std::default_delete<uint8_t[]>());
  261. if (statedLength > 0 && this->byteLength != statedLength) {
  262. throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
  263. " bytes, but found " + to_string(dataURI.dataLength));
  264. }
  265. } else { // assume raw data
  266. if (statedLength != dataURI.dataLength) {
  267. throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) +
  268. " bytes, but found " + to_string(dataURI.dataLength));
  269. }
  270. this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete<uint8_t[]>());
  271. memcpy(this->mData.get(), dataURI.data, dataURI.dataLength);
  272. }
  273. } else { // Local file
  274. if (byteLength > 0) {
  275. std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir) : "";
  276. IOStream *file = r.OpenFile(dir + uri, "rb");
  277. if (file) {
  278. bool ok = LoadFromStream(*file, byteLength);
  279. delete file;
  280. if (!ok)
  281. throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"");
  282. } else {
  283. throw DeadlyImportError("GLTF: could not open referenced file \"" + std::string(uri) + "\"");
  284. }
  285. }
  286. }
  287. }
  288. inline bool Buffer::LoadFromStream(IOStream &stream, size_t length, size_t baseOffset) {
  289. byteLength = length ? length : stream.FileSize();
  290. if (baseOffset) {
  291. stream.Seek(baseOffset, aiOrigin_SET);
  292. }
  293. mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>());
  294. if (stream.Read(mData.get(), byteLength, 1) != 1) {
  295. return false;
  296. }
  297. return true;
  298. }
  299. inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) {
  300. // Check pointer to data
  301. if (pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided.");
  302. // Check offset
  303. if (pOffset > byteLength) {
  304. const uint8_t val_size = 32;
  305. char val[val_size];
  306. ai_snprintf(val, val_size, AI_SIZEFMT, pOffset);
  307. throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region.");
  308. }
  309. // Check length
  310. if ((pOffset + pEncodedData_Length) > byteLength) {
  311. const uint8_t val_size = 64;
  312. char val[val_size];
  313. ai_snprintf(val, val_size, AI_SIZEFMT, AI_SIZEFMT, pOffset, pEncodedData_Length);
  314. throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range.");
  315. }
  316. // Add new region
  317. EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID));
  318. // And set new value for "byteLength"
  319. byteLength += (pDecodedData_Length - pEncodedData_Length);
  320. }
  321. inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
  322. if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return;
  323. for (SEncodedRegion *reg : EncodedRegion_List) {
  324. if (reg->ID == pID) {
  325. EncodedRegion_Current = reg;
  326. return;
  327. }
  328. }
  329. throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found.");
  330. }
  331. inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) {
  332. const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count;
  333. uint8_t *new_data;
  334. if ((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false;
  335. new_data = new uint8_t[new_data_size];
  336. // Copy data which place before replacing part.
  337. memcpy(new_data, mData.get(), pBufferData_Offset);
  338. // Copy new data.
  339. memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count);
  340. // Copy data which place after replacing part.
  341. memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset);
  342. // Apply new data
  343. mData.reset(new_data, std::default_delete<uint8_t[]>());
  344. byteLength = new_data_size;
  345. return true;
  346. }
  347. inline size_t Buffer::AppendData(uint8_t *data, size_t length) {
  348. size_t offset = this->byteLength;
  349. Grow(length);
  350. memcpy(mData.get() + offset, data, length);
  351. return offset;
  352. }
  353. inline void Buffer::Grow(size_t amount) {
  354. if (amount <= 0) return;
  355. if (capacity >= byteLength + amount) {
  356. byteLength += amount;
  357. return;
  358. }
  359. // Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers,
  360. // originally it would look like: static_cast<size_t>(capacity * 1.5f)
  361. capacity = std::max(capacity + (capacity >> 1), byteLength + amount);
  362. uint8_t *b = new uint8_t[capacity];
  363. if (mData) memcpy(b, mData.get(), byteLength);
  364. mData.reset(b, std::default_delete<uint8_t[]>());
  365. byteLength += amount;
  366. }
  367. //
  368. // struct BufferView
  369. //
  370. inline void BufferView::Read(Value &obj, Asset &r) {
  371. const char *bufferId = MemberOrDefault<const char *>(obj, "buffer", 0);
  372. if (bufferId) {
  373. buffer = r.buffers.Get(bufferId);
  374. }
  375. byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
  376. byteLength = MemberOrDefault(obj, "byteLength", 0u);
  377. }
  378. //
  379. // struct Accessor
  380. //
  381. inline void Accessor::Read(Value &obj, Asset &r) {
  382. const char *bufferViewId = MemberOrDefault<const char *>(obj, "bufferView", 0);
  383. if (bufferViewId) {
  384. bufferView = r.bufferViews.Get(bufferViewId);
  385. }
  386. byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
  387. byteStride = MemberOrDefault(obj, "byteStride", 0u);
  388. componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
  389. count = MemberOrDefault(obj, "count", 0u);
  390. const char *typestr;
  391. type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
  392. }
  393. inline unsigned int Accessor::GetNumComponents() {
  394. return AttribType::GetNumComponents(type);
  395. }
  396. inline unsigned int Accessor::GetBytesPerComponent() {
  397. return int(ComponentTypeSize(componentType));
  398. }
  399. inline unsigned int Accessor::GetElementSize() {
  400. return GetNumComponents() * GetBytesPerComponent();
  401. }
  402. inline uint8_t *Accessor::GetPointer() {
  403. if (!bufferView || !bufferView->buffer) return 0;
  404. uint8_t *basePtr = bufferView->buffer->GetPointer();
  405. if (!basePtr) return 0;
  406. size_t offset = byteOffset + bufferView->byteOffset;
  407. // Check if region is encoded.
  408. if (bufferView->buffer->EncodedRegion_Current != nullptr) {
  409. const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset;
  410. const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length;
  411. if ((offset >= begin) && (offset < end))
  412. return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin];
  413. }
  414. return basePtr + offset;
  415. }
  416. namespace {
  417. inline void CopyData(size_t count,
  418. const uint8_t *src, size_t src_stride,
  419. uint8_t *dst, size_t dst_stride) {
  420. if (src_stride == dst_stride) {
  421. memcpy(dst, src, count * src_stride);
  422. } else {
  423. size_t sz = std::min(src_stride, dst_stride);
  424. for (size_t i = 0; i < count; ++i) {
  425. memcpy(dst, src, sz);
  426. if (sz < dst_stride) {
  427. memset(dst + sz, 0, dst_stride - sz);
  428. }
  429. src += src_stride;
  430. dst += dst_stride;
  431. }
  432. }
  433. }
  434. } // namespace
  435. template <class T>
  436. bool Accessor::ExtractData(T *&outData) {
  437. uint8_t *data = GetPointer();
  438. if (!data) return false;
  439. const size_t elemSize = GetElementSize();
  440. const size_t totalSize = elemSize * count;
  441. const size_t stride = byteStride ? byteStride : elemSize;
  442. const size_t targetElemSize = sizeof(T);
  443. ai_assert(elemSize <= targetElemSize);
  444. ai_assert(count * stride <= bufferView->byteLength);
  445. outData = new T[count];
  446. if (stride == elemSize && targetElemSize == elemSize) {
  447. memcpy(outData, data, totalSize);
  448. } else {
  449. for (size_t i = 0; i < count; ++i) {
  450. memcpy(outData + i, data + i * stride, elemSize);
  451. }
  452. }
  453. return true;
  454. }
  455. inline void Accessor::WriteData(size_t cnt, const void *src_buffer, size_t src_stride) {
  456. uint8_t *buffer_ptr = bufferView->buffer->GetPointer();
  457. size_t offset = byteOffset + bufferView->byteOffset;
  458. size_t dst_stride = GetNumComponents() * GetBytesPerComponent();
  459. const uint8_t *src = reinterpret_cast<const uint8_t *>(src_buffer);
  460. uint8_t *dst = reinterpret_cast<uint8_t *>(buffer_ptr + offset);
  461. ai_assert(dst + count * dst_stride <= buffer_ptr + bufferView->buffer->byteLength);
  462. CopyData(cnt, src, src_stride, dst, dst_stride);
  463. }
  464. inline Accessor::Indexer::Indexer(Accessor &acc) :
  465. accessor(acc), data(acc.GetPointer()), elemSize(acc.GetElementSize()), stride(acc.byteStride ? acc.byteStride : elemSize) {
  466. }
  467. //! Accesses the i-th value as defined by the accessor
  468. template <class T>
  469. T Accessor::Indexer::GetValue(int i) {
  470. ai_assert(data);
  471. ai_assert(i * stride < accessor.bufferView->byteLength);
  472. T value = T();
  473. memcpy(&value, data + i * stride, elemSize);
  474. //value >>= 8 * (sizeof(T) - elemSize);
  475. return value;
  476. }
  477. inline Image::Image() :
  478. width(0), height(0), mDataLength(0) {
  479. }
  480. inline void Image::Read(Value &obj, Asset &r) {
  481. // Check for extensions first (to detect binary embedded data)
  482. if (Value *extensions = FindObject(obj, "extensions")) {
  483. if (r.extensionsUsed.KHR_binary_glTF) {
  484. if (Value *ext = FindObject(*extensions, "KHR_binary_glTF")) {
  485. width = MemberOrDefault(*ext, "width", 0);
  486. height = MemberOrDefault(*ext, "height", 0);
  487. ReadMember(*ext, "mimeType", mimeType);
  488. const char *bufferViewId;
  489. if (ReadMember(*ext, "bufferView", bufferViewId)) {
  490. Ref<BufferView> bv = r.bufferViews.Get(bufferViewId);
  491. if (bv) {
  492. mDataLength = bv->byteLength;
  493. mData.reset(new uint8_t[mDataLength]);
  494. memcpy(mData.get(), bv->buffer->GetPointer() + bv->byteOffset, mDataLength);
  495. }
  496. }
  497. }
  498. }
  499. }
  500. if (!mDataLength) {
  501. Value *curUri = FindString(obj, "uri");
  502. if (nullptr != curUri) {
  503. const char *uristr = curUri->GetString();
  504. glTFCommon::Util::DataURI dataURI;
  505. if (ParseDataURI(uristr, curUri->GetStringLength(), dataURI)) {
  506. mimeType = dataURI.mediaType;
  507. if (dataURI.base64) {
  508. uint8_t *ptr = nullptr;
  509. mDataLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
  510. mData.reset(ptr);
  511. }
  512. } else {
  513. this->uri = uristr;
  514. }
  515. }
  516. }
  517. }
  518. inline uint8_t *Image::StealData() {
  519. mDataLength = 0;
  520. return mData.release();
  521. }
  522. inline void Image::SetData(uint8_t *data, size_t length, Asset &r) {
  523. Ref<Buffer> b = r.GetBodyBuffer();
  524. if (b) { // binary file: append to body
  525. std::string bvId = r.FindUniqueID(this->id, "imgdata");
  526. bufferView = r.bufferViews.Create(bvId);
  527. bufferView->buffer = b;
  528. bufferView->byteLength = length;
  529. bufferView->byteOffset = b->AppendData(data, length);
  530. } else { // text file: will be stored as a data uri
  531. uint8_t *temp = new uint8_t[length];
  532. memcpy(temp, data, length);
  533. this->mData.reset(temp);
  534. this->mDataLength = length;
  535. }
  536. }
  537. inline void Sampler::Read(Value &obj, Asset & /*r*/) {
  538. SetDefaults();
  539. ReadMember(obj, "magFilter", magFilter);
  540. ReadMember(obj, "minFilter", minFilter);
  541. ReadMember(obj, "wrapS", wrapS);
  542. ReadMember(obj, "wrapT", wrapT);
  543. }
  544. inline void Sampler::SetDefaults() {
  545. magFilter = SamplerMagFilter_Linear;
  546. minFilter = SamplerMinFilter_Linear;
  547. wrapS = SamplerWrap_Repeat;
  548. wrapT = SamplerWrap_Repeat;
  549. }
  550. inline void Texture::Read(Value &obj, Asset &r) {
  551. const char *sourcestr;
  552. if (ReadMember(obj, "source", sourcestr)) {
  553. source = r.images.Get(sourcestr);
  554. }
  555. const char *samplerstr;
  556. if (ReadMember(obj, "sampler", samplerstr)) {
  557. sampler = r.samplers.Get(samplerstr);
  558. }
  559. }
  560. namespace {
  561. inline void ReadMaterialProperty(Asset &r, Value &vals, const char *propName, TexProperty &out) {
  562. if (Value *prop = FindMember(vals, propName)) {
  563. if (prop->IsString()) {
  564. out.texture = r.textures.Get(prop->GetString());
  565. } else {
  566. ReadValue(*prop, out.color);
  567. }
  568. }
  569. }
  570. } // namespace
  571. inline void Material::Read(Value &material, Asset &r) {
  572. SetDefaults();
  573. if (Value *values = FindObject(material, "values")) {
  574. ReadMaterialProperty(r, *values, "ambient", this->ambient);
  575. ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
  576. ReadMaterialProperty(r, *values, "specular", this->specular);
  577. ReadMember(*values, "transparency", transparency);
  578. ReadMember(*values, "shininess", shininess);
  579. }
  580. if (Value *extensions = FindObject(material, "extensions")) {
  581. if (r.extensionsUsed.KHR_materials_common) {
  582. if (Value *ext = FindObject(*extensions, "KHR_materials_common")) {
  583. if (Value *tnq = FindString(*ext, "technique")) {
  584. const char *t = tnq->GetString();
  585. if (strcmp(t, "BLINN") == 0)
  586. technique = Technique_BLINN;
  587. else if (strcmp(t, "PHONG") == 0)
  588. technique = Technique_PHONG;
  589. else if (strcmp(t, "LAMBERT") == 0)
  590. technique = Technique_LAMBERT;
  591. else if (strcmp(t, "CONSTANT") == 0)
  592. technique = Technique_CONSTANT;
  593. }
  594. if (Value *values = FindObject(*ext, "values")) {
  595. ReadMaterialProperty(r, *values, "ambient", this->ambient);
  596. ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
  597. ReadMaterialProperty(r, *values, "specular", this->specular);
  598. ReadMember(*values, "doubleSided", doubleSided);
  599. ReadMember(*values, "transparent", transparent);
  600. ReadMember(*values, "transparency", transparency);
  601. ReadMember(*values, "shininess", shininess);
  602. }
  603. }
  604. }
  605. }
  606. }
  607. namespace {
  608. void SetVector(vec4 &v, float x, float y, float z, float w) {
  609. v[0] = x;
  610. v[1] = y;
  611. v[2] = z;
  612. v[3] = w;
  613. }
  614. } // namespace
  615. inline void Material::SetDefaults() {
  616. SetVector(ambient.color, 0, 0, 0, 1);
  617. SetVector(diffuse.color, 0, 0, 0, 1);
  618. SetVector(specular.color, 0, 0, 0, 1);
  619. SetVector(emission.color, 0, 0, 0, 1);
  620. doubleSided = false;
  621. transparent = false;
  622. transparency = 1.0;
  623. shininess = 0.0;
  624. technique = Technique_undefined;
  625. }
  626. namespace {
  627. template <int N>
  628. inline int Compare(const char *attr, const char (&str)[N]) {
  629. return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
  630. }
  631. inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) {
  632. if ((pos = Compare(attr, "POSITION"))) {
  633. v = &(p.attributes.position);
  634. } else if ((pos = Compare(attr, "NORMAL"))) {
  635. v = &(p.attributes.normal);
  636. } else if ((pos = Compare(attr, "TEXCOORD"))) {
  637. v = &(p.attributes.texcoord);
  638. } else if ((pos = Compare(attr, "COLOR"))) {
  639. v = &(p.attributes.color);
  640. } else if ((pos = Compare(attr, "JOINT"))) {
  641. v = &(p.attributes.joint);
  642. } else if ((pos = Compare(attr, "JOINTMATRIX"))) {
  643. v = &(p.attributes.jointmatrix);
  644. } else if ((pos = Compare(attr, "WEIGHT"))) {
  645. v = &(p.attributes.weight);
  646. } else
  647. return false;
  648. return true;
  649. }
  650. } // namespace
  651. inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
  652. /****************** Mesh primitives ******************/
  653. Value *curPrimitives = FindArray(pJSON_Object, "primitives");
  654. if (nullptr != curPrimitives) {
  655. this->primitives.resize(curPrimitives->Size());
  656. for (unsigned int i = 0; i < curPrimitives->Size(); ++i) {
  657. Value &primitive = (*curPrimitives)[i];
  658. Primitive &prim = this->primitives[i];
  659. prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES);
  660. if (Value *attrs = FindObject(primitive, "attributes")) {
  661. for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
  662. if (!it->value.IsString()) continue;
  663. const char *attr = it->name.GetString();
  664. // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX,
  665. // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
  666. int undPos = 0;
  667. Mesh::AccessorList *vec = 0;
  668. if (GetAttribVector(prim, attr, vec, undPos)) {
  669. size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
  670. if ((*vec).size() <= idx) (*vec).resize(idx + 1);
  671. (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString());
  672. }
  673. }
  674. }
  675. if (Value *indices = FindString(primitive, "indices")) {
  676. prim.indices = pAsset_Root.accessors.Get(indices->GetString());
  677. }
  678. if (Value *material = FindString(primitive, "material")) {
  679. prim.material = pAsset_Root.materials.Get(material->GetString());
  680. }
  681. }
  682. }
  683. /****************** Mesh extensions ******************/
  684. Value *json_extensions = FindObject(pJSON_Object, "extensions");
  685. if (json_extensions == nullptr) goto mr_skip_extensions;
  686. for (Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++) {
  687. #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
  688. if (it_memb->name.GetString() == std::string("Open3DGC-compression")) {
  689. // Search for compressed data.
  690. // Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and
  691. // new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure.
  692. Value *comp_data = FindObject(it_memb->value, "compressedData");
  693. if (comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\".");
  694. ASSIMP_LOG_INFO("GLTF: Decompressing Open3DGC data.");
  695. /************** Read data from JSON-document **************/
  696. #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \
  697. if (!ReadMember(*comp_data, pFieldName, pOut)) { \
  698. throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \
  699. }
  700. const char *mode_str;
  701. const char *type_str;
  702. ComponentType component_type;
  703. SCompression_Open3DGC *ext_o3dgc = new SCompression_Open3DGC;
  704. MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer);
  705. MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset);
  706. MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type);
  707. MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str);
  708. MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count);
  709. MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str);
  710. MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount);
  711. MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount);
  712. #undef MESH_READ_COMPRESSEDDATA_MEMBER
  713. // Check some values
  714. if (strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data.");
  715. if (component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data.");
  716. // Set read/write data mode.
  717. if (strcmp(mode_str, "binary") == 0)
  718. ext_o3dgc->Binary = true;
  719. else if (strcmp(mode_str, "ascii") == 0)
  720. ext_o3dgc->Binary = false;
  721. else
  722. throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\".");
  723. /************************ Decoding ************************/
  724. Decode_O3DGC(*ext_o3dgc, pAsset_Root);
  725. Extension.push_back(ext_o3dgc); // store info in mesh extensions list.
  726. } // if(it_memb->name.GetString() == "Open3DGC-compression")
  727. else
  728. #endif
  729. {
  730. throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\".");
  731. }
  732. } // for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++)
  733. mr_skip_extensions:
  734. return; // After label some operators must be present.
  735. }
  736. #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
  737. inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root) {
  738. typedef unsigned short IndicesType; ///< \sa glTFExporter::ExportMeshes.
  739. o3dgc::SC3DMCDecoder<IndicesType> decoder;
  740. o3dgc::IndexedFaceSet<IndicesType> ifs;
  741. o3dgc::BinaryStream bstream;
  742. uint8_t *decoded_data;
  743. size_t decoded_data_size = 0;
  744. Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
  745. // Read data from buffer and place it in BinaryStream for decoder.
  746. // Just "Count" because always is used type equivalent to uint8_t.
  747. bstream.LoadFromBuffer(&buf->GetPointer()[pCompression_Open3DGC.Offset], static_cast<unsigned long>(pCompression_Open3DGC.Count));
  748. // After decoding header we can get size of primitives.
  749. if (decoder.DecodeHeader(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC header.");
  750. /****************** Get sizes of arrays and check sizes ******************/
  751. // Note. See "Limitations for meshes when using Open3DGC-compression".
  752. // Indices
  753. size_t size_coordindex = ifs.GetNCoordIndex() * 3; // See float attributes note.
  754. if (primitives[0].indices->count != size_coordindex)
  755. throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + to_string(size_coordindex) +
  756. ") not equal to uncompressed (" + to_string(primitives[0].indices->count) + ").");
  757. size_coordindex *= sizeof(IndicesType);
  758. // Coordinates
  759. size_t size_coord = ifs.GetNCoord(); // See float attributes note.
  760. if (primitives[0].attributes.position[0]->count != size_coord)
  761. throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + to_string(size_coord) +
  762. ") not equal to uncompressed (" + to_string(primitives[0].attributes.position[0]->count) + ").");
  763. size_coord *= 3 * sizeof(float);
  764. // Normals
  765. size_t size_normal = ifs.GetNNormal(); // See float attributes note.
  766. if (primitives[0].attributes.normal[0]->count != size_normal)
  767. throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + to_string(size_normal) +
  768. ") not equal to uncompressed (" + to_string(primitives[0].attributes.normal[0]->count) + ").");
  769. size_normal *= 3 * sizeof(float);
  770. // Additional attributes.
  771. std::vector<size_t> size_floatattr;
  772. std::vector<size_t> size_intattr;
  773. size_floatattr.resize(ifs.GetNumFloatAttributes());
  774. size_intattr.resize(ifs.GetNumIntAttributes());
  775. decoded_data_size = size_coordindex + size_coord + size_normal;
  776. for (size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) {
  777. // size = number_of_elements * components_per_element * size_of_component.
  778. // Note. But as you can see above, at first we are use this variable in meaning "count". After checking count of objects...
  779. size_t tval = ifs.GetNFloatAttribute(static_cast<unsigned long>(idx));
  780. switch (ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))) {
  781. case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
  782. // Check situation when encoded data contain texture coordinates but primitive not.
  783. if (idx_texcoord < primitives[0].attributes.texcoord.size()) {
  784. if (primitives[0].attributes.texcoord[idx]->count != tval)
  785. throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + to_string(tval) +
  786. ") not equal to uncompressed (" + to_string(primitives[0].attributes.texcoord[idx]->count) + ").");
  787. idx_texcoord++;
  788. } else {
  789. ifs.SetNFloatAttribute(static_cast<unsigned long>(idx), 0ul); // Disable decoding this attribute.
  790. }
  791. break;
  792. default:
  793. throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
  794. }
  795. tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real); // After checking count of objects we can get size of array.
  796. size_floatattr[idx] = tval;
  797. decoded_data_size += tval;
  798. }
  799. for (size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) {
  800. // size = number_of_elements * components_per_element * size_of_component. See float attributes note.
  801. size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx));
  802. switch (ifs.GetIntAttributeType(static_cast<unsigned long>(idx))) {
  803. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
  804. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
  805. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
  806. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
  807. break;
  808. default:
  809. throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
  810. }
  811. tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long); // See float attributes note.
  812. size_intattr[idx] = tval;
  813. decoded_data_size += tval;
  814. }
  815. // Create array for decoded data.
  816. decoded_data = new uint8_t[decoded_data_size];
  817. /****************** Set right array regions for decoder ******************/
  818. auto get_buf_offset = [](Ref<Accessor> &pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; };
  819. // Indices
  820. ifs.SetCoordIndex((IndicesType *const)(decoded_data + get_buf_offset(primitives[0].indices)));
  821. // Coordinates
  822. ifs.SetCoord((o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0])));
  823. // Normals
  824. if (size_normal) {
  825. ifs.SetNormal((o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0])));
  826. }
  827. for (size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) {
  828. switch (ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))) {
  829. case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
  830. if (idx_texcoord < primitives[0].attributes.texcoord.size()) {
  831. // See above about absent attributes.
  832. ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real *const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx])));
  833. idx_texcoord++;
  834. }
  835. break;
  836. default:
  837. throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
  838. }
  839. }
  840. for (size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) {
  841. switch (ifs.GetIntAttributeType(static_cast<unsigned int>(idx))) {
  842. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
  843. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
  844. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
  845. case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
  846. break;
  847. // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
  848. default:
  849. throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
  850. }
  851. }
  852. //
  853. // Decode data
  854. //
  855. if (decoder.DecodePayload(ifs, bstream) != o3dgc::O3DGC_OK) {
  856. throw DeadlyImportError("GLTF: can not decode Open3DGC data.");
  857. }
  858. // Set encoded region for "buffer".
  859. buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id);
  860. // No. Do not delete "output_data". After calling "EncodedRegion_Mark" bufferView is owner of "output_data".
  861. // "delete [] output_data;"
  862. }
  863. #endif
  864. inline void Camera::Read(Value &obj, Asset & /*r*/) {
  865. type = MemberOrDefault(obj, "type", Camera::Perspective);
  866. const char *subobjId = (type == Camera::Orthographic) ? "ortographic" : "perspective";
  867. Value *it = FindObject(obj, subobjId);
  868. if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
  869. if (type == Camera::Perspective) {
  870. perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
  871. perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f / 2.f);
  872. perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
  873. perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
  874. } else {
  875. ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
  876. ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
  877. ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
  878. ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
  879. }
  880. }
  881. inline void Light::Read(Value &obj, Asset & /*r*/) {
  882. SetDefaults();
  883. Value *curType = FindString(obj, "type");
  884. if (nullptr != curType) {
  885. const char *t = curType->GetString();
  886. if (strcmp(t, "ambient") == 0)
  887. this->type = Type_ambient;
  888. else if (strcmp(t, "directional") == 0)
  889. this->type = Type_directional;
  890. else if (strcmp(t, "point") == 0)
  891. this->type = Type_point;
  892. else if (strcmp(t, "spot") == 0)
  893. this->type = Type_spot;
  894. if (this->type != Type_undefined) {
  895. if (Value *vals = FindString(obj, t)) {
  896. ReadMember(*vals, "color", color);
  897. ReadMember(*vals, "constantAttenuation", constantAttenuation);
  898. ReadMember(*vals, "linearAttenuation", linearAttenuation);
  899. ReadMember(*vals, "quadraticAttenuation", quadraticAttenuation);
  900. ReadMember(*vals, "distance", distance);
  901. ReadMember(*vals, "falloffAngle", falloffAngle);
  902. ReadMember(*vals, "falloffExponent", falloffExponent);
  903. }
  904. }
  905. }
  906. }
  907. inline void Light::SetDefaults() {
  908. #ifndef M_PI
  909. const float M_PI = 3.14159265358979323846f;
  910. #endif
  911. type = Type_undefined;
  912. SetVector(color, 0.f, 0.f, 0.f, 1.f);
  913. constantAttenuation = 0.f;
  914. linearAttenuation = 1.f;
  915. quadraticAttenuation = 1.f;
  916. distance = 0.f;
  917. falloffAngle = static_cast<float>(M_PI / 2.f);
  918. falloffExponent = 0.f;
  919. }
  920. inline void Node::Read(Value &obj, Asset &r) {
  921. if (name.empty()) {
  922. name = id;
  923. }
  924. Value *curChildren = FindArray(obj, "children");
  925. if (nullptr != curChildren) {
  926. this->children.reserve(curChildren->Size());
  927. for (unsigned int i = 0; i < curChildren->Size(); ++i) {
  928. Value &child = (*curChildren)[i];
  929. if (child.IsString()) {
  930. // get/create the child node
  931. Ref<Node> chn = r.nodes.Get(child.GetString());
  932. if (chn) this->children.push_back(chn);
  933. }
  934. }
  935. }
  936. Value *curMatrix = FindArray(obj, "matrix");
  937. if (nullptr != curMatrix) {
  938. ReadValue(*curMatrix, this->matrix);
  939. } else {
  940. ReadMember(obj, "translation", translation);
  941. ReadMember(obj, "scale", scale);
  942. ReadMember(obj, "rotation", rotation);
  943. }
  944. Value *curMeshes = FindArray(obj, "meshes");
  945. if (nullptr != curMeshes) {
  946. unsigned int numMeshes = (unsigned int)curMeshes->Size();
  947. std::vector<unsigned int> meshList;
  948. this->meshes.reserve(numMeshes);
  949. for (unsigned i = 0; i < numMeshes; ++i) {
  950. if ((*curMeshes)[i].IsString()) {
  951. Ref<Mesh> mesh = r.meshes.Get((*curMeshes)[i].GetString());
  952. if (mesh) {
  953. this->meshes.push_back(mesh);
  954. }
  955. }
  956. }
  957. }
  958. Value *curCamera = FindString(obj, "camera");
  959. if (nullptr != curCamera) {
  960. this->camera = r.cameras.Get(curCamera->GetString());
  961. if (this->camera) {
  962. this->camera->id = this->id;
  963. }
  964. }
  965. // TODO load "skeletons", "skin", "jointName"
  966. if (Value *extensions = FindObject(obj, "extensions")) {
  967. if (r.extensionsUsed.KHR_materials_common) {
  968. if (Value *ext = FindObject(*extensions, "KHR_materials_common")) {
  969. Value *curLight = FindString(*ext, "light");
  970. if (nullptr != curLight) {
  971. this->light = r.lights.Get(curLight->GetString());
  972. }
  973. }
  974. }
  975. }
  976. }
  977. inline void Scene::Read(Value &obj, Asset &r) {
  978. if (Value *array = FindArray(obj, "nodes")) {
  979. for (unsigned int i = 0; i < array->Size(); ++i) {
  980. if (!(*array)[i].IsString()) continue;
  981. Ref<Node> node = r.nodes.Get((*array)[i].GetString());
  982. if (node)
  983. this->nodes.push_back(node);
  984. }
  985. }
  986. }
  987. inline void AssetMetadata::Read(Document &doc) {
  988. // read the version, etc.
  989. if (Value *obj = FindObject(doc, "asset")) {
  990. ReadMember(*obj, "copyright", copyright);
  991. ReadMember(*obj, "generator", generator);
  992. premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false);
  993. if (Value *versionString = FindString(*obj, "version")) {
  994. version = versionString->GetString();
  995. } else if (Value *versionNumber = FindNumber(*obj, "version")) {
  996. char buf[4];
  997. ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
  998. version = buf;
  999. }
  1000. Value *curProfile = FindObject(*obj, "profile");
  1001. if (nullptr != curProfile) {
  1002. ReadMember(*curProfile, "api", this->profile.api);
  1003. ReadMember(*curProfile, "version", this->profile.version);
  1004. }
  1005. }
  1006. if (version.empty() || version[0] != '1') {
  1007. throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
  1008. }
  1009. }
  1010. //
  1011. // Asset methods implementation
  1012. //
  1013. inline void Asset::ReadBinaryHeader(IOStream &stream) {
  1014. GLB_Header header;
  1015. if (stream.Read(&header, sizeof(header), 1) != 1) {
  1016. throw DeadlyImportError("GLTF: Unable to read the file header");
  1017. }
  1018. if (strncmp((char *)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
  1019. throw DeadlyImportError("GLTF: Invalid binary glTF file");
  1020. }
  1021. AI_SWAP4(header.version);
  1022. asset.version = to_string(header.version);
  1023. if (header.version != 1) {
  1024. throw DeadlyImportError("GLTF: Unsupported binary glTF version");
  1025. }
  1026. AI_SWAP4(header.sceneFormat);
  1027. if (header.sceneFormat != SceneFormat_JSON) {
  1028. throw DeadlyImportError("GLTF: Unsupported binary glTF scene format");
  1029. }
  1030. AI_SWAP4(header.length);
  1031. AI_SWAP4(header.sceneLength);
  1032. mSceneLength = static_cast<size_t>(header.sceneLength);
  1033. mBodyOffset = sizeof(header) + mSceneLength;
  1034. mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
  1035. mBodyLength = header.length - mBodyOffset;
  1036. }
  1037. inline void Asset::Load(const std::string &pFile, bool isBinary) {
  1038. mCurrentAssetDir.clear();
  1039. /*int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
  1040. if (pos != int(std::string::npos)) mCurrentAssetDir = pFile.substr(0, pos + 1);*/
  1041. mCurrentAssetDir = getCurrentAssetDir(pFile);
  1042. shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true));
  1043. if (!stream) {
  1044. throw DeadlyImportError("GLTF: Could not open file for reading");
  1045. }
  1046. // is binary? then read the header
  1047. if (isBinary) {
  1048. SetAsBinary(); // also creates the body buffer
  1049. ReadBinaryHeader(*stream);
  1050. } else {
  1051. mSceneLength = stream->FileSize();
  1052. mBodyLength = 0;
  1053. }
  1054. // read the scene data
  1055. std::vector<char> sceneData(mSceneLength + 1);
  1056. sceneData[mSceneLength] = '\0';
  1057. if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
  1058. throw DeadlyImportError("GLTF: Could not read the file contents");
  1059. }
  1060. // parse the JSON document
  1061. Document doc;
  1062. doc.ParseInsitu(&sceneData[0]);
  1063. if (doc.HasParseError()) {
  1064. char buffer[32];
  1065. ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
  1066. throw DeadlyImportError(std::string("GLTF: JSON parse error, offset ") + buffer + ": " + GetParseError_En(doc.GetParseError()));
  1067. }
  1068. if (!doc.IsObject()) {
  1069. throw DeadlyImportError("GLTF: JSON document root must be a JSON object");
  1070. }
  1071. // Fill the buffer instance for the current file embedded contents
  1072. if (mBodyLength > 0) {
  1073. if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) {
  1074. throw DeadlyImportError("GLTF: Unable to read gltf file");
  1075. }
  1076. }
  1077. // Load the metadata
  1078. asset.Read(doc);
  1079. ReadExtensionsUsed(doc);
  1080. // Prepare the dictionaries
  1081. for (size_t i = 0; i < mDicts.size(); ++i) {
  1082. mDicts[i]->AttachToDocument(doc);
  1083. }
  1084. // Read the "scene" property, which specifies which scene to load
  1085. // and recursively load everything referenced by it
  1086. Value *curScene = FindString(doc, "scene");
  1087. if (nullptr != curScene) {
  1088. this->scene = scenes.Get(curScene->GetString());
  1089. }
  1090. // Clean up
  1091. for (size_t i = 0; i < mDicts.size(); ++i) {
  1092. mDicts[i]->DetachFromDocument();
  1093. }
  1094. }
  1095. inline void Asset::SetAsBinary() {
  1096. if (!extensionsUsed.KHR_binary_glTF) {
  1097. extensionsUsed.KHR_binary_glTF = true;
  1098. mBodyBuffer = buffers.Create("binary_glTF");
  1099. mBodyBuffer->MarkAsSpecial();
  1100. }
  1101. }
  1102. inline void Asset::ReadExtensionsUsed(Document &doc) {
  1103. Value *extsUsed = FindArray(doc, "extensionsUsed");
  1104. if (!extsUsed) return;
  1105. std::gltf_unordered_map<std::string, bool> exts;
  1106. for (unsigned int i = 0; i < extsUsed->Size(); ++i) {
  1107. if ((*extsUsed)[i].IsString()) {
  1108. exts[(*extsUsed)[i].GetString()] = true;
  1109. }
  1110. }
  1111. CHECK_EXT(KHR_binary_glTF);
  1112. CHECK_EXT(KHR_materials_common);
  1113. #undef CHECK_EXT
  1114. }
  1115. inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool absolute) {
  1116. #ifdef ASSIMP_API
  1117. (void)absolute;
  1118. return mIOSystem->Open(path, mode);
  1119. #else
  1120. if (path.size() < 2) return 0;
  1121. if (!absolute && path[1] != ':' && path[0] != '/') { // relative?
  1122. path = mCurrentAssetDir + path;
  1123. }
  1124. FILE *f = fopen(path.c_str(), mode);
  1125. return f ? new IOStream(f) : 0;
  1126. #endif
  1127. }
  1128. inline std::string Asset::FindUniqueID(const std::string &str, const char *suffix) {
  1129. std::string id = str;
  1130. if (!id.empty()) {
  1131. if (mUsedIds.find(id) == mUsedIds.end())
  1132. return id;
  1133. id += "_";
  1134. }
  1135. id += suffix;
  1136. Asset::IdMap::iterator it = mUsedIds.find(id);
  1137. if (it == mUsedIds.end())
  1138. return id;
  1139. char buffer[1024];
  1140. int offset = ai_snprintf(buffer, sizeof(buffer), "%s_", id.c_str());
  1141. for (int i = 0; it != mUsedIds.end(); ++i) {
  1142. ai_snprintf(buffer + offset, sizeof(buffer) - offset, "%d", i);
  1143. id = buffer;
  1144. it = mUsedIds.find(id);
  1145. }
  1146. return id;
  1147. }
  1148. #if _MSC_VER
  1149. # pragma warning(pop)
  1150. #endif // _MSC_VER
  1151. } // namespace glTF