OgreImporter.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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. using namespace boost;
  8. #include "OgreImporter.h"
  9. #include "irrXMLWrapper.h"
  10. namespace Assimp
  11. {
  12. namespace Ogre
  13. {
  14. bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
  15. {
  16. if(!checkSig)//Check File Extension
  17. {
  18. std::string extension("mesh.xml");
  19. int l=extension.length();
  20. return pFile.substr(pFile.length()-l, l)==extension;
  21. }
  22. else//Check file Header
  23. {
  24. const char* tokens[] = {"<mesh>"};
  25. return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
  26. }
  27. }
  28. void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
  29. {
  30. m_CurrentFilename=pFile;
  31. m_CurrentIOHandler=pIOHandler;
  32. m_CurrentScene=pScene;
  33. //Open the File:
  34. boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
  35. if( file.get() == NULL)
  36. throw new ImportErrorException("Failed to open file "+pFile+".");
  37. //Read the Mesh File:
  38. boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
  39. XmlReader* MeshFile = irr::io::createIrrXMLReader(mIOWrapper.get());
  40. if(!MeshFile)//parse the xml file
  41. throw new ImportErrorException("Failed to create XML Reader for "+pFile);
  42. DefaultLogger::get()->info("Mesh File opened");
  43. //Read root Node:
  44. if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="mesh"))
  45. {
  46. throw new ImportErrorException("Root Node is not <mesh>! "+pFile+" "+MeshFile->getNodeName());
  47. }
  48. //Go to the submeshs:
  49. if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="submeshes"))
  50. {
  51. throw new ImportErrorException("No <submeshes> node in <mesh> node! "+pFile);
  52. }
  53. //-------------------Read all submeshs:-----------------------
  54. XmlRead(MeshFile);
  55. while(string(MeshFile->getNodeName())=="submesh")//read the index values (the faces):
  56. {
  57. SubMesh NewSubMesh;
  58. NewSubMesh.MaterialName=GetAttribute<string>(MeshFile, "material");
  59. DefaultLogger::get()->info("Loading Submehs with Material: "+NewSubMesh.MaterialName);
  60. ReadSubMesh(NewSubMesh, MeshFile);
  61. }
  62. //_______________________________________________________________-
  63. //-----------------Read the skeleton:----------------------
  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. }
  72. void OgreImporter::GetExtensionList(std::string &append)
  73. {
  74. append+="*.mesh.xml";
  75. }
  76. void OgreImporter::SetupProperties(const Importer* pImp)
  77. {
  78. m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
  79. }
  80. void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
  81. {
  82. vector<Face> FaceList;
  83. vector<aiVector3D> Positions; bool HasPositions=false;
  84. vector<aiVector3D> Normals; bool HasNormals=false;
  85. vector<aiVector3D> Uvs; unsigned int NumUvs=0;//nearly always 2d, but assimp has always 3d texcoords
  86. XmlRead(Reader);
  87. //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work korrekt, wenn the order
  88. //of faces and geometry changed, and not if we habe more than one of one
  89. while(Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry")
  90. {
  91. if(string(Reader->getNodeName())=="faces")//Read the face list
  92. {
  93. //some info logging:
  94. unsigned int NumFaces=GetAttribute<int>(Reader, "count");
  95. stringstream ss; ss <<"Submesh has " << NumFaces << " Faces.";
  96. DefaultLogger::get()->info(ss.str());
  97. while(XmlRead(Reader) && Reader->getNodeName()==string("face"))
  98. {
  99. Face NewFace;
  100. NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1");
  101. NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2");
  102. NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3");
  103. if(Reader->getAttributeValue("v4"))//this should be supported in the future
  104. {
  105. throw new ImportErrorException("Submesh has quads, only traingles are supported!");
  106. }
  107. FaceList.push_back(NewFace);
  108. }
  109. }
  110. else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
  111. {
  112. //some info logging:
  113. unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
  114. stringstream ss; ss<<"VertexCount: "<<NumVertices;
  115. DefaultLogger::get()->info(ss.str());
  116. //General Informations about vertices
  117. XmlRead(Reader);
  118. if(!(Reader->getNodeName()==string("vertexbuffer")))
  119. {
  120. throw new ImportErrorException("vertexbuffer node is not first in geometry node!");
  121. }
  122. HasPositions=GetAttribute<bool>(Reader, "positions");
  123. HasNormals=GetAttribute<bool>(Reader, "normals");
  124. NumUvs=GetAttribute<int>(Reader, "texture_coords");
  125. if(NumUvs>1)
  126. throw new ImportErrorException("too many texcoords (just 1 supported!)");
  127. //read all the vertices:
  128. XmlRead(Reader);
  129. while(Reader->getNodeName()==string("vertex"))
  130. {
  131. //read all vertex attributes:
  132. //Position
  133. if(HasPositions)
  134. {
  135. XmlRead(Reader);
  136. aiVector3D NewPos;
  137. NewPos.x=GetAttribute<float>(Reader, "x");
  138. NewPos.y=GetAttribute<float>(Reader, "y");
  139. NewPos.z=GetAttribute<float>(Reader, "z");
  140. Positions.push_back(NewPos);
  141. }
  142. //Normal
  143. if(HasNormals)
  144. {
  145. XmlRead(Reader);
  146. aiVector3D NewNormal;
  147. NewNormal.x=GetAttribute<float>(Reader, "x");
  148. NewNormal.y=GetAttribute<float>(Reader, "y");
  149. NewNormal.z=GetAttribute<float>(Reader, "z");
  150. Normals.push_back(NewNormal);
  151. }
  152. //Uv:
  153. if(1==NumUvs)
  154. {
  155. XmlRead(Reader);
  156. aiVector3D NewUv;
  157. NewUv.x=GetAttribute<float>(Reader, "u");
  158. NewUv.y=GetAttribute<float>(Reader, "v");
  159. Uvs.push_back(NewUv);
  160. }
  161. XmlRead(Reader);
  162. }
  163. }
  164. }
  165. DefaultLogger::get()->info(str(format("Positionen: %1% Normale: %2% TexCoords: %3%") % Positions.size() % Normals.size() % Uvs.size()));
  166. //Make all Vertexes unique: (this is required by assimp)
  167. vector<Face> UniqueFaceList(FaceList.size());
  168. vector<aiVector3D> UniquePositions(FaceList.size()*3);//*3 because each face consits of 3 vertexes, because we only support triangles^^
  169. vector<aiVector3D> UniqueNormals(FaceList.size()*3);
  170. vector<aiVector3D> UniqueUvs(FaceList.size()*3);
  171. for(unsigned int i=0; i<FaceList.size(); ++i)
  172. {
  173. UniquePositions[3*i+0]=Positions[FaceList[i].VertexIndices[0]];
  174. UniquePositions[3*i+1]=Positions[FaceList[i].VertexIndices[1]];
  175. UniquePositions[3*i+2]=Positions[FaceList[i].VertexIndices[2]];
  176. UniqueNormals[3*i+0]=Normals[FaceList[i].VertexIndices[0]];
  177. UniqueNormals[3*i+1]=Normals[FaceList[i].VertexIndices[1]];
  178. UniqueNormals[3*i+2]=Normals[FaceList[i].VertexIndices[2]];
  179. UniqueUvs[3*i+0]=Uvs[FaceList[i].VertexIndices[0]];
  180. UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
  181. UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
  182. UniqueFaceList[i].VertexIndices[0]=3*i+0;
  183. UniqueFaceList[i].VertexIndices[1]=3*i+1;
  184. UniqueFaceList[i].VertexIndices[2]=3*i+2;
  185. }
  186. //----------------Load the Material:-------------------------------
  187. aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
  188. //_________________________________________________________________
  189. //Mesh is fully loaded, copy it into the aiScene:
  190. if(m_CurrentScene->mNumMeshes!=0)
  191. throw new ImportErrorException("Currently only one mesh per File is allowed!!");
  192. //---------------------Create the aiMesh:-----------------------
  193. aiMesh* NewAiMesh=new aiMesh();
  194. //Positions
  195. NewAiMesh->mVertices=new aiVector3D[UniquePositions.size()];
  196. memcpy(NewAiMesh->mVertices, &UniquePositions[0], UniquePositions.size()*sizeof(aiVector3D));
  197. NewAiMesh->mNumVertices=UniquePositions.size();
  198. //Normals
  199. NewAiMesh->mNormals=new aiVector3D[UniqueNormals.size()];
  200. memcpy(NewAiMesh->mNormals, &UniqueNormals[0], UniqueNormals.size()*sizeof(aiVector3D));
  201. //Uvs
  202. NewAiMesh->mNumUVComponents[0]=2;
  203. //NewAiMesh->mTextureCoords=new aiVector3D*[1];
  204. NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
  205. memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
  206. //Faces
  207. NewAiMesh->mFaces=new aiFace[UniqueFaceList.size()];
  208. for(unsigned int i=0; i<UniqueFaceList.size(); ++i)
  209. {
  210. NewAiMesh->mFaces[i].mNumIndices=3;
  211. NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
  212. NewAiMesh->mFaces[i].mIndices[0]=UniqueFaceList[i].VertexIndices[0];
  213. NewAiMesh->mFaces[i].mIndices[1]=UniqueFaceList[i].VertexIndices[1];
  214. NewAiMesh->mFaces[i].mIndices[2]=UniqueFaceList[i].VertexIndices[2];
  215. }
  216. NewAiMesh->mNumFaces=UniqueFaceList.size();
  217. //Set the Material:
  218. NewAiMesh->mMaterialIndex=0;
  219. if(m_CurrentScene->mMaterials)
  220. throw new ImportErrorException("only 1 material supported at this time!");
  221. m_CurrentScene->mMaterials=new aiMaterial*[1];
  222. m_CurrentScene->mNumMaterials=1;
  223. m_CurrentScene->mMaterials[0]=MeshMat;
  224. //________________________________________________________________
  225. //Attach the mesh to the scene:
  226. m_CurrentScene->mNumMeshes=1;
  227. m_CurrentScene->mMeshes=new aiMesh*;
  228. m_CurrentScene->mMeshes[0]=NewAiMesh;
  229. //stringstream ss; ss <<"Last Node: <" << Reader->getNodeName() << ">";
  230. //throw new ImportErrorException(ss.str());
  231. }
  232. aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
  233. {
  234. MaterialHelper *NewMaterial=new MaterialHelper();
  235. NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);
  236. /*For bettetr understanding of the material parser, here is a material example file:
  237. material Sarg
  238. {
  239. receive_shadows on
  240. technique
  241. {
  242. pass
  243. {
  244. ambient 0.500000 0.500000 0.500000 1.000000
  245. diffuse 0.640000 0.640000 0.640000 1.000000
  246. specular 0.500000 0.500000 0.500000 1.000000 12.500000
  247. emissive 0.000000 0.000000 0.000000 1.000000
  248. texture_unit
  249. {
  250. texture SargTextur.tga
  251. tex_address_mode wrap
  252. filtering linear linear none
  253. }
  254. }
  255. }
  256. }
  257. */
  258. string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material";
  259. DefaultLogger::get()->info(str(format("Trying to load %1%") % MaterialFileName));
  260. //Read the file into memory and put it in a stringstream
  261. stringstream ss;
  262. {// after this block, the temporarly loaded data will be released
  263. IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
  264. if(NULL==MatFilePtr)
  265. {
  266. MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
  267. if(NULL==MatFilePtr)
  268. {
  269. DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!");
  270. return NewMaterial;
  271. }
  272. }
  273. scoped_ptr<IOStream> MaterialFile(MatFilePtr);
  274. vector<char> FileData(MaterialFile->FileSize());
  275. MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
  276. BaseImporter::ConvertToUTF8(FileData);
  277. ss << &FileData[0];
  278. }
  279. string Line;
  280. ss >> Line;
  281. unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another
  282. while(!ss.eof())
  283. {
  284. if(Line=="material")
  285. {
  286. ss >> Line;
  287. if(Line==MaterialName)//Load the next material
  288. {
  289. ss >> Line;
  290. if(Line!="{")
  291. throw new ImportErrorException("empty material!");
  292. while(Line!="}")//read until the end of the material
  293. {
  294. //Proceed to the first technique
  295. ss >> Line;
  296. if(Line=="technique")
  297. {
  298. ss >> Line;
  299. if(Line!="{")
  300. throw new ImportErrorException("empty technique!");
  301. while(Line!="}")//read until the end of the technique
  302. {
  303. ss >> Line;
  304. if(Line=="pass")
  305. {
  306. ss >> Line;
  307. if(Line!="{")
  308. throw new ImportErrorException("empty pass!");
  309. while(Line!="}")//read until the end of the pass
  310. {
  311. ss >> Line;
  312. if(Line=="ambient")
  313. {
  314. //read the ambient light values:
  315. }
  316. else if(Line=="diffuse")
  317. {
  318. }
  319. else if(Line=="specular")
  320. {
  321. }
  322. else if(Line=="emmisive")
  323. {
  324. }
  325. else if(Line=="texture_unit")
  326. {
  327. ss >> Line;
  328. if(Line!="{")
  329. throw new ImportErrorException("empty texture unit!");
  330. while(Line!="}")//read until the end of the texture_unit
  331. {
  332. ss >> Line;
  333. if(Line=="texture")
  334. {
  335. ss >> Line;
  336. NewMaterial->AddProperty(&aiString(Line.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
  337. }
  338. }//end of texture unit
  339. }
  340. }
  341. }
  342. }//end of technique
  343. }
  344. }//end of material
  345. }
  346. else {} //this is the wrong material, proceed the file until we reach the next material
  347. }
  348. ss >> Line;
  349. }
  350. return NewMaterial;
  351. }
  352. }//namespace Ogre
  353. }//namespace Assimp
  354. #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER