ExporterMesh.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "Exporter.h"
  6. #include <cmath>
  7. enum class ComponentFormat : uint32_t
  8. {
  9. NONE,
  10. R8,
  11. R8G8,
  12. R8G8B8,
  13. R8G8B8A8,
  14. R16,
  15. R16G16,
  16. R16G16B16,
  17. R16G16B16A16,
  18. R32,
  19. R32G32,
  20. R32G32B32,
  21. R32G32B32A32,
  22. R10G10B10A2,
  23. COUNT
  24. };
  25. enum class FormatTransform : uint32_t
  26. {
  27. NONE,
  28. UNORM,
  29. SNORM,
  30. UINT,
  31. SINT,
  32. FLOAT,
  33. COUNT
  34. };
  35. struct Format
  36. {
  37. ComponentFormat m_components = ComponentFormat::NONE;
  38. FormatTransform m_transform = FormatTransform::NONE;
  39. };
  40. const uint32_t FLAG_QUADS = 1;
  41. struct Header
  42. {
  43. char m_magic[8]; ///< Magic word.
  44. uint32_t m_flags;
  45. uint32_t m_flags2;
  46. Format m_positionsFormat;
  47. Format m_normalsFormat;
  48. Format m_tangentsFormat;
  49. Format m_colorsFormat; ///< Vertex color.
  50. Format m_uvsFormat;
  51. Format m_boneWeightsFormat;
  52. Format m_boneIndicesFormat;
  53. Format m_indicesFormat; ///< Vertex indices.
  54. uint32_t m_totalIndicesCount;
  55. uint32_t m_totalVerticesCount;
  56. uint32_t m_uvsChannelCount;
  57. uint32_t m_subMeshCount;
  58. uint8_t m_padding[32];
  59. };
  60. struct SubMesh
  61. {
  62. uint32_t m_firstIndex = 0;
  63. uint32_t m_indicesCount = 0;
  64. };
  65. struct Vertex
  66. {
  67. float m_position[3];
  68. uint16_t m_uv[2];
  69. uint32_t m_normal;
  70. uint32_t m_tangent;
  71. };
  72. struct BoneVertex : Vertex
  73. {
  74. uint8_t m_weights[4] = {0, 0, 0, 0};
  75. uint16_t m_boneIndices[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
  76. };
  77. static_assert(sizeof(BoneVertex) == 9 * 4, "Wrong size");
  78. static uint16_t toF16(float f)
  79. {
  80. union Val32
  81. {
  82. int32_t i;
  83. float f;
  84. uint32_t u;
  85. };
  86. uint16_t out;
  87. Val32 v32;
  88. v32.f = f;
  89. int32_t i = v32.i;
  90. int32_t s = (i >> 16) & 0x00008000;
  91. int32_t e = ((i >> 23) & 0x000000ff) - (127 - 15);
  92. int32_t m = i & 0x007fffff;
  93. if(e <= 0)
  94. {
  95. if(e < -10)
  96. {
  97. out = 0;
  98. }
  99. else
  100. {
  101. m = (m | 0x00800000) >> (1 - e);
  102. if(m & 0x00001000)
  103. {
  104. m += 0x00002000;
  105. }
  106. out = s | (m >> 13);
  107. }
  108. }
  109. else if(e == 0xff - (127 - 15))
  110. {
  111. if(m == 0)
  112. {
  113. out = s | 0x7c00;
  114. }
  115. else
  116. {
  117. m >>= 13;
  118. out = s | 0x7c00 | m | (m == 0);
  119. }
  120. }
  121. else
  122. {
  123. if(m & 0x00001000)
  124. {
  125. m += 0x00002000;
  126. if(m & 0x00800000)
  127. {
  128. m = 0;
  129. e += 1;
  130. }
  131. }
  132. if(e > 30)
  133. {
  134. assert(0 && "Overflow");
  135. out = s | 0x7c00;
  136. }
  137. else
  138. {
  139. out = s | (e << 10) | (m >> 13);
  140. }
  141. }
  142. return out;
  143. }
  144. union SignedR10G10B10A10
  145. {
  146. struct
  147. {
  148. int m_x : 10;
  149. int m_y : 10;
  150. int m_z : 10;
  151. int m_w : 2;
  152. } m_unpacked;
  153. uint32_t m_packed;
  154. };
  155. uint32_t toR10G10B10A2Sint(float r, float g, float b, float a)
  156. {
  157. SignedR10G10B10A10 out;
  158. out.m_unpacked.m_x = int(round(r * 511.0));
  159. out.m_unpacked.m_y = int(round(g * 511.0));
  160. out.m_unpacked.m_z = int(round(b * 511.0));
  161. out.m_unpacked.m_w = int(round(a * 1.0));
  162. return out.m_packed;
  163. }
  164. void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsigned vertCountPerFace) const
  165. {
  166. std::string name = mesh.mName.C_Str();
  167. std::fstream file;
  168. LOGI("Exporting mesh %s", name.c_str());
  169. // Open file
  170. file.open(m_outputDirectory + name + ".ankimesh", std::ios::out | std::ios::binary);
  171. Header header;
  172. memset(&header, 0, sizeof(header));
  173. // Checks
  174. if(mesh.mNumFaces == 0)
  175. {
  176. ERROR("Incorrect face number");
  177. }
  178. if(mesh.mVertices == 0)
  179. {
  180. ERROR("Incorrect vertex count number");
  181. }
  182. if(!mesh.HasPositions())
  183. {
  184. ERROR("Missing positions");
  185. }
  186. if(!mesh.HasNormals())
  187. {
  188. ERROR("Missing normals");
  189. }
  190. if(!mesh.HasTangentsAndBitangents())
  191. {
  192. ERROR("Missing tangents");
  193. }
  194. if(!mesh.HasTextureCoords(0))
  195. {
  196. ERROR("Missing UVs");
  197. }
  198. // Write header
  199. static const char* magic = "ANKIMES3";
  200. memcpy(&header.m_magic, magic, 8);
  201. if(vertCountPerFace == 4)
  202. {
  203. header.m_flags = FLAG_QUADS;
  204. }
  205. header.m_positionsFormat.m_components = ComponentFormat::R32G32B32;
  206. header.m_positionsFormat.m_transform = FormatTransform::FLOAT;
  207. header.m_normalsFormat.m_components = ComponentFormat::R10G10B10A2;
  208. header.m_normalsFormat.m_transform = FormatTransform::SNORM;
  209. header.m_tangentsFormat.m_components = ComponentFormat::R10G10B10A2;
  210. header.m_tangentsFormat.m_transform = FormatTransform::SNORM;
  211. header.m_uvsFormat.m_components = ComponentFormat::R16G16;
  212. header.m_uvsFormat.m_transform = FormatTransform::FLOAT;
  213. header.m_indicesFormat.m_components = ComponentFormat::R16;
  214. header.m_indicesFormat.m_transform = FormatTransform::UINT;
  215. header.m_totalIndicesCount = mesh.mNumFaces * vertCountPerFace;
  216. header.m_totalVerticesCount = mesh.mNumVertices;
  217. header.m_uvsChannelCount = 1;
  218. header.m_subMeshCount = 1;
  219. const bool hasBoneWeights = mesh.mNumBones > 0;
  220. if(hasBoneWeights)
  221. {
  222. header.m_boneIndicesFormat.m_components = ComponentFormat::R16G16B16A16;
  223. header.m_boneIndicesFormat.m_transform = FormatTransform::UINT;
  224. header.m_boneWeightsFormat.m_components = ComponentFormat::R8G8B8A8;
  225. header.m_boneWeightsFormat.m_transform = FormatTransform::UNORM;
  226. }
  227. file.write(reinterpret_cast<char*>(&header), sizeof(header));
  228. // Gather the bone weights
  229. struct VertWeights
  230. {
  231. float m_weights[4];
  232. uint32_t m_boneIndices[4];
  233. uint32_t m_boneCount = 0;
  234. };
  235. std::vector<VertWeights> weights;
  236. if(hasBoneWeights)
  237. {
  238. weights.resize(mesh.mNumVertices);
  239. for(unsigned i = 0; i < mesh.mNumBones; ++i)
  240. {
  241. const aiBone& bone = *mesh.mBones[i];
  242. for(unsigned j = 0; j < bone.mNumWeights; ++j)
  243. {
  244. const aiVertexWeight& aiWeight = bone.mWeights[j];
  245. assert(aiWeight.mVertexId < weights.size());
  246. VertWeights& vert = weights[aiWeight.mVertexId];
  247. if(vert.m_boneCount == 4)
  248. {
  249. ERROR("Vertex has more than 4 bone weights");
  250. }
  251. vert.m_boneIndices[vert.m_boneCount] = i;
  252. vert.m_weights[vert.m_boneCount] = aiWeight.mWeight;
  253. ++vert.m_boneCount;
  254. }
  255. }
  256. }
  257. // Write sub meshes
  258. SubMesh smesh;
  259. smesh.m_firstIndex = 0;
  260. smesh.m_indicesCount = header.m_totalIndicesCount;
  261. file.write(reinterpret_cast<char*>(&smesh), sizeof(smesh));
  262. // Write indices
  263. for(unsigned i = 0; i < mesh.mNumFaces; i++)
  264. {
  265. const aiFace& face = mesh.mFaces[i];
  266. if(face.mNumIndices != vertCountPerFace)
  267. {
  268. ERROR("For some reason assimp returned wrong number of verts for a face (face.mNumIndices=%d). Probably"
  269. "degenerates in input file",
  270. face.mNumIndices);
  271. }
  272. for(unsigned j = 0; j < vertCountPerFace; j++)
  273. {
  274. uint32_t index32 = face.mIndices[j];
  275. if(index32 > 0xFFFF)
  276. {
  277. ERROR("Index too big");
  278. }
  279. uint16_t index = index32;
  280. file.write(reinterpret_cast<char*>(&index), sizeof(index));
  281. }
  282. }
  283. // Write vertices
  284. aiMatrix3x3 normalMat;
  285. if(transform)
  286. {
  287. normalMat = aiMatrix3x3(*transform);
  288. }
  289. for(unsigned i = 0; i < mesh.mNumVertices; i++)
  290. {
  291. aiVector3D pos = mesh.mVertices[i];
  292. aiVector3D n = mesh.mNormals[i];
  293. aiVector3D t = mesh.mTangents[i];
  294. aiVector3D b = mesh.mBitangents[i];
  295. const aiVector3D& uv = mesh.mTextureCoords[0][i];
  296. if(transform)
  297. {
  298. pos = (*transform) * pos;
  299. n = normalMat * n;
  300. t = normalMat * t;
  301. b = normalMat * b;
  302. }
  303. if(m_flipyz)
  304. {
  305. static const aiMatrix4x4 toLefthanded(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
  306. pos = toLefthanded * pos;
  307. n = toLefthanded * n;
  308. t = toLefthanded * t;
  309. b = toLefthanded * b;
  310. }
  311. BoneVertex vert;
  312. // Position
  313. vert.m_position[0] = pos[0];
  314. vert.m_position[1] = pos[1];
  315. vert.m_position[2] = pos[2];
  316. // Tex coords
  317. vert.m_uv[0] = toF16(uv[0]);
  318. vert.m_uv[1] = toF16(uv[1]);
  319. // Normal
  320. vert.m_normal = toR10G10B10A2Sint(n[0], n[1], n[2], 0.0);
  321. // Tangent
  322. float w = ((n ^ t) * b < 0.0) ? 1.0 : -1.0;
  323. vert.m_tangent = toR10G10B10A2Sint(t[0], t[1], t[2], w);
  324. // Write
  325. if(hasBoneWeights)
  326. {
  327. // Normalize weights
  328. float totalWeight = 0;
  329. for(unsigned j = 0; j < weights[i].m_boneCount; ++j)
  330. {
  331. totalWeight += weights[i].m_weights[j];
  332. }
  333. if(totalWeight > 0.0)
  334. {
  335. for(unsigned j = 0; j < weights[i].m_boneCount; ++j)
  336. {
  337. weights[i].m_weights[j] /= totalWeight;
  338. }
  339. }
  340. for(unsigned j = 0; j < weights[i].m_boneCount; ++j)
  341. {
  342. vert.m_boneIndices[j] = weights[i].m_boneIndices[j];
  343. vert.m_weights[j] = weights[i].m_weights[j] * 0xFF;
  344. }
  345. file.write(reinterpret_cast<char*>(&vert), sizeof(BoneVertex));
  346. }
  347. else
  348. {
  349. file.write(reinterpret_cast<char*>(&vert), sizeof(Vertex));
  350. }
  351. }
  352. }