OgreImporter: Remove unnecessary m_currentX state. Improve and clean OgreMaterial: split tech/pass/texture_unit to their own functions. Document missing features and potential bugs. Improve the original authors 'detection from texture filename' logic (enabled with AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME). Add generic detection from texture unit name, which is commonly used in Ogre materials.
parent
6c51fa2072
commit
f98584cdea
|
@ -38,9 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file OgreImporter.cpp
|
|
||||||
* @brief Implementation of the Ogre XML (.mesh.xml) loader.
|
|
||||||
*/
|
|
||||||
#include "AssimpPCH.h"
|
#include "AssimpPCH.h"
|
||||||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||||
|
|
||||||
|
@ -85,10 +82,6 @@ bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandle
|
||||||
|
|
||||||
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
|
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
|
||||||
{
|
{
|
||||||
m_CurrentFilename = pFile;
|
|
||||||
m_CurrentIOHandler = pIOHandler;
|
|
||||||
m_CurrentScene = pScene;
|
|
||||||
|
|
||||||
// -------------------- Initial file and XML operations --------------------
|
// -------------------- Initial file and XML operations --------------------
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
|
@ -155,7 +148,7 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
/** @todo What is the correct way of handling empty ref here.
|
/** @todo What is the correct way of handling empty ref here.
|
||||||
Does Assimp require there to be a valid material index for each mesh,
|
Does Assimp require there to be a valid material index for each mesh,
|
||||||
even if its a dummy material. */
|
even if its a dummy material. */
|
||||||
aiMaterial* material = LoadMaterial(submesh->MaterialName);
|
aiMaterial* material = ReadMaterial(pFile, pIOHandler, submesh->MaterialName);
|
||||||
materials.push_back(material);
|
materials.push_back(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,13 +172,14 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
|
|
||||||
vector<Bone> Bones;
|
vector<Bone> Bones;
|
||||||
vector<Animation> Animations;
|
vector<Animation> Animations;
|
||||||
|
|
||||||
if (CurrentNodeNameEquals(reader, nnSkeletonLink))
|
if (CurrentNodeNameEquals(reader, nnSkeletonLink))
|
||||||
{
|
{
|
||||||
string SkeletonFile = GetAttribute<string>(reader.get(), "name");
|
string skeletonFile = GetAttribute<string>(reader.get(), "name");
|
||||||
if (!SkeletonFile.empty())
|
if (!skeletonFile.empty())
|
||||||
LoadSkeleton(SkeletonFile, Bones, Animations);
|
ReadSkeleton(pFile, pIOHandler, pScene, skeletonFile, Bones, Animations);
|
||||||
else
|
else
|
||||||
DefaultLogger::get()->debug("Found a unusual <" + nnSkeletonLink + "> with a empty reference");
|
DefaultLogger::get()->debug("Found a unusual <" + nnSkeletonLink + "> with a empty file reference");
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -204,34 +198,34 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
// -------------------- Apply to aiScene --------------------
|
// -------------------- Apply to aiScene --------------------
|
||||||
|
|
||||||
//put the aiMaterials in the scene:
|
//put the aiMaterials in the scene:
|
||||||
m_CurrentScene->mMaterials=new aiMaterial*[materials.size()];
|
pScene->mMaterials=new aiMaterial*[materials.size()];
|
||||||
m_CurrentScene->mNumMaterials=materials.size();
|
pScene->mNumMaterials=materials.size();
|
||||||
for(unsigned int i=0; i<materials.size(); ++i)
|
for(unsigned int i=0; i<materials.size(); ++i)
|
||||||
m_CurrentScene->mMaterials[i]=materials[i];
|
pScene->mMaterials[i]=materials[i];
|
||||||
|
|
||||||
//create the aiMehs...
|
//create the aiMehs...
|
||||||
vector<aiMesh*> aiMeshes;
|
vector<aiMesh*> aiMeshes;
|
||||||
BOOST_FOREACH(boost::shared_ptr<SubMesh> theSubMesh, subMeshes)
|
BOOST_FOREACH(boost::shared_ptr<SubMesh> theSubMesh, subMeshes)
|
||||||
{
|
{
|
||||||
aiMeshes.push_back(CreateAssimpSubMesh(*theSubMesh, Bones));
|
aiMeshes.push_back(CreateAssimpSubMesh(pScene, *theSubMesh, Bones));
|
||||||
}
|
}
|
||||||
//... and put them in the scene:
|
//... and put them in the scene:
|
||||||
m_CurrentScene->mNumMeshes=aiMeshes.size();
|
pScene->mNumMeshes=aiMeshes.size();
|
||||||
m_CurrentScene->mMeshes=new aiMesh*[aiMeshes.size()];
|
pScene->mMeshes=new aiMesh*[aiMeshes.size()];
|
||||||
memcpy(m_CurrentScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size());
|
memcpy(pScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size());
|
||||||
|
|
||||||
//Create the root node
|
//Create the root node
|
||||||
m_CurrentScene->mRootNode=new aiNode("root");
|
pScene->mRootNode=new aiNode("root");
|
||||||
|
|
||||||
//link the meshs with the root node:
|
//link the meshs with the root node:
|
||||||
m_CurrentScene->mRootNode->mMeshes=new unsigned int[subMeshes.size()];
|
pScene->mRootNode->mMeshes=new unsigned int[subMeshes.size()];
|
||||||
m_CurrentScene->mRootNode->mNumMeshes=subMeshes.size();
|
pScene->mRootNode->mNumMeshes=subMeshes.size();
|
||||||
|
|
||||||
for(unsigned int i=0; i<subMeshes.size(); ++i)
|
for(unsigned int i=0; i<subMeshes.size(); ++i)
|
||||||
m_CurrentScene->mRootNode->mMeshes[i]=i;
|
pScene->mRootNode->mMeshes[i]=i;
|
||||||
|
|
||||||
CreateAssimpSkeleton(Bones, Animations);
|
CreateAssimpSkeleton(pScene, Bones, Animations);
|
||||||
PutAnimationsInScene(Bones, Animations);
|
PutAnimationsInScene(pScene, Bones, Animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,8 +237,8 @@ const aiImporterDesc* OgreImporter::GetInfo () const
|
||||||
|
|
||||||
void OgreImporter::SetupProperties(const Importer* pImp)
|
void OgreImporter::SetupProperties(const Importer* pImp)
|
||||||
{
|
{
|
||||||
m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||||
m_TextureTypeFromFilename=pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
|
m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -93,35 +93,42 @@ private:
|
||||||
static void ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry);
|
static void ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry);
|
||||||
|
|
||||||
/// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned.
|
/// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned.
|
||||||
aiMesh* CreateAssimpSubMesh(const SubMesh &submesh, const std::vector<Bone>& bones) const;
|
aiMesh* CreateAssimpSubMesh(aiScene *pScene, const SubMesh &submesh, const std::vector<Bone>& bones) const;
|
||||||
|
|
||||||
//-------------------------------- OgreSkeleton.cpp -------------------------------
|
//-------------------------------- OgreSkeleton.cpp -------------------------------
|
||||||
|
|
||||||
/// Writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
|
/// 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<Bone> &Bones, std::vector<Animation> &Animations) const;
|
void ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOHandler, const aiScene *pScene,
|
||||||
|
const std::string &skeletonFile, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
|
||||||
|
|
||||||
/// Converts the animations in aiAnimations and puts them into the scene.
|
/// Converts the animations in aiAnimations and puts them into the scene.
|
||||||
void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
void PutAnimationsInScene(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||||
|
|
||||||
/// Creates the aiSkeleton in current scene.
|
/// Creates the aiSkeleton in current scene.
|
||||||
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
void CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||||
|
|
||||||
/// Recursivly creates a filled aiNode from a given root bone.
|
/// Recursivly creates a filled aiNode from a given root bone.
|
||||||
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
|
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
|
||||||
|
|
||||||
//-------------------------------- OgreMaterial.cpp -------------------------------
|
//-------------------------------- OgreMaterial.cpp -------------------------------
|
||||||
|
|
||||||
aiMaterial* LoadMaterial(const std::string MaterialName) const;
|
/// Reads material
|
||||||
void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial) const;
|
aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
|
||||||
|
|
||||||
|
// These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
|
||||||
|
bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
|
||||||
|
bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);
|
||||||
|
bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
|
||||||
|
|
||||||
// Now we don't have to give theses parameters to all functions
|
// Now we don't have to give theses parameters to all functions
|
||||||
/// @todo Remove this m_Current* bookkeeping.
|
/// @todo Remove this m_Current* bookkeeping.
|
||||||
std::string m_CurrentFilename;
|
|
||||||
std::string m_MaterialLibFilename;
|
std::string m_userDefinedMaterialLibFile;
|
||||||
bool m_TextureTypeFromFilename;
|
bool m_detectTextureTypeFromFilename;
|
||||||
IOSystem* m_CurrentIOHandler;
|
|
||||||
aiScene *m_CurrentScene;
|
|
||||||
SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh
|
SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh
|
||||||
|
|
||||||
|
std::map<aiTextureType, unsigned int> m_textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Simplified face.
|
/// Simplified face.
|
||||||
|
|
|
@ -60,34 +60,35 @@ namespace Assimp
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static const string partComment = "//";
|
||||||
|
static const string partBlockStart = "{";
|
||||||
|
static const string partBlockEnd = "}";
|
||||||
|
|
||||||
|
/// Skips a line from current @ss position until a newline. Returns the skipped part.
|
||||||
aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
std::string SkipLine(stringstream &ss)
|
||||||
{
|
{
|
||||||
/*For better understanding of the material parser, here is a material example file:
|
string skipped;
|
||||||
|
getline(ss, skipped);
|
||||||
|
return skipped;
|
||||||
|
}
|
||||||
|
|
||||||
material Sarg
|
/// Skips a line and reads next element from @c ss to @c nextElement.
|
||||||
{
|
/** @return Skipped line content until newline. */
|
||||||
receive_shadows on
|
std::string NextAfterNewLine(stringstream &ss, std::string &nextElement)
|
||||||
technique
|
{
|
||||||
{
|
string skipped = SkipLine(ss);
|
||||||
pass
|
ss >> nextElement;
|
||||||
{
|
return skipped;
|
||||||
ambient 0.500000 0.500000 0.500000 1.000000
|
}
|
||||||
diffuse 0.640000 0.640000 0.640000 1.000000
|
|
||||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
|
||||||
emissive 0.000000 0.000000 0.000000 1.000000
|
|
||||||
texture_unit
|
|
||||||
{
|
|
||||||
texture SargTextur.tga
|
|
||||||
tex_address_mode wrap
|
|
||||||
filtering linear linear none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName)
|
||||||
|
{
|
||||||
|
/// @todo Should we return null ptr here or a empty material?
|
||||||
|
if (materialName.empty())
|
||||||
|
return new aiMaterial();
|
||||||
|
|
||||||
|
// Full reference and examples of Ogre Material Script
|
||||||
|
// can be found from http://www.ogre3d.org/docs/manual/manual_14.html
|
||||||
|
|
||||||
/*and here is another one:
|
/*and here is another one:
|
||||||
|
|
||||||
|
@ -112,342 +113,421 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Read the file into memory and put it in a stringstream
|
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
{// after this block, the temporarly loaded data will be released
|
|
||||||
|
|
||||||
/*
|
// Scope for scopre_ptr auto release
|
||||||
We have 3 guesses for the Material filename:
|
{
|
||||||
- the Material Name
|
/* There are three .material options in priority order:
|
||||||
- the Name of the mesh file
|
1) File with the material name (materialName)
|
||||||
- the DefaultMaterialLib (which you can set before importing)
|
2) File with the mesh files base name (pFile)
|
||||||
*/
|
3) Optional user defined material library file (m_userDefinedMaterialLibFile) */
|
||||||
|
std::vector<string> potentialFiles;
|
||||||
|
potentialFiles.push_back(materialName + ".material");
|
||||||
|
potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material");
|
||||||
|
if (!m_userDefinedMaterialLibFile.empty())
|
||||||
|
potentialFiles.push_back(m_userDefinedMaterialLibFile);
|
||||||
|
|
||||||
IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialName+".material");
|
IOStream *materialFile = 0;
|
||||||
if(NULL==MatFilePtr)
|
for(size_t i=0; i<potentialFiles.size(); ++i)
|
||||||
{
|
{
|
||||||
//the filename typically ends with .mesh or .mesh.xml
|
materialFile = pIOHandler->Open(potentialFiles[i]);
|
||||||
const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.rfind(".mesh"))+".material";
|
if (materialFile)
|
||||||
|
break;
|
||||||
|
DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist");
|
||||||
|
}
|
||||||
|
if (!materialFile)
|
||||||
|
{
|
||||||
|
/// @todo Should we return null ptr here or a empty material?
|
||||||
|
DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'");
|
||||||
|
return new aiMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
|
boost::scoped_ptr<IOStream> stream(materialFile);
|
||||||
if(NULL==MatFilePtr)
|
if (stream->FileSize() == 0)
|
||||||
{
|
|
||||||
//try the default mat Library
|
|
||||||
if(NULL==MatFilePtr)
|
|
||||||
{
|
|
||||||
|
|
||||||
MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
|
|
||||||
if(NULL==MatFilePtr)
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!");
|
|
||||||
return new aiMaterial();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Fill the stream
|
|
||||||
boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr);
|
|
||||||
if(MaterialFile->FileSize()>0)
|
|
||||||
{
|
{
|
||||||
vector<char> FileData(MaterialFile->FileSize());
|
/// @todo Should we return null ptr here or a empty material?
|
||||||
MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
|
DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)");
|
||||||
BaseImporter::ConvertToUTF8(FileData);
|
return new aiMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
FileData.push_back('\0');//terminate the string with zero, so that the ss can parse it correctly
|
// Read bytes
|
||||||
ss << &FileData[0];
|
vector<char> data(stream->FileSize());
|
||||||
}
|
stream->Read(&data[0], stream->FileSize(), 1);
|
||||||
else
|
|
||||||
{
|
// Convert to UTF-8 and terminate the string for ss
|
||||||
DefaultLogger::get()->warn("Material " + MaterialName + " seams to be empty");
|
BaseImporter::ConvertToUTF8(data);
|
||||||
return NULL;
|
data.push_back('\0');
|
||||||
}
|
|
||||||
|
ss << &data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug("Reading material '" + materialName + "'");
|
||||||
|
|
||||||
//create the material
|
aiMaterial *material = new aiMaterial();
|
||||||
aiMaterial *NewMaterial=new aiMaterial();
|
m_textures.clear();
|
||||||
|
|
||||||
|
aiString ts(materialName);
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_NAME);
|
||||||
|
|
||||||
aiString ts(MaterialName.c_str());
|
// The stringstream will push words from a line until newline.
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_NAME);
|
// It will also trim whitespace from line start and between words.
|
||||||
|
string linePart;
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
const string partMaterial = "material";
|
||||||
|
const string partTechnique = "technique";
|
||||||
|
|
||||||
string Line;
|
|
||||||
ss >> Line;
|
|
||||||
// unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another
|
|
||||||
while(!ss.eof())
|
while(!ss.eof())
|
||||||
{
|
{
|
||||||
if(Line=="material")
|
// Skip commented lines
|
||||||
|
if (linePart == partComment)
|
||||||
{
|
{
|
||||||
ss >> Line;
|
string postComment = NextAfterNewLine(ss, linePart);
|
||||||
if(Line==MaterialName)//Load the next material
|
DefaultLogger::get()->debug("//" + postComment + " (comment line ignored)");
|
||||||
{
|
continue;
|
||||||
string RestOfLine;
|
|
||||||
getline(ss, RestOfLine);//ignore the rest of the line
|
|
||||||
ss >> Line;
|
|
||||||
|
|
||||||
if(Line!="{")
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->warn("empyt material!");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(Line!="}")//read until the end of the material
|
|
||||||
{
|
|
||||||
//Proceed to the first technique
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="technique")
|
|
||||||
{
|
|
||||||
ReadTechnique(ss, NewMaterial);
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultLogger::get()->info(Line);
|
|
||||||
//read informations from a custom material:
|
|
||||||
if(Line=="set")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="$specular")//todo load this values:
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if(Line=="$diffuse")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if(Line=="$ambient")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if(Line=="$colormap")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
|
||||||
}
|
|
||||||
if(Line=="$normalmap")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Line=="$shininess_strength")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
float Shininess=fast_atof(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Line=="$shininess_exponent")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
float Shininess=fast_atof(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Properties from Venetica:
|
|
||||||
if(Line=="$diffuse_map")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line[0]=='"')// "file" -> file
|
|
||||||
Line=Line.substr(1, Line.size()-2);
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
|
||||||
}
|
|
||||||
if(Line=="$specular_map")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line[0]=='"')// "file" -> file
|
|
||||||
Line=Line.substr(1, Line.size()-2);
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
|
|
||||||
}
|
|
||||||
if(Line=="$normal_map")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line[0]=='"')// "file" -> file
|
|
||||||
Line=Line.substr(1, Line.size()-2);
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
|
||||||
}
|
|
||||||
if(Line=="$light_map")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line[0]=='"')// "file" -> file
|
|
||||||
Line=Line.substr(1, Line.size()-2);
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//end of material
|
|
||||||
}
|
|
||||||
else {} //this is the wrong material, proceed the file until we reach the next material
|
|
||||||
}
|
}
|
||||||
ss >> Line;
|
if (linePart != partMaterial)
|
||||||
}
|
|
||||||
|
|
||||||
return NewMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial) const
|
|
||||||
{
|
|
||||||
unsigned int CurrentDiffuseTextureId=0;
|
|
||||||
unsigned int CurrentSpecularTextureId=0;
|
|
||||||
unsigned int CurrentNormalTextureId=0;
|
|
||||||
unsigned int CurrentLightTextureId=0;
|
|
||||||
|
|
||||||
|
|
||||||
string RestOfLine;
|
|
||||||
getline(ss, RestOfLine);//ignore the rest of the line
|
|
||||||
|
|
||||||
string Line;
|
|
||||||
ss >> Line;
|
|
||||||
if(Line!="{")
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->warn("empty technique!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while(Line!="}")//read until the end of the technique
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="pass")
|
|
||||||
{
|
{
|
||||||
getline(ss, RestOfLine);//ignore the rest of the line
|
ss >> linePart;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ss >> Line;
|
ss >> linePart;
|
||||||
if(Line!="{")
|
if (linePart != materialName)
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->warn("empty pass!");
|
//DefaultLogger::get()->debug(Formatter::format() << "Found material '" << linePart << "' that does not match at index " << ss.tellg());
|
||||||
return;
|
ss >> linePart;
|
||||||
}
|
continue;
|
||||||
while(Line!="}")//read until the end of the pass
|
}
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="ambient")
|
|
||||||
{
|
|
||||||
float r,g,b;
|
|
||||||
ss >> r >> g >> b;
|
|
||||||
const aiColor3D Color(r,g,b);
|
|
||||||
NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_AMBIENT);
|
|
||||||
}
|
|
||||||
else if(Line=="diffuse")
|
|
||||||
{
|
|
||||||
float r,g,b;
|
|
||||||
ss >> r >> g >> b;
|
|
||||||
const aiColor3D Color(r,g,b);
|
|
||||||
NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_DIFFUSE);
|
|
||||||
}
|
|
||||||
else if(Line=="specular")
|
|
||||||
{
|
|
||||||
float r,g,b;
|
|
||||||
ss >> r >> g >> b;
|
|
||||||
const aiColor3D Color(r,g,b);
|
|
||||||
NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_SPECULAR);
|
|
||||||
}
|
|
||||||
else if(Line=="emmisive")
|
|
||||||
{
|
|
||||||
float r,g,b;
|
|
||||||
ss >> r >> g >> b;
|
|
||||||
const aiColor3D Color(r,g,b);
|
|
||||||
NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_EMISSIVE);
|
|
||||||
}
|
|
||||||
else if(Line=="texture_unit")
|
|
||||||
{
|
|
||||||
getline(ss, RestOfLine);//ignore the rest of the line
|
|
||||||
|
|
||||||
std::string TextureName;
|
NextAfterNewLine(ss, linePart);
|
||||||
int TextureType=-1;
|
if (linePart != partBlockStart)
|
||||||
int UvSet=0;
|
{
|
||||||
|
DefaultLogger::get()->error(Formatter::format() << "Invalid material: block start missing near index " << ss.tellg());
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug("material '" + materialName + "'");
|
||||||
|
|
||||||
ss >> Line;
|
while(linePart != partBlockEnd)
|
||||||
if(Line!="{")
|
{
|
||||||
throw DeadlyImportError("empty texture unit!");
|
// Proceed to the first technique
|
||||||
while(Line!="}")//read until the end of the texture_unit
|
ss >> linePart;
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="texture")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
TextureName=Line;
|
|
||||||
|
|
||||||
if(m_TextureTypeFromFilename)
|
|
||||||
{
|
|
||||||
if(Line.find("_n.")!=string::npos)// Normalmap
|
|
||||||
{
|
|
||||||
TextureType=aiTextureType_NORMALS;
|
|
||||||
}
|
|
||||||
else if(Line.find("_s.")!=string::npos)// Specularmap
|
|
||||||
{
|
|
||||||
TextureType=aiTextureType_SPECULAR;
|
|
||||||
}
|
|
||||||
else if(Line.find("_l.")!=string::npos)// Lightmap
|
|
||||||
{
|
|
||||||
TextureType=aiTextureType_LIGHTMAP;
|
|
||||||
}
|
|
||||||
else// colormap
|
|
||||||
{
|
|
||||||
TextureType=aiTextureType_DIFFUSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TextureType=aiTextureType_DIFFUSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(Line=="tex_coord_set")
|
|
||||||
{
|
|
||||||
ss >> UvSet;
|
|
||||||
}
|
|
||||||
else if(Line=="colour_op")//TODO implement this
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
ss >> Line;
|
|
||||||
if("replace"==Line)//I don't think, assimp has something for this...
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if("modulate"==Line)
|
|
||||||
{
|
|
||||||
//TODO: set value
|
|
||||||
//NewMaterial->AddProperty(aiTextureOp_Multiply)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}//end of texture unit
|
|
||||||
Line="";//clear the } that would end the outer loop
|
|
||||||
|
|
||||||
//give the texture to assimp:
|
|
||||||
|
|
||||||
aiString ts(TextureName.c_str());
|
if (linePart == partTechnique)
|
||||||
switch(TextureType)
|
{
|
||||||
{
|
string techniqueName = trim(SkipLine(ss));
|
||||||
case aiTextureType_DIFFUSE:
|
ReadTechnique(techniqueName, ss, material);
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, CurrentDiffuseTextureId));
|
|
||||||
NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentDiffuseTextureId));
|
|
||||||
CurrentDiffuseTextureId++;
|
|
||||||
break;
|
|
||||||
case aiTextureType_NORMALS:
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, CurrentNormalTextureId));
|
|
||||||
NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentNormalTextureId));
|
|
||||||
CurrentNormalTextureId++;
|
|
||||||
break;
|
|
||||||
case aiTextureType_SPECULAR:
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, CurrentSpecularTextureId));
|
|
||||||
NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentSpecularTextureId));
|
|
||||||
CurrentSpecularTextureId++;
|
|
||||||
break;
|
|
||||||
case aiTextureType_LIGHTMAP:
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, CurrentLightTextureId));
|
|
||||||
NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentLightTextureId));
|
|
||||||
CurrentLightTextureId++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DefaultLogger::get()->warn("Invalid Texture Type!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Line="";//clear the } that would end the outer loop
|
|
||||||
|
// Read informations from a custom material
|
||||||
|
/** @todo This "set $x y" does not seem to be a official Ogre material system feature.
|
||||||
|
Materials can inherit other materials and override texture units by using the (unique)
|
||||||
|
parent texture unit name in your cloned material.
|
||||||
|
This is not yet supported and below code is probably some hack from the original
|
||||||
|
author of this Ogre importer. Should be removed? */
|
||||||
|
if(linePart=="set")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
if(linePart=="$specular")//todo load this values:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if(linePart=="$diffuse")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if(linePart=="$ambient")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if(linePart=="$colormap")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||||
|
}
|
||||||
|
if(linePart=="$normalmap")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(linePart=="$shininess_strength")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
float Shininess=fast_atof(linePart.c_str());
|
||||||
|
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(linePart=="$shininess_exponent")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
float Shininess=fast_atof(linePart.c_str());
|
||||||
|
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Properties from Venetica:
|
||||||
|
if(linePart=="$diffuse_map")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
if(linePart[0]=='"')// "file" -> file
|
||||||
|
linePart=linePart.substr(1, linePart.size()-2);
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||||
|
}
|
||||||
|
if(linePart=="$specular_map")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
if(linePart[0]=='"')// "file" -> file
|
||||||
|
linePart=linePart.substr(1, linePart.size()-2);
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
|
||||||
|
}
|
||||||
|
if(linePart=="$normal_map")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
if(linePart[0]=='"')// "file" -> file
|
||||||
|
linePart=linePart.substr(1, linePart.size()-2);
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||||
|
}
|
||||||
|
if(linePart=="$light_map")
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
if(linePart[0]=='"')// "file" -> file
|
||||||
|
linePart=linePart.substr(1, linePart.size()-2);
|
||||||
|
aiString ts(linePart.c_str());
|
||||||
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}//end of technique
|
ss >> linePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material)
|
||||||
|
{
|
||||||
|
string linePart;
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
}//namespace Ogre
|
if (linePart != partBlockStart)
|
||||||
}//namespace Assimp
|
{
|
||||||
|
DefaultLogger::get()->error(Formatter::format() << "Invalid material: Technique block start missing near index " << ss.tellg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER
|
DefaultLogger::get()->debug(" technique '" + techniqueName + "'");
|
||||||
|
|
||||||
|
const string partPass = "pass";
|
||||||
|
|
||||||
|
while(linePart != partBlockEnd)
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
// Skip commented lines
|
||||||
|
if (linePart == partComment)
|
||||||
|
{
|
||||||
|
string postComment = SkipLine(ss);
|
||||||
|
DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @todo Techniques have other attributes than just passes.
|
||||||
|
if (linePart == partPass)
|
||||||
|
{
|
||||||
|
string passName = trim(SkipLine(ss));
|
||||||
|
ReadPass(passName, ss, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material)
|
||||||
|
{
|
||||||
|
string linePart;
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
if (linePart != partBlockStart)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error(Formatter::format() << "Invalid material: Pass block start missing near index " << ss.tellg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(" pass '" + passName + "'");
|
||||||
|
|
||||||
|
const string partAmbient = "ambient";
|
||||||
|
const string partDiffuse = "diffuse";
|
||||||
|
const string partSpecular = "specular";
|
||||||
|
const string partEmissive = "emissive";
|
||||||
|
const string partTextureUnit = "texture_unit";
|
||||||
|
|
||||||
|
while(linePart != partBlockEnd)
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
// Skip commented lines
|
||||||
|
if (linePart == partComment)
|
||||||
|
{
|
||||||
|
string postComment = SkipLine(ss);
|
||||||
|
DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
/// @todo Support alpha via aiColor4D.
|
||||||
|
if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive)
|
||||||
|
{
|
||||||
|
float r, g, b;
|
||||||
|
ss >> r >> g >> b;
|
||||||
|
const aiColor3D color(r, g, b);
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b);
|
||||||
|
|
||||||
|
if (linePart == partAmbient)
|
||||||
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
else if (linePart == partDiffuse)
|
||||||
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
|
else if (linePart == partSpecular)
|
||||||
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||||
|
else if (linePart == partEmissive)
|
||||||
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
|
}
|
||||||
|
else if (linePart == partTextureUnit)
|
||||||
|
{
|
||||||
|
string textureUnitName = trim(SkipLine(ss));
|
||||||
|
ReadTextureUnit(textureUnitName, ss, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material)
|
||||||
|
{
|
||||||
|
string linePart;
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
if (linePart != partBlockStart)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error(Formatter::format() << "Invalid material: Texture unit block start missing near index " << ss.tellg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(" texture_unit '" + textureUnitName + "'");
|
||||||
|
|
||||||
|
const string partTexture = "texture";
|
||||||
|
const string partTextCoordSet = "tex_coord_set";
|
||||||
|
const string partColorOp = "colour_op";
|
||||||
|
|
||||||
|
aiTextureType textureType = aiTextureType_NONE;
|
||||||
|
std::string textureRef;
|
||||||
|
int uvCoord = 0;
|
||||||
|
|
||||||
|
while(linePart != partBlockEnd)
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
|
||||||
|
// Skip commented lines
|
||||||
|
if (linePart == partComment)
|
||||||
|
{
|
||||||
|
string postComment = SkipLine(ss);
|
||||||
|
DefaultLogger::get()->debug(" //" + postComment + " (comment line ignored)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linePart == partTexture)
|
||||||
|
{
|
||||||
|
ss >> linePart;
|
||||||
|
textureRef = linePart;
|
||||||
|
|
||||||
|
// User defined Assimp config property to detect texture type from filename.
|
||||||
|
if (m_detectTextureTypeFromFilename)
|
||||||
|
{
|
||||||
|
size_t posSuffix = textureRef.find_last_of(".");
|
||||||
|
size_t posUnderscore = textureRef.find_last_of("_");
|
||||||
|
|
||||||
|
if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore)
|
||||||
|
{
|
||||||
|
string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
|
||||||
|
DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'");
|
||||||
|
|
||||||
|
if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
|
||||||
|
textureType = aiTextureType_NORMALS;
|
||||||
|
else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
|
||||||
|
textureType = aiTextureType_SPECULAR;
|
||||||
|
else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
|
||||||
|
textureType = aiTextureType_LIGHTMAP;
|
||||||
|
else if (identifier == "_disp" || identifier == "_displacement")
|
||||||
|
textureType = aiTextureType_DISPLACEMENT;
|
||||||
|
else
|
||||||
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
|
// Detect from texture unit name. This cannot be too broad as
|
||||||
|
// authors might give names like "LightSaber" or "NormalNinja".
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string unitNameLower = Ogre::ToLower(textureUnitName);
|
||||||
|
if (unitNameLower.find("normalmap") != string::npos)
|
||||||
|
textureType = aiTextureType_NORMALS;
|
||||||
|
else if (unitNameLower.find("specularmap") != string::npos)
|
||||||
|
textureType = aiTextureType_SPECULAR;
|
||||||
|
else if (unitNameLower.find("lightmap") != string::npos)
|
||||||
|
textureType = aiTextureType_LIGHTMAP;
|
||||||
|
else if (unitNameLower.find("displacementmap") != string::npos)
|
||||||
|
textureType = aiTextureType_DISPLACEMENT;
|
||||||
|
else
|
||||||
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (linePart == partTextCoordSet)
|
||||||
|
{
|
||||||
|
ss >> uvCoord;
|
||||||
|
}
|
||||||
|
/// @todo Implement
|
||||||
|
else if(linePart == partColorOp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
ss >> linePart;
|
||||||
|
if("replace"==linePart)//I don't think, assimp has something for this...
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if("modulate"==linePart)
|
||||||
|
{
|
||||||
|
//TODO: set value
|
||||||
|
//material->AddProperty(aiTextureOp_Multiply)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textureRef.empty())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("Texture reference is empty, ignoring texture_unit.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (textureType == aiTextureType_NONE)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int textureTypeIndex = m_textures[textureType];
|
||||||
|
m_textures[textureType]++;
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(Formatter::format() << " texture '" << textureRef << "' type " << textureType
|
||||||
|
<< " index " << textureTypeIndex << " UV " << uvCoord);
|
||||||
|
|
||||||
|
aiString assimpTextureRef(textureRef);
|
||||||
|
material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex));
|
||||||
|
material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Ogre
|
||||||
|
} // Assimp
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||||
|
|
|
@ -442,15 +442,9 @@ void OgreImporter::ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry)
|
||||||
//_________________________________________________________
|
//_________________________________________________________
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aiMesh* OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submesh, const vector<Bone>& bones) const
|
||||||
|
|
||||||
|
|
||||||
aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& submesh, const vector<Bone>& bones) const
|
|
||||||
{
|
{
|
||||||
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
aiMesh* NewAiMesh = new aiMesh();
|
||||||
(void)m_CurrentScene;
|
|
||||||
|
|
||||||
aiMesh* NewAiMesh=new aiMesh();
|
|
||||||
|
|
||||||
//Positions
|
//Positions
|
||||||
NewAiMesh->mVertices=new aiVector3D[submesh.Positions.size()];
|
NewAiMesh->mVertices=new aiVector3D[submesh.Positions.size()];
|
||||||
|
|
|
@ -52,41 +52,36 @@ namespace Assimp
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOHandler, const aiScene *pScene,
|
||||||
|
const std::string &skeletonFile, vector<Bone> &Bones, vector<Animation> &Animations) const
|
||||||
void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vector<Animation> &Animations) const
|
|
||||||
{
|
{
|
||||||
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
|
||||||
(void)m_CurrentScene;
|
|
||||||
|
|
||||||
|
|
||||||
//most likely the skeleton file will only end with .skeleton
|
//most likely the skeleton file will only end with .skeleton
|
||||||
//But this is a xml reader, so we need: .skeleton.xml
|
//But this is a xml reader, so we need: .skeleton.xml
|
||||||
FileName+=".xml";
|
string skeletonPath = skeletonFile + ".xml";
|
||||||
|
|
||||||
DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName);
|
DefaultLogger::get()->debug(string("Loading Skeleton: ")+skeletonFile);
|
||||||
|
|
||||||
//Open the File:
|
//Open the File:
|
||||||
boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName));
|
boost::scoped_ptr<IOStream> File(pIOHandler->Open(skeletonFile));
|
||||||
if(NULL==File.get())
|
if(NULL==File.get())
|
||||||
throw DeadlyImportError("Failed to open skeleton file "+FileName+".");
|
throw DeadlyImportError("Failed to open skeleton file "+skeletonFile+".");
|
||||||
|
|
||||||
//Read the Mesh File:
|
//Read the Mesh File:
|
||||||
boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
|
boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
|
||||||
XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
|
XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
|
||||||
if(!SkeletonFile)
|
if(!SkeletonFile)
|
||||||
throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName);
|
throw DeadlyImportError(string("Failed to create XML Reader for ")+skeletonFile);
|
||||||
|
|
||||||
NextNode(SkeletonFile);
|
NextNode(SkeletonFile);
|
||||||
if(string("skeleton")!=SkeletonFile->getNodeName())
|
if(string("skeleton")!=SkeletonFile->getNodeName())
|
||||||
throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName);
|
throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+skeletonFile);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------load bones-----------------------------------------
|
//------------------------------------load bones-----------------------------------------
|
||||||
NextNode(SkeletonFile);
|
NextNode(SkeletonFile);
|
||||||
if(string("bones")!=SkeletonFile->getNodeName())
|
if(string("bones")!=SkeletonFile->getNodeName())
|
||||||
throw DeadlyImportError("No bones node in skeleton "+FileName);
|
throw DeadlyImportError("No bones node in skeleton "+skeletonFile);
|
||||||
|
|
||||||
NextNode(SkeletonFile);
|
NextNode(SkeletonFile);
|
||||||
|
|
||||||
|
@ -138,7 +133,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vecto
|
||||||
IdsOk=false;
|
IdsOk=false;
|
||||||
}
|
}
|
||||||
if(!IdsOk)
|
if(!IdsOk)
|
||||||
throw DeadlyImportError("Bone Ids are not valid!"+FileName);
|
throw DeadlyImportError("Bone Ids are not valid!"+skeletonFile);
|
||||||
}
|
}
|
||||||
DefaultLogger::get()->debug((Formatter::format(),"Number of bones: ",Bones.size()));
|
DefaultLogger::get()->debug((Formatter::format(),"Number of bones: ",Bones.size()));
|
||||||
//________________________________________________________________________________
|
//________________________________________________________________________________
|
||||||
|
@ -150,7 +145,7 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vecto
|
||||||
|
|
||||||
//----------------------------load bonehierarchy--------------------------------
|
//----------------------------load bonehierarchy--------------------------------
|
||||||
if(string("bonehierarchy")!=SkeletonFile->getNodeName())
|
if(string("bonehierarchy")!=SkeletonFile->getNodeName())
|
||||||
throw DeadlyImportError("no bonehierarchy node in "+FileName);
|
throw DeadlyImportError("no bonehierarchy node in "+skeletonFile);
|
||||||
|
|
||||||
DefaultLogger::get()->debug("loading bonehierarchy...");
|
DefaultLogger::get()->debug("loading bonehierarchy...");
|
||||||
NextNode(SkeletonFile);
|
NextNode(SkeletonFile);
|
||||||
|
@ -280,11 +275,11 @@ void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vecto
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &/*Animations*/)
|
void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &/*Animations*/)
|
||||||
{
|
{
|
||||||
if(!m_CurrentScene->mRootNode)
|
if(!pScene->mRootNode)
|
||||||
throw DeadlyImportError("No root node exists!!");
|
throw DeadlyImportError("No root node exists!!");
|
||||||
if(0!=m_CurrentScene->mRootNode->mNumChildren)
|
if(0!=pScene->mRootNode->mNumChildren)
|
||||||
throw DeadlyImportError("Root Node already has childnodes!");
|
throw DeadlyImportError("Root Node already has childnodes!");
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,26 +290,27 @@ void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const st
|
||||||
if(-1==theBone.ParentId) //the bone is a root bone
|
if(-1==theBone.ParentId) //the bone is a root bone
|
||||||
{
|
{
|
||||||
//which will recursily add all other nodes
|
//which will recursily add all other nodes
|
||||||
RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));
|
RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, pScene->mRootNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RootBoneNodes.size() > 0)
|
if(RootBoneNodes.size() > 0)
|
||||||
{
|
{
|
||||||
m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size();
|
pScene->mRootNode->mNumChildren=RootBoneNodes.size();
|
||||||
m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
|
pScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
|
||||||
memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
|
memcpy(pScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OgreImporter::PutAnimationsInScene(aiScene *pScene, const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
|
||||||
void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
|
|
||||||
{
|
{
|
||||||
//-----------------Create the Assimp Animations --------------------
|
// TODO: Auf nicht vorhandene Animationskeys achten!
|
||||||
|
// @todo Pay attention to non-existing animation Keys (google translated from above german comment)
|
||||||
|
|
||||||
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 been called
|
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 been called
|
||||||
{
|
{
|
||||||
m_CurrentScene->mNumAnimations=Animations.size();
|
pScene->mNumAnimations=Animations.size();
|
||||||
m_CurrentScene->mAnimations=new aiAnimation*[Animations.size()];
|
pScene->mAnimations=new aiAnimation*[Animations.size()];
|
||||||
for(unsigned int i=0; i<Animations.size(); ++i)//create all animations
|
for(unsigned int i=0; i<Animations.size(); ++i)//create all animations
|
||||||
{
|
{
|
||||||
aiAnimation* NewAnimation=new aiAnimation();
|
aiAnimation* NewAnimation=new aiAnimation();
|
||||||
|
@ -382,12 +378,9 @@ void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const st
|
||||||
NewAnimation->mChannels[j]=NewNodeAnim;
|
NewAnimation->mChannels[j]=NewNodeAnim;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentScene->mAnimations[i]=NewAnimation;
|
pScene->mAnimations[i]=NewAnimation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO: Auf nicht vorhandene Animationskeys achten!
|
|
||||||
//#pragma warning (s.o.)
|
|
||||||
//__________________________________________________________________
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
#include "ParsingUtils.h"
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
#include "fast_atof.h"
|
#include "fast_atof.h"
|
||||||
|
|
||||||
|
@ -6,7 +7,7 @@ namespace Assimp
|
||||||
{
|
{
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef irr::io::IrrXMLReader XmlReader;
|
typedef irr::io::IrrXMLReader XmlReader;
|
||||||
|
|
||||||
static void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
|
static void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
|
||||||
|
@ -88,5 +89,40 @@ inline bool CurrentNodeNameEquals(const XmlReader* reader, const std::string &na
|
||||||
return (ASSIMP_stricmp(std::string(reader->getNodeName()), name) == 0);
|
return (ASSIMP_stricmp(std::string(reader->getNodeName()), name) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a lower cased copy of @s.
|
||||||
|
static inline std::string ToLower(std::string s)
|
||||||
|
{
|
||||||
|
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// From http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
|
||||||
|
|
||||||
|
// trim from start
|
||||||
|
static inline std::string <rim(std::string &s, bool newlines = true)
|
||||||
|
{
|
||||||
|
if (!newlines)
|
||||||
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
|
||||||
|
else
|
||||||
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from end
|
||||||
|
static inline std::string &rtrim(std::string &s, bool newlines = true)
|
||||||
|
{
|
||||||
|
if (!newlines)
|
||||||
|
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
|
||||||
|
else
|
||||||
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
// trim from both ends
|
||||||
|
static inline std::string &trim(std::string &s, bool newlines = true)
|
||||||
|
{
|
||||||
|
return ltrim(rtrim(s, newlines), newlines);
|
||||||
|
}
|
||||||
|
|
||||||
} // Ogre
|
} // Ogre
|
||||||
} // Assimp
|
} // Assimp
|
||||||
|
|
Loading…
Reference in New Issue