GltfImporter.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. #pragma once
  6. #include <AnKi/Importer/Common.h>
  7. #include <AnKi/Util/String.h>
  8. #include <AnKi/Util/StringList.h>
  9. #include <AnKi/Util/File.h>
  10. #include <AnKi/Util/HashMap.h>
  11. #include <AnKi/Resource/Common.h>
  12. #include <AnKi/Math.h>
  13. #include <Cgltf/cgltf.h>
  14. namespace anki {
  15. /// @addtogroup importer
  16. /// @{
  17. /// @memberof GltfImporter
  18. class GltfImporterInitInfo
  19. {
  20. public:
  21. CString m_inputFilename;
  22. CString m_outDirectory;
  23. CString m_rpath;
  24. CString m_texrpath;
  25. Bool m_optimizeMeshes = true;
  26. F32 m_lodFactor = 1.0f;
  27. U32 m_lodCount = 1;
  28. F32 m_lightIntensityScale = 1.0f;
  29. U32 m_threadCount = MAX_U32;
  30. CString m_comment;
  31. };
  32. /// Import GLTF and spit AnKi scenes.
  33. class GltfImporter
  34. {
  35. public:
  36. GltfImporter(GenericMemoryPoolAllocator<U8> alloc);
  37. ~GltfImporter();
  38. ANKI_USE_RESULT Error init(const GltfImporterInitInfo& initInfo);
  39. ANKI_USE_RESULT Error writeAll();
  40. private:
  41. class PtrHasher
  42. {
  43. public:
  44. U64 operator()(const void* ptr)
  45. {
  46. return computeHash(&ptr, sizeof(ptr));
  47. }
  48. };
  49. // Data
  50. static const char* XML_HEADER;
  51. GenericMemoryPoolAllocator<U8> m_alloc;
  52. StringAuto m_inputFname = {m_alloc};
  53. StringAuto m_outDir = {m_alloc};
  54. StringAuto m_rpath = {m_alloc};
  55. StringAuto m_texrpath = {m_alloc};
  56. cgltf_data* m_gltf = nullptr;
  57. F32 m_normalsMergeAngle = toRad(30.0f);
  58. ThreadHive* m_hive = nullptr;
  59. File m_sceneFile;
  60. Atomic<I32> m_errorInThread{0};
  61. HashMapAuto<const void*, U32, PtrHasher> m_nodePtrToIdx{m_alloc}; ///< Need an index for the unnamed nodes.
  62. F32 m_lodFactor = 1.0f;
  63. U32 m_lodCount = 1;
  64. F32 m_lightIntensityScale = 1.0f;
  65. Bool m_optimizeMeshes = false;
  66. StringAuto m_comment{m_alloc};
  67. /// Don't generate LODs for meshes with less vertices than this number.
  68. U32 m_skipLodVertexCountThreshold = 256;
  69. // Misc
  70. ANKI_USE_RESULT Error getExtras(const cgltf_extras& extras, HashMapAuto<CString, StringAuto>& out);
  71. ANKI_USE_RESULT Error parseArrayOfNumbers(CString str, DynamicArrayAuto<F64>& out,
  72. const U32* expectedArraySize = nullptr);
  73. void populateNodePtrToIdx();
  74. void populateNodePtrToIdxInternal(const cgltf_node& node, U32& idx);
  75. StringAuto getNodeName(const cgltf_node& node);
  76. template<typename T, typename TFunc>
  77. static void visitAccessor(const cgltf_accessor& accessor, TFunc func);
  78. template<typename T>
  79. static void readAccessor(const cgltf_accessor& accessor, DynamicArrayAuto<T>& out)
  80. {
  81. visitAccessor<T>(accessor, [&](const T& val) {
  82. out.emplaceBack(val);
  83. });
  84. }
  85. StringAuto fixFilename(CString in) const
  86. {
  87. StringAuto out(m_alloc, in);
  88. out.replaceAll("|", "_");
  89. out.replaceAll(" ", "_");
  90. return out;
  91. }
  92. F32 computeLodFactor(U32 lod) const
  93. {
  94. ANKI_ASSERT(lod < m_lodCount);
  95. return 1.0f - m_lodFactor * F32(lod);
  96. }
  97. Bool skipMeshLod(const cgltf_mesh& mesh, U32 lod) const
  98. {
  99. return U32(computeLodFactor(lod) * F32(getMeshTotalVertexCount(mesh))) < m_skipLodVertexCountThreshold;
  100. }
  101. static U32 getMeshTotalVertexCount(const cgltf_mesh& mesh);
  102. StringAuto computeModelResourceFilename(const cgltf_mesh& mesh) const
  103. {
  104. StringListAuto list(m_alloc);
  105. list.pushBackSprintf("%s%s", m_rpath.cstr(), mesh.name);
  106. for(U i = 0; i < mesh.primitives_count; ++i)
  107. {
  108. list.pushBackSprintf("_%s", mesh.primitives[i].material->name);
  109. }
  110. list.pushBack(".ankimdl");
  111. StringAuto out(m_alloc);
  112. list.join("", out);
  113. return out;
  114. }
  115. // Resources
  116. ANKI_USE_RESULT Error writeMesh(const cgltf_mesh& mesh, CString nameOverride, F32 decimateFactor);
  117. ANKI_USE_RESULT Error writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayTypes);
  118. ANKI_USE_RESULT Error writeModel(const cgltf_mesh& mesh);
  119. ANKI_USE_RESULT Error writeAnimation(const cgltf_animation& anim);
  120. ANKI_USE_RESULT Error writeSkeleton(const cgltf_skin& skin);
  121. // Scene
  122. ANKI_USE_RESULT Error writeTransform(const Transform& trf);
  123. ANKI_USE_RESULT Error visitNode(const cgltf_node& node, const Transform& parentTrf,
  124. const HashMapAuto<CString, StringAuto>& parentExtras);
  125. ANKI_USE_RESULT Error writeLight(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
  126. ANKI_USE_RESULT Error writeCamera(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
  127. ANKI_USE_RESULT Error writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
  128. };
  129. /// @}
  130. template<typename T, typename TFunc>
  131. void GltfImporter::visitAccessor(const cgltf_accessor& accessor, TFunc func)
  132. {
  133. const U8* base =
  134. static_cast<const U8*>(accessor.buffer_view->buffer->data) + accessor.offset + accessor.buffer_view->offset;
  135. PtrSize stride = accessor.buffer_view->stride;
  136. if(stride == 0)
  137. {
  138. stride = accessor.stride;
  139. }
  140. ANKI_ASSERT(stride);
  141. ANKI_ASSERT(stride >= sizeof(T));
  142. const U count = accessor.count;
  143. for(U i = 0; i < count; ++i)
  144. {
  145. const U8* ptr = base + stride * i;
  146. T val;
  147. memcpy(&val, ptr, sizeof(T)); // Memcpy because the input buffer might not be aligned
  148. func(val);
  149. }
  150. }
  151. } // end namespace anki