OgreImporter.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. #include "AssimpPCH.h"
  2. #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
  3. #include <vector>
  4. #include <sstream>
  5. using namespace std;
  6. #include "boost/format.hpp"
  7. #include "boost/foreach.hpp"
  8. using namespace boost;
  9. #include "OgreImporter.h"
  10. #include "irrXMLWrapper.h"
  11. namespace Assimp
  12. {
  13. namespace Ogre
  14. {
  15. bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
  16. {
  17. if(!checkSig)//Check File Extension
  18. {
  19. std::string extension("mesh.xml");
  20. int l=extension.length();
  21. return pFile.substr(pFile.length()-l, l)==extension;
  22. }
  23. else//Check file Header
  24. {
  25. const char* tokens[] = {"<mesh>"};
  26. return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
  27. }
  28. }
  29. void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
  30. {
  31. m_CurrentFilename=pFile;
  32. m_CurrentIOHandler=pIOHandler;
  33. m_CurrentScene=pScene;
  34. //Open the File:
  35. boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
  36. if( file.get() == NULL)
  37. throw new ImportErrorException("Failed to open file "+pFile+".");
  38. //Read the Mesh File:
  39. boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
  40. XmlReader* MeshFile = irr::io::createIrrXMLReader(mIOWrapper.get());
  41. if(!MeshFile)//parse the xml file
  42. throw new ImportErrorException("Failed to create XML Reader for "+pFile);
  43. DefaultLogger::get()->debug("Mesh File opened");
  44. //Read root Node:
  45. if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="mesh"))
  46. {
  47. throw new ImportErrorException("Root Node is not <mesh>! "+pFile+" "+MeshFile->getNodeName());
  48. }
  49. //Go to the submeshs:
  50. if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="submeshes"))
  51. {
  52. throw new ImportErrorException("No <submeshes> node in <mesh> node! "+pFile);
  53. }
  54. //-------------------Read all submeshs:-----------------------
  55. XmlRead(MeshFile);
  56. while(string(MeshFile->getNodeName())=="submesh")//read the index values (the faces):
  57. {
  58. SubMesh NewSubMesh;
  59. NewSubMesh.MaterialName=GetAttribute<string>(MeshFile, "material");
  60. DefaultLogger::get()->debug("Loading Submehs with Material: "+NewSubMesh.MaterialName);
  61. ReadSubMesh(NewSubMesh, MeshFile);
  62. }
  63. //____________________________________________________________
  64. //-----------------Create the root node-----------------------
  65. pScene->mRootNode=new aiNode("root");
  66. //link the mesh with the root node:
  67. pScene->mRootNode->mMeshes=new unsigned int[1];
  68. pScene->mRootNode->mMeshes[0]=0;
  69. pScene->mRootNode->mNumMeshes=1;
  70. //____________________________________________________________
  71. //----------------Load the skeleton: -------------------------------
  72. if(MeshFile->getNodeName()==string("skeletonlink"))
  73. {
  74. string SkeletonFile=GetAttribute<string>(MeshFile, "name");
  75. LoadSkeleton(SkeletonFile);
  76. }
  77. else
  78. DefaultLogger::get()->warn(MeshFile->getNodeName());
  79. //__________________________________________________________________
  80. }
  81. void OgreImporter::GetExtensionList(std::string &append)
  82. {
  83. append+="*.mesh.xml";
  84. }
  85. void OgreImporter::SetupProperties(const Importer* pImp)
  86. {
  87. m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
  88. }
  89. void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
  90. {
  91. vector<Face> FaceList;
  92. vector<aiVector3D> Positions; bool HasPositions=false;
  93. vector<aiVector3D> Normals; bool HasNormals=false;
  94. vector<aiVector3D> Uvs; unsigned int NumUvs=0;//nearly always 2d, but assimp has always 3d texcoords
  95. vector< vector<Weight> > Weights;
  96. XmlRead(Reader);
  97. //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, wenn the order
  98. //of faces and geometry changed, and not if we habe more than one of one
  99. while(Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry" || Reader->getNodeName()==string("boneassignments"))
  100. {
  101. if(string(Reader->getNodeName())=="faces")//Read the face list
  102. {
  103. //some info logging:
  104. unsigned int NumFaces=GetAttribute<int>(Reader, "count");
  105. stringstream ss; ss <<"Submesh has " << NumFaces << " Faces.";
  106. DefaultLogger::get()->debug(ss.str());
  107. while(XmlRead(Reader) && Reader->getNodeName()==string("face"))
  108. {
  109. Face NewFace;
  110. NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1");
  111. NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2");
  112. NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3");
  113. if(Reader->getAttributeValue("v4"))//this should be supported in the future
  114. {
  115. throw new ImportErrorException("Submesh has quads, only traingles are supported!");
  116. }
  117. FaceList.push_back(NewFace);
  118. }
  119. }//end of faces
  120. else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
  121. {
  122. //some info logging:
  123. unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
  124. stringstream ss; ss<<"VertexCount: "<<NumVertices;
  125. DefaultLogger::get()->debug(ss.str());
  126. //General Informations about vertices
  127. XmlRead(Reader);
  128. if(!(Reader->getNodeName()==string("vertexbuffer")))
  129. {
  130. throw new ImportErrorException("vertexbuffer node is not first in geometry node!");
  131. }
  132. HasPositions=GetAttribute<bool>(Reader, "positions");
  133. HasNormals=GetAttribute<bool>(Reader, "normals");
  134. if(!Reader->getAttributeValue("texture_coords"))//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute
  135. NumUvs=0;
  136. else
  137. NumUvs=GetAttribute<int>(Reader, "texture_coords");
  138. if(NumUvs>1)
  139. throw new ImportErrorException("too many texcoords (just 1 supported!)");
  140. //read all the vertices:
  141. XmlRead(Reader);
  142. while(Reader->getNodeName()==string("vertex"))
  143. {
  144. //read all vertex attributes:
  145. //Position
  146. if(HasPositions)
  147. {
  148. XmlRead(Reader);
  149. aiVector3D NewPos;
  150. NewPos.x=GetAttribute<float>(Reader, "x");
  151. NewPos.y=GetAttribute<float>(Reader, "y");
  152. NewPos.z=GetAttribute<float>(Reader, "z");
  153. Positions.push_back(NewPos);
  154. }
  155. //Normal
  156. if(HasNormals)
  157. {
  158. XmlRead(Reader);
  159. aiVector3D NewNormal;
  160. NewNormal.x=GetAttribute<float>(Reader, "x");
  161. NewNormal.y=GetAttribute<float>(Reader, "y");
  162. NewNormal.z=GetAttribute<float>(Reader, "z");
  163. Normals.push_back(NewNormal);
  164. }
  165. //Uv:
  166. if(1==NumUvs)
  167. {
  168. XmlRead(Reader);
  169. aiVector3D NewUv;
  170. NewUv.x=GetAttribute<float>(Reader, "u");
  171. NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
  172. Uvs.push_back(NewUv);
  173. }
  174. XmlRead(Reader);
  175. }
  176. }//end of "geometry
  177. else if(string(Reader->getNodeName())=="boneassignments")
  178. {
  179. Weights.resize(Positions.size());
  180. while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
  181. {
  182. Weight NewWeight;
  183. unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
  184. NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
  185. NewWeight.Value=GetAttribute<float>(Reader, "weight");
  186. Weights[VertexId].push_back(NewWeight);
  187. //XmlRead(Reader);//Once i had this line, and than i got only every second boneassignment, but my first test models had even boneassignment counts, so i thougt, everything would work. And yes, i HATE irrXML!!!
  188. }
  189. }//end of boneassignments
  190. }
  191. DefaultLogger::get()->debug(str(format("Positionen: %1% Normale: %2% TexCoords: %3%") % Positions.size() % Normals.size() % Uvs.size()));
  192. DefaultLogger::get()->warn(Reader->getNodeName());
  193. //---------------Make all Vertexes unique: (this is required by assimp)-----------------------
  194. vector<Face> UniqueFaceList(FaceList.size());
  195. vector<aiVector3D> UniquePositions(FaceList.size()*3);//*3 because each face consits of 3 vertexes, because we only support triangles^^
  196. vector<aiVector3D> UniqueNormals(FaceList.size()*3);
  197. vector<aiVector3D> UniqueUvs(FaceList.size()*3);
  198. vector< vector<Weight> > UniqueWeights(FaceList.size()*3);
  199. for(unsigned int i=0; i<FaceList.size(); ++i)
  200. {
  201. UniquePositions[3*i+0]=Positions[FaceList[i].VertexIndices[0]];
  202. UniquePositions[3*i+1]=Positions[FaceList[i].VertexIndices[1]];
  203. UniquePositions[3*i+2]=Positions[FaceList[i].VertexIndices[2]];
  204. UniqueNormals[3*i+0]=Normals[FaceList[i].VertexIndices[0]];
  205. UniqueNormals[3*i+1]=Normals[FaceList[i].VertexIndices[1]];
  206. UniqueNormals[3*i+2]=Normals[FaceList[i].VertexIndices[2]];
  207. if(1==NumUvs)
  208. {
  209. UniqueUvs[3*i+0]=Uvs[FaceList[i].VertexIndices[0]];
  210. UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
  211. UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
  212. }
  213. UniqueWeights[3*i+0]=UniqueWeights[FaceList[i].VertexIndices[0]];
  214. UniqueWeights[3*i+1]=UniqueWeights[FaceList[i].VertexIndices[1]];
  215. UniqueWeights[3*i+2]=UniqueWeights[FaceList[i].VertexIndices[2]];
  216. UniqueFaceList[i].VertexIndices[0]=3*i+0;
  217. UniqueFaceList[i].VertexIndices[1]=3*i+1;
  218. UniqueFaceList[i].VertexIndices[2]=3*i+2;
  219. }
  220. //_________________________________________________________________________________________
  221. //----------------Load the Material:-------------------------------
  222. aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
  223. //_________________________________________________________________
  224. //Mesh is fully loaded, copy it into the aiScene:
  225. if(m_CurrentScene->mNumMeshes!=0)
  226. throw new ImportErrorException("Currently only one mesh per File is allowed!!");
  227. //---------------------Create the aiMesh:-----------------------
  228. aiMesh* NewAiMesh=new aiMesh();
  229. //Positions
  230. NewAiMesh->mVertices=new aiVector3D[UniquePositions.size()];
  231. memcpy(NewAiMesh->mVertices, &UniquePositions[0], UniquePositions.size()*sizeof(aiVector3D));
  232. NewAiMesh->mNumVertices=UniquePositions.size();
  233. //Normals
  234. NewAiMesh->mNormals=new aiVector3D[UniqueNormals.size()];
  235. memcpy(NewAiMesh->mNormals, &UniqueNormals[0], UniqueNormals.size()*sizeof(aiVector3D));
  236. //Uvs
  237. if(0!=NumUvs)
  238. {
  239. NewAiMesh->mNumUVComponents[0]=2;
  240. NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
  241. memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
  242. }
  243. //Bones
  244. /*NewAiMesh->mNumBones=UniqueWeights.size();
  245. NewAiMesh->mBones=new aiBone*[UniqueWeights.size()];
  246. for(un*/
  247. //Faces
  248. NewAiMesh->mFaces=new aiFace[UniqueFaceList.size()];
  249. for(unsigned int i=0; i<UniqueFaceList.size(); ++i)
  250. {
  251. NewAiMesh->mFaces[i].mNumIndices=3;
  252. NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
  253. NewAiMesh->mFaces[i].mIndices[0]=UniqueFaceList[i].VertexIndices[0];
  254. NewAiMesh->mFaces[i].mIndices[1]=UniqueFaceList[i].VertexIndices[1];
  255. NewAiMesh->mFaces[i].mIndices[2]=UniqueFaceList[i].VertexIndices[2];
  256. }
  257. NewAiMesh->mNumFaces=UniqueFaceList.size();
  258. //Set the Material:
  259. NewAiMesh->mMaterialIndex=0;
  260. if(m_CurrentScene->mMaterials)
  261. throw new ImportErrorException("only 1 material supported at this time!");
  262. m_CurrentScene->mMaterials=new aiMaterial*[1];
  263. m_CurrentScene->mNumMaterials=1;
  264. m_CurrentScene->mMaterials[0]=MeshMat;
  265. //_____________________________________________________________________________
  266. //Attach the mesh to the scene:
  267. m_CurrentScene->mNumMeshes=1;
  268. m_CurrentScene->mMeshes=new aiMesh*;
  269. m_CurrentScene->mMeshes[0]=NewAiMesh;
  270. }
  271. aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
  272. {
  273. MaterialHelper *NewMaterial=new MaterialHelper();
  274. NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);
  275. /*For bettetr understanding of the material parser, here is a material example file:
  276. material Sarg
  277. {
  278. receive_shadows on
  279. technique
  280. {
  281. pass
  282. {
  283. ambient 0.500000 0.500000 0.500000 1.000000
  284. diffuse 0.640000 0.640000 0.640000 1.000000
  285. specular 0.500000 0.500000 0.500000 1.000000 12.500000
  286. emissive 0.000000 0.000000 0.000000 1.000000
  287. texture_unit
  288. {
  289. texture SargTextur.tga
  290. tex_address_mode wrap
  291. filtering linear linear none
  292. }
  293. }
  294. }
  295. }
  296. */
  297. string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material";
  298. DefaultLogger::get()->info(str(format("Trying to load %1%") % MaterialFileName));
  299. //Read the file into memory and put it in a stringstream
  300. stringstream ss;
  301. {// after this block, the temporarly loaded data will be released
  302. IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
  303. if(NULL==MatFilePtr)
  304. {
  305. MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
  306. if(NULL==MatFilePtr)
  307. {
  308. DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!");
  309. return NewMaterial;
  310. }
  311. }
  312. scoped_ptr<IOStream> MaterialFile(MatFilePtr);
  313. vector<char> FileData(MaterialFile->FileSize());
  314. MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
  315. BaseImporter::ConvertToUTF8(FileData);
  316. ss << &FileData[0];
  317. }
  318. string Line;
  319. ss >> Line;
  320. unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another
  321. while(!ss.eof())
  322. {
  323. if(Line=="material")
  324. {
  325. ss >> Line;
  326. if(Line==MaterialName)//Load the next material
  327. {
  328. ss >> Line;
  329. if(Line!="{")
  330. throw new ImportErrorException("empty material!");
  331. while(Line!="}")//read until the end of the material
  332. {
  333. //Proceed to the first technique
  334. ss >> Line;
  335. if(Line=="technique")
  336. {
  337. ss >> Line;
  338. if(Line!="{")
  339. throw new ImportErrorException("empty technique!");
  340. while(Line!="}")//read until the end of the technique
  341. {
  342. ss >> Line;
  343. if(Line=="pass")
  344. {
  345. ss >> Line;
  346. if(Line!="{")
  347. throw new ImportErrorException("empty pass!");
  348. while(Line!="}")//read until the end of the pass
  349. {
  350. ss >> Line;
  351. if(Line=="ambient")
  352. {
  353. //read the ambient light values:
  354. }
  355. else if(Line=="diffuse")
  356. {
  357. }
  358. else if(Line=="specular")
  359. {
  360. }
  361. else if(Line=="emmisive")
  362. {
  363. }
  364. else if(Line=="texture_unit")
  365. {
  366. ss >> Line;
  367. if(Line!="{")
  368. throw new ImportErrorException("empty texture unit!");
  369. while(Line!="}")//read until the end of the texture_unit
  370. {
  371. ss >> Line;
  372. if(Line=="texture")
  373. {
  374. ss >> Line;
  375. NewMaterial->AddProperty(&aiString(Line.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
  376. }
  377. }//end of texture unit
  378. }
  379. }
  380. }
  381. }//end of technique
  382. }
  383. DefaultLogger::get()->info(Line);
  384. //read informations from a custom material:
  385. if(Line=="set")
  386. {
  387. ss >> Line;
  388. if(Line=="$specular")//todo load this values:
  389. {
  390. }
  391. if(Line=="$diffuse")
  392. {
  393. }
  394. if(Line=="$ambient")
  395. {
  396. }
  397. if(Line=="$colormap")
  398. {
  399. ss >> Line;
  400. NewMaterial->AddProperty(&aiString(Line.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
  401. }
  402. if(Line=="$normalmap")
  403. {
  404. ss >> Line;
  405. NewMaterial->AddProperty(&aiString(Line.c_str()), AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
  406. }
  407. }
  408. }//end of material
  409. }
  410. else {} //this is the wrong material, proceed the file until we reach the next material
  411. }
  412. ss >> Line;
  413. }
  414. return NewMaterial;
  415. }
  416. void OgreImporter::LoadSkeleton(std::string FileName)
  417. {
  418. //most likely the skeleton file will only end with .skeleton
  419. //But this is a xml reader, so we need: .skeleton.xml
  420. FileName+=".xml";
  421. DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName);
  422. //Open the File:
  423. boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName));
  424. if(NULL==File.get())
  425. throw new ImportErrorException("Failed to open skeleton file "+FileName+".");
  426. //Read the Mesh File:
  427. boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
  428. XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
  429. if(!SkeletonFile)
  430. throw new ImportErrorException(string("Failed to create XML Reader for ")+FileName);
  431. //Variables to store the data from the skeleton file:
  432. vector<Bone> Bones;
  433. //Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
  434. XmlRead(SkeletonFile);
  435. if(string("skeleton")!=SkeletonFile->getNodeName())
  436. throw new ImportErrorException("No <skeleton> node in SkeletonFile: "+FileName);
  437. //------------------------------------load bones-----------------------------------------
  438. XmlRead(SkeletonFile);
  439. if(string("bones")!=SkeletonFile->getNodeName())
  440. throw new ImportErrorException("No bones node in skeleton "+FileName);
  441. XmlRead(SkeletonFile);
  442. while(string("bone")==SkeletonFile->getNodeName())
  443. {
  444. //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appera, so what....
  445. //read a new bone:
  446. Bone NewBone;
  447. NewBone.Id=GetAttribute<int>(SkeletonFile, "id");
  448. NewBone.Name=GetAttribute<string>(SkeletonFile, "name");
  449. //load the position:
  450. XmlRead(SkeletonFile);
  451. if(string("position")!=SkeletonFile->getNodeName())
  452. throw new ImportErrorException("Position is not first node in Bone!");
  453. NewBone.Position.x=GetAttribute<float>(SkeletonFile, "x");
  454. NewBone.Position.y=GetAttribute<float>(SkeletonFile, "y");
  455. NewBone.Position.z=GetAttribute<float>(SkeletonFile, "z");
  456. //Rotation:
  457. XmlRead(SkeletonFile);
  458. if(string("rotation")!=SkeletonFile->getNodeName())
  459. throw new ImportErrorException("Rotation is not the second node in Bone!");
  460. NewBone.RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
  461. XmlRead(SkeletonFile);
  462. if(string("axis")!=SkeletonFile->getNodeName())
  463. throw new ImportErrorException("No axis specified for bone rotation!");
  464. NewBone.RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
  465. NewBone.RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
  466. NewBone.RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
  467. //append the newly loaded bone to the bone list
  468. Bones.push_back(NewBone);
  469. //Proceed to the next bone:
  470. XmlRead(SkeletonFile);
  471. }
  472. //The bones in the file a not neccesarly ordered by there id's so we do it now:
  473. sort(Bones.begin(), Bones.end());
  474. //now the id of each bone should be equal to its position in the vector:
  475. //so we do a simple check:
  476. {
  477. bool IdsOk=true;
  478. for(int i=0; i<static_cast<signed int>(Bones.size()); ++i)//i is signed, because all Id's are also signed!
  479. {
  480. if(Bones[i].Id!=i)
  481. IdsOk=false;
  482. }
  483. if(!IdsOk)
  484. throw new ImportErrorException("Bone Ids are not valid!"+FileName);
  485. }
  486. DefaultLogger::get()->debug(str(format("Number of bones: %1%") % Bones.size()));
  487. //________________________________________________________________________________
  488. //----------------------------load bonehierarchy--------------------------------
  489. if(string("bonehierarchy")!=SkeletonFile->getNodeName())
  490. throw new ImportErrorException("no bonehierarchy node in "+FileName);
  491. DefaultLogger::get()->debug("loading bonehierarchy...");
  492. XmlRead(SkeletonFile);
  493. while(string("boneparent")==SkeletonFile->getNodeName())
  494. {
  495. string Child, Parent;
  496. Child=GetAttribute<string>(SkeletonFile, "bone");
  497. Parent=GetAttribute<string>(SkeletonFile, "parent");
  498. unsigned int ChildId, ParentId;
  499. ChildId=find(Bones.begin(), Bones.end(), Child)->Id;
  500. ParentId=find(Bones.begin(), Bones.end(), Parent)->Id;
  501. Bones[ChildId].ParentId=ParentId;
  502. Bones[ParentId].Children.push_back(ChildId);
  503. XmlRead(SkeletonFile);//i once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks??
  504. }
  505. //_____________________________________________________________________________
  506. //---------------------------load animations-----------------------------
  507. vector<Animation> Animations;
  508. if(string("animations")==SkeletonFile->getNodeName())//animations are optional values
  509. {
  510. DefaultLogger::get()->debug("Loading Animations");
  511. XmlRead(SkeletonFile);
  512. while(string("animation")==SkeletonFile->getNodeName())
  513. {
  514. Animation NewAnimation;
  515. NewAnimation.Name=GetAttribute<string>(SkeletonFile, "name");
  516. NewAnimation.Length=GetAttribute<float>(SkeletonFile, "length");
  517. //Load all Tracks
  518. XmlRead(SkeletonFile);
  519. if(string("tracks")!=SkeletonFile->getNodeName())
  520. throw new ImportErrorException("no tracks node in animation");
  521. XmlRead(SkeletonFile);
  522. while(string("track")==SkeletonFile->getNodeName())
  523. {
  524. Track NewTrack;
  525. NewTrack.BoneName=GetAttribute<string>(SkeletonFile, "bone");
  526. //Load all keyframes;
  527. XmlRead(SkeletonFile);
  528. if(string("keyframes")!=SkeletonFile->getNodeName())
  529. throw new ImportErrorException("no keyframes node!");
  530. XmlRead(SkeletonFile);
  531. while(string("keyframe")==SkeletonFile->getNodeName())
  532. {
  533. Keyframe NewKeyframe;
  534. NewKeyframe.Time=GetAttribute<float>(SkeletonFile, "time");
  535. //Position:
  536. XmlRead(SkeletonFile);
  537. if(string("translate")!=SkeletonFile->getNodeName())
  538. throw new ImportErrorException("translate node not first in keyframe");
  539. NewKeyframe.Position.x=GetAttribute<float>(SkeletonFile, "x");
  540. NewKeyframe.Position.y=GetAttribute<float>(SkeletonFile, "y");
  541. NewKeyframe.Position.z=GetAttribute<float>(SkeletonFile, "z");
  542. //Rotation:
  543. XmlRead(SkeletonFile);
  544. if(string("rotate")!=SkeletonFile->getNodeName())
  545. throw new ImportErrorException("rotate is not second node in keyframe");
  546. float RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
  547. aiVector3D RotationAxis;
  548. XmlRead(SkeletonFile);
  549. if(string("axis")!=SkeletonFile->getNodeName())
  550. throw new ImportErrorException("No axis for keyframe rotation!");
  551. RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
  552. RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
  553. RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
  554. NewKeyframe.Rotation=aiQuaternion(RotationAxis, RotationAngle);
  555. //Scaling:
  556. XmlRead(SkeletonFile);
  557. if(string("scale")!=SkeletonFile->getNodeName())
  558. throw new ImportErrorException("no scalling key in keyframe!");
  559. NewKeyframe.Scaling.x=GetAttribute<float>(SkeletonFile, "x");
  560. NewKeyframe.Scaling.y=GetAttribute<float>(SkeletonFile, "y");
  561. NewKeyframe.Scaling.z=GetAttribute<float>(SkeletonFile, "z");
  562. NewTrack.Keyframes.push_back(NewKeyframe);
  563. XmlRead(SkeletonFile);
  564. }
  565. NewAnimation.Tracks.push_back(NewTrack);
  566. }
  567. Animations.push_back(NewAnimation);
  568. }
  569. }
  570. //_____________________________________________________________________________
  571. //-----------------skeleton is completly loaded, now but it in the assimp scene:-------------------------------
  572. if(!m_CurrentScene->mRootNode)
  573. throw new ImportErrorException("No root node exists!!");
  574. if(0!=m_CurrentScene->mRootNode->mNumChildren)
  575. throw new ImportErrorException("Root Node already has childnodes!");
  576. //--------------Creatre the assimp bone hierarchy-----------------
  577. DefaultLogger::get()->debug("Root Bones");
  578. vector<aiNode*> RootBoneNodes;
  579. BOOST_FOREACH(Bone theBone, Bones)
  580. {
  581. if(-1==theBone.ParentId) //the bone is a root bone
  582. {
  583. DefaultLogger::get()->debug(theBone.Name);
  584. RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));
  585. }
  586. }
  587. m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size();
  588. m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
  589. memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
  590. //_______________________________________________________________
  591. //-----------------Create the Assimp Animations --------------------
  592. if(Animations.size()>0)//Maybe the model had only a skeleton and no animations. (If it also has no skeleton, this function would'nt have benn called
  593. {
  594. m_CurrentScene->mNumAnimations=Animations.size();
  595. m_CurrentScene->mAnimations=new aiAnimation*[Animations.size()];
  596. for(unsigned int i=0; i<Animations.size(); ++i)//create all animations
  597. {
  598. aiAnimation* NewAnimation=new aiAnimation();
  599. NewAnimation->mName=Animations[i].Name;
  600. NewAnimation->mDuration=Animations[i].Length;
  601. NewAnimation->mTicksPerSecond=0.05f;
  602. //Create all tracks in this animation
  603. NewAnimation->mNumChannels=Animations[i].Tracks.size();
  604. NewAnimation->mChannels=new aiNodeAnim*[Animations[i].Tracks.size()];
  605. for(unsigned int j=0; j<Animations[i].Tracks.size(); ++j)
  606. {
  607. aiNodeAnim* NewNodeAnim=new aiNodeAnim();
  608. NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName;
  609. //Create the keyframe arrays...
  610. unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size();
  611. NewNodeAnim->mNumPositionKeys=KeyframeCount;
  612. NewNodeAnim->mPositionKeys=new aiVectorKey[KeyframeCount];
  613. NewNodeAnim->mNumRotationKeys=KeyframeCount;
  614. NewNodeAnim->mRotationKeys=new aiQuatKey[KeyframeCount];
  615. NewNodeAnim->mNumScalingKeys=KeyframeCount;
  616. NewNodeAnim->mScalingKeys=new aiVectorKey[KeyframeCount];
  617. //...and fill them
  618. for(unsigned int k=0; k<KeyframeCount; ++k)
  619. {
  620. NewNodeAnim->mPositionKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
  621. NewNodeAnim->mPositionKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Position;
  622. NewNodeAnim->mRotationKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
  623. NewNodeAnim->mRotationKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Rotation;
  624. NewNodeAnim->mScalingKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time;
  625. NewNodeAnim->mScalingKeys[k].mValue=Animations[i].Tracks[j].Keyframes[k].Scaling;
  626. }
  627. NewAnimation->mChannels[j]=NewNodeAnim;
  628. }
  629. m_CurrentScene->mAnimations[i]=NewAnimation;
  630. }
  631. }
  632. //__________________________________________________________________
  633. }
  634. aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* ParentNode)
  635. {
  636. //----Create the node for this bone and set its values-----
  637. aiNode* NewNode=new aiNode(Bones[BoneId].Name);
  638. NewNode->mParent=ParentNode;
  639. //create a matrix from the transformation values of the ogre bone
  640. NewNode->mTransformation=aiMatrix4x4::Translation(Bones[BoneId].Position, aiMatrix4x4())
  641. *
  642. aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, aiMatrix4x4())
  643. ;
  644. //__________________________________________________________
  645. //----recursivly create all children Nodes:------
  646. NewNode->mNumChildren=Bones[BoneId].Children.size();
  647. NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
  648. for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
  649. {
  650. NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode);
  651. }
  652. //____________________________________________________
  653. return NewNode;
  654. }
  655. }//namespace Ogre
  656. }//namespace Assimp
  657. #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER