GltfImporter.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Importer/GltfImporter.h>
  6. #include <AnKi/Util/System.h>
  7. #include <AnKi/Util/ThreadHive.h>
  8. #include <AnKi/Util/StringList.h>
  9. #if ANKI_COMPILER_GCC_COMPATIBLE
  10. # pragma GCC diagnostic push
  11. # pragma GCC diagnostic ignored "-Wconversion"
  12. #endif
  13. #define CGLTF_IMPLEMENTATION
  14. #include <Cgltf/cgltf.h>
  15. #if ANKI_COMPILER_GCC_COMPATIBLE
  16. # pragma GCC diagnostic pop
  17. #endif
  18. namespace anki
  19. {
  20. static F32 computeLightRadius(const Vec3 color)
  21. {
  22. // Based on the attenuation equation: att = 1 - fragLightDist^2 / lightRadius^2
  23. const F32 minAtt = 0.01f;
  24. const F32 maxIntensity = max(max(color.x(), color.y()), color.z());
  25. return sqrt(maxIntensity / minAtt);
  26. }
  27. #if 0
  28. static ANKI_USE_RESULT Error getUniformScale(const Mat4& m, F32& out)
  29. {
  30. const F32 SCALE_THRESHOLD = 0.01f; // 1 cm
  31. Vec3 xAxis = m.getColumn(0).xyz();
  32. Vec3 yAxis = m.getColumn(1).xyz();
  33. Vec3 zAxis = m.getColumn(2).xyz();
  34. const F32 scale = xAxis.getLength();
  35. if(absolute(scale - yAxis.getLength()) > SCALE_THRESHOLD || absolute(scale - zAxis.getLength()) > SCALE_THRESHOLD)
  36. {
  37. ANKI_IMPORTER_LOGE("No uniform scale in the matrix");
  38. return Error::USER_DATA;
  39. }
  40. out = scale;
  41. return Error::NONE;
  42. }
  43. #endif
  44. static void removeScale(Mat4& m)
  45. {
  46. Vec3 xAxis = m.getColumn(0).xyz();
  47. Vec3 yAxis = m.getColumn(1).xyz();
  48. Vec3 zAxis = m.getColumn(2).xyz();
  49. xAxis.normalize();
  50. yAxis.normalize();
  51. zAxis.normalize();
  52. Mat3 rot;
  53. rot.setColumns(xAxis, yAxis, zAxis);
  54. m.setRotationPart(rot);
  55. }
  56. static void getNodeTransform(const cgltf_node& node, Vec3& tsl, Mat3& rot, Vec3& scale)
  57. {
  58. if(node.has_matrix)
  59. {
  60. Mat4 trf = Mat4(node.matrix);
  61. Vec3 xAxis = trf.getColumn(0).xyz();
  62. Vec3 yAxis = trf.getColumn(1).xyz();
  63. Vec3 zAxis = trf.getColumn(2).xyz();
  64. scale = Vec3(xAxis.getLength(), yAxis.getLength(), zAxis.getLength());
  65. removeScale(trf);
  66. rot = trf.getRotationPart();
  67. tsl = trf.getTranslationPart().xyz();
  68. }
  69. else
  70. {
  71. if(node.has_translation)
  72. {
  73. tsl = Vec3(node.translation[0], node.translation[1], node.translation[2]);
  74. }
  75. else
  76. {
  77. tsl = Vec3(0.0f);
  78. }
  79. if(node.has_rotation)
  80. {
  81. rot = Mat3(Quat(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3]));
  82. }
  83. else
  84. {
  85. rot = Mat3::getIdentity();
  86. }
  87. if(node.has_scale)
  88. {
  89. ANKI_ASSERT(node.scale[0] > 0.0f);
  90. ANKI_ASSERT(node.scale[1] > 0.0f);
  91. ANKI_ASSERT(node.scale[2] > 0.0f);
  92. scale = Vec3(node.scale[0], node.scale[1], node.scale[2]);
  93. }
  94. else
  95. {
  96. scale = Vec3(1.0f);
  97. }
  98. }
  99. }
  100. static ANKI_USE_RESULT Error getNodeTransform(const cgltf_node& node, Transform& trf)
  101. {
  102. Vec3 tsl;
  103. Mat3 rot;
  104. Vec3 scale;
  105. getNodeTransform(node, tsl, rot, scale);
  106. const F32 scaleEpsilon = 0.01f;
  107. if(absolute(scale[0] - scale[1]) > scaleEpsilon || absolute(scale[0] - scale[2]) > scaleEpsilon)
  108. {
  109. ANKI_IMPORTER_LOGE("Expecting uniform scale");
  110. return Error::USER_DATA;
  111. }
  112. trf.setOrigin(tsl.xyz0());
  113. trf.setRotation(Mat3x4(Vec3(0.0f), rot));
  114. trf.setScale(scale[0]);
  115. return Error::NONE;
  116. }
  117. const char* GltfImporter::XML_HEADER = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
  118. GltfImporter::GltfImporter(GenericMemoryPoolAllocator<U8> alloc)
  119. : m_alloc(alloc)
  120. {
  121. }
  122. GltfImporter::~GltfImporter()
  123. {
  124. if(m_gltf)
  125. {
  126. cgltf_free(m_gltf);
  127. m_gltf = nullptr;
  128. }
  129. m_alloc.deleteInstance(m_hive);
  130. }
  131. Error GltfImporter::init(const GltfImporterInitInfo& initInfo)
  132. {
  133. m_inputFname.create(initInfo.m_inputFilename);
  134. m_outDir.create(initInfo.m_outDirectory);
  135. m_rpath.create(initInfo.m_rpath);
  136. m_texrpath.create(initInfo.m_texrpath);
  137. m_optimizeMeshes = initInfo.m_optimizeMeshes;
  138. m_comment.create(initInfo.m_comment);
  139. m_lightIntensityScale = max(initInfo.m_lightIntensityScale, EPSILON);
  140. m_lodCount = clamp(initInfo.m_lodCount, 1u, 3u);
  141. m_lodFactor = clamp(initInfo.m_lodFactor, 0.0f, 1.0f);
  142. if(m_lodFactor * F32(m_lodCount - 1) > 0.7f)
  143. {
  144. ANKI_IMPORTER_LOGE("LOD factor is too high %f", m_lodFactor);
  145. return Error::USER_DATA;
  146. }
  147. if(m_lodFactor < EPSILON || m_lodCount == 1)
  148. {
  149. m_lodCount = 1;
  150. m_lodFactor = 0.0f;
  151. }
  152. ANKI_IMPORTER_LOGI("Having %u LODs with LOD factor %f", m_lodCount, m_lodFactor);
  153. cgltf_options options = {};
  154. cgltf_result res = cgltf_parse_file(&options, m_inputFname.cstr(), &m_gltf);
  155. if(res != cgltf_result_success)
  156. {
  157. ANKI_IMPORTER_LOGE("Failed to open the GLTF file. Code: %d", res);
  158. return Error::FUNCTION_FAILED;
  159. }
  160. res = cgltf_load_buffers(&options, m_gltf, m_inputFname.cstr());
  161. if(res != cgltf_result_success)
  162. {
  163. ANKI_IMPORTER_LOGE("Failed to load GLTF data. Code: %d", res);
  164. return Error::FUNCTION_FAILED;
  165. }
  166. if(initInfo.m_threadCount > 0)
  167. {
  168. const U32 threadCount = min(getCpuCoresCount(), initInfo.m_threadCount);
  169. m_hive = m_alloc.newInstance<ThreadHive>(threadCount, m_alloc, true);
  170. }
  171. return Error::NONE;
  172. }
  173. Error GltfImporter::writeAll()
  174. {
  175. populateNodePtrToIdx();
  176. for(const cgltf_animation* anim = m_gltf->animations; anim < m_gltf->animations + m_gltf->animations_count; ++anim)
  177. {
  178. ANKI_CHECK(writeAnimation(*anim));
  179. }
  180. StringAuto sceneFname(m_alloc);
  181. sceneFname.sprintf("%sScene.lua", m_outDir.cstr());
  182. ANKI_CHECK(m_sceneFile.open(sceneFname.toCString(), FileOpenFlag::WRITE));
  183. ANKI_CHECK(m_sceneFile.writeText("-- Generated by: %s\n", m_comment.cstr()));
  184. ANKI_CHECK(m_sceneFile.writeText("local scene = getSceneGraph()\nlocal events = getEventManager()\n"));
  185. // Nodes
  186. Error err = Error::NONE;
  187. for(const cgltf_scene* scene = m_gltf->scenes; scene < m_gltf->scenes + m_gltf->scenes_count && !err; ++scene)
  188. {
  189. for(cgltf_node* const* node = scene->nodes; node < scene->nodes + scene->nodes_count && !err; ++node)
  190. {
  191. err = visitNode(*(*node), Transform::getIdentity(), HashMapAuto<CString, StringAuto>(m_alloc));
  192. }
  193. }
  194. if(m_hive)
  195. {
  196. m_hive->waitAllTasks();
  197. }
  198. // Check error
  199. if(err)
  200. {
  201. ANKI_IMPORTER_LOGE("Error happened in main thread");
  202. return err;
  203. }
  204. const Error threadErr = m_errorInThread.load();
  205. if(threadErr)
  206. {
  207. ANKI_IMPORTER_LOGE("Error happened in a thread");
  208. return threadErr;
  209. }
  210. return err;
  211. }
  212. Error GltfImporter::getExtras(const cgltf_extras& extras, HashMapAuto<CString, StringAuto>& out)
  213. {
  214. cgltf_size extrasSize;
  215. cgltf_copy_extras_json(m_gltf, &extras, nullptr, &extrasSize);
  216. if(extrasSize == 0)
  217. {
  218. return Error::NONE;
  219. }
  220. DynamicArrayAuto<char, PtrSize> json(m_alloc);
  221. json.create(extrasSize + 1);
  222. cgltf_result res = cgltf_copy_extras_json(m_gltf, &extras, &json[0], &extrasSize);
  223. if(res != cgltf_result_success)
  224. {
  225. ANKI_IMPORTER_LOGE("cgltf_copy_extras_json failed: %d", res);
  226. return Error::FUNCTION_FAILED;
  227. }
  228. json[json.getSize() - 1] = '\0';
  229. // Get token count
  230. CString jsonTxt(&json[0]);
  231. jsmn_parser parser;
  232. jsmn_init(&parser);
  233. const I tokenCount = jsmn_parse(&parser, jsonTxt.cstr(), jsonTxt.getLength(), nullptr, 0);
  234. if(tokenCount < 1)
  235. {
  236. return Error::NONE;
  237. }
  238. DynamicArrayAuto<jsmntok_t> tokens(m_alloc);
  239. tokens.create(U32(tokenCount));
  240. // Get tokens
  241. jsmn_init(&parser);
  242. jsmn_parse(&parser, jsonTxt.cstr(), jsonTxt.getLength(), &tokens[0], tokens.getSize());
  243. StringListAuto tokenStrings(m_alloc);
  244. for(const jsmntok_t& token : tokens)
  245. {
  246. if(token.type != JSMN_STRING && token.type != JSMN_PRIMITIVE)
  247. {
  248. continue;
  249. }
  250. StringAuto tokenStr(m_alloc);
  251. tokenStr.create(&jsonTxt[token.start], &jsonTxt[token.end]);
  252. tokenStrings.pushBack(tokenStr.toCString());
  253. }
  254. if((tokenStrings.getSize() % 2) != 0)
  255. {
  256. ANKI_IMPORTER_LOGE("Unable to parse: %s", jsonTxt.cstr());
  257. return Error::FUNCTION_FAILED;
  258. }
  259. // Write them to the map
  260. auto it = tokenStrings.getBegin();
  261. while(it != tokenStrings.getEnd())
  262. {
  263. auto it2 = it;
  264. ++it2;
  265. out.emplace(it->toCString(), StringAuto(m_alloc, it2->toCString()));
  266. ++it;
  267. ++it;
  268. }
  269. return Error::NONE;
  270. }
  271. void GltfImporter::populateNodePtrToIdxInternal(const cgltf_node& node, U32& idx)
  272. {
  273. m_nodePtrToIdx.emplace(&node, idx++);
  274. for(cgltf_node* const* c = node.children; c < node.children + node.children_count; ++c)
  275. {
  276. populateNodePtrToIdxInternal(**c, idx);
  277. }
  278. }
  279. void GltfImporter::populateNodePtrToIdx()
  280. {
  281. U32 idx = 0;
  282. for(const cgltf_scene* scene = m_gltf->scenes; scene < m_gltf->scenes + m_gltf->scenes_count; ++scene)
  283. {
  284. for(cgltf_node* const* node = scene->nodes; node < scene->nodes + scene->nodes_count; ++node)
  285. {
  286. populateNodePtrToIdxInternal(**node, idx);
  287. }
  288. }
  289. }
  290. StringAuto GltfImporter::getNodeName(const cgltf_node& node)
  291. {
  292. StringAuto out{m_alloc};
  293. if(node.name)
  294. {
  295. out.create(node.name);
  296. }
  297. else
  298. {
  299. auto it = m_nodePtrToIdx.find(&node);
  300. ANKI_ASSERT(it != m_nodePtrToIdx.getEnd());
  301. out.sprintf("unnamed_node_%u", *it);
  302. }
  303. return out;
  304. }
  305. Error GltfImporter::parseArrayOfNumbers(CString str, DynamicArrayAuto<F64>& out, const U32* expectedArraySize)
  306. {
  307. StringListAuto list(m_alloc);
  308. list.splitString(str, ' ');
  309. out.create(U32(list.getSize()));
  310. Error err = Error::NONE;
  311. auto it = list.getBegin();
  312. auto end = list.getEnd();
  313. U32 i = 0;
  314. while(it != end && !err)
  315. {
  316. err = it->toNumber(out[i++]);
  317. ++it;
  318. }
  319. if(err)
  320. {
  321. ANKI_IMPORTER_LOGE("Failed to parse floats: %s", str.cstr());
  322. }
  323. if(expectedArraySize && *expectedArraySize != out.getSize())
  324. {
  325. ANKI_IMPORTER_LOGE("Failed to parse floats. Expecting %u floats got %u: %s", *expectedArraySize, out.getSize(),
  326. str.cstr());
  327. }
  328. return Error::NONE;
  329. }
  330. Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf,
  331. const HashMapAuto<CString, StringAuto>& parentExtras)
  332. {
  333. // Check error from a thread
  334. const Error threadErr = m_errorInThread.load();
  335. if(threadErr)
  336. {
  337. ANKI_IMPORTER_LOGE("Error happened in a thread");
  338. return threadErr;
  339. }
  340. HashMapAuto<CString, StringAuto> outExtras(m_alloc);
  341. if(node.light)
  342. {
  343. ANKI_CHECK(writeLight(node, parentExtras));
  344. Transform localTrf;
  345. ANKI_CHECK(getNodeTransform(node, localTrf));
  346. localTrf.setScale(1.0f); // Remove scale
  347. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  348. }
  349. else if(node.camera)
  350. {
  351. ANKI_CHECK(writeCamera(node, parentExtras));
  352. Transform localTrf;
  353. ANKI_CHECK(getNodeTransform(node, localTrf));
  354. localTrf.setScale(1.0f); // Remove scale
  355. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  356. }
  357. else if(node.mesh)
  358. {
  359. // Handle special nodes
  360. HashMapAuto<CString, StringAuto> extras(parentExtras);
  361. ANKI_CHECK(getExtras(node.mesh->extras, extras));
  362. ANKI_CHECK(getExtras(node.extras, extras));
  363. HashMapAuto<CString, StringAuto>::Iterator it;
  364. const Bool skipRt = (it = extras.find("no_rt")) != extras.getEnd() && (*it == "true" || *it == "1");
  365. if((it = extras.find("particles")) != extras.getEnd())
  366. {
  367. const StringAuto& fname = *it;
  368. Bool gpuParticles = false;
  369. if((it = extras.find("gpu_particles")) != extras.getEnd() && *it == "true")
  370. {
  371. gpuParticles = true;
  372. }
  373. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:new%sParticleEmitterNode(\"%s\")\n",
  374. (gpuParticles) ? "Gpu" : "", getNodeName(node).cstr()));
  375. ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():get%sParticleEmitterComponent()\n",
  376. (gpuParticles) ? "Gpu" : ""));
  377. ANKI_CHECK(m_sceneFile.writeText("comp:loadParticleEmitterResource(\"%s\")\n", fname.cstr()));
  378. Transform localTrf;
  379. ANKI_CHECK(getNodeTransform(node, localTrf));
  380. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  381. }
  382. else if((it = extras.find("collision")) != extras.getEnd() && *it == "true")
  383. {
  384. ANKI_CHECK(
  385. m_sceneFile.writeText("\nnode = scene:newStaticCollisionNode(\"%s\")\n", getNodeName(node).cstr()));
  386. ANKI_CHECK(m_sceneFile.writeText("comp = scene:getSceneNodeBase():getBodyComponent()\n"));
  387. ANKI_CHECK(
  388. m_sceneFile.writeText("comp:loadMeshResource(\"%s%s.ankimesh\")\n", m_rpath.cstr(), node.mesh->name));
  389. Transform localTrf;
  390. ANKI_CHECK(getNodeTransform(node, localTrf));
  391. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  392. }
  393. else if((it = extras.find("reflection_probe")) != extras.getEnd() && *it == "true")
  394. {
  395. Vec3 tsl;
  396. Mat3 rot;
  397. Vec3 scale;
  398. getNodeTransform(node, tsl, rot, scale);
  399. const Vec3 boxSize = scale * 2.0f;
  400. ANKI_CHECK(
  401. m_sceneFile.writeText("\nnode = scene:newReflectionProbeNode(\"%s\")\n", getNodeName(node).cstr()));
  402. ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getReflectionProbeComponent()\n"));
  403. ANKI_CHECK(m_sceneFile.writeText("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
  404. boxSize.z()));
  405. const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
  406. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  407. }
  408. else if((it = extras.find("gi_probe")) != extras.getEnd() && *it == "true")
  409. {
  410. Vec3 tsl;
  411. Mat3 rot;
  412. Vec3 scale;
  413. getNodeTransform(node, tsl, rot, scale);
  414. const Vec3 boxSize = scale * 2.0f;
  415. F32 fadeDistance = -1.0f;
  416. if((it = extras.find("gi_probe_fade_distance")) != extras.getEnd())
  417. {
  418. ANKI_CHECK(it->toNumber(fadeDistance));
  419. }
  420. F32 cellSize = -1.0f;
  421. if((it = extras.find("gi_probe_cell_size")) != extras.getEnd())
  422. {
  423. ANKI_CHECK(it->toNumber(cellSize));
  424. }
  425. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newGlobalIlluminationProbeNode(\"%s\")\n",
  426. getNodeName(node).cstr()));
  427. ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getGlobalIlluminationProbeComponent()\n"));
  428. ANKI_CHECK(m_sceneFile.writeText("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
  429. boxSize.z()));
  430. if(fadeDistance > 0.0f)
  431. {
  432. ANKI_CHECK(m_sceneFile.writeText("comp:setFadeDistance(%f)\n", fadeDistance));
  433. }
  434. if(cellSize > 0.0f)
  435. {
  436. ANKI_CHECK(m_sceneFile.writeText("comp:setCellSize(%f)\n", cellSize));
  437. }
  438. const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
  439. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  440. }
  441. else if((it = extras.find("decal")) != extras.getEnd() && *it == "true")
  442. {
  443. StringAuto diffuseAtlas(m_alloc);
  444. if((it = extras.find("decal_diffuse_atlas")) != extras.getEnd())
  445. {
  446. diffuseAtlas.create(it->toCString());
  447. }
  448. StringAuto diffuseSubtexture(m_alloc);
  449. if((it = extras.find("decal_diffuse_sub_texture")) != extras.getEnd())
  450. {
  451. diffuseSubtexture.create(it->toCString());
  452. }
  453. F32 diffuseFactor = -1.0f;
  454. if((it = extras.find("decal_diffuse_factor")) != extras.getEnd())
  455. {
  456. ANKI_CHECK(it->toNumber(diffuseFactor));
  457. }
  458. StringAuto specularRougnessMetallicAtlas(m_alloc);
  459. if((it = extras.find("decal_specular_roughness_metallic_atlas")) != extras.getEnd())
  460. {
  461. specularRougnessMetallicAtlas.create(it->toCString());
  462. }
  463. StringAuto specularRougnessMetallicSubtexture(m_alloc);
  464. if((it = extras.find("decal_specular_roughness_metallic_sub_texture")) != extras.getEnd())
  465. {
  466. specularRougnessMetallicSubtexture.create(it->toCString());
  467. }
  468. F32 specularRougnessMetallicFactor = -1.0f;
  469. if((it = extras.find("decal_specular_roughness_metallic_factor")) != extras.getEnd())
  470. {
  471. ANKI_CHECK(it->toNumber(specularRougnessMetallicFactor));
  472. }
  473. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newDecalNode(\"%s\")\n", getNodeName(node).cstr()));
  474. ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getDecalComponent()\n"));
  475. if(diffuseAtlas)
  476. {
  477. ANKI_CHECK(m_sceneFile.writeText("comp:setDiffuseDecal(\"%s\", \"%s\", %f)\n", diffuseAtlas.cstr(),
  478. diffuseSubtexture.cstr(), diffuseFactor));
  479. }
  480. if(specularRougnessMetallicAtlas)
  481. {
  482. ANKI_CHECK(m_sceneFile.writeText(
  483. "comp:setSpecularRoughnessDecal(\"%s\", \"%s\", %f)\n", specularRougnessMetallicAtlas.cstr(),
  484. specularRougnessMetallicSubtexture.cstr(), specularRougnessMetallicFactor));
  485. }
  486. Vec3 tsl;
  487. Mat3 rot;
  488. Vec3 scale;
  489. getNodeTransform(node, tsl, rot, scale);
  490. const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
  491. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  492. }
  493. else
  494. {
  495. // Model node
  496. // Async because it's slow
  497. struct Ctx
  498. {
  499. GltfImporter* m_importer;
  500. const cgltf_mesh* m_mesh;
  501. Array<const cgltf_material*, 128> m_materials;
  502. U32 m_materialCount = 0;
  503. const cgltf_skin* m_skin;
  504. RayTypeBit m_rayTypes;
  505. };
  506. Ctx* ctx = m_alloc.newInstance<Ctx>();
  507. ctx->m_importer = this;
  508. ctx->m_mesh = node.mesh;
  509. for(U32 i = 0; i < node.mesh->primitives_count; ++i)
  510. {
  511. ctx->m_materials[ctx->m_materialCount++] = node.mesh->primitives[i].material;
  512. }
  513. ctx->m_skin = node.skin;
  514. ctx->m_rayTypes = (skipRt) ? RayTypeBit::NONE : RayTypeBit::ALL;
  515. HashMapAuto<CString, StringAuto>::Iterator it2;
  516. const Bool selfCollision = (it2 = extras.find("collision_mesh")) != extras.getEnd() && *it2 == "self";
  517. U32 maxLod = 0;
  518. if(m_lodCount > 1 && !skipMeshLod(*node.mesh, 1))
  519. {
  520. maxLod = 1;
  521. }
  522. if(m_lodCount > 2 && !skipMeshLod(*node.mesh, 2))
  523. {
  524. maxLod = 2;
  525. }
  526. // Thread task
  527. auto callback = [](void* userData, U32 threadId, ThreadHive& hive, ThreadHiveSemaphore* signalSemaphore) {
  528. Ctx& self = *static_cast<Ctx*>(userData);
  529. // LOD 0
  530. Error err = self.m_importer->writeMesh(*self.m_mesh, CString(), self.m_importer->computeLodFactor(0));
  531. // LOD 1
  532. if(!err && self.m_importer->m_lodCount > 1 && !self.m_importer->skipMeshLod(*self.m_mesh, 1))
  533. {
  534. StringAuto name(self.m_importer->m_alloc);
  535. name.sprintf("%s_lod1", self.m_mesh->name);
  536. err = self.m_importer->writeMesh(*self.m_mesh, name, self.m_importer->computeLodFactor(1));
  537. }
  538. // LOD 2
  539. if(!err && self.m_importer->m_lodCount > 2 && !self.m_importer->skipMeshLod(*self.m_mesh, 2))
  540. {
  541. StringAuto name(self.m_importer->m_alloc);
  542. name.sprintf("%s_lod2", self.m_mesh->name);
  543. err = self.m_importer->writeMesh(*self.m_mesh, name, self.m_importer->computeLodFactor(2));
  544. }
  545. for(U32 i = 0; i < self.m_materialCount && !err; ++i)
  546. {
  547. err = self.m_importer->writeMaterial(*self.m_materials[i], self.m_rayTypes);
  548. }
  549. if(!err)
  550. {
  551. err = self.m_importer->writeModel(*self.m_mesh);
  552. }
  553. if(!err && self.m_skin)
  554. {
  555. err = self.m_importer->writeSkeleton(*self.m_skin);
  556. }
  557. if(err)
  558. {
  559. self.m_importer->m_errorInThread.store(err._getCode());
  560. }
  561. self.m_importer->m_alloc.deleteInstance(&self);
  562. };
  563. if(m_hive)
  564. {
  565. m_hive->submitTask(callback, ctx);
  566. }
  567. else
  568. {
  569. callback(ctx, 0, *m_hive, nullptr);
  570. }
  571. ANKI_CHECK(writeModelNode(node, parentExtras));
  572. Transform localTrf;
  573. ANKI_CHECK(getNodeTransform(node, localTrf));
  574. ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
  575. if(selfCollision)
  576. {
  577. ANKI_CHECK(m_sceneFile.writeText("node2 = scene:newStaticCollisionNode(\"%s_cl\")\n",
  578. getNodeName(node).cstr()));
  579. ANKI_CHECK(m_sceneFile.writeText("comp = node2:getSceneNodeBase():getBodyComponent()\n"));
  580. if(maxLod == 0)
  581. {
  582. ANKI_CHECK(m_sceneFile.writeText("comp:loadMeshResource(\"%s%s.ankimesh\")\n", m_rpath.cstr(),
  583. node.mesh->name));
  584. }
  585. else
  586. {
  587. ANKI_CHECK(m_sceneFile.writeText("comp:loadMeshResource(\"%s%s_lod%u.ankimesh\")\n", m_rpath.cstr(),
  588. node.mesh->name, maxLod));
  589. }
  590. ANKI_CHECK(m_sceneFile.writeText("comp:setWorldTransform(trf)\n"));
  591. }
  592. }
  593. }
  594. else
  595. {
  596. ANKI_IMPORTER_LOGW("Ignoring node %s. Assuming transform node", getNodeName(node).cstr());
  597. ANKI_CHECK(getExtras(node.extras, outExtras));
  598. }
  599. // Visit children
  600. Transform nodeTrf;
  601. {
  602. Vec3 tsl;
  603. Mat3 rot;
  604. Vec3 scale;
  605. getNodeTransform(node, tsl, rot, scale);
  606. nodeTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), scale.x());
  607. }
  608. for(cgltf_node* const* c = node.children; c < node.children + node.children_count; ++c)
  609. {
  610. ANKI_CHECK(visitNode(*(*c), nodeTrf, outExtras));
  611. }
  612. return Error::NONE;
  613. }
  614. Error GltfImporter::writeTransform(const Transform& trf)
  615. {
  616. ANKI_CHECK(m_sceneFile.writeText("trf = Transform.new()\n"));
  617. ANKI_CHECK(m_sceneFile.writeText("trf:setOrigin(Vec4.new(%f, %f, %f, 0))\n", trf.getOrigin().x(),
  618. trf.getOrigin().y(), trf.getOrigin().z()));
  619. ANKI_CHECK(m_sceneFile.writeText("rot = Mat3x4.new()\n"));
  620. ANKI_CHECK(m_sceneFile.writeText("rot:setAll("));
  621. for(U i = 0; i < 12; i++)
  622. {
  623. ANKI_CHECK(m_sceneFile.writeText((i != 11) ? "%f, " : "%f)\n", trf.getRotation()[i]));
  624. }
  625. ANKI_CHECK(m_sceneFile.writeText("trf:setRotation(rot)\n"));
  626. ANKI_CHECK(m_sceneFile.writeText("trf:setScale(%f)\n", trf.getScale()));
  627. ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)\n"));
  628. return Error::NONE;
  629. }
  630. Error GltfImporter::writeModel(const cgltf_mesh& mesh)
  631. {
  632. const StringAuto modelFname = computeModelResourceFilename(mesh);
  633. ANKI_IMPORTER_LOGI("Importing model %s", modelFname.cstr());
  634. HashMapAuto<CString, StringAuto> extras(m_alloc);
  635. ANKI_CHECK(getExtras(mesh.extras, extras));
  636. File file;
  637. ANKI_CHECK(file.open(modelFname.toCString(), FileOpenFlag::WRITE));
  638. ANKI_CHECK(file.writeText("<model>\n"));
  639. ANKI_CHECK(file.writeText("\t<modelPatches>\n"));
  640. for(U32 primIdx = 0; primIdx < mesh.primitives_count; ++primIdx)
  641. {
  642. if(mesh.primitives_count == 1)
  643. {
  644. ANKI_CHECK(file.writeText("\t\t<modelPatch>\n"));
  645. }
  646. else
  647. {
  648. ANKI_CHECK(file.writeText("\t\t<modelPatch subMeshIndex=\"%u\">\n", primIdx));
  649. }
  650. ANKI_CHECK(file.writeText("\t\t\t<mesh>%s%s.ankimesh</mesh>\n", m_rpath.cstr(), mesh.name));
  651. if(m_lodCount > 1 && !skipMeshLod(mesh, 1))
  652. {
  653. StringAuto name(m_alloc);
  654. name.sprintf("%s_lod1", mesh.name);
  655. ANKI_CHECK(file.writeText("\t\t\t<mesh1>%s%s.ankimesh</mesh1>\n", m_rpath.cstr(), name.cstr()));
  656. }
  657. if(m_lodCount > 2 && !skipMeshLod(mesh, 2))
  658. {
  659. StringAuto name(m_alloc);
  660. name.sprintf("%s_lod2", mesh.name);
  661. ANKI_CHECK(file.writeText("\t\t\t<mesh2>%s%s.ankimesh</mesh2>\n", m_rpath.cstr(), name.cstr()));
  662. }
  663. HashMapAuto<CString, StringAuto> materialExtras(m_alloc);
  664. ANKI_CHECK(getExtras(mesh.primitives[primIdx].material->extras, materialExtras));
  665. auto mtlOverride = materialExtras.find("material_override");
  666. if(mtlOverride != materialExtras.getEnd())
  667. {
  668. ANKI_CHECK(file.writeText("\t\t\t<material>%s</material>\n", mtlOverride->cstr()));
  669. }
  670. else
  671. {
  672. ANKI_CHECK(file.writeText("\t\t\t<material>%s%s.ankimtl</material>\n", m_rpath.cstr(),
  673. mesh.primitives[primIdx].material->name));
  674. }
  675. ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
  676. }
  677. ANKI_CHECK(file.writeText("\t</modelPatches>\n"));
  678. ANKI_CHECK(file.writeText("</model>\n"));
  679. return Error::NONE;
  680. }
  681. template<typename T>
  682. class GltfAnimKey
  683. {
  684. public:
  685. Second m_time;
  686. T m_value;
  687. };
  688. class GltfAnimChannel
  689. {
  690. public:
  691. StringAuto m_name;
  692. DynamicArrayAuto<GltfAnimKey<Vec3>> m_positions;
  693. DynamicArrayAuto<GltfAnimKey<Quat>> m_rotations;
  694. DynamicArrayAuto<GltfAnimKey<F32>> m_scales;
  695. GltfAnimChannel(GenericMemoryPoolAllocator<U8> alloc)
  696. : m_name(alloc)
  697. , m_positions(alloc)
  698. , m_rotations(alloc)
  699. , m_scales(alloc)
  700. {
  701. }
  702. };
  703. /// Optimize out same animation keys.
  704. template<typename T, typename TZeroFunc, typename TLerpFunc>
  705. static void optimizeChannel(DynamicArrayAuto<GltfAnimKey<T>>& arr, const T& identity, TZeroFunc isZeroFunc,
  706. TLerpFunc lerpFunc)
  707. {
  708. if(arr.getSize() < 3)
  709. {
  710. return;
  711. }
  712. DynamicArrayAuto<GltfAnimKey<T>> newArr(arr.getAllocator());
  713. newArr.emplaceBack(arr.getFront());
  714. for(U32 i = 1; i < arr.getSize() - 1; ++i)
  715. {
  716. const GltfAnimKey<T>& left = arr[i - 1];
  717. const GltfAnimKey<T>& middle = arr[i];
  718. const GltfAnimKey<T>& right = arr[i + 1];
  719. if(left.m_value == middle.m_value && middle.m_value == right.m_value)
  720. {
  721. // Skip it
  722. }
  723. else
  724. {
  725. const F32 factor = F32((middle.m_time - left.m_time) / (right.m_time - left.m_time));
  726. ANKI_ASSERT(factor > 0.0f && factor < 1.0f);
  727. const T lerpRez = lerpFunc(left.m_value, right.m_value, factor);
  728. if(isZeroFunc(middle.m_value - lerpRez))
  729. {
  730. // It's redundant, skip it
  731. }
  732. else
  733. {
  734. newArr.emplaceBack(middle);
  735. }
  736. }
  737. }
  738. newArr.emplaceBack(arr.getBack());
  739. ANKI_ASSERT(newArr.getSize() <= arr.getSize());
  740. // Check if identity
  741. if(newArr.getSize() == 2 && isZeroFunc(newArr[0].m_value - newArr[1].m_value)
  742. && isZeroFunc(newArr[0].m_value - identity))
  743. {
  744. newArr.destroy();
  745. }
  746. arr.destroy();
  747. arr = std::move(newArr);
  748. }
  749. Error GltfImporter::writeAnimation(const cgltf_animation& anim)
  750. {
  751. StringAuto fname(m_alloc);
  752. fname.sprintf("%s%s.ankianim", m_outDir.cstr(), anim.name);
  753. fname = fixFilename(fname);
  754. ANKI_IMPORTER_LOGI("Importing animation %s", fname.cstr());
  755. // Gather the channels
  756. HashMapAuto<CString, Array<const cgltf_animation_channel*, 3>> channelMap(m_alloc);
  757. U32 channelCount = 0;
  758. for(U i = 0; i < anim.channels_count; ++i)
  759. {
  760. const cgltf_animation_channel& channel = anim.channels[i];
  761. const StringAuto channelName = getNodeName(*channel.target_node);
  762. U idx;
  763. switch(channel.target_path)
  764. {
  765. case cgltf_animation_path_type_translation:
  766. idx = 0;
  767. break;
  768. case cgltf_animation_path_type_rotation:
  769. idx = 1;
  770. break;
  771. case cgltf_animation_path_type_scale:
  772. idx = 2;
  773. break;
  774. default:
  775. ANKI_ASSERT(0);
  776. idx = 0;
  777. }
  778. auto it = channelMap.find(channelName.toCString());
  779. if(it != channelMap.getEnd())
  780. {
  781. (*it)[idx] = &channel;
  782. }
  783. else
  784. {
  785. Array<const cgltf_animation_channel*, 3> arr = {};
  786. arr[idx] = &channel;
  787. channelMap.emplace(channelName.toCString(), arr);
  788. ++channelCount;
  789. }
  790. }
  791. // Gather the keys
  792. DynamicArrayAuto<GltfAnimChannel> tempChannels(m_alloc, channelCount, m_alloc);
  793. channelCount = 0;
  794. for(auto it = channelMap.getBegin(); it != channelMap.getEnd(); ++it)
  795. {
  796. Array<const cgltf_animation_channel*, 3> arr = *it;
  797. const cgltf_animation_channel& anyChannel = (arr[0]) ? *arr[0] : ((arr[1]) ? *arr[1] : *arr[2]);
  798. const StringAuto channelName = getNodeName(*anyChannel.target_node);
  799. tempChannels[channelCount].m_name = channelName;
  800. // Positions
  801. if(arr[0])
  802. {
  803. const cgltf_animation_channel& channel = *arr[0];
  804. DynamicArrayAuto<F32> keys(m_alloc);
  805. readAccessor(*channel.sampler->input, keys);
  806. DynamicArrayAuto<Vec3> positions(m_alloc);
  807. readAccessor(*channel.sampler->output, positions);
  808. if(keys.getSize() != positions.getSize())
  809. {
  810. ANKI_IMPORTER_LOGE("Position count should match they keyframes");
  811. return Error::USER_DATA;
  812. }
  813. for(U32 i = 0; i < keys.getSize(); ++i)
  814. {
  815. GltfAnimKey<Vec3> key;
  816. key.m_time = keys[i];
  817. key.m_value = Vec3(positions[i].x(), positions[i].y(), positions[i].z());
  818. tempChannels[channelCount].m_positions.emplaceBack(key);
  819. }
  820. }
  821. // Rotations
  822. if(arr[1])
  823. {
  824. const cgltf_animation_channel& channel = *arr[1];
  825. DynamicArrayAuto<F32> keys(m_alloc);
  826. readAccessor(*channel.sampler->input, keys);
  827. DynamicArrayAuto<Quat> rotations(m_alloc);
  828. readAccessor(*channel.sampler->output, rotations);
  829. if(keys.getSize() != rotations.getSize())
  830. {
  831. ANKI_IMPORTER_LOGE("Rotation count should match they keyframes");
  832. return Error::USER_DATA;
  833. }
  834. for(U32 i = 0; i < keys.getSize(); ++i)
  835. {
  836. GltfAnimKey<Quat> key;
  837. key.m_time = keys[i];
  838. key.m_value = Quat(rotations[i].x(), rotations[i].y(), rotations[i].z(), rotations[i].w());
  839. tempChannels[channelCount].m_rotations.emplaceBack(key);
  840. }
  841. }
  842. // Scales
  843. if(arr[2])
  844. {
  845. const cgltf_animation_channel& channel = *arr[2];
  846. DynamicArrayAuto<F32> keys(m_alloc);
  847. readAccessor(*channel.sampler->input, keys);
  848. DynamicArrayAuto<Vec3> scales(m_alloc);
  849. readAccessor(*channel.sampler->output, scales);
  850. if(keys.getSize() != scales.getSize())
  851. {
  852. ANKI_IMPORTER_LOGE("Scale count should match they keyframes");
  853. return Error::USER_DATA;
  854. }
  855. for(U32 i = 0; i < keys.getSize(); ++i)
  856. {
  857. const F32 scaleEpsilon = 0.0001f;
  858. if(absolute(scales[i][0] - scales[i][1]) > scaleEpsilon
  859. || absolute(scales[i][0] - scales[i][2]) > scaleEpsilon)
  860. {
  861. ANKI_IMPORTER_LOGE("Expecting uniform scale");
  862. return Error::USER_DATA;
  863. }
  864. GltfAnimKey<F32> key;
  865. key.m_time = keys[i];
  866. key.m_value = scales[i][0];
  867. if(absolute(key.m_value - 1.0f) <= scaleEpsilon)
  868. {
  869. key.m_value = 1.0f;
  870. }
  871. tempChannels[channelCount].m_scales.emplaceBack(key);
  872. }
  873. }
  874. ++channelCount;
  875. }
  876. // Optimize animation
  877. constexpr F32 KILL_EPSILON = 0.001f; // 1 millimiter
  878. for(GltfAnimChannel& channel : tempChannels)
  879. {
  880. optimizeChannel(
  881. channel.m_positions, Vec3(0.0f), [&](const Vec3& a) -> Bool { return a.abs() < KILL_EPSILON; },
  882. [&](const Vec3& a, const Vec3& b, F32 u) -> Vec3 { return linearInterpolate(a, b, u); });
  883. optimizeChannel(
  884. channel.m_rotations, Quat::getIdentity(),
  885. [&](const Quat& a) -> Bool { return a.abs() < Quat(EPSILON * 20.0f); },
  886. [&](const Quat& a, const Quat& b, F32 u) -> Quat { return a.slerp(b, u); });
  887. optimizeChannel(
  888. channel.m_scales, 1.0f, [&](const F32& a) -> Bool { return absolute(a) < KILL_EPSILON; },
  889. [&](const F32& a, const F32& b, F32 u) -> F32 { return linearInterpolate(a, b, u); });
  890. }
  891. // Write file
  892. File file;
  893. ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
  894. ANKI_CHECK(file.writeText("%s\n<animation>\n", XML_HEADER));
  895. ANKI_CHECK(file.writeText("\t<channels>\n"));
  896. for(const GltfAnimChannel& channel : tempChannels)
  897. {
  898. ANKI_CHECK(file.writeText("\t\t<channel name=\"%s\">\n", channel.m_name.cstr()));
  899. // Positions
  900. if(channel.m_positions.getSize())
  901. {
  902. ANKI_CHECK(file.writeText("\t\t\t<positionKeys>\n"));
  903. for(const GltfAnimKey<Vec3>& key : channel.m_positions)
  904. {
  905. ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f %f %f</key>\n", key.m_time, key.m_value.x(),
  906. key.m_value.y(), key.m_value.z()));
  907. }
  908. ANKI_CHECK(file.writeText("\t\t\t</positionKeys>\n"));
  909. }
  910. // Rotations
  911. if(channel.m_rotations.getSize())
  912. {
  913. ANKI_CHECK(file.writeText("\t\t\t<rotationKeys>\n"));
  914. for(const GltfAnimKey<Quat>& key : channel.m_rotations)
  915. {
  916. ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f %f %f %f</key>\n", key.m_time, key.m_value.x(),
  917. key.m_value.y(), key.m_value.z(), key.m_value.w()));
  918. }
  919. ANKI_CHECK(file.writeText("\t\t\t</rotationKeys>\n"));
  920. }
  921. // Scales
  922. if(channel.m_scales.getSize())
  923. {
  924. ANKI_CHECK(file.writeText("\t\t\t<scaleKeys>\n"));
  925. for(const GltfAnimKey<F32>& key : channel.m_scales)
  926. {
  927. ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f</key>\n", key.m_time, key.m_value));
  928. }
  929. ANKI_CHECK(file.writeText("\t\t\t</scaleKeys>\n"));
  930. }
  931. ANKI_CHECK(file.writeText("\t\t</channel>\n"));
  932. }
  933. ANKI_CHECK(file.writeText("\t</channels>\n"));
  934. ANKI_CHECK(file.writeText("</animation>\n"));
  935. return Error::NONE;
  936. }
  937. Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
  938. {
  939. StringAuto fname(m_alloc);
  940. fname.sprintf("%s%s.ankiskel", m_outDir.cstr(), skin.name);
  941. ANKI_IMPORTER_LOGI("Importing skeleton %s", fname.cstr());
  942. // Get matrices
  943. DynamicArrayAuto<Mat4> boneMats(m_alloc);
  944. readAccessor(*skin.inverse_bind_matrices, boneMats);
  945. if(boneMats.getSize() != skin.joints_count)
  946. {
  947. ANKI_IMPORTER_LOGE("Bone matrices should match the joint count");
  948. return Error::USER_DATA;
  949. }
  950. // Write file
  951. File file;
  952. ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
  953. ANKI_CHECK(file.writeText("%s\n<skeleton>\n", XML_HEADER));
  954. ANKI_CHECK(file.writeText("\t<bones>\n", XML_HEADER));
  955. for(U32 i = 0; i < skin.joints_count; ++i)
  956. {
  957. const cgltf_node& boneNode = *skin.joints[i];
  958. StringAuto parent(m_alloc);
  959. // Name & parent
  960. ANKI_CHECK(file.writeText("\t\t<bone name=\"%s\" ", getNodeName(boneNode).cstr()));
  961. if(boneNode.parent && getNodeName(*boneNode.parent) != skin.name)
  962. {
  963. ANKI_CHECK(file.writeText("parent=\"%s\" ", getNodeName(*boneNode.parent).cstr()));
  964. }
  965. // Bone transform
  966. ANKI_CHECK(file.writeText("boneTransform=\""));
  967. Mat4 btrf(&boneMats[i][0]);
  968. btrf.transpose();
  969. for(U32 j = 0; j < 16; j++)
  970. {
  971. ANKI_CHECK(file.writeText("%f ", btrf[j]));
  972. }
  973. ANKI_CHECK(file.writeText("\" "));
  974. // Transform
  975. Transform trf;
  976. ANKI_CHECK(getNodeTransform(boneNode, trf));
  977. Mat4 mat{trf};
  978. ANKI_CHECK(file.writeText("transform=\""));
  979. for(U j = 0; j < 16; j++)
  980. {
  981. ANKI_CHECK(file.writeText("%f ", mat[j]));
  982. }
  983. ANKI_CHECK(file.writeText("\" "));
  984. ANKI_CHECK(file.writeText("/>\n"));
  985. }
  986. ANKI_CHECK(file.writeText("\t</bones>\n"));
  987. ANKI_CHECK(file.writeText("</skeleton>\n"));
  988. return Error::NONE;
  989. }
  990. Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
  991. {
  992. const cgltf_light& light = *node.light;
  993. StringAuto nodeName = getNodeName(node);
  994. ANKI_IMPORTER_LOGI("Importing light %s", nodeName.cstr());
  995. HashMapAuto<CString, StringAuto> extras(parentExtras);
  996. ANKI_CHECK(getExtras(light.extras, extras));
  997. CString lightTypeStr;
  998. switch(light.type)
  999. {
  1000. case cgltf_light_type_point:
  1001. lightTypeStr = "Point";
  1002. break;
  1003. case cgltf_light_type_spot:
  1004. lightTypeStr = "Spot";
  1005. break;
  1006. case cgltf_light_type_directional:
  1007. lightTypeStr = "Directional";
  1008. break;
  1009. default:
  1010. ANKI_IMPORTER_LOGE("Unsupporter light type %d", light.type);
  1011. return Error::USER_DATA;
  1012. }
  1013. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:new%sLightNode(\"%s\")\n", lightTypeStr.cstr(), nodeName.cstr()));
  1014. ANKI_CHECK(m_sceneFile.writeText("lcomp = node:getSceneNodeBase():getLightComponent()\n"));
  1015. Vec3 color(light.color[0], light.color[1], light.color[2]);
  1016. color *= light.intensity;
  1017. color *= m_lightIntensityScale;
  1018. ANKI_CHECK(
  1019. m_sceneFile.writeText("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
  1020. auto shadow = extras.find("shadow");
  1021. if(shadow != extras.getEnd())
  1022. {
  1023. if(*shadow == "true")
  1024. {
  1025. ANKI_CHECK(m_sceneFile.writeText("lcomp:setShadowEnabled(1)\n"));
  1026. }
  1027. else
  1028. {
  1029. ANKI_CHECK(m_sceneFile.writeText("lcomp:setShadowEnabled(0)\n"));
  1030. }
  1031. }
  1032. if(light.type == cgltf_light_type_point)
  1033. {
  1034. ANKI_CHECK(m_sceneFile.writeText("lcomp:setRadius(%f)\n",
  1035. (light.range > 0.0f) ? light.range : computeLightRadius(color)));
  1036. }
  1037. else if(light.type == cgltf_light_type_spot)
  1038. {
  1039. ANKI_CHECK(m_sceneFile.writeText("lcomp:setDistance(%f)\n",
  1040. (light.range > 0.0f) ? light.range : computeLightRadius(color)));
  1041. const F32 outer = light.spot_outer_cone_angle * 2.0f;
  1042. ANKI_CHECK(m_sceneFile.writeText("lcomp:setOuterAngle(%f)\n", outer));
  1043. auto angStr = extras.find("inner_cone_angle_factor");
  1044. F32 inner;
  1045. if(angStr != extras.getEnd())
  1046. {
  1047. F32 factor;
  1048. ANKI_CHECK(angStr->toNumber(factor));
  1049. inner = light.spot_inner_cone_angle * 2.0f * min(1.0f, factor);
  1050. }
  1051. else
  1052. {
  1053. inner = light.spot_inner_cone_angle * 2.0f;
  1054. }
  1055. if(inner >= 0.95f * outer)
  1056. {
  1057. inner = 0.75f * outer;
  1058. }
  1059. ANKI_CHECK(m_sceneFile.writeText("lcomp:setInnerAngle(%f)\n", inner));
  1060. }
  1061. auto lensFlaresFname = extras.find("lens_flare");
  1062. if(lensFlaresFname != extras.getEnd())
  1063. {
  1064. ANKI_CHECK(m_sceneFile.writeText("lfcomp = node:getSceneNodeBase():getLensFlareComponent()\n"));
  1065. ANKI_CHECK(m_sceneFile.writeText("lfcomp:loadImageResource(\"%s\")\n", lensFlaresFname->cstr()));
  1066. auto lsSpriteSize = extras.find("lens_flare_first_sprite_size");
  1067. auto lsColor = extras.find("lens_flare_color");
  1068. if(lsSpriteSize != extras.getEnd())
  1069. {
  1070. DynamicArrayAuto<F64> numbers(m_alloc);
  1071. const U32 count = 2;
  1072. ANKI_CHECK(parseArrayOfNumbers(lsSpriteSize->toCString(), numbers, &count));
  1073. ANKI_CHECK(m_sceneFile.writeText("lfcomp:setFirstFlareSize(Vec2.new(%f, %f))\n", numbers[0], numbers[1]));
  1074. }
  1075. if(lsColor != extras.getEnd())
  1076. {
  1077. DynamicArrayAuto<F64> numbers(m_alloc);
  1078. const U32 count = 4;
  1079. ANKI_CHECK(parseArrayOfNumbers(lsColor->toCString(), numbers, &count));
  1080. ANKI_CHECK(m_sceneFile.writeText("lfcomp:setColorMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
  1081. numbers[1], numbers[2], numbers[3]));
  1082. }
  1083. }
  1084. auto lightEventIntensity = extras.find("light_event_intensity");
  1085. auto lightEventFrequency = extras.find("light_event_frequency");
  1086. if(lightEventIntensity != extras.getEnd() || lightEventFrequency != extras.getEnd())
  1087. {
  1088. ANKI_CHECK(m_sceneFile.writeText("event = events:newLightEvent(0.0, -1.0, node:getSceneNodeBase())\n"));
  1089. if(lightEventIntensity != extras.getEnd())
  1090. {
  1091. DynamicArrayAuto<F64> numbers(m_alloc);
  1092. const U32 count = 4;
  1093. ANKI_CHECK(parseArrayOfNumbers(lightEventIntensity->toCString(), numbers, &count));
  1094. ANKI_CHECK(m_sceneFile.writeText("event:setIntensityMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
  1095. numbers[1], numbers[2], numbers[3]));
  1096. }
  1097. if(lightEventFrequency != extras.getEnd())
  1098. {
  1099. DynamicArrayAuto<F64> numbers(m_alloc);
  1100. const U32 count = 2;
  1101. ANKI_CHECK(parseArrayOfNumbers(lightEventFrequency->toCString(), numbers, &count));
  1102. ANKI_CHECK(m_sceneFile.writeText("event:setFrequency(%f, %f)\n", numbers[0], numbers[1]));
  1103. }
  1104. }
  1105. return Error::NONE;
  1106. }
  1107. Error GltfImporter::writeCamera(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
  1108. {
  1109. if(node.camera->type != cgltf_camera_type_perspective)
  1110. {
  1111. ANKI_IMPORTER_LOGW("Unsupported camera type: %s", getNodeName(node).cstr());
  1112. return Error::NONE;
  1113. }
  1114. const cgltf_camera_perspective& cam = node.camera->perspective;
  1115. ANKI_IMPORTER_LOGI("Importing camera %s", getNodeName(node).cstr());
  1116. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newPerspectiveCameraNode(\"%s\")\n", getNodeName(node).cstr()));
  1117. ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node:getSceneNodeBase())\n"));
  1118. ANKI_CHECK(m_sceneFile.writeText("frustumc = node:getSceneNodeBase():getFrustumComponent()\n"));
  1119. ANKI_CHECK(m_sceneFile.writeText("frustumc:setPerspective(%f, %f, getMainRenderer():getAspectRatio() * %f, %f)\n",
  1120. cam.znear, cam.zfar, cam.yfov, cam.yfov));
  1121. ANKI_CHECK(m_sceneFile.writeText("frustumc:setShadowCascadesDistancePower(1.5)\n"));
  1122. ANKI_CHECK(m_sceneFile.writeText("frustumc:setEffectiveShadowDistance(%f)\n", min(cam.zfar, 100.0f)));
  1123. return Error::NONE;
  1124. }
  1125. Error GltfImporter::writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
  1126. {
  1127. ANKI_IMPORTER_LOGI("Importing model node %s", getNodeName(node).cstr());
  1128. HashMapAuto<CString, StringAuto> extras(parentExtras);
  1129. ANKI_CHECK(getExtras(node.extras, extras));
  1130. const StringAuto modelFname = computeModelResourceFilename(*node.mesh);
  1131. ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newModelNode(\"%s\")\n", getNodeName(node).cstr()));
  1132. ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getModelComponent():loadModelResource(\"%s\")\n",
  1133. modelFname.cstr()));
  1134. if(node.skin)
  1135. {
  1136. ANKI_CHECK(m_sceneFile.writeText(
  1137. "node:getSceneNodeBase():getSkinComponent():loadSkeletonResource(\"%s%s.ankiskel\")\n", m_rpath.cstr(),
  1138. node.skin->name));
  1139. }
  1140. return Error::NONE;
  1141. }
  1142. } // end namespace anki