Main.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include <assimp/Importer.hpp>
  2. #include <assimp/scene.h>
  3. #include <assimp/postprocess.h>
  4. #include <iostream>
  5. #include <stdexcept>
  6. #include <cstdarg>
  7. #include <fstream>
  8. #include <cstdint>
  9. #include <sstream>
  10. #include <cassert>
  11. #include "Common.h"
  12. //==============================================================================
  13. /// Load the scene
  14. static void load(
  15. Exporter& exporter,
  16. const std::string& filename)
  17. {
  18. LOGI("Loading file %s\n", filename.c_str());
  19. const aiScene* scene = exporter.importer.ReadFile(filename, 0
  20. //| aiProcess_FindInstances
  21. | aiProcess_Triangulate
  22. | aiProcess_JoinIdenticalVertices
  23. //| aiProcess_SortByPType
  24. | aiProcess_ImproveCacheLocality
  25. | aiProcess_OptimizeMeshes
  26. | aiProcess_RemoveRedundantMaterials
  27. );
  28. if(!scene)
  29. {
  30. ERROR("%s\n", exporter.importer.GetErrorString());
  31. }
  32. exporter.scene = scene;
  33. LOGI("File loaded successfully!\n");
  34. }
  35. //==============================================================================
  36. static void parseCommandLineArgs(int argc, char** argv, Exporter& exporter)
  37. {
  38. static const char* usage = R"(Usage: %s in_file out_dir [options]
  39. Options:
  40. -rpath <string> : Append a string to the meshes and materials
  41. -texrpath <string> : Append a string to the textures paths
  42. -flipyz : Flip y with z (For blender exports)
  43. )";
  44. // Parse config
  45. if(argc < 3)
  46. {
  47. goto error;
  48. }
  49. exporter.inputFname = argv[1];
  50. exporter.outDir = argv[2] + std::string("/");
  51. for(int i = 3; i < argc; i++)
  52. {
  53. if(strcmp(argv[i], "-texrpath") == 0)
  54. {
  55. ++i;
  56. if(i < argc)
  57. {
  58. exporter.texrpath = argv[i] + std::string("/");
  59. }
  60. else
  61. {
  62. goto error;
  63. }
  64. }
  65. else if(strcmp(argv[i], "-rpath") == 0)
  66. {
  67. ++i;
  68. if(i < argc)
  69. {
  70. exporter.rpath = argv[i] + std::string("/");
  71. }
  72. else
  73. {
  74. goto error;
  75. }
  76. }
  77. else if(strcmp(argv[i], "-flipyz") == 0)
  78. {
  79. exporter.flipyz = true;
  80. }
  81. else
  82. {
  83. goto error;
  84. }
  85. }
  86. if(exporter.rpath.empty())
  87. {
  88. exporter.rpath = exporter.outDir;
  89. }
  90. if(exporter.texrpath.empty())
  91. {
  92. exporter.texrpath = exporter.outDir;
  93. }
  94. return;
  95. error:
  96. printf(usage, argv[0]);
  97. exit(1);
  98. }
  99. //==============================================================================
  100. static void visitNode(Exporter& exporter, const aiNode* ainode)
  101. {
  102. if(ainode == nullptr)
  103. {
  104. return;
  105. }
  106. // For every mesh of this node
  107. for(unsigned i = 0; i < ainode->mNumMeshes; i++)
  108. {
  109. unsigned meshIndex = ainode->mMeshes[i];
  110. unsigned mtlIndex = exporter.scene->mMeshes[meshIndex]->mMaterialIndex;
  111. // Find if there is another node with the same model
  112. std::vector<Node>::iterator it;
  113. for(it = exporter.nodes.begin(); it != exporter.nodes.end(); it++)
  114. {
  115. const Node& node = *it;
  116. const Model& model = exporter.models[node.modelIndex];
  117. if(model.meshIndex == meshIndex && model.mtlIndex == mtlIndex)
  118. {
  119. break;
  120. }
  121. }
  122. if(it != exporter.nodes.end())
  123. {
  124. // A node with the same model exists. It's instanced
  125. Node& node = *it;
  126. Model& model = exporter.models[node.modelIndex];
  127. assert(node.transforms.size() > 0);
  128. node.transforms.push_back(ainode->mTransformation);
  129. model.instanced = true;
  130. break;
  131. }
  132. // Create new model
  133. Model mdl;
  134. mdl.meshIndex = meshIndex;
  135. mdl.mtlIndex = mtlIndex;
  136. exporter.models.push_back(mdl);
  137. // Create new node
  138. Node node;
  139. node.modelIndex = exporter.models.size() - 1;
  140. node.transforms.push_back(ainode->mTransformation);
  141. exporter.nodes.push_back(node);
  142. }
  143. // Go to children
  144. for(uint32_t i = 0; i < ainode->mNumChildren; i++)
  145. {
  146. visitNode(exporter, ainode->mChildren[i]);
  147. }
  148. }
  149. //==============================================================================
  150. static void writeNodeTransform(const Exporter& exporter, std::ofstream& file,
  151. const std::string& node, const aiMatrix4x4& mat)
  152. {
  153. aiMatrix4x4 m = toAnkiMatrix(mat, exporter.flipyz);
  154. float pos[3];
  155. pos[0] = m[0][3];
  156. pos[1] = m[1][3];
  157. pos[2] = m[2][3];
  158. file << "pos = Vec3.new()\n";
  159. file << "pos:setX(" << pos[0] << ")\n";
  160. file << "pos:setY(" << pos[1] << ")\n";
  161. file << "pos:setZ(" << pos[2] << ")\n";
  162. file << node
  163. << ":getSceneNodeBase():getMoveComponent():setLocalOrigin(pos)\n";
  164. file << "rot = Mat3.new()\n";
  165. for(unsigned j = 0; j < 3; j++)
  166. {
  167. for(unsigned i = 0; i < 3; i++)
  168. {
  169. file << "rot:setAt(" << j << ", " << i << ", " << m[j][i] << ")\n";
  170. }
  171. }
  172. file << node
  173. << ":getSceneNodeBase():getMoveComponent():setLocalRotation(rot)\n";
  174. }
  175. //==============================================================================
  176. static void exportScene(Exporter& exporter)
  177. {
  178. LOGI("Exporting scene to %s\n", exporter.outDir.c_str());
  179. //
  180. // Open scene file
  181. //
  182. std::ofstream file;
  183. file.open(exporter.outDir + "scene.lua");
  184. file << "scene = SceneGraphSingleton.get()\n";
  185. //
  186. // Get all the data
  187. //
  188. const aiNode* node = exporter.scene->mRootNode;
  189. visitNode(exporter, node);
  190. //
  191. // Export nodes
  192. //
  193. for(uint32_t i = 0; i < exporter.nodes.size(); i++)
  194. {
  195. Node& node = exporter.nodes[i];
  196. Model& model = exporter.models[node.modelIndex];
  197. exportMesh(exporter,
  198. *exporter.scene->mMeshes[model.meshIndex], nullptr);
  199. exportMaterial(exporter,
  200. *exporter.scene->mMaterials[model.mtlIndex],
  201. model.instanced);
  202. exportModel(exporter, model);
  203. std::string name = getModelName(exporter, model);
  204. // Write the main node
  205. file << "\nnode = scene:newModelNode(\"" << name << "\", \""
  206. << exporter.rpath << name << ".ankimdl" << "\")\n";
  207. writeNodeTransform(exporter, file, "node", node.transforms[0]);
  208. // Write instance nodes
  209. for(unsigned j = 1; j < node.transforms.size(); j++)
  210. {
  211. file << "inst = scene:newInstanceNode(\""
  212. << name << "_inst" << (j - 1) << "\")\n"
  213. << "node:getSceneNodeBase():addChild("
  214. << "inst:getSceneNodeBase())\n";
  215. writeNodeTransform(exporter, file, "inst", node.transforms[j]);
  216. }
  217. }
  218. //
  219. // Animations
  220. //
  221. for(unsigned i = 0; i < exporter.scene->mNumAnimations; i++)
  222. {
  223. exportAnimation(exporter, *exporter.scene->mAnimations[i], i);
  224. }
  225. LOGI("Done exporting scene!\n");
  226. }
  227. //==============================================================================
  228. int main(int argc, char** argv)
  229. {
  230. try
  231. {
  232. Exporter exporter;
  233. parseCommandLineArgs(argc, argv, exporter);
  234. // Load file
  235. load(exporter, exporter.inputFname);
  236. // Export
  237. exportScene(exporter);
  238. }
  239. catch(std::exception& e)
  240. {
  241. std::cerr << "Exception: " << e.what() << std::endl;
  242. }
  243. }