ObjFileImporter.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. #include "ObjFileImporter.h"
  2. #include "ObjFileParser.h"
  3. #include "ObjFileData.h"
  4. #include "../include/IOStream.h"
  5. #include "../include/IOSystem.h"
  6. #include "../include/aiMesh.h"
  7. #include "../include/aiScene.h"
  8. #include "../include/aiAssert.h"
  9. #include "MaterialSystem.h"
  10. #include "../include/DefaultLogger.h"
  11. #include <boost/scoped_ptr.hpp>
  12. #include <boost/format.hpp>
  13. namespace Assimp
  14. {
  15. // ------------------------------------------------------------------------------------------------
  16. using namespace std;
  17. //! Obj-file-format extention
  18. const string ObjFileImporter::OBJ_EXT = "obj";
  19. // ------------------------------------------------------------------------------------------------
  20. // Default constructor
  21. ObjFileImporter::ObjFileImporter() :
  22. m_pRootObject(NULL),
  23. m_strAbsPath("\\")
  24. {
  25. }
  26. // ------------------------------------------------------------------------------------------------
  27. // Destructor
  28. ObjFileImporter::~ObjFileImporter()
  29. {
  30. // Release root object instance
  31. if (NULL != m_pRootObject)
  32. {
  33. delete m_pRootObject;
  34. m_pRootObject = NULL;
  35. }
  36. }
  37. // ------------------------------------------------------------------------------------------------
  38. // Returns true, fi file is an obj file
  39. bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
  40. {
  41. if (pFile.empty())
  42. return false;
  43. string::size_type pos = pFile.find_last_of(".");
  44. if (string::npos == pos)
  45. return false;
  46. const string ext = pFile.substr(pos+1, pFile.size() - pos - 1);
  47. if (ext == OBJ_EXT)
  48. return true;
  49. return false;
  50. }
  51. // ------------------------------------------------------------------------------------------------
  52. // Obj-file import implementation
  53. void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
  54. {
  55. // Read file into memory
  56. const std::string mode = "rb";
  57. boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
  58. if (NULL == file.get())
  59. throw new ImportErrorException( "Failed to open file " + pFile + ".");
  60. // Get the filesize and vaslidate it, throwing an exception when failes
  61. size_t fileSize = file->FileSize();
  62. if( fileSize < 16)
  63. throw new ImportErrorException( "OBJ-file is too small.");
  64. // Allocate buffer and read file into it
  65. m_Buffer.resize( fileSize );
  66. const size_t readsize = file->Read(&m_Buffer.front(), sizeof(char), fileSize);
  67. assert (readsize == fileSize);
  68. //
  69. std::string strDirectory("\\"), strModelName;
  70. std::string::size_type pos = pFile.find_last_of("\\");
  71. if (pos != std::string::npos)
  72. {
  73. strDirectory = pFile.substr(0, pos);
  74. strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
  75. }
  76. else
  77. {
  78. strModelName = pFile;
  79. }
  80. // parse the file into a temporary representation
  81. ObjFileParser parser(m_Buffer, strDirectory, strModelName);
  82. // And create the proper return structures out of it
  83. CreateDataFromImport(parser.GetModel(), pScene);
  84. }
  85. // ------------------------------------------------------------------------------------------------
  86. // Create the data from parsed obj-file
  87. void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene)
  88. {
  89. if (0L == pModel)
  90. return;
  91. // Create the root node of the scene
  92. pScene->mRootNode = new aiNode();
  93. if (!pModel->m_ModelName.empty())
  94. {
  95. // Set the name of the scene
  96. pScene->mRootNode->mName.Set(pModel->m_ModelName);
  97. }
  98. else
  99. {
  100. // This is an error, so break down the application
  101. assert (false);
  102. }
  103. // Create nodes for the whole scene
  104. std::vector<aiMesh*> MeshArray;
  105. for (size_t index = 0; index < pModel->m_Objects.size(); index++)
  106. {
  107. createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
  108. }
  109. // Create mesh pointer buffer for this scene
  110. if (pScene->mNumMeshes > 0)
  111. {
  112. pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
  113. for (size_t index =0; index < MeshArray.size(); index++)
  114. {
  115. pScene->mMeshes [ index ] = MeshArray[ index ];
  116. }
  117. }
  118. // Create all materials
  119. for (size_t index = 0; index < pModel->m_Objects.size(); index++)
  120. {
  121. createMaterial( pModel, pModel->m_Objects[ index ], pScene );
  122. }
  123. }
  124. // ------------------------------------------------------------------------------------------------
  125. // Creates all nodes of the model
  126. aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
  127. aiNode *pParent, aiScene* pScene,
  128. std::vector<aiMesh*> &MeshArray)
  129. {
  130. if (NULL == pData)
  131. return NULL;
  132. // Store older mesh size to be able to computate mesh offsets for new mesh instances
  133. size_t oldMeshSize = MeshArray.size();
  134. aiNode *pNode = new aiNode();
  135. if (pParent != NULL)
  136. this->appendChildToParentNode(pParent, pNode);
  137. aiMesh *pMesh = NULL;
  138. for (unsigned int meshIndex = 0; meshIndex < pModel->m_Meshes.size(); meshIndex++)
  139. {
  140. pMesh = new aiMesh();
  141. MeshArray.push_back( pMesh );
  142. createTopology( pModel, pData, meshIndex, pMesh );
  143. }
  144. // Create all nodes from the subobjects stored in the current object
  145. if (!pData->m_SubObjects.empty())
  146. {
  147. pNode->mNumChildren = (unsigned int)pData->m_SubObjects.size();
  148. pNode->mChildren = new aiNode*[pData->m_SubObjects.size()];
  149. pNode->mNumMeshes = 1;
  150. pNode->mMeshes = new unsigned int[1];
  151. // Loop over all child objects, TODO
  152. /*for (size_t index = 0; index < pData->m_SubObjects.size(); index++)
  153. {
  154. // Create all child nodes
  155. pNode->mChildren[ index ] = createNodes( pModel, pData, pNode, pScene, MeshArray );
  156. for (unsigned int meshIndex = 0; meshIndex < pData->m_SubObjects[ index ]->m_Meshes.size(); meshIndex++)
  157. {
  158. pMesh = new aiMesh();
  159. MeshArray.push_back( pMesh );
  160. createTopology( pModel, pData, meshIndex, pMesh );
  161. }
  162. // Create material of this object
  163. createMaterial(pModel, pData->m_SubObjects[ index ], pScene);
  164. }*/
  165. }
  166. // Set mesh instances into scene- and node-instances
  167. const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
  168. if ( meshSizeDiff > 0 )
  169. {
  170. pNode->mMeshes = new unsigned int[ meshSizeDiff ];
  171. pNode->mNumMeshes = meshSizeDiff;
  172. size_t index = 0;
  173. for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
  174. {
  175. pNode->mMeshes[ index ] = pScene->mNumMeshes;
  176. pScene->mNumMeshes++;
  177. index++;
  178. }
  179. }
  180. return pNode;
  181. }
  182. // ------------------------------------------------------------------------------------------------
  183. // Create topology data
  184. void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
  185. const ObjFile::Object* pData,
  186. unsigned int uiMeshIndex,
  187. aiMesh* pMesh )
  188. {
  189. // Checking preconditions
  190. ai_assert( NULL != pModel );
  191. if (NULL == pData)
  192. return;
  193. // Create faces
  194. ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
  195. pMesh->mNumFaces = (unsigned int) pObjMesh->m_Faces.size();
  196. pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
  197. pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
  198. // Copy all data from all stored meshes
  199. for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
  200. {
  201. aiFace *pFace = &pMesh->mFaces[ index ];
  202. const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
  203. pFace->mNumIndices = (unsigned int) uiNumIndices;
  204. if (pFace->mNumIndices > 0)
  205. {
  206. pFace->mIndices = new unsigned int[ uiNumIndices ];
  207. ObjFile::Face::IndexArray *pIndexArray = pObjMesh->m_Faces[ index ]->m_pVertices;
  208. ai_assert ( NULL != pIndexArray );
  209. for ( size_t a=0; a<pFace->mNumIndices; a++ )
  210. {
  211. pFace->mIndices[ a ] = pIndexArray->at( a );
  212. }
  213. }
  214. else
  215. {
  216. pFace->mIndices = NULL;
  217. }
  218. }
  219. // Create mesh vertices
  220. createVertexArray(pModel, pData, uiMeshIndex, pMesh);
  221. }
  222. // ------------------------------------------------------------------------------------------------
  223. void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
  224. const ObjFile::Object* pCurrentObject,
  225. unsigned int uiMeshIndex,
  226. aiMesh* pMesh)
  227. {
  228. // Checking preconditions
  229. ai_assert ( NULL != pCurrentObject );
  230. // Break, if no faces are stored in object
  231. if (pCurrentObject->m_Faces.empty())
  232. return;
  233. // Get current mesh
  234. ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
  235. if ( NULL == pObjMesh )
  236. return;
  237. // Copy vertices of this mesh instance
  238. pMesh->mNumVertices = (unsigned int) pObjMesh->m_uiNumIndices;
  239. pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
  240. // Allocate buffer for normal vectors
  241. if ( !pModel->m_Normals.empty() )
  242. pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
  243. // Allocate buffer for texture coordinates
  244. if ( !pModel->m_TextureCoord.empty() )
  245. {
  246. for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++)
  247. pMesh->mTextureCoords[ i ] = new aiVector3D[ pModel->m_TextureCoord.size() ];
  248. }
  249. // Copy vertices, normals and textures into aiMesh instance
  250. unsigned int newIndex = 0;
  251. for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
  252. {
  253. // get destination face
  254. aiFace *pDestFace = &pMesh->mFaces[ index ];
  255. // get source face
  256. ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
  257. // Copy all index arrays
  258. for ( size_t vertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
  259. {
  260. unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
  261. assert ( vertex < pModel->m_Vertices.size() );
  262. pMesh->mVertices[ newIndex ] = *pModel->m_Vertices[ vertex ];
  263. if ( !pModel->m_Normals.empty() )
  264. {
  265. const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
  266. assert( normal < pModel->m_Normals.size() );
  267. pMesh->mNormals[ newIndex ] = *pModel->m_Normals[ normal ];
  268. }
  269. if ( !pModel->m_TextureCoord.empty() )
  270. {
  271. const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
  272. ai_assert ( tex < pModel->m_TextureCoord.size() );
  273. for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++)
  274. {
  275. aiVector2D coord2d = *pModel->m_TextureCoord[ tex ];
  276. pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
  277. }
  278. }
  279. assert( pMesh->mNumVertices > newIndex );
  280. pDestFace->mIndices[ vertexIndex ] = newIndex;
  281. newIndex++;
  282. }
  283. }
  284. }
  285. // ------------------------------------------------------------------------------------------------
  286. void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
  287. {
  288. iNumMeshes = 0;
  289. if (rObjects.empty())
  290. return;
  291. iNumMeshes += (unsigned int)rObjects.size();
  292. for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
  293. it != rObjects.end();
  294. ++it)
  295. {
  296. if (!(*it)->m_SubObjects.empty())
  297. {
  298. countObjects((*it)->m_SubObjects, iNumMeshes);
  299. }
  300. }
  301. }
  302. // ------------------------------------------------------------------------------------------------
  303. void ObjFileImporter::createMaterial(const ObjFile::Model* pModel, const ObjFile::Object* pData,
  304. aiScene* pScene)
  305. {
  306. ai_assert (NULL != pScene);
  307. if (NULL == pData)
  308. return;
  309. const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
  310. pScene->mNumMaterials = 0;
  311. if ( pModel->m_MaterialLib.empty() )
  312. return;
  313. pScene->mMaterials = new aiMaterial*[ numMaterials ];
  314. for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
  315. {
  316. Assimp::MaterialHelper* mat = new Assimp::MaterialHelper();
  317. // Store material name
  318. std::map<std::string, ObjFile::Material*>::const_iterator it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
  319. // No material found, use the default material
  320. if ( pModel->m_MaterialMap.end() == it)
  321. continue;
  322. ObjFile::Material *pCurrentMaterial = (*it).second;
  323. mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
  324. mat->AddProperty<int>( &pCurrentMaterial->illumination_model, 1, AI_MATKEY_SHADING_MODEL);
  325. // Adding material colors
  326. mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
  327. mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
  328. mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
  329. mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
  330. // Adding textures
  331. if ( 0 != pCurrentMaterial->texture.length )
  332. mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
  333. // Store material property info in material array in scene
  334. pScene->mMaterials[ pScene->mNumMaterials ] = mat;
  335. pScene->mNumMaterials++;
  336. }
  337. // Test number of created materials.
  338. ai_assert( pScene->mNumMaterials == numMaterials );
  339. }
  340. // ------------------------------------------------------------------------------------------------
  341. // Appends this node to the parent node
  342. void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
  343. {
  344. // Checking preconditions
  345. ai_assert (NULL != pParent);
  346. ai_assert (NULL != pChild);
  347. // Assign parent to child
  348. pChild->mParent = pParent;
  349. size_t sNumChildren = 0;
  350. // If already children was assigned to the parent node, store them in a
  351. std::vector<aiNode*> temp;
  352. if (pParent->mChildren != NULL)
  353. {
  354. sNumChildren = pParent->mNumChildren;
  355. ai_assert (0 != sNumChildren);
  356. for (size_t index = 0; index < pParent->mNumChildren; index++)
  357. {
  358. temp.push_back(pParent->mChildren [ index ] );
  359. }
  360. delete [] pParent->mChildren;
  361. }
  362. // Copy node instances into parent node
  363. pParent->mNumChildren++;
  364. pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
  365. for (size_t index = 0; index < pParent->mNumChildren-1; index++)
  366. {
  367. pParent->mChildren[ index ] = temp [ index ];
  368. }
  369. pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
  370. }
  371. // ------------------------------------------------------------------------------------------------
  372. } // Namespace Assimp