From a85b851442cafbac5ca35642c5e7940a2d2570b0 Mon Sep 17 00:00:00 2001 From: jonathanklein Date: Mon, 19 Apr 2010 17:50:52 +0000 Subject: [PATCH] - Multiple Submeshes are loaded now - In standard materials the colors are now loaded - not excessively tested, but it should work git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@704 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/OgreImporter.cpp | 113 ++++++++++++++++++++++------------ code/OgreImporter.h | 21 +++++-- code/OgreImporterMaterial.cpp | 19 +++++- 3 files changed, 103 insertions(+), 50 deletions(-) diff --git a/code/OgreImporter.cpp b/code/OgreImporter.cpp index 5306cdbe9..5877d1a24 100644 --- a/code/OgreImporter.cpp +++ b/code/OgreImporter.cpp @@ -70,40 +70,35 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass } - //-------------------Read the submesh:----------------------- - SubMesh theSubMesh; + //-------------------Read the submeshs and materials:----------------------- + std::list > SubMeshes; + vector Materials; XmlRead(MeshFile); - if(MeshFile->getNodeName()==string("submesh")) + while(MeshFile->getNodeName()==string("submesh")) { - theSubMesh.MaterialName=GetAttribute(MeshFile, "material"); - DefaultLogger::get()->debug("Loading Submehs with Material: "+theSubMesh.MaterialName); - ReadSubMesh(theSubMesh, MeshFile); - + SubMesh* theSubMesh=new SubMesh(); + theSubMesh->MaterialName=GetAttribute(MeshFile, "material"); + DefaultLogger::get()->debug("Loading Submehs with Material: "+theSubMesh->MaterialName); + ReadSubMesh(*theSubMesh, MeshFile); + + //just a index in a array, we add a mesh in each loop cycle, so we get indicies like 0, 1, 2 ... n; + //so it is important to do this before pushing the mesh in the vector! + theSubMesh->MaterialIndex=SubMeshes.size(); + + SubMeshes.push_back(shared_ptr(theSubMesh)); + //Load the Material: - aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName); + aiMaterial* MeshMat=LoadMaterial(theSubMesh->MaterialName); //Set the Material: - if(m_CurrentScene->mMaterials) - throw DeadlyImportError("only 1 material supported at this time!"); - m_CurrentScene->mMaterials=new aiMaterial*[1]; - m_CurrentScene->mNumMaterials=1; - m_CurrentScene->mMaterials[0]=MeshMat; - theSubMesh.MaterialIndex=0; + Materials.push_back(MeshMat); } - //check for second root node: - if(MeshFile->getNodeName()==string("submesh")) - throw DeadlyImportError("more than one submesh in the file, abording!"); - //____________________________________________________________ + if(SubMeshes.empty()) + throw DeadlyImportError("no submesh loaded!"); + if(SubMeshes.size()!=Materials.size()) + throw DeadlyImportError("materialcount doesn't match mesh count!"); - - //-----------------Create the root node----------------------- - pScene->mRootNode=new aiNode("root"); - - //link the mesh with the root node: - pScene->mRootNode->mMeshes=new unsigned int[1]; - pScene->mRootNode->mMeshes[0]=0; - pScene->mRootNode->mNumMeshes=1; //____________________________________________________________ @@ -122,8 +117,39 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass } //__________________________________________________________________ - CreateAssimpSubMesh(theSubMesh, Bones); + + //----------------- Now fill the Assimp scene --------------------------- + + //put the aiMaterials in the scene: + m_CurrentScene->mMaterials=new aiMaterial*[Materials.size()]; + m_CurrentScene->mNumMaterials=Materials.size(); + for(unsigned int i=0; imMaterials[i]=Materials[i]; + + //create the aiMehs... + vector aiMeshes; + BOOST_FOREACH(shared_ptr theSubMesh, SubMeshes) + { + aiMeshes.push_back(CreateAssimpSubMesh(*theSubMesh, Bones)); + } + //... and put them in the scene: + m_CurrentScene->mNumMeshes=aiMeshes.size(); + m_CurrentScene->mMeshes=new aiMesh*[aiMeshes.size()]; + memcpy(m_CurrentScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size()); + + //Create the root node + m_CurrentScene->mRootNode=new aiNode("root"); + + //link the meshs with the root node: + m_CurrentScene->mRootNode->mMeshes=new unsigned int[SubMeshes.size()]; + m_CurrentScene->mRootNode->mNumMeshes=SubMeshes.size(); + for(unsigned int i=0; imRootNode->mMeshes[i]=i; + + + CreateAssimpSkeleton(Bones, Animations); + //___________________________________________________________ } @@ -331,20 +357,12 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader) } -void OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector& Bones) +aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector& Bones) const { - //Mesh is fully loaded, copy it into the aiScene: - if(m_CurrentScene->mNumMeshes!=0) - throw DeadlyImportError("Currently only one mesh per File is allowed!!"); + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene aiMesh* NewAiMesh=new aiMesh(); - - //Attach the mesh to the scene: - m_CurrentScene->mNumMeshes=1; - m_CurrentScene->mMeshes=new aiMesh*; - m_CurrentScene->mMeshes[0]=NewAiMesh; - - + //Positions NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()]; memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D)); @@ -426,11 +444,16 @@ void OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vectormMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh + + return NewAiMesh; } -void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vector &Animations) +void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vector &Animations) const { + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene + + //most likely the skeleton file will only end with .skeleton //But this is a xml reader, so we need: .skeleton.xml FileName+=".xml"; @@ -500,6 +523,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto } //The bones in the file a not neccesarly ordered by there id's so we do it now: std::sort(Bones.begin(), Bones.end()); + //now the id of each bone should be equal to its position in the vector: //so we do a simple check: { @@ -633,8 +657,10 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector &Bones, vecto } -void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations) +void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations) const { + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene + //-----------------skeleton is completly loaded, now put it in the assimp scene:------------------------------- if(!m_CurrentScene->mRootNode) @@ -657,8 +683,11 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const st m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()]; memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size()); //_______________________________________________________________ +} +void OgreImporter::PutAnimationsInScene(const std::vector &Bones, const std::vector &Animations) +{ //-----------------Create the Assimp Animations -------------------- 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 { @@ -739,8 +768,10 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector &Bones, const st -aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector &Bones, aiNode* ParentNode) +aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector &Bones, aiNode* ParentNode) const { + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene + //----Create the node for this bone and set its values----- aiNode* NewNode=new aiNode(Bones[BoneId].Name); NewNode->mParent=ParentNode; diff --git a/code/OgreImporter.h b/code/OgreImporter.h index 624c8fe07..00724b69d 100644 --- a/code/OgreImporter.h +++ b/code/OgreImporter.h @@ -30,16 +30,25 @@ public: virtual void SetupProperties(const Importer* pImp); private: - ///Helper Functions to read parts of the XML File + /// Helper Functions to read parts of the XML File void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value - void LoadSkeleton(std::string FileName, std::vector &Bones, std::vector &Animations);///< writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it! - void CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector& Bones); - void CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations); - aiMaterial* LoadMaterial(const std::string MaterialName); + /// writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it! + void LoadSkeleton(std::string FileName, std::vector &Bones, std::vector &Animations) const; + + /// converts the animations in aiAnimations and puts them into the scene + void PutAnimationsInScene(const std::vector &Bones, const std::vector &Animations); + + /// uses the bone data to convert a SubMesh into a aiMesh which will be created and returned + aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector& Bones) const; + + + void CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations) const; + + aiMaterial* LoadMaterial(const std::string MaterialName) const; ///Recursivly creates a filled aiNode from a given root bone - aiNode* CreateAiNodeFromBone(int BoneId, const std::vector &Bones, aiNode* ParentNode); + aiNode* CreateAiNodeFromBone(int BoneId, const std::vector &Bones, aiNode* ParentNode) const; //Now we don't have to give theses parameters to all functions std::string m_CurrentFilename; diff --git a/code/OgreImporterMaterial.cpp b/code/OgreImporterMaterial.cpp index 9ec54a382..1b9310e3f 100644 --- a/code/OgreImporterMaterial.cpp +++ b/code/OgreImporterMaterial.cpp @@ -26,8 +26,10 @@ namespace Ogre -aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) +aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const { + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene + MaterialHelper *NewMaterial=new MaterialHelper(); aiString ts(MaterialName.c_str()); @@ -70,7 +72,7 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename); if(NULL==MatFilePtr) { - DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!"); + DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!"); return NewMaterial; } } @@ -118,16 +120,27 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) ss >> Line; if(Line=="ambient") { - //read the ambient light values: + aiColor3D Color; + ss >> Color.r >> Color.g >> Color.b; + NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_AMBIENT); } else if(Line=="diffuse") { + aiColor3D Color; + ss >> Color.r >> Color.g >> Color.b; + NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_DIFFUSE); } else if(Line=="specular") { + aiColor3D Color; + ss >> Color.r >> Color.g >> Color.b; + NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_SPECULAR); } else if(Line=="emmisive") { + aiColor3D Color; + ss >> Color.r >> Color.g >> Color.b; + NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_EMISSIVE); } else if(Line=="texture_unit") {