MeshLoader.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #include "anki/resource/MeshLoader.h"
  2. #include "anki/util/BinaryStream.h"
  3. #include <fstream>
  4. #include <cstring>
  5. #include <unordered_map>
  6. namespace anki {
  7. //==============================================================================
  8. // Misc =
  9. //==============================================================================
  10. /// The hash functor
  11. struct Hasher
  12. {
  13. size_t operator()(const Vec3& pos) const
  14. {
  15. F32 sum = pos.x() * 100.0 + pos.y() * 10.0 + pos.z();
  16. size_t hash = 0;
  17. memcpy(&hash, &sum, sizeof(F32));
  18. return hash;
  19. }
  20. };
  21. /// The value of the hash map
  22. struct MapValue
  23. {
  24. U8 indicesCount = 0;
  25. Array<U32, 16> indices;
  26. };
  27. typedef std::unordered_map<Vec3, MapValue, Hasher> FixNormalsMap;
  28. //==============================================================================
  29. // MeshLoader =
  30. //==============================================================================
  31. //==============================================================================
  32. void MeshLoader::load(const char* filename)
  33. {
  34. // Try
  35. try
  36. {
  37. // Open the file
  38. std::fstream file(filename, std::fstream::in | std::fstream::binary);
  39. if(!file.is_open())
  40. {
  41. throw ANKI_EXCEPTION("Cannot open file:" + filename);
  42. }
  43. BinaryStream bs(file.rdbuf());
  44. // Magic word
  45. char magic[8];
  46. bs.read(magic, sizeof(magic));
  47. if(bs.fail() || memcmp(magic, "ANKIMESH", 8))
  48. {
  49. throw ANKI_EXCEPTION("Incorrect magic word");
  50. }
  51. // Mesh name
  52. std::string meshName = bs.readString();
  53. // Verts num
  54. uint vertsNum = bs.readUint();
  55. vertCoords.resize(vertsNum);
  56. // Vert coords
  57. for(Vec3& vertCoord : vertCoords)
  58. {
  59. for(U j = 0; j < 3; j++)
  60. {
  61. vertCoord[j] = bs.readFloat();
  62. }
  63. }
  64. // Faces num
  65. U facesNum = bs.readUint();
  66. tris.resize(facesNum);
  67. // Faces IDs
  68. for(Triangle& tri : tris)
  69. {
  70. for(U j = 0; j < 3; j++)
  71. {
  72. tri.vertIds[j] = bs.readUint();
  73. // a sanity check
  74. if(tri.vertIds[j] >= vertCoords.size())
  75. {
  76. throw ANKI_EXCEPTION("Vert index out of bounds");
  77. }
  78. }
  79. }
  80. // Tex coords num
  81. U texCoordsNum = bs.readUint();
  82. texCoords.resize(texCoordsNum);
  83. // Tex coords
  84. for(Vec2& texCoord : texCoords)
  85. {
  86. for(uint i = 0; i < 2; i++)
  87. {
  88. texCoord[i] = bs.readFloat();
  89. }
  90. }
  91. // Vert weights num
  92. U vertWeightsNum = bs.readUint();
  93. vertWeights.resize(vertWeightsNum);
  94. // Vert weights
  95. for(VertexWeight& vw : vertWeights)
  96. {
  97. // get the bone connections num
  98. uint boneConnections = bs.readUint();
  99. // we treat as error if one vert doesnt have a bone
  100. if(boneConnections < 1)
  101. {
  102. throw ANKI_EXCEPTION("Vert sould have at least one bone");
  103. }
  104. // and here is another possible error
  105. if(boneConnections > VertexWeight::MAX_BONES_PER_VERT)
  106. {
  107. uint tmp = VertexWeight::MAX_BONES_PER_VERT;
  108. throw ANKI_EXCEPTION("Cannot have more than "
  109. + std::to_string(tmp) + " bones per vertex");
  110. }
  111. vw.bonesNum = boneConnections;
  112. // for all the weights of the current vertes
  113. for(uint i = 0; i < vw.bonesNum; i++)
  114. {
  115. // read bone id
  116. uint boneId = bs.readUint();
  117. vw.boneIds[i] = boneId;
  118. // read the weight of that bone
  119. float weight = bs.readFloat();
  120. vw.weights[i] = weight;
  121. }
  122. } // end for all vert weights
  123. doPostLoad();
  124. }
  125. catch(Exception& e)
  126. {
  127. throw ANKI_EXCEPTION("Loading of file failed: " + filename) << e;
  128. }
  129. }
  130. //==============================================================================
  131. void MeshLoader::doPostLoad()
  132. {
  133. // Sanity checks
  134. if(vertCoords.size() < 1 || tris.size() < 1)
  135. {
  136. throw ANKI_EXCEPTION("Vert coords and tris must be filled");
  137. }
  138. if(texCoords.size() != 0 && texCoords.size() != vertCoords.size())
  139. {
  140. throw ANKI_EXCEPTION("Tex coords num must be "
  141. "zero or equal to the vertex "
  142. "coords num");
  143. }
  144. if(vertWeights.size() != 0 && vertWeights.size() != vertCoords.size())
  145. {
  146. throw ANKI_EXCEPTION("Vert weights num must be zero or equal to the "
  147. "vertex coords num");
  148. }
  149. createAllNormals();
  150. fixNormals();
  151. if(texCoords.size() > 0)
  152. {
  153. createVertTangents();
  154. }
  155. createVertIndeces();
  156. }
  157. //==============================================================================
  158. void MeshLoader::createVertIndeces()
  159. {
  160. vertIndices.resize(tris.size() * 3);
  161. U j = 0;
  162. for(U i = 0; i < tris.size(); ++i)
  163. {
  164. vertIndices[j + 0] = tris[i].vertIds[0];
  165. vertIndices[j + 1] = tris[i].vertIds[1];
  166. vertIndices[j + 2] = tris[i].vertIds[2];
  167. j += 3;
  168. }
  169. }
  170. //==============================================================================
  171. void MeshLoader::createFaceNormals()
  172. {
  173. for(Triangle& tri : tris)
  174. {
  175. const Vec3& v0 = vertCoords[tri.vertIds[0]];
  176. const Vec3& v1 = vertCoords[tri.vertIds[1]];
  177. const Vec3& v2 = vertCoords[tri.vertIds[2]];
  178. tri.normal = (v1 - v0).cross(v2 - v0);
  179. if(tri.normal != Vec3(0.0))
  180. {
  181. //tri.normal.normalize();
  182. }
  183. else
  184. {
  185. tri.normal = Vec3(1.0, 0.0, 0.0);
  186. }
  187. }
  188. }
  189. //==============================================================================
  190. void MeshLoader::createVertNormals()
  191. {
  192. vertNormals.resize(vertCoords.size());
  193. for(Vec3& vertNormal : vertNormals)
  194. {
  195. vertNormal = Vec3(0.0, 0.0, 0.0);
  196. }
  197. for(Triangle& tri : tris)
  198. {
  199. vertNormals[tri.vertIds[0]] += tri.normal;
  200. vertNormals[tri.vertIds[1]] += tri.normal;
  201. vertNormals[tri.vertIds[2]] += tri.normal;
  202. }
  203. for(Vec3& vertNormal : vertNormals)
  204. {
  205. vertNormal.normalize();
  206. }
  207. }
  208. //==============================================================================
  209. void MeshLoader::createVertTangents()
  210. {
  211. vertTangents.resize(vertCoords.size(), Vec4(0.0)); // alloc
  212. Vector<Vec3> bitagents(vertCoords.size(), Vec3(0.0));
  213. for(uint i = 0; i < tris.size(); i++)
  214. {
  215. const Triangle& tri = tris[i];
  216. const I i0 = tri.vertIds[0];
  217. const I i1 = tri.vertIds[1];
  218. const I i2 = tri.vertIds[2];
  219. const Vec3& v0 = vertCoords[i0];
  220. const Vec3& v1 = vertCoords[i1];
  221. const Vec3& v2 = vertCoords[i2];
  222. Vec3 edge01 = v1 - v0;
  223. Vec3 edge02 = v2 - v0;
  224. Vec2 uvedge01 = texCoords[i1] - texCoords[i0];
  225. Vec2 uvedge02 = texCoords[i2] - texCoords[i0];
  226. F32 det = (uvedge01.y() * uvedge02.x()) -
  227. (uvedge01.x() * uvedge02.y());
  228. if(isZero(det))
  229. {
  230. //ANKI_LOGW(getRsrcName() << ": det == " << fixed << det);
  231. det = 0.0001;
  232. }
  233. else
  234. {
  235. // Calc the det
  236. det = 1.0 / det;
  237. // Add a noise to the det to avoid zero tangents on mirrored cases
  238. det *= ((rand() % 10) * getEpsilon<F32>());
  239. }
  240. Vec3 t = (edge02 * uvedge01.y() - edge01 * uvedge02.y()) * det;
  241. Vec3 b = (edge02 * uvedge01.x() - edge01 * uvedge02.x()) * det;
  242. //t.normalize();
  243. //b.normalize();
  244. vertTangents[i0] += Vec4(t, 1.0);
  245. vertTangents[i1] += Vec4(t, 1.0);
  246. vertTangents[i2] += Vec4(t, 1.0);
  247. bitagents[i0] += b;
  248. bitagents[i1] += b;
  249. bitagents[i2] += b;
  250. }
  251. for(U i = 0; i < vertTangents.size(); i++)
  252. {
  253. Vec3 t = vertTangents[i].xyz();
  254. const Vec3& n = vertNormals[i];
  255. Vec3& b = bitagents[i];
  256. t = t - n * n.dot(t);
  257. t.normalize();
  258. b.normalize();
  259. F32 w = ((n.cross(t)).dot(b) < 0.0) ? 1.0 : -1.0;
  260. vertTangents[i] = Vec4(t, w);
  261. }
  262. }
  263. //==============================================================================
  264. void MeshLoader::fixNormals()
  265. {
  266. FixNormalsMap map;
  267. // For all verts
  268. for(U i = 1; i < vertCoords.size(); i++)
  269. {
  270. const Vec3& pos = vertCoords[i];
  271. Vec3& norm = vertNormals[i];
  272. // Find pos
  273. FixNormalsMap::iterator it = map.find(pos);
  274. // Check if found
  275. if(it == map.end())
  276. {
  277. // Not found
  278. MapValue val;
  279. val.indices[0] = i;
  280. val.indicesCount = 1;
  281. map[pos] = val;
  282. }
  283. else
  284. {
  285. // Found
  286. MapValue& mapVal = it->second;
  287. ANKI_ASSERT(mapVal.indicesCount > 0);
  288. // Search the verts with the same position
  289. for(U j = 0; j < mapVal.indicesCount; j++)
  290. {
  291. const Vec3& posB = vertCoords[mapVal.indices[j]];
  292. Vec3& normB = vertNormals[mapVal.indices[j]];
  293. ANKI_ASSERT(posB == pos);
  294. (void)posB;
  295. F32 dot = norm.dot(normB);
  296. F32 ang = acos(dot);
  297. if(ang <= NORMALS_ANGLE_MERGE)
  298. {
  299. Vec3 newNormal = (norm + normB) * 0.5;
  300. newNormal.normalize();
  301. norm = newNormal;
  302. normB = newNormal;
  303. }
  304. }
  305. // Update the map
  306. mapVal.indices[mapVal.indicesCount++] = i;
  307. }
  308. }
  309. }
  310. } // end namespace anki