OgreImporter: Added brackets for all conditional etc. statements, even when there is a single line as requested by @kimkulling. I'm still not sure about the coding convention but looked for guidance in the obj importer code. Now newline before { if only one line and no else/else if after it, othewise a newline before it.
parent
22a4215c06
commit
9ad74e461e
|
@ -74,7 +74,6 @@ const aiImporterDesc* OgreImporter::GetInfo() const
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OgreImporter::SetupProperties(const Importer* pImp)
|
void OgreImporter::SetupProperties(const Importer* pImp)
|
||||||
{
|
{
|
||||||
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||||
|
@ -83,8 +82,9 @@ void OgreImporter::SetupProperties(const Importer* pImp)
|
||||||
|
|
||||||
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
|
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
|
||||||
{
|
{
|
||||||
if (!checkSig)
|
if (!checkSig) {
|
||||||
return EndsWith(pFile, ".mesh.xml", false);
|
return EndsWith(pFile, ".mesh.xml", false);
|
||||||
|
}
|
||||||
|
|
||||||
const char* tokens[] = { "<mesh>" };
|
const char* tokens[] = { "<mesh>" };
|
||||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||||
|
@ -96,21 +96,24 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
|
boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
|
||||||
if (file.get() == NULL)
|
if (!file.get()) {
|
||||||
throw DeadlyImportError("Failed to open file " + pFile);
|
throw DeadlyImportError("Failed to open file " + pFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get()));
|
boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get()));
|
||||||
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
|
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||||
if (!reader)
|
if (!reader) {
|
||||||
throw DeadlyImportError("Failed to create XML Reader for " + pFile);
|
throw DeadlyImportError("Failed to create XML Reader for " + pFile);
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug("Opened a XML reader for " + pFile);
|
DefaultLogger::get()->debug("Opened a XML reader for " + pFile);
|
||||||
|
|
||||||
// Read root node
|
// Read root node
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
if (!CurrentNodeNameEquals(reader, "mesh"))
|
if (!CurrentNodeNameEquals(reader, "mesh")) {
|
||||||
throw DeadlyImportError("Root node is not <mesh> but <" + string(reader->getNodeName()) + "> in " + pFile);
|
throw DeadlyImportError("Root node is not <mesh> but <" + string(reader->getNodeName()) + "> in " + pFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Node names
|
// Node names
|
||||||
const string nnSharedGeometry = "sharedgeometry";
|
const string nnSharedGeometry = "sharedgeometry";
|
||||||
|
@ -130,14 +133,16 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
unsigned int NumVertices = GetAttribute<unsigned int>(reader.get(), "vertexcount");
|
unsigned int NumVertices = GetAttribute<unsigned int>(reader.get(), "vertexcount");
|
||||||
|
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
while(CurrentNodeNameEquals(reader, nnVertexBuffer))
|
while(CurrentNodeNameEquals(reader, nnVertexBuffer)) {
|
||||||
ReadVertexBuffer(m_SharedGeometry, reader.get(), NumVertices);
|
ReadVertexBuffer(m_SharedGeometry, reader.get(), NumVertices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- Sub Meshes --------------------
|
// -------------------- Sub Meshes --------------------
|
||||||
|
|
||||||
if (!CurrentNodeNameEquals(reader, nnSubMeshes))
|
if (!CurrentNodeNameEquals(reader, nnSubMeshes)) {
|
||||||
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
|
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
|
||||||
|
}
|
||||||
|
|
||||||
vector<boost::shared_ptr<SubMesh> > subMeshes;
|
vector<boost::shared_ptr<SubMesh> > subMeshes;
|
||||||
vector<aiMaterial*> materials;
|
vector<aiMaterial*> materials;
|
||||||
|
@ -162,20 +167,23 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
materials.push_back(material);
|
materials.push_back(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subMeshes.empty())
|
if (subMeshes.empty()) {
|
||||||
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
|
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
|
||||||
|
}
|
||||||
|
|
||||||
// This is really a internal error if we failed to create dummy materials.
|
// This is really a internal error if we failed to create dummy materials.
|
||||||
if (subMeshes.size() != materials.size())
|
if (subMeshes.size() != materials.size()) {
|
||||||
throw DeadlyImportError("Internal Error: Material count does not match the submesh count");
|
throw DeadlyImportError("Internal Error: Material count does not match the submesh count");
|
||||||
|
}
|
||||||
|
|
||||||
// Skip submesh names.
|
// Skip submesh names.
|
||||||
/// @todo Should these be read to scene etc. metadata?
|
/// @todo Should these be read to scene etc. metadata?
|
||||||
if (CurrentNodeNameEquals(reader, nnSubMeshNames))
|
if (CurrentNodeNameEquals(reader, nnSubMeshNames))
|
||||||
{
|
{
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
while(CurrentNodeNameEquals(reader, nnSubMesh))
|
while(CurrentNodeNameEquals(reader, nnSubMesh)) {
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- Skeleton --------------------
|
// -------------------- Skeleton --------------------
|
||||||
|
@ -187,17 +195,24 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
{
|
{
|
||||||
string skeletonFile = GetAttribute<string>(reader.get(), "name");
|
string skeletonFile = GetAttribute<string>(reader.get(), "name");
|
||||||
if (!skeletonFile.empty())
|
if (!skeletonFile.empty())
|
||||||
|
{
|
||||||
ReadSkeleton(pFile, pIOHandler, pScene, skeletonFile, Bones, Animations);
|
ReadSkeleton(pFile, pIOHandler, pScene, skeletonFile, Bones, Animations);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DefaultLogger::get()->debug("Found a unusual <" + nnSkeletonLink + "> with a empty file reference");
|
DefaultLogger::get()->debug("Found a unusual <" + nnSkeletonLink + "> with a empty file reference");
|
||||||
|
}
|
||||||
NextNode(reader.get());
|
NextNode(reader.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DefaultLogger::get()->debug("Mesh has no assigned skeleton with <" + nnSkeletonLink + ">");
|
DefaultLogger::get()->debug("Mesh has no assigned skeleton with <" + nnSkeletonLink + ">");
|
||||||
|
}
|
||||||
|
|
||||||
// Now there might be <boneassignments> for the shared geometry
|
// Now there might be <boneassignments> for the shared geometry
|
||||||
if (CurrentNodeNameEquals(reader, "boneassignments"))
|
if (CurrentNodeNameEquals(reader, "boneassignments")) {
|
||||||
ReadBoneWeights(m_SharedGeometry, reader.get());
|
ReadBoneWeights(m_SharedGeometry, reader.get());
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------- Process Results --------------------
|
// -------------------- Process Results --------------------
|
||||||
BOOST_FOREACH(boost::shared_ptr<SubMesh> submesh, subMeshes)
|
BOOST_FOREACH(boost::shared_ptr<SubMesh> submesh, subMeshes)
|
||||||
|
@ -211,8 +226,9 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
pScene->mMaterials = new aiMaterial*[materials.size()];
|
pScene->mMaterials = new aiMaterial*[materials.size()];
|
||||||
pScene->mNumMaterials = materials.size();
|
pScene->mNumMaterials = materials.size();
|
||||||
|
|
||||||
for(size_t i=0, len=materials.size(); i<len; ++i)
|
for(size_t i=0, len=materials.size(); i<len; ++i) {
|
||||||
pScene->mMaterials[i] = materials[i];
|
pScene->mMaterials[i] = materials[i];
|
||||||
|
}
|
||||||
|
|
||||||
// Meshes
|
// Meshes
|
||||||
pScene->mMeshes = new aiMesh*[subMeshes.size()];
|
pScene->mMeshes = new aiMesh*[subMeshes.size()];
|
||||||
|
@ -229,8 +245,9 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
pScene->mRootNode->mMeshes = new unsigned int[subMeshes.size()];
|
pScene->mRootNode->mMeshes = new unsigned int[subMeshes.size()];
|
||||||
pScene->mRootNode->mNumMeshes = subMeshes.size();
|
pScene->mRootNode->mNumMeshes = subMeshes.size();
|
||||||
|
|
||||||
for(size_t i=0, len=subMeshes.size(); i<len; ++i)
|
for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
|
||||||
pScene->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
|
pScene->mRootNode->mMeshes[i] = static_cast<unsigned int>(i);
|
||||||
|
}
|
||||||
|
|
||||||
// Skeleton and animations
|
// Skeleton and animations
|
||||||
CreateAssimpSkeleton(pScene, Bones, Animations);
|
CreateAssimpSkeleton(pScene, Bones, Animations);
|
||||||
|
|
|
@ -62,8 +62,9 @@ static const string partBlockEnd = "}";
|
||||||
aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName)
|
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?
|
/// @todo Should we return null ptr here or a empty material?
|
||||||
if (materialName.empty())
|
if (materialName.empty()) {
|
||||||
return new aiMaterial();
|
return new aiMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
// Full reference and examples of Ogre Material Script
|
// Full reference and examples of Ogre Material Script
|
||||||
// can be found from http://www.ogre3d.org/docs/manual/manual_14.html
|
// can be found from http://www.ogre3d.org/docs/manual/manual_14.html
|
||||||
|
@ -109,8 +110,9 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
||||||
for(size_t i=0; i<potentialFiles.size(); ++i)
|
for(size_t i=0; i<potentialFiles.size(); ++i)
|
||||||
{
|
{
|
||||||
materialFile = pIOHandler->Open(potentialFiles[i]);
|
materialFile = pIOHandler->Open(potentialFiles[i]);
|
||||||
if (materialFile)
|
if (materialFile) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist");
|
DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist");
|
||||||
}
|
}
|
||||||
if (!materialFile)
|
if (!materialFile)
|
||||||
|
@ -204,76 +206,74 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
||||||
parent texture unit name in your cloned material.
|
parent texture unit name in your cloned material.
|
||||||
This is not yet supported and below code is probably some hack from the original
|
This is not yet supported and below code is probably some hack from the original
|
||||||
author of this Ogre importer. Should be removed? */
|
author of this Ogre importer. Should be removed? */
|
||||||
if(linePart=="set")
|
if (linePart=="set")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
if(linePart=="$specular")//todo load this values:
|
if (linePart=="$specular")//todo load this values:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
if(linePart=="$diffuse")
|
else if (linePart=="$diffuse")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
if(linePart=="$ambient")
|
else if (linePart=="$ambient")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
if(linePart=="$colormap")
|
else if (linePart=="$colormap")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
aiString ts(linePart.c_str());
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||||
}
|
}
|
||||||
if(linePart=="$normalmap")
|
else if (linePart=="$normalmap")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
aiString ts(linePart.c_str());
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||||
}
|
}
|
||||||
|
else if (linePart=="$shininess_strength")
|
||||||
if(linePart=="$shininess_strength")
|
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
float Shininess=fast_atof(linePart.c_str());
|
float Shininess = fast_atof(linePart.c_str());
|
||||||
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
|
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||||
}
|
}
|
||||||
|
else if (linePart=="$shininess_exponent")
|
||||||
if(linePart=="$shininess_exponent")
|
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
float Shininess=fast_atof(linePart.c_str());
|
float Shininess = fast_atof(linePart.c_str());
|
||||||
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
|
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Properties from Venetica:
|
//Properties from Venetica:
|
||||||
if(linePart=="$diffuse_map")
|
else if (linePart=="$diffuse_map")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
if(linePart[0]=='"')// "file" -> file
|
if (linePart[0] == '"')// "file" -> file
|
||||||
linePart=linePart.substr(1, linePart.size()-2);
|
linePart = linePart.substr(1, linePart.size()-2);
|
||||||
aiString ts(linePart.c_str());
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||||
}
|
}
|
||||||
if(linePart=="$specular_map")
|
else if (linePart=="$specular_map")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
if(linePart[0]=='"')// "file" -> file
|
if (linePart[0] == '"')// "file" -> file
|
||||||
linePart=linePart.substr(1, linePart.size()-2);
|
linePart = linePart.substr(1, linePart.size()-2);
|
||||||
aiString ts(linePart.c_str());
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
|
||||||
}
|
}
|
||||||
if(linePart=="$normal_map")
|
else if (linePart=="$normal_map")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
if(linePart[0]=='"')// "file" -> file
|
if (linePart[0]=='"')// "file" -> file
|
||||||
linePart=linePart.substr(1, linePart.size()-2);
|
linePart = linePart.substr(1, linePart.size()-2);
|
||||||
aiString ts(linePart.c_str());
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
||||||
}
|
}
|
||||||
if(linePart=="$light_map")
|
else if (linePart=="$light_map")
|
||||||
{
|
{
|
||||||
ss >> linePart;
|
ss >> linePart;
|
||||||
if(linePart[0]=='"')// "file" -> file
|
if (linePart[0]=='"') {
|
||||||
linePart=linePart.substr(1, linePart.size()-2);
|
linePart = linePart.substr(1, linePart.size() - 2);
|
||||||
aiString ts(linePart.c_str());
|
}
|
||||||
|
aiString ts(linePart);
|
||||||
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
|
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,13 +363,21 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b);
|
DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b);
|
||||||
|
|
||||||
if (linePart == partAmbient)
|
if (linePart == partAmbient)
|
||||||
|
{
|
||||||
material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
}
|
||||||
else if (linePart == partDiffuse)
|
else if (linePart == partDiffuse)
|
||||||
|
{
|
||||||
material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||||
|
}
|
||||||
else if (linePart == partSpecular)
|
else if (linePart == partSpecular)
|
||||||
|
{
|
||||||
material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||||
|
}
|
||||||
else if (linePart == partEmissive)
|
else if (linePart == partEmissive)
|
||||||
|
{
|
||||||
material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
|
material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (linePart == partTextureUnit)
|
else if (linePart == partTextureUnit)
|
||||||
{
|
{
|
||||||
|
@ -430,18 +438,30 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
|
||||||
DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'");
|
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")
|
if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
|
||||||
|
{
|
||||||
textureType = aiTextureType_NORMALS;
|
textureType = aiTextureType_NORMALS;
|
||||||
|
}
|
||||||
else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
|
else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
|
||||||
|
{
|
||||||
textureType = aiTextureType_SPECULAR;
|
textureType = aiTextureType_SPECULAR;
|
||||||
|
}
|
||||||
else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
|
else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
|
||||||
|
{
|
||||||
textureType = aiTextureType_LIGHTMAP;
|
textureType = aiTextureType_LIGHTMAP;
|
||||||
|
}
|
||||||
else if (identifier == "_disp" || identifier == "_displacement")
|
else if (identifier == "_disp" || identifier == "_displacement")
|
||||||
|
{
|
||||||
textureType = aiTextureType_DISPLACEMENT;
|
textureType = aiTextureType_DISPLACEMENT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
textureType = aiTextureType_DIFFUSE;
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
textureType = aiTextureType_DIFFUSE;
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Detect from texture unit name. This cannot be too broad as
|
// Detect from texture unit name. This cannot be too broad as
|
||||||
// authors might give names like "LightSaber" or "NormalNinja".
|
// authors might give names like "LightSaber" or "NormalNinja".
|
||||||
|
@ -449,15 +469,25 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr
|
||||||
{
|
{
|
||||||
string unitNameLower = Ogre::ToLower(textureUnitName);
|
string unitNameLower = Ogre::ToLower(textureUnitName);
|
||||||
if (unitNameLower.find("normalmap") != string::npos)
|
if (unitNameLower.find("normalmap") != string::npos)
|
||||||
|
{
|
||||||
textureType = aiTextureType_NORMALS;
|
textureType = aiTextureType_NORMALS;
|
||||||
|
}
|
||||||
else if (unitNameLower.find("specularmap") != string::npos)
|
else if (unitNameLower.find("specularmap") != string::npos)
|
||||||
|
{
|
||||||
textureType = aiTextureType_SPECULAR;
|
textureType = aiTextureType_SPECULAR;
|
||||||
|
}
|
||||||
else if (unitNameLower.find("lightmap") != string::npos)
|
else if (unitNameLower.find("lightmap") != string::npos)
|
||||||
|
{
|
||||||
textureType = aiTextureType_LIGHTMAP;
|
textureType = aiTextureType_LIGHTMAP;
|
||||||
|
}
|
||||||
else if (unitNameLower.find("displacementmap") != string::npos)
|
else if (unitNameLower.find("displacementmap") != string::npos)
|
||||||
|
{
|
||||||
textureType = aiTextureType_DISPLACEMENT;
|
textureType = aiTextureType_DISPLACEMENT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
textureType = aiTextureType_DIFFUSE;
|
textureType = aiTextureType_DIFFUSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (linePart == partTextCoordSet)
|
else if (linePart == partTextCoordSet)
|
||||||
|
|
|
@ -54,12 +54,15 @@ namespace Ogre
|
||||||
|
|
||||||
void OgreImporter::ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh, XmlReader *reader)
|
void OgreImporter::ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh, XmlReader *reader)
|
||||||
{
|
{
|
||||||
if (reader->getAttributeValue("material"))
|
if (reader->getAttributeValue("material")) {
|
||||||
submesh.MaterialName = GetAttribute<string>(reader, "material");
|
submesh.MaterialName = GetAttribute<string>(reader, "material");
|
||||||
if (reader->getAttributeValue("use32bitindexes"))
|
}
|
||||||
|
if (reader->getAttributeValue("use32bitindexes")) {
|
||||||
submesh.Use32bitIndexes = GetAttribute<bool>(reader, "use32bitindexes");
|
submesh.Use32bitIndexes = GetAttribute<bool>(reader, "use32bitindexes");
|
||||||
if (reader->getAttributeValue("usesharedvertices"))
|
}
|
||||||
|
if (reader->getAttributeValue("usesharedvertices")) {
|
||||||
submesh.UseSharedGeometry = GetAttribute<bool>(reader, "usesharedvertices");
|
submesh.UseSharedGeometry = GetAttribute<bool>(reader, "usesharedvertices");
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug(Formatter::format() << "Reading submesh " << submeshIndex);
|
DefaultLogger::get()->debug(Formatter::format() << "Reading submesh " << submeshIndex);
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " - Material '" << submesh.MaterialName << "'");
|
DefaultLogger::get()->debug(Formatter::format() << " - Material '" << submesh.MaterialName << "'");
|
||||||
|
@ -100,8 +103,9 @@ void OgreImporter::ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh
|
||||||
NewFace.VertexIndices[2] = GetAttribute<int>(reader, "v3");
|
NewFace.VertexIndices[2] = GetAttribute<int>(reader, "v3");
|
||||||
|
|
||||||
/// @todo Support quads
|
/// @todo Support quads
|
||||||
if (!quadWarned && reader->getAttributeValue("v4"))
|
if (!quadWarned && reader->getAttributeValue("v4")) {
|
||||||
DefaultLogger::get()->warn("Submesh has quads, only triangles are supported at the moment!");
|
DefaultLogger::get()->warn("Submesh has quads, only triangles are supported at the moment!");
|
||||||
|
}
|
||||||
|
|
||||||
submesh.Faces.push_back(NewFace);
|
submesh.Faces.push_back(NewFace);
|
||||||
|
|
||||||
|
@ -111,20 +115,27 @@ void OgreImporter::ReadSubMesh(const unsigned int submeshIndex, SubMesh &submesh
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submesh.Faces.size() == numFaces)
|
if (submesh.Faces.size() == numFaces)
|
||||||
|
{
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " - Faces " << numFaces);
|
DefaultLogger::get()->debug(Formatter::format() << " - Faces " << numFaces);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Faces.size() << " faces when should have read " << numFaces);
|
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Faces.size() << " faces when should have read " << numFaces);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (currentNodeName == nnGeometry)
|
else if (currentNodeName == nnGeometry)
|
||||||
{
|
{
|
||||||
unsigned int numVertices = GetAttribute<int>(reader, "vertexcount");
|
unsigned int numVertices = GetAttribute<int>(reader, "vertexcount");
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
while(string(reader->getNodeName()) == nnVertexBuffer)
|
while(string(reader->getNodeName()) == nnVertexBuffer) {
|
||||||
ReadVertexBuffer(submesh, reader, numVertices);
|
ReadVertexBuffer(submesh, reader, numVertices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (reader->getNodeName() == nnBoneAssignments)
|
else if (reader->getNodeName() == nnBoneAssignments)
|
||||||
|
{
|
||||||
ReadBoneWeights(submesh, reader);
|
ReadBoneWeights(submesh, reader);
|
||||||
|
}
|
||||||
|
|
||||||
currentNodeName = reader->getNodeName();
|
currentNodeName = reader->getNodeName();
|
||||||
}
|
}
|
||||||
|
@ -157,13 +168,15 @@ void OgreImporter::ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const u
|
||||||
if (reader->getAttributeValue("texture_coords"))
|
if (reader->getAttributeValue("texture_coords"))
|
||||||
{
|
{
|
||||||
submesh.Uvs.resize(GetAttribute<unsigned int>(reader, "texture_coords"));
|
submesh.Uvs.resize(GetAttribute<unsigned int>(reader, "texture_coords"));
|
||||||
for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
|
for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i) {
|
||||||
submesh.Uvs[i].reserve(numVertices);
|
submesh.Uvs[i].reserve(numVertices);
|
||||||
|
}
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " - Has " << submesh.Uvs.size() << " texture coords");
|
DefaultLogger::get()->debug(Formatter::format() << " - Has " << submesh.Uvs.size() << " texture coords");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submesh.HasPositions)
|
if (!submesh.HasPositions) {
|
||||||
throw DeadlyImportError("Vertex buffer does not contain positions!");
|
throw DeadlyImportError("Vertex buffer does not contain positions!");
|
||||||
|
}
|
||||||
|
|
||||||
const string nnVertex = "vertex";
|
const string nnVertex = "vertex";
|
||||||
const string nnPosition = "position";
|
const string nnPosition = "position";
|
||||||
|
@ -227,8 +240,9 @@ void OgreImporter::ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const u
|
||||||
{
|
{
|
||||||
for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
|
for(size_t i=0, len=submesh.Uvs.size(); i<len; ++i)
|
||||||
{
|
{
|
||||||
if (currentNodeName != nnTexCoord)
|
if (currentNodeName != nnTexCoord) {
|
||||||
throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
|
throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D NewUv;
|
aiVector3D NewUv;
|
||||||
NewUv.x = GetAttribute<float>(reader, "u");
|
NewUv.x = GetAttribute<float>(reader, "u");
|
||||||
|
@ -248,26 +262,39 @@ void OgreImporter::ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const u
|
||||||
if (currentNodeName == nnBinormal)
|
if (currentNodeName == nnBinormal)
|
||||||
{
|
{
|
||||||
if (warnBinormal)
|
if (warnBinormal)
|
||||||
|
{
|
||||||
warnBinormal = false;
|
warnBinormal = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
warn = false;
|
warn = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (currentNodeName == nnColorDiffuse)
|
else if (currentNodeName == nnColorDiffuse)
|
||||||
{
|
{
|
||||||
if (warnColorDiffuse)
|
if (warnColorDiffuse)
|
||||||
|
{
|
||||||
warnColorDiffuse = false;
|
warnColorDiffuse = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
warn = false;
|
warn = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (currentNodeName == nnColorSpecular)
|
else if (currentNodeName == nnColorSpecular)
|
||||||
{
|
{
|
||||||
if (warnColorSpecular)
|
if (warnColorSpecular)
|
||||||
|
{
|
||||||
warnColorSpecular = false;
|
warnColorSpecular = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
warn = false;
|
warn = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (warn)
|
if (warn) {
|
||||||
DefaultLogger::get()->warn(string("Vertex buffer attribute read not implemented for element: ") + currentNodeName);
|
DefaultLogger::get()->warn(string("Vertex buffer attribute read not implemented for element: ") + currentNodeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance
|
// Advance
|
||||||
|
@ -282,15 +309,18 @@ void OgreImporter::ReadVertexBuffer(SubMesh &submesh, XmlReader *reader, const u
|
||||||
" Tangents " << submesh.Tangents.size());
|
" Tangents " << submesh.Tangents.size());
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (submesh.HasNormals && submesh.Normals.size() != numVertices)
|
if (submesh.HasNormals && submesh.Normals.size() != numVertices) {
|
||||||
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Normals.size() << " normals when should have read " << numVertices);
|
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Normals.size() << " normals when should have read " << numVertices);
|
||||||
if (submesh.HasTangents && submesh.Tangents.size() != numVertices)
|
}
|
||||||
|
if (submesh.HasTangents && submesh.Tangents.size() != numVertices) {
|
||||||
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Tangents.size() << " tangents when should have read " << numVertices);
|
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Tangents.size() << " tangents when should have read " << numVertices);
|
||||||
|
}
|
||||||
for(unsigned int i=0; i<submesh.Uvs.size(); ++i)
|
for(unsigned int i=0; i<submesh.Uvs.size(); ++i)
|
||||||
{
|
{
|
||||||
if (submesh.Uvs[i].size() != numVertices)
|
if (submesh.Uvs[i].size() != numVertices) {
|
||||||
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Uvs[i].size()
|
throw DeadlyImportError(Formatter::format() << "Read only " << submesh.Uvs[i].size()
|
||||||
<< " uvs for uv index " << i << " when should have read " << numVertices);
|
<< " uvs for uv index " << i << " when should have read " << numVertices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,8 +365,9 @@ void OgreImporter::ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry)
|
||||||
vector<vector<BoneWeight> > uniqueWeights(uniqueVertexCount);
|
vector<vector<BoneWeight> > uniqueWeights(uniqueVertexCount);
|
||||||
vector<vector<aiVector3D> > uniqueUvs(submesh.UseSharedGeometry ? sharedGeometry.Uvs.size() : submesh.Uvs.size());
|
vector<vector<aiVector3D> > uniqueUvs(submesh.UseSharedGeometry ? sharedGeometry.Uvs.size() : submesh.Uvs.size());
|
||||||
|
|
||||||
for(size_t uvi=0; uvi<uniqueUvs.size(); ++uvi)
|
for(size_t uvi=0; uvi<uniqueUvs.size(); ++uvi) {
|
||||||
uniqueUvs[uvi].resize(uniqueVertexCount);
|
uniqueUvs[uvi].resize(uniqueVertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
/* Support for shared geometry.
|
/* Support for shared geometry.
|
||||||
We can use this loop to copy vertex informations from the shared data pool. In order to do so
|
We can use this loop to copy vertex informations from the shared data pool. In order to do so
|
||||||
|
@ -417,13 +448,17 @@ void OgreImporter::ProcessSubMesh(SubMesh &submesh, SubMesh &sharedGeometry)
|
||||||
std::vector<BoneWeight> &weights = submesh.Weights[vertexId];
|
std::vector<BoneWeight> &weights = submesh.Weights[vertexId];
|
||||||
|
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId)
|
for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId) {
|
||||||
sum += weights[boneId].Value;
|
sum += weights[boneId].Value;
|
||||||
|
}
|
||||||
|
|
||||||
//check if the sum is too far away from 1
|
//check if the sum is too far away from 1
|
||||||
if ((sum < (1.0f - 0.05f)) || (sum > (1.0f + 0.05f)))
|
if ((sum < (1.0f - 0.05f)) || (sum > (1.0f + 0.05f)))
|
||||||
for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId)
|
{
|
||||||
|
for(size_t boneId=0, blen=weights.size(); boneId<blen; ++boneId) {
|
||||||
weights[boneId].Value /= sum;
|
weights[boneId].Value /= sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,8 +520,9 @@ aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submes
|
||||||
for(size_t boneId=0, len=submesh.BonesUsed; boneId<len; ++boneId)
|
for(size_t boneId=0, len=submesh.BonesUsed; boneId<len; ++boneId)
|
||||||
{
|
{
|
||||||
const vector<aiVertexWeight> &boneWeights = assimpWeights[boneId];
|
const vector<aiVertexWeight> &boneWeights = assimpWeights[boneId];
|
||||||
if (boneWeights.size() == 0)
|
if (boneWeights.size() == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// @note The bones list is sorted by id's, this was done in LoadSkeleton.
|
// @note The bones list is sorted by id's, this was done in LoadSkeleton.
|
||||||
aiBone *assimpBone = new aiBone();
|
aiBone *assimpBone = new aiBone();
|
||||||
|
@ -504,8 +540,9 @@ aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submes
|
||||||
dest->mBones = new aiBone*[assimpBones.size()];
|
dest->mBones = new aiBone*[assimpBones.size()];
|
||||||
dest->mNumBones = assimpBones.size();
|
dest->mNumBones = assimpBones.size();
|
||||||
|
|
||||||
for(size_t i=0, len=assimpBones.size(); i<len; ++i)
|
for(size_t i=0, len=assimpBones.size(); i<len; ++i) {
|
||||||
dest->mBones[i] = assimpBones[i];
|
dest->mBones[i] = assimpBones[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Faces
|
// Faces
|
||||||
|
|
|
@ -18,9 +18,13 @@ 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 = "")
|
||||||
{
|
{
|
||||||
if (!error.empty())
|
if (!error.empty())
|
||||||
|
{
|
||||||
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
|
throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
|
throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -31,7 +35,9 @@ inline int GetAttribute<int>(const XmlReader* reader, const std::string &name)
|
||||||
{
|
{
|
||||||
const char* value = reader->getAttributeValue(name.c_str());
|
const char* value = reader->getAttributeValue(name.c_str());
|
||||||
if (value)
|
if (value)
|
||||||
|
{
|
||||||
return atoi(value);
|
return atoi(value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowAttibuteError(reader, name);
|
ThrowAttibuteError(reader, name);
|
||||||
|
@ -44,7 +50,9 @@ inline unsigned int GetAttribute<unsigned int>(const XmlReader* reader, const st
|
||||||
{
|
{
|
||||||
const char* value = reader->getAttributeValue(name.c_str());
|
const char* value = reader->getAttributeValue(name.c_str());
|
||||||
if (value)
|
if (value)
|
||||||
|
{
|
||||||
return static_cast<unsigned int>(atoi(value)); ///< @todo Find a better way...
|
return static_cast<unsigned int>(atoi(value)); ///< @todo Find a better way...
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowAttibuteError(reader, name);
|
ThrowAttibuteError(reader, name);
|
||||||
|
@ -57,7 +65,9 @@ inline float GetAttribute<float>(const XmlReader* reader, const std::string &nam
|
||||||
{
|
{
|
||||||
const char* value = reader->getAttributeValue(name.c_str());
|
const char* value = reader->getAttributeValue(name.c_str());
|
||||||
if (value)
|
if (value)
|
||||||
|
{
|
||||||
return fast_atof(value);
|
return fast_atof(value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowAttibuteError(reader, name);
|
ThrowAttibuteError(reader, name);
|
||||||
|
@ -70,7 +80,9 @@ inline std::string GetAttribute<std::string>(const XmlReader* reader, const std:
|
||||||
{
|
{
|
||||||
const char* value = reader->getAttributeValue(name.c_str());
|
const char* value = reader->getAttributeValue(name.c_str());
|
||||||
if (value)
|
if (value)
|
||||||
|
{
|
||||||
return std::string(value);
|
return std::string(value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowAttibuteError(reader, name);
|
ThrowAttibuteError(reader, name);
|
||||||
|
@ -83,9 +95,13 @@ inline bool GetAttribute<bool>(const XmlReader* reader, const std::string &name)
|
||||||
{
|
{
|
||||||
std::string value = GetAttribute<std::string>(reader, name);
|
std::string value = GetAttribute<std::string>(reader, name);
|
||||||
if (ASSIMP_stricmp(value, "true") == 0)
|
if (ASSIMP_stricmp(value, "true") == 0)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
else if (ASSIMP_stricmp(value, "false") == 0)
|
else if (ASSIMP_stricmp(value, "false") == 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowAttibuteError(reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
|
ThrowAttibuteError(reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
|
||||||
|
@ -97,8 +113,9 @@ inline bool NextNode(XmlReader* reader)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!reader->read())
|
if (!reader->read()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while(reader->getNodeType() != irr::io::EXN_ELEMENT);
|
while(reader->getNodeType() != irr::io::EXN_ELEMENT);
|
||||||
return true;
|
return true;
|
||||||
|
@ -137,12 +154,17 @@ static inline std::string ToLower(std::string s)
|
||||||
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
|
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
|
||||||
{
|
{
|
||||||
if (s.empty() || suffix.empty())
|
if (s.empty() || suffix.empty())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
else if (s.length() < suffix.length())
|
else if (s.length() < suffix.length())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!caseSensitive)
|
if (!caseSensitive) {
|
||||||
return EndsWith(ToLower(s), ToLower(suffix), true);
|
return EndsWith(ToLower(s), ToLower(suffix), true);
|
||||||
|
}
|
||||||
|
|
||||||
size_t len = suffix.length();
|
size_t len = suffix.length();
|
||||||
std::string sSuffix = s.substr(s.length()-len, len);
|
std::string sSuffix = s.substr(s.length()-len, len);
|
||||||
|
@ -155,9 +177,13 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo
|
||||||
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
|
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
|
||||||
{
|
{
|
||||||
if (!newlines)
|
if (!newlines)
|
||||||
|
{
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +191,13 @@ static inline std::string &TrimLeft(std::string &s, bool newlines = true)
|
||||||
static inline std::string &TrimRight(std::string &s, bool newlines = true)
|
static inline std::string &TrimRight(std::string &s, bool newlines = true)
|
||||||
{
|
{
|
||||||
if (!newlines)
|
if (!newlines)
|
||||||
|
{
|
||||||
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
|
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,53 +69,60 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::scoped_ptr<IOStream> file(pIOHandler->Open(filename));
|
boost::scoped_ptr<IOStream> file(pIOHandler->Open(filename));
|
||||||
if (!file.get())
|
if (!file.get()) {
|
||||||
throw DeadlyImportError("Failed to open skeleton file " + filename);
|
throw DeadlyImportError("Failed to open skeleton file " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
boost::scoped_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
|
boost::scoped_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
|
||||||
XmlReader* reader = irr::io::createIrrXMLReader(stream.get());
|
XmlReader* reader = irr::io::createIrrXMLReader(stream.get());
|
||||||
if (!reader)
|
if (!reader) {
|
||||||
throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
|
throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug("Reading skeleton '" + filename + "'");
|
DefaultLogger::get()->debug("Reading skeleton '" + filename + "'");
|
||||||
|
|
||||||
// Root
|
// Root
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "skeleton"))
|
if (!CurrentNodeNameEquals(reader, "skeleton")) {
|
||||||
throw DeadlyImportError("Root node is not <skeleton> but <" + string(reader->getNodeName()) + "> in " + filename);
|
throw DeadlyImportError("Root node is not <skeleton> but <" + string(reader->getNodeName()) + "> in " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
// Bones
|
// Bones
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "bones"))
|
if (!CurrentNodeNameEquals(reader, "bones")) {
|
||||||
throw DeadlyImportError("No <bones> node in skeleton " + skeletonFile);
|
throw DeadlyImportError("No <bones> node in skeleton " + skeletonFile);
|
||||||
|
}
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
while(CurrentNodeNameEquals(reader, "bone"))
|
while(CurrentNodeNameEquals(reader, "bone"))
|
||||||
{
|
{
|
||||||
//TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what....
|
/** @todo Fix this mandatory ordering. Some exporters might just write rotation first etc.
|
||||||
/// @todo What does the above mean?
|
There is no technical reason this has to be so strict. */
|
||||||
|
|
||||||
Bone bone;
|
Bone bone;
|
||||||
bone.Id = GetAttribute<int>(reader, "id");
|
bone.Id = GetAttribute<int>(reader, "id");
|
||||||
bone.Name = GetAttribute<string>(reader, "name");
|
bone.Name = GetAttribute<string>(reader, "name");
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "position"))
|
if (!CurrentNodeNameEquals(reader, "position")) {
|
||||||
throw DeadlyImportError("Position is not first node in Bone!");
|
throw DeadlyImportError("Position is not first node in Bone!");
|
||||||
|
}
|
||||||
|
|
||||||
bone.Position.x = GetAttribute<float>(reader, "x");
|
bone.Position.x = GetAttribute<float>(reader, "x");
|
||||||
bone.Position.y = GetAttribute<float>(reader, "y");
|
bone.Position.y = GetAttribute<float>(reader, "y");
|
||||||
bone.Position.z = GetAttribute<float>(reader, "z");
|
bone.Position.z = GetAttribute<float>(reader, "z");
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "rotation"))
|
if (!CurrentNodeNameEquals(reader, "rotation")) {
|
||||||
throw DeadlyImportError("Rotation is not the second node in Bone!");
|
throw DeadlyImportError("Rotation is not the second node in Bone!");
|
||||||
|
}
|
||||||
|
|
||||||
bone.RotationAngle = GetAttribute<float>(reader, "angle");
|
bone.RotationAngle = GetAttribute<float>(reader, "angle");
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "axis"))
|
if (!CurrentNodeNameEquals(reader, "axis")) {
|
||||||
throw DeadlyImportError("No axis specified for bone rotation!");
|
throw DeadlyImportError("No axis specified for bone rotation!");
|
||||||
|
}
|
||||||
|
|
||||||
bone.RotationAxis.x = GetAttribute<float>(reader, "x");
|
bone.RotationAxis.x = GetAttribute<float>(reader, "x");
|
||||||
bone.RotationAxis.y = GetAttribute<float>(reader, "y");
|
bone.RotationAxis.y = GetAttribute<float>(reader, "y");
|
||||||
|
@ -133,14 +140,18 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
/** @note Left this from original authors code, but not sure if this is strictly necessary
|
/** @note Left this from original authors code, but not sure if this is strictly necessary
|
||||||
as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
|
as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
|
||||||
for (size_t i=0, len=Bones.size(); i<len; ++i)
|
for (size_t i=0, len=Bones.size(); i<len; ++i)
|
||||||
if (static_cast<int>(Bones[i].Id) != static_cast<int>(i))
|
{
|
||||||
|
if (static_cast<int>(Bones[i].Id) != static_cast<int>(i)) {
|
||||||
throw DeadlyImportError("Bone Ids are not in sequence in " + skeletonFile);
|
throw DeadlyImportError("Bone Ids are not in sequence in " + skeletonFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " - Bones " << Bones.size());
|
DefaultLogger::get()->debug(Formatter::format() << " - Bones " << Bones.size());
|
||||||
|
|
||||||
// Bone hierarchy
|
// Bone hierarchy
|
||||||
if (!CurrentNodeNameEquals(reader, "bonehierarchy"))
|
if (!CurrentNodeNameEquals(reader, "bonehierarchy")) {
|
||||||
throw DeadlyImportError("No <bonehierarchy> node found after <bones> in " + skeletonFile);
|
throw DeadlyImportError("No <bonehierarchy> node found after <bones> in " + skeletonFile);
|
||||||
|
}
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
while(CurrentNodeNameEquals(reader, "boneparent"))
|
while(CurrentNodeNameEquals(reader, "boneparent"))
|
||||||
|
@ -157,7 +168,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
iterParent->Children.push_back(iterChild->Id);
|
iterParent->Children.push_back(iterChild->Id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
DefaultLogger::get()->warn("Failed to find bones for parenting: Child " + childName + " Parent " + parentName);
|
DefaultLogger::get()->warn("Failed to find bones for parenting: Child " + childName + " Parent " + parentName);
|
||||||
|
}
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
}
|
}
|
||||||
|
@ -165,8 +178,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
// Calculate bone matrices for root bones. Recursively does their children.
|
// Calculate bone matrices for root bones. Recursively does their children.
|
||||||
BOOST_FOREACH(Bone &theBone, Bones)
|
BOOST_FOREACH(Bone &theBone, Bones)
|
||||||
{
|
{
|
||||||
if (!theBone.IsParented())
|
if (!theBone.IsParented()) {
|
||||||
theBone.CalculateBoneToWorldSpaceMatrix(Bones);
|
theBone.CalculateBoneToWorldSpaceMatrix(Bones);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aiVector3D zeroVec(0.f, 0.f, 0.f);
|
aiVector3D zeroVec(0.f, 0.f, 0.f);
|
||||||
|
@ -185,8 +199,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
|
|
||||||
// Tracks
|
// Tracks
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "tracks"))
|
if (!CurrentNodeNameEquals(reader, "tracks")) {
|
||||||
throw DeadlyImportError("No <tracks> node found in animation '" + animation.Name + "' in " + skeletonFile);
|
throw DeadlyImportError("No <tracks> node found in animation '" + animation.Name + "' in " + skeletonFile);
|
||||||
|
}
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
while(CurrentNodeNameEquals(reader, "track"))
|
while(CurrentNodeNameEquals(reader, "track"))
|
||||||
|
@ -196,8 +211,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
|
|
||||||
// Keyframes
|
// Keyframes
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if (!CurrentNodeNameEquals(reader, "keyframes"))
|
if (!CurrentNodeNameEquals(reader, "keyframes")) {
|
||||||
throw DeadlyImportError("No <keyframes> node found in a track in animation '" + animation.Name + "' in " + skeletonFile);
|
throw DeadlyImportError("No <keyframes> node found in a track in animation '" + animation.Name + "' in " + skeletonFile);
|
||||||
|
}
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
while(CurrentNodeNameEquals(reader, "keyframe"))
|
while(CurrentNodeNameEquals(reader, "keyframe"))
|
||||||
|
@ -219,8 +235,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
float angle = GetAttribute<float>(reader, "angle");
|
float angle = GetAttribute<float>(reader, "angle");
|
||||||
|
|
||||||
NextNode(reader);
|
NextNode(reader);
|
||||||
if(string("axis")!=reader->getNodeName())
|
if (!CurrentNodeNameEquals(reader, "axis")) {
|
||||||
throw DeadlyImportError("No axis for keyframe rotation!");
|
throw DeadlyImportError("No axis for keyframe rotation in animation '" + animation.Name + "'");
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D axis;
|
aiVector3D axis;
|
||||||
axis.x = GetAttribute<float>(reader, "x");
|
axis.x = GetAttribute<float>(reader, "x");
|
||||||
|
@ -230,8 +247,9 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
if (axis.Equal(zeroVec))
|
if (axis.Equal(zeroVec))
|
||||||
{
|
{
|
||||||
axis.x = 1.0f;
|
axis.x = 1.0f;
|
||||||
if (angle != 0)
|
if (angle != 0) {
|
||||||
DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation '" + animation.Name + "'");
|
DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation '" + animation.Name + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keyFrame.Rotation = aiQuaternion(axis, angle);
|
keyFrame.Rotation = aiQuaternion(axis, angle);
|
||||||
}
|
}
|
||||||
|
@ -256,20 +274,24 @@ void OgreImporter::ReadSkeleton(const std::string &pFile, Assimp::IOSystem *pIOH
|
||||||
|
|
||||||
void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, 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 (bones.empty())
|
if (bones.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!pScene->mRootNode)
|
if (!pScene->mRootNode) {
|
||||||
throw DeadlyImportError("Creating Assimp skeleton: No root node created!");
|
throw DeadlyImportError("Creating Assimp skeleton: No root node created!");
|
||||||
if (pScene->mRootNode->mNumChildren > 0)
|
}
|
||||||
|
if (pScene->mRootNode->mNumChildren > 0) {
|
||||||
throw DeadlyImportError("Creating Assimp skeleton: Root node already has children!");
|
throw DeadlyImportError("Creating Assimp skeleton: Root node already has children!");
|
||||||
|
}
|
||||||
|
|
||||||
// Bones
|
// Bones
|
||||||
vector<aiNode*> rootBones;
|
vector<aiNode*> rootBones;
|
||||||
BOOST_FOREACH(const Bone &bone, bones)
|
BOOST_FOREACH(const Bone &bone, bones)
|
||||||
{
|
{
|
||||||
if (!bone.IsParented())
|
if (!bone.IsParented()) {
|
||||||
rootBones.push_back(CreateNodeFromBone(bone.Id, bones, pScene->mRootNode));
|
rootBones.push_back(CreateNodeFromBone(bone.Id, bones, pScene->mRootNode));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rootBones.empty())
|
if (!rootBones.empty())
|
||||||
|
@ -277,8 +299,9 @@ void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone>
|
||||||
pScene->mRootNode->mChildren = new aiNode*[rootBones.size()];
|
pScene->mRootNode->mChildren = new aiNode*[rootBones.size()];
|
||||||
pScene->mRootNode->mNumChildren = rootBones.size();
|
pScene->mRootNode->mNumChildren = rootBones.size();
|
||||||
|
|
||||||
for(size_t i=0, len=rootBones.size(); i<len; ++i)
|
for(size_t i=0, len=rootBones.size(); i<len; ++i) {
|
||||||
pScene->mRootNode->mChildren[i] = rootBones[i];
|
pScene->mRootNode->mChildren[i] = rootBones[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Auf nicht vorhandene Animationskeys achten!
|
// TODO: Auf nicht vorhandene Animationskeys achten!
|
||||||
|
@ -315,8 +338,9 @@ void OgreImporter::CreateAssimpSkeleton(aiScene *pScene, const std::vector<Bone>
|
||||||
vector<Bone>::const_iterator boneIter = find(bones.begin(), bones.end(), tSource.BoneName);
|
vector<Bone>::const_iterator boneIter = find(bones.begin(), bones.end(), tSource.BoneName);
|
||||||
if (boneIter == bones.end())
|
if (boneIter == bones.end())
|
||||||
{
|
{
|
||||||
for(unsigned int a=0; a<ai; a++)
|
for(size_t createdAnimationIndex=0; createdAnimationIndex<ai; createdAnimationIndex++) {
|
||||||
delete pScene->mAnimations[a];
|
delete pScene->mAnimations[createdAnimationIndex];
|
||||||
|
}
|
||||||
delete [] pScene->mAnimations;
|
delete [] pScene->mAnimations;
|
||||||
pScene->mAnimations = NULL;
|
pScene->mAnimations = NULL;
|
||||||
pScene->mNumAnimations = 0;
|
pScene->mNumAnimations = 0;
|
||||||
|
@ -387,8 +411,9 @@ aiNode* OgreImporter::CreateNodeFromBone(int boneId, const std::vector<Bone> &bo
|
||||||
boneNode->mChildren = new aiNode*[source.Children.size()];
|
boneNode->mChildren = new aiNode*[source.Children.size()];
|
||||||
boneNode->mNumChildren = source.Children.size();
|
boneNode->mNumChildren = source.Children.size();
|
||||||
|
|
||||||
for(size_t i=0, len=source.Children.size(); i<len; ++i)
|
for(size_t i=0, len=source.Children.size(); i<len; ++i) {
|
||||||
boneNode->mChildren[i] = CreateNodeFromBone(source.Children[i], bones, boneNode);
|
boneNode->mChildren[i] = CreateNodeFromBone(source.Children[i], bones, boneNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return boneNode;
|
return boneNode;
|
||||||
|
@ -400,9 +425,13 @@ void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones)
|
||||||
aiMatrix4x4 transform = aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1) * aiMatrix4x4::Translation(-Position, t0);
|
aiMatrix4x4 transform = aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1) * aiMatrix4x4::Translation(-Position, t0);
|
||||||
|
|
||||||
if (!IsParented())
|
if (!IsParented())
|
||||||
|
{
|
||||||
BoneToWorldSpace = transform;
|
BoneToWorldSpace = transform;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
BoneToWorldSpace = transform * Bones[ParentId].BoneToWorldSpace;
|
BoneToWorldSpace = transform * Bones[ParentId].BoneToWorldSpace;
|
||||||
|
}
|
||||||
|
|
||||||
// Recursively for all children now that the parent matrix has been calculated.
|
// Recursively for all children now that the parent matrix has been calculated.
|
||||||
BOOST_FOREACH(int childId, Children)
|
BOOST_FOREACH(int childId, Children)
|
||||||
|
|
Loading…
Reference in New Issue