GltfImporter.cpp 38 KB

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