Model.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "Common.h"
  2. #include <cassert>
  3. //==============================================================================
  4. void exportMesh(
  5. const Exporter& exporter,
  6. const aiMesh& mesh,
  7. const std::string* name_,
  8. const aiMatrix4x4* transform)
  9. {
  10. std::string name = (name_) ? *name_ : mesh.mName.C_Str();
  11. std::fstream file;
  12. LOGI("Exporting mesh %s\n", name.c_str());
  13. uint32_t vertsCount = mesh.mNumVertices;
  14. // Open file
  15. file.open(exporter.outDir + name + ".ankimesh",
  16. std::ios::out | std::ios::binary);
  17. // Write magic word
  18. file.write("ANKIMESH", 8);
  19. // Write the name
  20. uint32_t size = name.size();
  21. file.write((char*)&size, sizeof(uint32_t));
  22. file.write(&name[0], size);
  23. // Write positions
  24. file.write((char*)&vertsCount, sizeof(uint32_t));
  25. for(uint32_t i = 0; i < mesh.mNumVertices; i++)
  26. {
  27. aiVector3D pos = mesh.mVertices[i];
  28. // Transform
  29. if(transform)
  30. {
  31. pos = (*transform) * pos;
  32. }
  33. // flip
  34. if(exporter.flipyz)
  35. {
  36. static const aiMatrix4x4 toLefthanded(
  37. 1, 0, 0, 0,
  38. 0, 0, 1, 0,
  39. 0, -1, 0, 0,
  40. 0, 0, 0, 1);
  41. pos = toLefthanded * pos;
  42. }
  43. for(uint32_t j = 0; j < 3; j++)
  44. {
  45. file.write((char*)&pos[j], sizeof(float));
  46. }
  47. }
  48. // Write the indices
  49. file.write((char*)&mesh.mNumFaces, sizeof(uint32_t));
  50. for(uint32_t i = 0; i < mesh.mNumFaces; i++)
  51. {
  52. const aiFace& face = mesh.mFaces[i];
  53. if(face.mNumIndices != 3)
  54. {
  55. ERROR("For some reason the assimp didn't triangulate\n");
  56. }
  57. for(uint32_t j = 0; j < 3; j++)
  58. {
  59. uint32_t index = face.mIndices[j];
  60. file.write((char*)&index, sizeof(uint32_t));
  61. }
  62. }
  63. // Write the tex coords
  64. file.write((char*)&vertsCount, sizeof(uint32_t));
  65. // For all channels
  66. for(uint32_t ch = 0; ch < mesh.GetNumUVChannels(); ch++)
  67. {
  68. if(mesh.mNumUVComponents[ch] != 2)
  69. {
  70. ERROR("Incorrect number of UV components\n");
  71. }
  72. // For all tex coords of this channel
  73. for(uint32_t i = 0; i < vertsCount; i++)
  74. {
  75. aiVector3D texCoord = mesh.mTextureCoords[ch][i];
  76. for(uint32_t j = 0; j < 2; j++)
  77. {
  78. file.write((char*)&texCoord[j], sizeof(float));
  79. }
  80. }
  81. }
  82. // Write bone weigths count
  83. if(mesh.HasBones())
  84. {
  85. #if 0
  86. // Write file
  87. file.write((char*)&vertsCount, sizeof(uint32_t));
  88. // Gather info for each vertex
  89. std::vector<Vw> vw;
  90. vw.resize(vertsCount);
  91. memset(&vw[0], 0, sizeof(Vw) * vertsCount);
  92. // For all bones
  93. for(uint32_t i = 0; i < mesh.mNumBones; i++)
  94. {
  95. const aiBone& bone = *mesh.mBones[i];
  96. // for every weights of the bone
  97. for(uint32_t j = 0; j < bone.mWeightsCount; j++)
  98. {
  99. const aiVertexWeight& weigth = bone.mWeights[j];
  100. // Sanity check
  101. if(weight.mVertexId >= vertCount)
  102. {
  103. ERROR("Out of bounds vert ID");
  104. }
  105. Vm& a = vm[weight.mVertexId];
  106. // Check out of bounds
  107. if(a.bonesCount >= MAX_BONES_PER_VERTEX)
  108. {
  109. LOGW("Too many bones for vertex %d\n", weigth.mVertexId);
  110. continue;
  111. }
  112. // Write to vertex
  113. a.boneIds[a.bonesCount] = i;
  114. a.weigths[a.bonesCount] = weigth.mWeigth;
  115. ++a.bonesCount;
  116. }
  117. // Now write the file
  118. }
  119. #endif
  120. }
  121. else
  122. {
  123. uint32_t num = 0;
  124. file.write((char*)&num, sizeof(uint32_t));
  125. }
  126. }
  127. //==============================================================================
  128. void exportSkeleton(const Exporter& exporter, const aiMesh& mesh)
  129. {
  130. assert(mesh.HasBones());
  131. std::string name = mesh.mName.C_Str();
  132. std::fstream file;
  133. LOGI("Exporting skeleton %s\n", name.c_str());
  134. // Open file
  135. file.open(exporter.outDir + name + ".skel", std::ios::out);
  136. file << XML_HEADER << "\n";
  137. file << "<skeleton>\n";
  138. file << "\t<bones>\n";
  139. bool rootBoneFound = false;
  140. for(uint32_t i = 0; i < mesh.mNumBones; i++)
  141. {
  142. const aiBone& bone = *mesh.mBones[i];
  143. file << "\t\t<bone>\n";
  144. // <name>
  145. file << "\t\t\t<name>" << bone.mName.C_Str() << "</name>\n";
  146. if(strcmp(bone.mName.C_Str(), "root") == 0)
  147. {
  148. rootBoneFound = true;
  149. }
  150. // <transform>
  151. file << "\t\t\t<transform>";
  152. for(uint32_t j = 0; j < 16; j++)
  153. {
  154. file << bone.mOffsetMatrix[j] << " ";
  155. }
  156. file << "</transform>\n";
  157. file << "\t\t</bone>\n";
  158. }
  159. if(!rootBoneFound)
  160. {
  161. ERROR("There should be one bone named \"root\"\n");
  162. }
  163. file << "\t</bones>\n";
  164. file << "</skeleton>\n";
  165. }
  166. //==============================================================================
  167. std::string getMaterialName(const aiMaterial& mtl)
  168. {
  169. aiString ainame;
  170. std::string name;
  171. if(mtl.Get(AI_MATKEY_NAME, ainame) == AI_SUCCESS)
  172. {
  173. name = ainame.C_Str();
  174. }
  175. else
  176. {
  177. ERROR("Material's name is missing\n");
  178. }
  179. return name;
  180. }
  181. //==============================================================================
  182. void exportMaterial(
  183. const Exporter& exporter,
  184. const aiMaterial& mtl,
  185. bool instanced,
  186. const std::string* name_)
  187. {
  188. std::string diffTex;
  189. std::string normTex;
  190. std::string name;
  191. if(name_)
  192. {
  193. name = *name_;
  194. }
  195. else
  196. {
  197. name = getMaterialName(mtl);
  198. }
  199. LOGI("Exporting material %s\n", name.c_str());
  200. // Diffuse texture
  201. if(mtl.GetTextureCount(aiTextureType_DIFFUSE) < 1)
  202. {
  203. ERROR("Material has no diffuse textures\n");
  204. }
  205. aiString path;
  206. if(mtl.GetTexture(aiTextureType_DIFFUSE, 0, &path) == AI_SUCCESS)
  207. {
  208. diffTex = getFilename(path.C_Str());
  209. }
  210. else
  211. {
  212. ERROR("Failed to retrieve texture\n");
  213. }
  214. // Normal texture
  215. if(mtl.GetTextureCount(aiTextureType_NORMALS) > 0)
  216. {
  217. if(mtl.GetTexture(aiTextureType_NORMALS, 0, &path) == AI_SUCCESS)
  218. {
  219. normTex = getFilename(path.C_Str());
  220. }
  221. else
  222. {
  223. ERROR("Failed to retrieve texture\n");
  224. }
  225. }
  226. // Write file
  227. static const char* diffMtlStr =
  228. #include "diffTemplateMtl.h"
  229. ;
  230. static const char* diffNormMtlStr =
  231. #include "diffNormTemplateMtl.h"
  232. ;
  233. std::fstream file;
  234. file.open(exporter.outDir + name + ".ankimtl", std::ios::out);
  235. // Chose the correct template
  236. std::string str;
  237. if(normTex.size() == 0)
  238. {
  239. str = diffMtlStr;
  240. }
  241. else
  242. {
  243. str = replaceAllString(diffNormMtlStr, "%normalMap%",
  244. exporter.texrpath + normTex);
  245. }
  246. str = replaceAllString(str, "%instanced%", (instanced) ? "1" : "0");
  247. str = replaceAllString(str, "%diffuseMap%", exporter.texrpath + diffTex);
  248. file << str;
  249. }