MeshData.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. #include <fstream>
  2. #include <cstring>
  3. #include <boost/lexical_cast.hpp>
  4. #include <boost/foreach.hpp>
  5. #include "anki/resource/MeshData.h"
  6. #include "anki/util/BinaryStream.h"
  7. namespace anki {
  8. //==============================================================================
  9. void MeshData::load(const char* filename)
  10. {
  11. // Try
  12. try
  13. {
  14. // Open the file
  15. std::fstream file(filename, std::fstream::in | std::fstream::binary);
  16. if(!file.is_open())
  17. {
  18. throw ANKI_EXCEPTION("Cannot open file \"" + filename + "\"");
  19. }
  20. BinaryStream bs(file.rdbuf());
  21. // Magic word
  22. char magic[8];
  23. bs.read(magic, 8);
  24. if(bs.fail() || memcmp(magic, "ANKIMESH", 8))
  25. {
  26. throw ANKI_EXCEPTION("Incorrect magic word");
  27. }
  28. // Mesh name
  29. std::string meshName = bs.readString();
  30. // Verts num
  31. uint vertsNum = bs.readUint();
  32. vertCoords.resize(vertsNum);
  33. // Vert coords
  34. BOOST_FOREACH(Vec3& vertCoord, vertCoords)
  35. {
  36. for(uint j = 0; j < 3; j++)
  37. {
  38. vertCoord[j] = bs.readFloat();
  39. }
  40. }
  41. // Faces num
  42. uint facesNum = bs.readUint();
  43. tris.resize(facesNum);
  44. // Faces IDs
  45. BOOST_FOREACH(Triangle& tri, tris)
  46. {
  47. for(uint j = 0; j < 3; j++)
  48. {
  49. tri.vertIds[j] = bs.readUint();
  50. // a sanity check
  51. if(tri.vertIds[j] >= vertCoords.size())
  52. {
  53. throw ANKI_EXCEPTION("Vert index out of bounds");
  54. }
  55. }
  56. }
  57. // Tex coords num
  58. uint texCoordsNum = bs.readUint();
  59. texCoords.resize(texCoordsNum);
  60. // Tex coords
  61. BOOST_FOREACH(Vec2& texCoord, texCoords)
  62. {
  63. for(uint i = 0; i < 2; i++)
  64. {
  65. texCoord[i] = bs.readFloat();
  66. }
  67. }
  68. // Vert weights num
  69. uint vertWeightsNum = bs.readUint();
  70. vertWeights.resize(vertWeightsNum);
  71. // Vert weights
  72. BOOST_FOREACH(VertexWeight& vw, vertWeights)
  73. {
  74. // get the bone connections num
  75. uint boneConnections = bs.readUint();
  76. // we treat as error if one vert doesnt have a bone
  77. if(boneConnections < 1)
  78. {
  79. throw ANKI_EXCEPTION("Vert sould have at least one bone");
  80. }
  81. // and here is another possible error
  82. if(boneConnections > VertexWeight::MAX_BONES_PER_VERT)
  83. {
  84. uint tmp = VertexWeight::MAX_BONES_PER_VERT;
  85. throw ANKI_EXCEPTION("Cannot have more than " +
  86. boost::lexical_cast<std::string>(tmp) +
  87. " bones per vertex");
  88. }
  89. vw.bonesNum = boneConnections;
  90. // for all the weights of the current vertes
  91. for(uint i = 0; i < vw.bonesNum; i++)
  92. {
  93. // read bone id
  94. uint boneId = bs.readUint();
  95. vw.boneIds[i] = boneId;
  96. // read the weight of that bone
  97. float weight = bs.readFloat();
  98. vw.weights[i] = weight;
  99. }
  100. } // end for all vert weights
  101. doPostLoad();
  102. }
  103. catch(Exception& e)
  104. {
  105. throw ANKI_EXCEPTION_R("File \"" + filename + "\"", e);
  106. }
  107. }
  108. //==============================================================================
  109. void MeshData::doPostLoad()
  110. {
  111. // Sanity checks
  112. if(vertCoords.size() < 1 || tris.size() < 1)
  113. {
  114. throw ANKI_EXCEPTION("Vert coords and tris must be filled");
  115. }
  116. if(texCoords.size() != 0 && texCoords.size() != vertCoords.size())
  117. {
  118. throw ANKI_EXCEPTION("Tex coords num must be "
  119. "zero or equal to the vertex "
  120. "coords num");
  121. }
  122. if(vertWeights.size() != 0 && vertWeights.size() != vertCoords.size())
  123. {
  124. throw ANKI_EXCEPTION("Vert weights num must be zero or equal to the "
  125. "vertex coords num");
  126. }
  127. createAllNormals();
  128. if(texCoords.size() > 0)
  129. {
  130. createVertTangents();
  131. }
  132. createVertIndeces();
  133. }
  134. //==============================================================================
  135. void MeshData::createVertIndeces()
  136. {
  137. vertIndeces.resize(tris.size() * 3);
  138. for(uint i = 0; i < tris.size(); i++)
  139. {
  140. vertIndeces[i * 3 + 0] = tris[i].vertIds[0];
  141. vertIndeces[i * 3 + 1] = tris[i].vertIds[1];
  142. vertIndeces[i * 3 + 2] = tris[i].vertIds[2];
  143. }
  144. }
  145. //==============================================================================
  146. void MeshData::createFaceNormals()
  147. {
  148. BOOST_FOREACH(Triangle& tri, tris)
  149. {
  150. const Vec3& v0 = vertCoords[tri.vertIds[0]];
  151. const Vec3& v1 = vertCoords[tri.vertIds[1]];
  152. const Vec3& v2 = vertCoords[tri.vertIds[2]];
  153. /*std::cout << v0 << std::endl;
  154. std::cout << v1 << std::endl;
  155. std::cout << v2 << std::endl;
  156. std::cout << std::endl;*/
  157. tri.normal = (v1 - v0).cross(v2 - v0);
  158. tri.normal.normalize();
  159. }
  160. }
  161. //==============================================================================
  162. void MeshData::createVertNormals()
  163. {
  164. vertNormals.resize(vertCoords.size());
  165. BOOST_FOREACH(Vec3& vertNormal, vertNormals)
  166. {
  167. vertNormal = Vec3(0.0, 0.0, 0.0);
  168. }
  169. BOOST_FOREACH(Triangle& tri, tris)
  170. {
  171. vertNormals[tri.vertIds[0]] += tri.normal;
  172. vertNormals[tri.vertIds[1]] += tri.normal;
  173. vertNormals[tri.vertIds[2]] += tri.normal;
  174. }
  175. BOOST_FOREACH(Vec3& vertNormal, vertNormals)
  176. {
  177. vertNormal.normalize();
  178. }
  179. }
  180. //==============================================================================
  181. void MeshData::createVertTangents()
  182. {
  183. vertTangents.resize(vertCoords.size(), Vec4(0.0)); // alloc
  184. std::vector<Vec3> bitagents(vertCoords.size(), Vec3(0.0));
  185. for(uint i = 0; i < tris.size(); i++)
  186. {
  187. const Triangle& tri = tris[i];
  188. const int i0 = tri.vertIds[0];
  189. const int i1 = tri.vertIds[1];
  190. const int i2 = tri.vertIds[2];
  191. const Vec3& v0 = vertCoords[i0];
  192. const Vec3& v1 = vertCoords[i1];
  193. const Vec3& v2 = vertCoords[i2];
  194. Vec3 edge01 = v1 - v0;
  195. Vec3 edge02 = v2 - v0;
  196. Vec2 uvedge01 = texCoords[i1] - texCoords[i0];
  197. Vec2 uvedge02 = texCoords[i2] - texCoords[i0];
  198. float det = (uvedge01.y() * uvedge02.x()) -
  199. (uvedge01.x() * uvedge02.y());
  200. if(Math::isZero(det))
  201. {
  202. //ANKI_WARNING(getRsrcName() << ": det == " << fixed << det);
  203. det = 0.0001;
  204. }
  205. else
  206. {
  207. det = 1.0 / det;
  208. }
  209. Vec3 t = (edge02 * uvedge01.y() - edge01 * uvedge02.y()) * det;
  210. Vec3 b = (edge02 * uvedge01.x() - edge01 * uvedge02.x()) * det;
  211. t.normalize();
  212. b.normalize();
  213. vertTangents[i0] += Vec4(t, 1.0);
  214. vertTangents[i1] += Vec4(t, 1.0);
  215. vertTangents[i2] += Vec4(t, 1.0);
  216. bitagents[i0] += b;
  217. bitagents[i1] += b;
  218. bitagents[i2] += b;
  219. }
  220. for(uint i = 0; i < vertTangents.size(); i++)
  221. {
  222. Vec3 t = Vec3(vertTangents[i]);
  223. const Vec3& n = vertNormals[i];
  224. Vec3& b = bitagents[i];
  225. //t = t - n * n.dot(t);
  226. t.normalize();
  227. b.normalize();
  228. float w = ((n.cross(t)).dot(b) < 0.0) ? 1.0 : -1.0;
  229. vertTangents[i] = Vec4(t, w);
  230. }
  231. }
  232. } // end namespace