WriteDumb.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2020, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file WriteTextDumb.cpp
  35. * @brief Implementation of the 'assimp dump' utility
  36. */
  37. #include "Main.h"
  38. #include "PostProcessing/ProcessHelper.h"
  39. const char* AICMD_MSG_DUMP_HELP =
  40. "assimp dump <model> [<out>] [-b] [-s] [-z] [common parameters]\n"
  41. "\t -b Binary output \n"
  42. "\t -s Shortened \n"
  43. "\t -z Compressed \n"
  44. "\t[See the assimp_cmd docs for a full list of all common parameters] \n"
  45. "\t -cfast Fast post processing preset, runs just a few important steps \n"
  46. "\t -cdefault Default post processing: runs all recommended steps\n"
  47. "\t -cfull Fires almost all post processing steps \n"
  48. ;
  49. #include "Common/assbin_chunks.h"
  50. #include <assimp/DefaultIOSystem.h>
  51. #include <code/Assbin/AssbinFileWriter.h>
  52. #include <memory>
  53. FILE* out = NULL;
  54. bool shortened = false;
  55. // -----------------------------------------------------------------------------------
  56. // Convert a name to standard XML format
  57. void ConvertName(aiString& out, const aiString& in)
  58. {
  59. out.length = 0;
  60. for (unsigned int i = 0; i < in.length; ++i) {
  61. switch (in.data[i]) {
  62. case '<':
  63. out.Append("&lt;");break;
  64. case '>':
  65. out.Append("&gt;");break;
  66. case '&':
  67. out.Append("&amp;");break;
  68. case '\"':
  69. out.Append("&quot;");break;
  70. case '\'':
  71. out.Append("&apos;");break;
  72. default:
  73. out.data[out.length++] = in.data[i];
  74. }
  75. }
  76. out.data[out.length] = 0;
  77. }
  78. // -----------------------------------------------------------------------------------
  79. // Write a single node as text dump
  80. void WriteNode(const aiNode* node, FILE* out, unsigned int depth)
  81. {
  82. char prefix[512];
  83. for (unsigned int i = 0; i < depth;++i)
  84. prefix[i] = '\t';
  85. prefix[depth] = '\0';
  86. const aiMatrix4x4& m = node->mTransformation;
  87. aiString name;
  88. ConvertName(name,node->mName);
  89. fprintf(out,"%s<Node name=\"%s\"> \n"
  90. "%s\t<Matrix4> \n"
  91. "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
  92. "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
  93. "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
  94. "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
  95. "%s\t</Matrix4> \n",
  96. prefix,name.data,prefix,
  97. prefix,m.a1,m.a2,m.a3,m.a4,
  98. prefix,m.b1,m.b2,m.b3,m.b4,
  99. prefix,m.c1,m.c2,m.c3,m.c4,
  100. prefix,m.d1,m.d2,m.d3,m.d4,prefix);
  101. if (node->mNumMeshes) {
  102. fprintf(out, "%s\t<MeshRefs num=\"%u\">\n%s\t",
  103. prefix,node->mNumMeshes,prefix);
  104. for (unsigned int i = 0; i < node->mNumMeshes;++i) {
  105. fprintf(out,"%u ",node->mMeshes[i]);
  106. }
  107. fprintf(out,"\n%s\t</MeshRefs>\n",prefix);
  108. }
  109. if (node->mNumChildren) {
  110. fprintf(out,"%s\t<NodeList num=\"%u\">\n",
  111. prefix,node->mNumChildren);
  112. for (unsigned int i = 0; i < node->mNumChildren;++i) {
  113. WriteNode(node->mChildren[i],out,depth+2);
  114. }
  115. fprintf(out,"%s\t</NodeList>\n",prefix);
  116. }
  117. fprintf(out,"%s</Node>\n",prefix);
  118. }
  119. // -------------------------------------------------------------------------------
  120. const char* TextureTypeToString(aiTextureType in)
  121. {
  122. switch (in)
  123. {
  124. case aiTextureType_NONE:
  125. return "n/a";
  126. case aiTextureType_DIFFUSE:
  127. return "Diffuse";
  128. case aiTextureType_SPECULAR:
  129. return "Specular";
  130. case aiTextureType_AMBIENT:
  131. return "Ambient";
  132. case aiTextureType_EMISSIVE:
  133. return "Emissive";
  134. case aiTextureType_OPACITY:
  135. return "Opacity";
  136. case aiTextureType_NORMALS:
  137. return "Normals";
  138. case aiTextureType_HEIGHT:
  139. return "Height";
  140. case aiTextureType_SHININESS:
  141. return "Shininess";
  142. case aiTextureType_DISPLACEMENT:
  143. return "Displacement";
  144. case aiTextureType_LIGHTMAP:
  145. return "Lightmap";
  146. case aiTextureType_REFLECTION:
  147. return "Reflection";
  148. case aiTextureType_UNKNOWN:
  149. return "Unknown";
  150. default:
  151. break;
  152. }
  153. ai_assert(false);
  154. return "BUG";
  155. }
  156. // -----------------------------------------------------------------------------------
  157. // Some chuncks of text will need to be encoded for XML
  158. // http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
  159. static std::string encodeXML(const std::string& data) {
  160. std::string buffer;
  161. buffer.reserve(data.size());
  162. for(size_t pos = 0; pos != data.size(); ++pos) {
  163. switch(data[pos]) {
  164. case '&': buffer.append("&amp;"); break;
  165. case '\"': buffer.append("&quot;"); break;
  166. case '\'': buffer.append("&apos;"); break;
  167. case '<': buffer.append("&lt;"); break;
  168. case '>': buffer.append("&gt;"); break;
  169. default: buffer.append(&data[pos], 1); break;
  170. }
  171. }
  172. return buffer;
  173. }
  174. // -----------------------------------------------------------------------------------
  175. // Write a text model dump
  176. void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened)
  177. {
  178. time_t tt = ::time(NULL);
  179. #if _WIN32
  180. tm* p = gmtime(&tt);
  181. #else
  182. struct tm now;
  183. tm* p = gmtime_r(&tt, &now);
  184. #endif
  185. ai_assert(nullptr != p);
  186. std::string c = cmd;
  187. std::string::size_type s;
  188. // https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632
  189. // -- not allowed in XML comments
  190. while((s = c.find("--")) != std::string::npos) {
  191. c[s] = '?';
  192. }
  193. aiString name;
  194. // write header
  195. fprintf(out,
  196. "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
  197. "<ASSIMP format_id=\"1\">\n\n"
  198. "<!-- XML Model dump produced by assimp dump\n"
  199. " Library version: %u.%u.%u\n"
  200. " Source: %s\n"
  201. " Command line: %s\n"
  202. " %s\n"
  203. "-->"
  204. " \n\n"
  205. "<Scene flags=\"%u\" postprocessing=\"%i\">\n",
  206. aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),src,c.c_str(),asctime(p),
  207. scene->mFlags,
  208. 0 /*globalImporter->GetEffectivePostProcessing()*/);
  209. // write the node graph
  210. WriteNode(scene->mRootNode, out, 0);
  211. #if 0
  212. // write cameras
  213. for (unsigned int i = 0; i < scene->mNumCameras;++i) {
  214. aiCamera* cam = scene->mCameras[i];
  215. ConvertName(name,cam->mName);
  216. // camera header
  217. fprintf(out,"\t<Camera parent=\"%s\">\n"
  218. "\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n"
  219. "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n"
  220. "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
  221. "\t\t<Float name=\"fov\" > %f </Float>\n"
  222. "\t\t<Float name=\"aspect\" > %f </Float>\n"
  223. "\t\t<Float name=\"near_clip\" > %f </Float>\n"
  224. "\t\t<Float name=\"far_clip\" > %f </Float>\n"
  225. "\t</Camera>\n",
  226. name.data,
  227. cam->mUp.x,cam->mUp.y,cam->mUp.z,
  228. cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
  229. cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
  230. cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
  231. }
  232. // write lights
  233. for (unsigned int i = 0; i < scene->mNumLights;++i) {
  234. aiLight* l = scene->mLights[i];
  235. ConvertName(name,l->mName);
  236. // light header
  237. fprintf(out,"\t<Light parent=\"%s\"> type=\"%s\"\n"
  238. "\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n"
  239. "\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n"
  240. "\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n",
  241. name.data,
  242. (l->mType == aiLightSource_DIRECTIONAL ? "directional" :
  243. (l->mType == aiLightSource_POINT ? "point" : "spot" )),
  244. l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
  245. l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
  246. l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
  247. if (l->mType != aiLightSource_DIRECTIONAL) {
  248. fprintf(out,
  249. "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
  250. "\t\t<Float name=\"atten_cst\" > %f </Float>\n"
  251. "\t\t<Float name=\"atten_lin\" > %f </Float>\n"
  252. "\t\t<Float name=\"atten_sqr\" > %f </Float>\n",
  253. l->mPosition.x,l->mPosition.y,l->mPosition.z,
  254. l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
  255. }
  256. if (l->mType != aiLightSource_POINT) {
  257. fprintf(out,
  258. "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n",
  259. l->mDirection.x,l->mDirection.y,l->mDirection.z);
  260. }
  261. if (l->mType == aiLightSource_SPOT) {
  262. fprintf(out,
  263. "\t\t<Float name=\"cone_out\" > %f </Float>\n"
  264. "\t\t<Float name=\"cone_inn\" > %f </Float>\n",
  265. l->mAngleOuterCone,l->mAngleInnerCone);
  266. }
  267. fprintf(out,"\t</Light>\n");
  268. }
  269. #endif
  270. // write textures
  271. if (scene->mNumTextures) {
  272. fprintf(out,"<TextureList num=\"%u\">\n",scene->mNumTextures);
  273. for (unsigned int i = 0; i < scene->mNumTextures;++i) {
  274. aiTexture* tex = scene->mTextures[i];
  275. bool compressed = (tex->mHeight == 0);
  276. // mesh header
  277. fprintf(out,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n",
  278. (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight),
  279. (compressed ? "true" : "false"));
  280. if (compressed) {
  281. fprintf(out,"\t\t<Data length=\"%u\"> \n",tex->mWidth);
  282. if (!shortened) {
  283. for (unsigned int n = 0; n < tex->mWidth;++n) {
  284. fprintf(out,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]);
  285. if (n && !(n % 50)) {
  286. fprintf(out,"\n");
  287. }
  288. }
  289. }
  290. }
  291. else if (!shortened){
  292. fprintf(out,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4);
  293. // const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1;
  294. for (unsigned int y = 0; y < tex->mHeight;++y) {
  295. for (unsigned int x = 0; x < tex->mWidth;++x) {
  296. aiTexel* tx = tex->pcData + y*tex->mWidth+x;
  297. unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a;
  298. fprintf(out,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
  299. // group by four for readibility
  300. if (0 == (x+y*tex->mWidth) % 4)
  301. fprintf(out,"\n");
  302. }
  303. }
  304. }
  305. fprintf(out,"\t\t</Data>\n\t</Texture>\n");
  306. }
  307. fprintf(out,"</TextureList>\n");
  308. }
  309. // write materials
  310. if (scene->mNumMaterials) {
  311. fprintf(out,"<MaterialList num=\"%u\">\n",scene->mNumMaterials);
  312. for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
  313. const aiMaterial* mat = scene->mMaterials[i];
  314. fprintf(out,"\t<Material>\n");
  315. fprintf(out,"\t\t<MatPropertyList num=\"%u\">\n",mat->mNumProperties);
  316. for (unsigned int n = 0; n < mat->mNumProperties;++n) {
  317. const aiMaterialProperty* prop = mat->mProperties[n];
  318. const char* sz = "";
  319. if (prop->mType == aiPTI_Float) {
  320. sz = "float";
  321. }
  322. else if (prop->mType == aiPTI_Integer) {
  323. sz = "integer";
  324. }
  325. else if (prop->mType == aiPTI_String) {
  326. sz = "string";
  327. }
  328. else if (prop->mType == aiPTI_Buffer) {
  329. sz = "binary_buffer";
  330. }
  331. fprintf(out,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%u\"",
  332. prop->mKey.data, sz,
  333. ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex);
  334. if (prop->mType == aiPTI_Float) {
  335. fprintf(out," size=\"%i\">\n\t\t\t\t",
  336. static_cast<int>(prop->mDataLength/sizeof(float)));
  337. for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
  338. fprintf(out,"%f ",*((float*)(prop->mData+p*sizeof(float))));
  339. }
  340. }
  341. else if (prop->mType == aiPTI_Integer) {
  342. fprintf(out," size=\"%i\">\n\t\t\t\t",
  343. static_cast<int>(prop->mDataLength/sizeof(int)));
  344. for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
  345. fprintf(out,"%i ",*((int*)(prop->mData+p*sizeof(int))));
  346. }
  347. }
  348. else if (prop->mType == aiPTI_Buffer) {
  349. fprintf(out," size=\"%i\">\n\t\t\t\t",
  350. static_cast<int>(prop->mDataLength));
  351. for (unsigned int p = 0; p < prop->mDataLength;++p) {
  352. fprintf(out,"%2x ",prop->mData[p]);
  353. if (p && 0 == p%30) {
  354. fprintf(out,"\n\t\t\t\t");
  355. }
  356. }
  357. }
  358. else if (prop->mType == aiPTI_String) {
  359. fprintf(out,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */);
  360. }
  361. fprintf(out,"\n\t\t\t</MatProperty>\n");
  362. }
  363. fprintf(out,"\t\t</MatPropertyList>\n");
  364. fprintf(out,"\t</Material>\n");
  365. }
  366. fprintf(out,"</MaterialList>\n");
  367. }
  368. // write animations
  369. if (scene->mNumAnimations) {
  370. fprintf(out,"<AnimationList num=\"%u\">\n",scene->mNumAnimations);
  371. for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
  372. aiAnimation* anim = scene->mAnimations[i];
  373. // anim header
  374. ConvertName(name,anim->mName);
  375. fprintf(out,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n",
  376. name.data, anim->mDuration, anim->mTicksPerSecond);
  377. // write bone animation channels
  378. if (anim->mNumChannels) {
  379. fprintf(out,"\t\t<NodeAnimList num=\"%u\">\n",anim->mNumChannels);
  380. for (unsigned int n = 0; n < anim->mNumChannels;++n) {
  381. aiNodeAnim* nd = anim->mChannels[n];
  382. // node anim header
  383. ConvertName(name,nd->mNodeName);
  384. fprintf(out,"\t\t\t<NodeAnim node=\"%s\">\n",name.data);
  385. if (!shortened) {
  386. // write position keys
  387. if (nd->mNumPositionKeys) {
  388. fprintf(out,"\t\t\t\t<PositionKeyList num=\"%u\">\n",nd->mNumPositionKeys);
  389. for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) {
  390. aiVectorKey* vc = nd->mPositionKeys+a;
  391. fprintf(out,"\t\t\t\t\t<PositionKey time=\"%e\">\n"
  392. "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n",
  393. vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
  394. }
  395. fprintf(out,"\t\t\t\t</PositionKeyList>\n");
  396. }
  397. // write scaling keys
  398. if (nd->mNumScalingKeys) {
  399. fprintf(out,"\t\t\t\t<ScalingKeyList num=\"%u\">\n",nd->mNumScalingKeys);
  400. for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) {
  401. aiVectorKey* vc = nd->mScalingKeys+a;
  402. fprintf(out,"\t\t\t\t\t<ScalingKey time=\"%e\">\n"
  403. "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n",
  404. vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
  405. }
  406. fprintf(out,"\t\t\t\t</ScalingKeyList>\n");
  407. }
  408. // write rotation keys
  409. if (nd->mNumRotationKeys) {
  410. fprintf(out,"\t\t\t\t<RotationKeyList num=\"%u\">\n",nd->mNumRotationKeys);
  411. for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
  412. aiQuatKey* vc = nd->mRotationKeys+a;
  413. fprintf(out,"\t\t\t\t\t<RotationKey time=\"%e\">\n"
  414. "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n",
  415. vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w);
  416. }
  417. fprintf(out,"\t\t\t\t</RotationKeyList>\n");
  418. }
  419. }
  420. fprintf(out,"\t\t\t</NodeAnim>\n");
  421. }
  422. fprintf(out,"\t\t</NodeAnimList>\n");
  423. }
  424. fprintf(out,"\t</Animation>\n");
  425. }
  426. fprintf(out,"</AnimationList>\n");
  427. }
  428. // write meshes
  429. if (scene->mNumMeshes) {
  430. fprintf(out,"<MeshList num=\"%u\">\n",scene->mNumMeshes);
  431. for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
  432. aiMesh* mesh = scene->mMeshes[i];
  433. // const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1;
  434. // mesh header
  435. fprintf(out,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%u\">\n",
  436. (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""),
  437. (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""),
  438. (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""),
  439. (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""),
  440. mesh->mMaterialIndex);
  441. // bones
  442. if (mesh->mNumBones) {
  443. fprintf(out,"\t\t<BoneList num=\"%u\">\n",mesh->mNumBones);
  444. for (unsigned int n = 0; n < mesh->mNumBones;++n) {
  445. aiBone* bone = mesh->mBones[n];
  446. ConvertName(name,bone->mName);
  447. // bone header
  448. fprintf(out,"\t\t\t<Bone name=\"%s\">\n"
  449. "\t\t\t\t<Matrix4> \n"
  450. "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
  451. "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
  452. "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
  453. "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
  454. "\t\t\t\t</Matrix4> \n",
  455. name.data,
  456. bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4,
  457. bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4,
  458. bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4,
  459. bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4);
  460. if (!shortened && bone->mNumWeights) {
  461. fprintf(out,"\t\t\t\t<WeightList num=\"%u\">\n",bone->mNumWeights);
  462. // bone weights
  463. for (unsigned int a = 0; a < bone->mNumWeights;++a) {
  464. aiVertexWeight* wght = bone->mWeights+a;
  465. fprintf(out,"\t\t\t\t\t<Weight index=\"%u\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n",
  466. wght->mVertexId,wght->mWeight);
  467. }
  468. fprintf(out,"\t\t\t\t</WeightList>\n");
  469. }
  470. fprintf(out,"\t\t\t</Bone>\n");
  471. }
  472. fprintf(out,"\t\t</BoneList>\n");
  473. }
  474. // faces
  475. if (!shortened && mesh->mNumFaces) {
  476. fprintf(out,"\t\t<FaceList num=\"%u\">\n",mesh->mNumFaces);
  477. for (unsigned int n = 0; n < mesh->mNumFaces; ++n) {
  478. aiFace& f = mesh->mFaces[n];
  479. fprintf(out,"\t\t\t<Face num=\"%u\">\n"
  480. "\t\t\t\t",f.mNumIndices);
  481. for (unsigned int j = 0; j < f.mNumIndices;++j)
  482. fprintf(out,"%u ",f.mIndices[j]);
  483. fprintf(out,"\n\t\t\t</Face>\n");
  484. }
  485. fprintf(out,"\t\t</FaceList>\n");
  486. }
  487. // vertex positions
  488. if (mesh->HasPositions()) {
  489. fprintf(out,"\t\t<Positions num=\"%u\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
  490. if (!shortened) {
  491. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  492. fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
  493. mesh->mVertices[n].x,
  494. mesh->mVertices[n].y,
  495. mesh->mVertices[n].z);
  496. }
  497. }
  498. fprintf(out,"\t\t</Positions>\n");
  499. }
  500. // vertex normals
  501. if (mesh->HasNormals()) {
  502. fprintf(out,"\t\t<Normals num=\"%u\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
  503. if (!shortened) {
  504. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  505. fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
  506. mesh->mNormals[n].x,
  507. mesh->mNormals[n].y,
  508. mesh->mNormals[n].z);
  509. }
  510. }
  511. else {
  512. }
  513. fprintf(out,"\t\t</Normals>\n");
  514. }
  515. // vertex tangents and bitangents
  516. if (mesh->HasTangentsAndBitangents()) {
  517. fprintf(out,"\t\t<Tangents num=\"%u\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
  518. if (!shortened) {
  519. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  520. fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
  521. mesh->mTangents[n].x,
  522. mesh->mTangents[n].y,
  523. mesh->mTangents[n].z);
  524. }
  525. }
  526. fprintf(out,"\t\t</Tangents>\n");
  527. fprintf(out,"\t\t<Bitangents num=\"%u\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
  528. if (!shortened) {
  529. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  530. fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
  531. mesh->mBitangents[n].x,
  532. mesh->mBitangents[n].y,
  533. mesh->mBitangents[n].z);
  534. }
  535. }
  536. fprintf(out,"\t\t</Bitangents>\n");
  537. }
  538. // texture coordinates
  539. for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
  540. if (!mesh->mTextureCoords[a])
  541. break;
  542. fprintf(out,"\t\t<TextureCoords num=\"%u\" set=\"%u\" num_components=\"%u\"> \n",mesh->mNumVertices,
  543. a,mesh->mNumUVComponents[a]);
  544. if (!shortened) {
  545. if (mesh->mNumUVComponents[a] == 3) {
  546. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  547. fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
  548. mesh->mTextureCoords[a][n].x,
  549. mesh->mTextureCoords[a][n].y,
  550. mesh->mTextureCoords[a][n].z);
  551. }
  552. }
  553. else {
  554. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  555. fprintf(out,"\t\t%0 8f %0 8f\n",
  556. mesh->mTextureCoords[a][n].x,
  557. mesh->mTextureCoords[a][n].y);
  558. }
  559. }
  560. }
  561. fprintf(out,"\t\t</TextureCoords>\n");
  562. }
  563. // vertex colors
  564. for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
  565. if (!mesh->mColors[a])
  566. break;
  567. fprintf(out,"\t\t<Colors num=\"%u\" set=\"%u\" num_components=\"4\"> \n",mesh->mNumVertices,a);
  568. if (!shortened) {
  569. for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
  570. fprintf(out,"\t\t%0 8f %0 8f %0 8f %0 8f\n",
  571. mesh->mColors[a][n].r,
  572. mesh->mColors[a][n].g,
  573. mesh->mColors[a][n].b,
  574. mesh->mColors[a][n].a);
  575. }
  576. }
  577. fprintf(out,"\t\t</Colors>\n");
  578. }
  579. fprintf(out,"\t</Mesh>\n");
  580. }
  581. fprintf(out,"</MeshList>\n");
  582. }
  583. fprintf(out,"</Scene>\n</ASSIMP>");
  584. }
  585. // -----------------------------------------------------------------------------------
  586. int Assimp_Dump (const char* const* params, unsigned int num)
  587. {
  588. const char* fail = "assimp dump: Invalid number of arguments. "
  589. "See \'assimp dump --help\'\r\n";
  590. // --help
  591. if (!strcmp( params[0], "-h") || !strcmp( params[0], "--help") || !strcmp( params[0], "-?") ) {
  592. printf("%s",AICMD_MSG_DUMP_HELP);
  593. return AssimpCmdError::Success;
  594. }
  595. // asssimp dump in out [options]
  596. if (num < 1) {
  597. printf("%s", fail);
  598. return AssimpCmdError::InvalidNumberOfArguments;
  599. }
  600. std::string in = std::string(params[0]);
  601. std::string out = (num > 1 ? std::string(params[1]) : std::string("-"));
  602. // store full command line
  603. std::string cmd;
  604. for (unsigned int i = (out[0] == '-' ? 1 : 2); i < num;++i) {
  605. if (!params[i])continue;
  606. cmd.append(params[i]);
  607. cmd.append(" ");
  608. }
  609. // get import flags
  610. ImportData import;
  611. ProcessStandardArguments(import,params+1,num-1);
  612. bool binary = false, shortened = false,compressed=false;
  613. // process other flags
  614. for (unsigned int i = 1; i < num;++i) {
  615. if (!params[i])continue;
  616. if (!strcmp( params[i], "-b") || !strcmp( params[i], "--binary")) {
  617. binary = true;
  618. }
  619. else if (!strcmp( params[i], "-s") || !strcmp( params[i], "--short")) {
  620. shortened = true;
  621. }
  622. else if (!strcmp( params[i], "-z") || !strcmp( params[i], "--compressed")) {
  623. compressed = true;
  624. }
  625. #if 0
  626. else if (i > 2 || params[i][0] == '-') {
  627. ::printf("Unknown parameter: %s\n",params[i]);
  628. return 10;
  629. }
  630. #endif
  631. }
  632. if (out[0] == '-') {
  633. // take file name from input file
  634. std::string::size_type s = in.find_last_of('.');
  635. if (s == std::string::npos) {
  636. s = in.length();
  637. }
  638. out = in.substr(0,s);
  639. out.append((binary ? ".assbin" : ".assxml"));
  640. if (shortened && binary) {
  641. out.append(".regress");
  642. }
  643. }
  644. // import the main model
  645. const aiScene* scene = ImportModel(import,in);
  646. if (!scene) {
  647. printf("assimp dump: Unable to load input file %s\n",in.c_str());
  648. return AssimpCmdError::FailedToLoadInputFile;
  649. }
  650. if (binary) {
  651. try {
  652. std::unique_ptr<IOSystem> pIOSystem(new DefaultIOSystem());
  653. DumpSceneToAssbin(out.c_str(), cmd.c_str(), pIOSystem.get(),
  654. scene, shortened, compressed);
  655. }
  656. catch (const std::exception& e) {
  657. printf("%s", ("assimp dump: " + std::string(e.what())).c_str());
  658. return AssimpCmdError::ExceptionWasRaised;
  659. }
  660. catch (...) {
  661. printf("assimp dump: An unknown exception occured.\n");
  662. return AssimpCmdError::ExceptionWasRaised;
  663. }
  664. }
  665. else {
  666. FILE* o = ::fopen(out.c_str(), "wt");
  667. if (!o) {
  668. printf("assimp dump: Unable to open output file %s\n",out.c_str());
  669. return AssimpCmdError::FailedToOpenOutputFile;
  670. }
  671. WriteDump (scene,o,in.c_str(),cmd.c_str(),shortened);
  672. fclose(o);
  673. }
  674. printf("assimp dump: Wrote output dump %s\n",out.c_str());
  675. return AssimpCmdError::Success;
  676. }