MeshLoader.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright (C) 2009-2018, 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/resource/MeshLoader.h>
  6. #include <anki/resource/ResourceManager.h>
  7. #include <anki/resource/ResourceFilesystem.h>
  8. namespace anki
  9. {
  10. MeshLoader::MeshLoader(ResourceManager* manager)
  11. : MeshLoader(manager, manager->getTempAllocator())
  12. {
  13. }
  14. MeshLoader::~MeshLoader()
  15. {
  16. m_subMeshes.destroy(m_alloc);
  17. }
  18. Error MeshLoader::load(const ResourceFilename& filename)
  19. {
  20. auto& alloc = m_alloc;
  21. // Load header
  22. ANKI_CHECK(m_manager->getFilesystem().openFile(filename, m_file));
  23. ANKI_CHECK(m_file->read(&m_header, sizeof(m_header)));
  24. ANKI_CHECK(checkHeader());
  25. // Read submesh info
  26. {
  27. m_subMeshes.create(alloc, m_header.m_subMeshCount);
  28. ANKI_CHECK(m_file->read(&m_subMeshes[0], m_subMeshes.getSizeInBytes()));
  29. // Checks
  30. const U32 indicesPerFace = !!(m_header.m_flags & MeshBinaryFile::Flag::QUAD) ? 4 : 3;
  31. U idxSum = 0;
  32. for(U i = 0; i < m_subMeshes.getSize(); i++)
  33. {
  34. const MeshBinaryFile::SubMesh& sm = m_subMeshes[0];
  35. if(sm.m_firstIndex != idxSum || (sm.m_indexCount % indicesPerFace) != 0)
  36. {
  37. ANKI_RESOURCE_LOGE("Incorrect sub mesh info");
  38. return Error::USER_DATA;
  39. }
  40. for(U d = 0; d < 3; ++d)
  41. {
  42. if(sm.m_aabbMin[i] >= sm.m_aabbMax[i])
  43. {
  44. ANKI_RESOURCE_LOGE("Wrong bounding box");
  45. return Error::USER_DATA;
  46. }
  47. }
  48. idxSum += sm.m_indexCount;
  49. }
  50. if(idxSum != m_header.m_totalIndexCount)
  51. {
  52. ANKI_RESOURCE_LOGE("Incorrect sub mesh info");
  53. return Error::USER_DATA;
  54. }
  55. }
  56. // Read vert buffer info
  57. {
  58. U32 vertBufferMask = 0;
  59. U32 vertBufferCount = 0;
  60. for(const MeshBinaryFile::VertexAttribute& attrib : m_header.m_vertexAttributes)
  61. {
  62. if(attrib.m_format == Format::NONE)
  63. {
  64. continue;
  65. }
  66. vertBufferCount = max(attrib.m_bufferBinding + 1, vertBufferCount);
  67. vertBufferMask |= 1 << attrib.m_bufferBinding;
  68. }
  69. if(U(__builtin_popcount(vertBufferMask)) != vertBufferCount)
  70. {
  71. ANKI_RESOURCE_LOGE("Problem in vertex buffers");
  72. return Error::USER_DATA;
  73. }
  74. if(vertBufferCount != m_header.m_vertexBufferCount)
  75. {
  76. ANKI_RESOURCE_LOGE("Wrong vertex buffer count in the header");
  77. return Error::USER_DATA;
  78. }
  79. }
  80. // Count and check the file size
  81. {
  82. U32 totalSize = sizeof(m_header);
  83. totalSize += sizeof(MeshBinaryFile::SubMesh) * m_header.m_subMeshCount;
  84. totalSize += getIndexBufferSize();
  85. for(U i = 0; i < m_header.m_vertexBufferCount; ++i)
  86. {
  87. totalSize += m_header.m_vertexBuffers[i].m_vertexStride * m_header.m_totalVertexCount;
  88. }
  89. if(totalSize != m_file->getSize())
  90. {
  91. ANKI_RESOURCE_LOGE("Unexpected file size");
  92. return Error::USER_DATA;
  93. }
  94. }
  95. return Error::NONE;
  96. }
  97. Error MeshLoader::checkFormat(VertexAttributeLocation type, ConstWeakArray<Format> supportedFormats) const
  98. {
  99. const MeshBinaryFile::VertexAttribute& attrib = m_header.m_vertexAttributes[type];
  100. // Check format
  101. Bool found = false;
  102. for(Format fmt : supportedFormats)
  103. {
  104. if(fmt == attrib.m_format)
  105. {
  106. found = true;
  107. break;
  108. }
  109. }
  110. if(!found)
  111. {
  112. ANKI_RESOURCE_LOGE(
  113. "Vertex attribute %u has unsupported format %u", U(type), U(m_header.m_vertexAttributes[type].m_format));
  114. return Error::USER_DATA;
  115. }
  116. if(!attrib.m_format)
  117. {
  118. // Attrib is not in use, no more checks
  119. return Error::NONE;
  120. }
  121. // Scale should be 1.0 for now
  122. if(attrib.m_scale != 1.0f)
  123. {
  124. ANKI_RESOURCE_LOGE("Vertex attribute %u should have 1.0 scale", U(type));
  125. return Error::USER_DATA;
  126. }
  127. return Error::NONE;
  128. }
  129. Error MeshLoader::checkHeader() const
  130. {
  131. const MeshBinaryFile::Header& h = m_header;
  132. // Header
  133. if(memcmp(&h.m_magic[0], MeshBinaryFile::MAGIC, 8) != 0)
  134. {
  135. ANKI_RESOURCE_LOGE("Wrong magic word");
  136. return Error::USER_DATA;
  137. }
  138. // Flags
  139. if((h.m_flags & ~MeshBinaryFile::Flag::ALL) != MeshBinaryFile::Flag::NONE)
  140. {
  141. ANKI_RESOURCE_LOGE("Wrong header flags");
  142. return Error::USER_DATA;
  143. }
  144. // Attributes
  145. ANKI_CHECK(checkFormat(
  146. VertexAttributeLocation::POSITION, Array<Format, 2>{{Format::R16G16B16A16_SFLOAT, Format::R32G32B32_SFLOAT}}));
  147. ANKI_CHECK(checkFormat(VertexAttributeLocation::NORMAL, Array<Format, 1>{{Format::A2B10G10R10_SNORM_PACK32}}));
  148. ANKI_CHECK(checkFormat(VertexAttributeLocation::TANGENT, Array<Format, 1>{{Format::A2B10G10R10_SNORM_PACK32}}));
  149. ANKI_CHECK(
  150. checkFormat(VertexAttributeLocation::UV, Array<Format, 2>{{Format::R16G16_UNORM, Format::R16G16_SFLOAT}}));
  151. ANKI_CHECK(checkFormat(
  152. VertexAttributeLocation::BONE_INDICES, Array<Format, 2>{{Format::NONE, Format::R16G16B16A16_UINT}}));
  153. ANKI_CHECK(
  154. checkFormat(VertexAttributeLocation::BONE_WEIGHTS, Array<Format, 2>{{Format::NONE, Format::R8G8B8A8_UNORM}}));
  155. // Indices format
  156. if(h.m_indexType != IndexType::U16 && h.m_indexType != IndexType::U32)
  157. {
  158. ANKI_RESOURCE_LOGE("Wrong format for indices");
  159. return Error::USER_DATA;
  160. }
  161. // m_totalIndexCount
  162. const U indicesPerFace = !!(h.m_flags & MeshBinaryFile::Flag::QUAD) ? 4 : 3;
  163. if(h.m_totalIndexCount == 0 || (h.m_totalIndexCount % indicesPerFace) != 0)
  164. {
  165. ANKI_RESOURCE_LOGE("Wrong index count");
  166. return Error::USER_DATA;
  167. }
  168. // m_totalVertexCount
  169. if(h.m_totalVertexCount == 0)
  170. {
  171. ANKI_RESOURCE_LOGE("Wrong vertex count");
  172. return Error::USER_DATA;
  173. }
  174. // m_subMeshCount
  175. if(h.m_subMeshCount == 0)
  176. {
  177. ANKI_RESOURCE_LOGE("Wrong submesh count");
  178. return Error::USER_DATA;
  179. }
  180. // AABB
  181. for(U d = 0; d < 3; ++d)
  182. {
  183. if(h.m_aabbMin[d] >= h.m_aabbMax[d])
  184. {
  185. ANKI_RESOURCE_LOGE("Wrong bounding box");
  186. return Error::USER_DATA;
  187. }
  188. }
  189. return Error::NONE;
  190. }
  191. Error MeshLoader::storeIndexBuffer(void* ptr, PtrSize size)
  192. {
  193. ANKI_ASSERT(isLoaded());
  194. ANKI_ASSERT(size == getIndexBufferSize());
  195. ANKI_ASSERT(m_loadedChunk == 0);
  196. if(ptr)
  197. {
  198. ANKI_CHECK(m_file->read(ptr, size));
  199. }
  200. else
  201. {
  202. ANKI_CHECK(m_file->seek(size, ResourceFile::SeekOrigin::CURRENT));
  203. }
  204. ++m_loadedChunk;
  205. return Error::NONE;
  206. }
  207. Error MeshLoader::storeVertexBuffer(U32 bufferIdx, void* ptr, PtrSize size)
  208. {
  209. ANKI_ASSERT(isLoaded());
  210. ANKI_ASSERT(bufferIdx < m_header.m_vertexBufferCount);
  211. ANKI_ASSERT(size == m_header.m_vertexBuffers[bufferIdx].m_vertexStride * m_header.m_totalVertexCount);
  212. ANKI_ASSERT(m_loadedChunk == bufferIdx + 1);
  213. if(ptr)
  214. {
  215. ANKI_CHECK(m_file->read(ptr, size));
  216. }
  217. else
  218. {
  219. ANKI_CHECK(m_file->seek(size, ResourceFile::SeekOrigin::CURRENT));
  220. }
  221. ++m_loadedChunk;
  222. return Error::NONE;
  223. }
  224. Error MeshLoader::storeIndicesAndPosition(DynamicArrayAuto<U32>& indices, DynamicArrayAuto<Vec3>& positions)
  225. {
  226. // Store indices
  227. {
  228. indices.resize(m_header.m_totalIndexCount);
  229. // Create staging buff
  230. const PtrSize idxBufferSize = getIndexBufferSize();
  231. DynamicArrayAuto<U8> staging(m_alloc);
  232. staging.create(idxBufferSize);
  233. // Store to staging buff
  234. ANKI_CHECK(storeIndexBuffer(&staging[0], staging.getSizeInBytes()));
  235. // Copy
  236. for(U i = 0; i < m_header.m_totalIndexCount; ++i)
  237. {
  238. if(m_header.m_indexType == IndexType::U32)
  239. {
  240. indices[i] = *reinterpret_cast<U32*>(&staging[i * 4]);
  241. }
  242. else
  243. {
  244. indices[i] = *reinterpret_cast<U16*>(&staging[i * 2]);
  245. }
  246. }
  247. }
  248. // Store positions
  249. {
  250. positions.resize(m_header.m_totalVertexCount);
  251. const MeshBinaryFile::VertexAttribute& attrib = m_header.m_vertexAttributes[VertexAttributeLocation::POSITION];
  252. const MeshBinaryFile::VertexBuffer& buffInfo = m_header.m_vertexBuffers[attrib.m_bufferBinding];
  253. // Create staging buff
  254. const PtrSize vertBuffSize = m_header.m_totalVertexCount * buffInfo.m_vertexStride;
  255. DynamicArrayAuto<U8> staging(m_alloc);
  256. staging.create(vertBuffSize);
  257. // Store to staging buff
  258. ANKI_CHECK(storeVertexBuffer(attrib.m_bufferBinding, &staging[0], staging.getSizeInBytes()));
  259. // Copy
  260. for(U i = 0; i < m_header.m_totalVertexCount; ++i)
  261. {
  262. Vec3 vert(0.0f);
  263. if(attrib.m_format == Format::R32G32B32_SFLOAT)
  264. {
  265. vert = *reinterpret_cast<Vec3*>(&staging[i * buffInfo.m_vertexStride + attrib.m_relativeOffset]);
  266. }
  267. else if(attrib.m_format == Format::R16G16B16A16_SFLOAT)
  268. {
  269. F16* f16 = reinterpret_cast<F16*>(&staging[i * buffInfo.m_vertexStride + attrib.m_relativeOffset]);
  270. vert[0] = f16[0].toF32();
  271. vert[1] = f16[1].toF32();
  272. vert[2] = f16[2].toF32();
  273. }
  274. else
  275. {
  276. ANKI_ASSERT(0);
  277. }
  278. positions[i] = vert;
  279. }
  280. }
  281. return Error::NONE;
  282. }
  283. } // end namespace anki