Ogre:
- better support for OgreXmlConverter generated files git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1177 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/5/head
parent
37fb338c1f
commit
521088e134
|
@ -326,7 +326,8 @@ SET( Obj_SRCS
|
||||||
SOURCE_GROUP( Obj FILES ${Obj_SRCS})
|
SOURCE_GROUP( Obj FILES ${Obj_SRCS})
|
||||||
|
|
||||||
SET( Ogre_SRCS
|
SET( Ogre_SRCS
|
||||||
OgreImporter.h
|
OgreImporter.hpp
|
||||||
|
OgreXmlHelper.hpp
|
||||||
OgreImporter.cpp
|
OgreImporter.cpp
|
||||||
OgreImporterMaterial.cpp
|
OgreImporterMaterial.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -140,7 +140,7 @@ corresponding preprocessor flag to selectively disable formats.
|
||||||
# include "LWSLoader.h"
|
# include "LWSLoader.h"
|
||||||
#endif
|
#endif
|
||||||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||||
# include "OgreImporter.h"
|
# include "OgreImporter.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
|
||||||
# include "MS3DLoader.h"
|
# include "MS3DLoader.h"
|
||||||
|
|
|
@ -54,7 +54,7 @@ using namespace std;
|
||||||
|
|
||||||
#include "TinyFormatter.h"
|
#include "TinyFormatter.h"
|
||||||
|
|
||||||
#include "OgreImporter.h"
|
#include "OgreImporter.hpp"
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +80,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_CurrentFilename=pFile;
|
||||||
|
@ -198,7 +197,6 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OgreImporter::GetExtensionList(std::set<std::string>& extensions)
|
void OgreImporter::GetExtensionList(std::set<std::string>& extensions)
|
||||||
{
|
{
|
||||||
extensions.insert("mesh.xml");
|
extensions.insert("mesh.xml");
|
||||||
|
@ -210,6 +208,7 @@ void OgreImporter::SetupProperties(const Importer* pImp)
|
||||||
m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
{
|
{
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
|
@ -242,63 +241,28 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
{
|
{
|
||||||
//some info logging:
|
//some info logging:
|
||||||
unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
|
unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
|
||||||
ostringstream ss; ss<<"VertexCount: "<<NumVertices;
|
ostringstream ss; ss<<"VertexCount: " << NumVertices;
|
||||||
DefaultLogger::get()->debug(ss.str());
|
DefaultLogger::get()->debug(ss.str());
|
||||||
|
|
||||||
//General Informations about vertices
|
//General Informations about vertices
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
if(!(Reader->getNodeName()==string("vertexbuffer")))
|
while(Reader->getNodeName()==string("vertexbuffer"))
|
||||||
{
|
{
|
||||||
throw DeadlyImportError("vertexbuffer node is not first in geometry node!");
|
ReadVertexBuffer(theSubMesh, Reader, NumVertices);
|
||||||
}
|
}
|
||||||
theSubMesh.HasPositions=GetAttribute<bool>(Reader, "positions");
|
|
||||||
theSubMesh.HasNormals=GetAttribute<bool>(Reader, "normals");
|
|
||||||
if(!Reader->getAttributeValue("texture_coords"))//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute
|
|
||||||
theSubMesh.NumUvs=0;
|
|
||||||
else
|
|
||||||
theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords");
|
|
||||||
if(theSubMesh.NumUvs>1)
|
|
||||||
throw DeadlyImportError("too many texcoords (just 1 supported!)");
|
|
||||||
|
|
||||||
//read all the vertices:
|
//some error checking on the loaded data
|
||||||
XmlRead(Reader);
|
if(!theSubMesh.HasPositions)
|
||||||
while(Reader->getNodeName()==string("vertex"))
|
throw DeadlyImportError("No positions could be loaded!");
|
||||||
{
|
|
||||||
//read all vertex attributes:
|
|
||||||
|
|
||||||
//Position
|
if(theSubMesh.HasNormals && theSubMesh.Normals.size() != NumVertices)
|
||||||
if(theSubMesh.HasPositions)
|
throw DeadlyImportError("Wrong Number of Normals loaded!");
|
||||||
{
|
|
||||||
XmlRead(Reader);
|
|
||||||
aiVector3D NewPos;
|
|
||||||
NewPos.x=GetAttribute<float>(Reader, "x");
|
|
||||||
NewPos.y=GetAttribute<float>(Reader, "y");
|
|
||||||
NewPos.z=GetAttribute<float>(Reader, "z");
|
|
||||||
theSubMesh.Positions.push_back(NewPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Normal
|
|
||||||
if(theSubMesh.HasNormals)
|
|
||||||
{
|
|
||||||
XmlRead(Reader);
|
|
||||||
aiVector3D NewNormal;
|
|
||||||
NewNormal.x=GetAttribute<float>(Reader, "x");
|
|
||||||
NewNormal.y=GetAttribute<float>(Reader, "y");
|
|
||||||
NewNormal.z=GetAttribute<float>(Reader, "z");
|
|
||||||
theSubMesh.Normals.push_back(NewNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Uv:
|
if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices)
|
||||||
if(1==theSubMesh.NumUvs)
|
throw DeadlyImportError("Wrong Number of Tangents loaded!");
|
||||||
{
|
|
||||||
XmlRead(Reader);
|
if(theSubMesh.NumUvs==1 && theSubMesh.Uvs.size() != NumVertices)
|
||||||
aiVector3D NewUv;
|
throw DeadlyImportError("Wrong Number of Uvs loaded!");
|
||||||
NewUv.x=GetAttribute<float>(Reader, "u");
|
|
||||||
NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
|
|
||||||
theSubMesh.Uvs.push_back(NewUv);
|
|
||||||
}
|
|
||||||
XmlRead(Reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
}//end of "geometry
|
}//end of "geometry
|
||||||
|
|
||||||
|
@ -324,7 +288,8 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
DefaultLogger::get()->debug((Formatter::format(),
|
DefaultLogger::get()->debug((Formatter::format(),
|
||||||
"Positionen: ",theSubMesh.Positions.size(),
|
"Positionen: ",theSubMesh.Positions.size(),
|
||||||
" Normale: ",theSubMesh.Normals.size(),
|
" Normale: ",theSubMesh.Normals.size(),
|
||||||
" TexCoords: ",theSubMesh.Uvs.size()
|
" TexCoords: ",theSubMesh.Uvs.size(),
|
||||||
|
" Tantents: ",theSubMesh.Tangents.size()
|
||||||
));
|
));
|
||||||
DefaultLogger::get()->warn(Reader->getNodeName());
|
DefaultLogger::get()->warn(Reader->getNodeName());
|
||||||
|
|
||||||
|
@ -335,6 +300,7 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^
|
unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^
|
||||||
vector<aiVector3D> UniquePositions(UniqueVertexCount);
|
vector<aiVector3D> UniquePositions(UniqueVertexCount);
|
||||||
vector<aiVector3D> UniqueNormals(UniqueVertexCount);
|
vector<aiVector3D> UniqueNormals(UniqueVertexCount);
|
||||||
|
vector<aiVector3D> UniqueTangents(UniqueVertexCount);
|
||||||
vector<aiVector3D> UniqueUvs(UniqueVertexCount);
|
vector<aiVector3D> UniqueUvs(UniqueVertexCount);
|
||||||
vector< vector<Weight> > UniqueWeights((theSubMesh.Weights.size() ? UniqueVertexCount : 0));
|
vector< vector<Weight> > UniqueWeights((theSubMesh.Weights.size() ? UniqueVertexCount : 0));
|
||||||
|
|
||||||
|
@ -349,9 +315,19 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
UniquePositions[3*i+1]=theSubMesh.Positions[Vertex2];
|
UniquePositions[3*i+1]=theSubMesh.Positions[Vertex2];
|
||||||
UniquePositions[3*i+2]=theSubMesh.Positions[Vertex3];
|
UniquePositions[3*i+2]=theSubMesh.Positions[Vertex3];
|
||||||
|
|
||||||
UniqueNormals[3*i+0]=theSubMesh.Normals[Vertex1];
|
if(theSubMesh.HasNormals)
|
||||||
UniqueNormals[3*i+1]=theSubMesh.Normals[Vertex2];
|
{
|
||||||
UniqueNormals[3*i+2]=theSubMesh.Normals[Vertex3];
|
UniqueNormals[3*i+0]=theSubMesh.Normals[Vertex1];
|
||||||
|
UniqueNormals[3*i+1]=theSubMesh.Normals[Vertex2];
|
||||||
|
UniqueNormals[3*i+2]=theSubMesh.Normals[Vertex3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(theSubMesh.HasTangents)
|
||||||
|
{
|
||||||
|
UniqueTangents[3*i+0]=theSubMesh.Tangents[Vertex1];
|
||||||
|
UniqueTangents[3*i+1]=theSubMesh.Tangents[Vertex2];
|
||||||
|
UniqueTangents[3*i+2]=theSubMesh.Tangents[Vertex3];
|
||||||
|
}
|
||||||
|
|
||||||
if(1==theSubMesh.NumUvs)
|
if(1==theSubMesh.NumUvs)
|
||||||
{
|
{
|
||||||
|
@ -360,7 +336,8 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
UniqueUvs[3*i+2]=theSubMesh.Uvs[Vertex3];
|
UniqueUvs[3*i+2]=theSubMesh.Uvs[Vertex3];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSubMesh.Weights.size()) {
|
if(theSubMesh.Weights.size())
|
||||||
|
{
|
||||||
UniqueWeights[3*i+0]=theSubMesh.Weights[Vertex1];
|
UniqueWeights[3*i+0]=theSubMesh.Weights[Vertex1];
|
||||||
UniqueWeights[3*i+1]=theSubMesh.Weights[Vertex2];
|
UniqueWeights[3*i+1]=theSubMesh.Weights[Vertex2];
|
||||||
UniqueWeights[3*i+2]=theSubMesh.Weights[Vertex3];
|
UniqueWeights[3*i+2]=theSubMesh.Weights[Vertex3];
|
||||||
|
@ -374,9 +351,11 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
//_________________________________________________________________________________________
|
//_________________________________________________________________________________________
|
||||||
|
|
||||||
//now we have the unique datas, but want them in the SubMesh, so we swap all the containers:
|
//now we have the unique datas, but want them in the SubMesh, so we swap all the containers:
|
||||||
|
//if we don't have one of them, we just swap empty containers, so everything is ok
|
||||||
theSubMesh.FaceList.swap(UniqueFaceList);
|
theSubMesh.FaceList.swap(UniqueFaceList);
|
||||||
theSubMesh.Positions.swap(UniquePositions);
|
theSubMesh.Positions.swap(UniquePositions);
|
||||||
theSubMesh.Normals.swap(UniqueNormals);
|
theSubMesh.Normals.swap(UniqueNormals);
|
||||||
|
theSubMesh.Tangents.swap(UniqueTangents);
|
||||||
theSubMesh.Uvs.swap(UniqueUvs);
|
theSubMesh.Uvs.swap(UniqueUvs);
|
||||||
theSubMesh.Weights.swap(UniqueWeights);
|
theSubMesh.Weights.swap(UniqueWeights);
|
||||||
|
|
||||||
|
@ -405,6 +384,119 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->debug("new Vertex Buffer");
|
||||||
|
|
||||||
|
bool ReadPositions=false;
|
||||||
|
bool ReadNormals=false;
|
||||||
|
bool ReadTangents=false;
|
||||||
|
bool ReadUvs=false;
|
||||||
|
|
||||||
|
//-------------------- check, what we need to read: --------------------------------
|
||||||
|
if(Reader->getAttributeValue("positions") && GetAttribute<bool>(Reader, "positions"))
|
||||||
|
{
|
||||||
|
ReadPositions=theSubMesh.HasPositions=true;
|
||||||
|
theSubMesh.Positions.reserve(NumVertices);
|
||||||
|
DefaultLogger::get()->debug("reading positions");
|
||||||
|
}
|
||||||
|
if(Reader->getAttributeValue("normals") && GetAttribute<bool>(Reader, "normals"))
|
||||||
|
{
|
||||||
|
ReadNormals=theSubMesh.HasNormals=true;
|
||||||
|
theSubMesh.Normals.reserve(NumVertices);
|
||||||
|
DefaultLogger::get()->debug("reading positions");
|
||||||
|
}
|
||||||
|
if(Reader->getAttributeValue("tangents") && GetAttribute<bool>(Reader, "tangents"))
|
||||||
|
{
|
||||||
|
ReadTangents=theSubMesh.HasTangents=true;
|
||||||
|
theSubMesh.Tangents.reserve(NumVertices);
|
||||||
|
DefaultLogger::get()->debug("reading positions");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute
|
||||||
|
if(!Reader->getAttributeValue("texture_coords"))
|
||||||
|
theSubMesh.NumUvs=0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadUvs=theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords");
|
||||||
|
theSubMesh.Uvs.reserve(NumVertices);
|
||||||
|
DefaultLogger::get()->debug("reading texture coords");
|
||||||
|
}
|
||||||
|
if(theSubMesh.NumUvs>1)
|
||||||
|
DefaultLogger::get()->warn("too many texcoords (just 1 supported!), no texcoords will be loaded!");
|
||||||
|
//___________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
//check if we will load anything
|
||||||
|
if(!(ReadPositions || ReadNormals || ReadTangents || ReadUvs))
|
||||||
|
DefaultLogger::get()->warn("vertexbuffer seams to be empty!");
|
||||||
|
|
||||||
|
|
||||||
|
//read all the vertices:
|
||||||
|
XmlRead(Reader);
|
||||||
|
|
||||||
|
/*it might happen, that we have more than one attribute per vertex (they are not splitted to different buffers)
|
||||||
|
so the break condition is a bit tricky (well, IrrXML just sucks :( )*/
|
||||||
|
while(Reader->getNodeName()==string("vertex")
|
||||||
|
||Reader->getNodeName()==string("position")
|
||||||
|
||Reader->getNodeName()==string("normal")
|
||||||
|
||Reader->getNodeName()==string("tangent")
|
||||||
|
||Reader->getNodeName()==string("texcoord"))
|
||||||
|
{
|
||||||
|
if(Reader->getNodeName()==string("vertex"))
|
||||||
|
XmlRead(Reader);//Read an attribute tag
|
||||||
|
|
||||||
|
//Position
|
||||||
|
if(ReadPositions && Reader->getNodeName()==string("position"))
|
||||||
|
{
|
||||||
|
aiVector3D NewPos;
|
||||||
|
NewPos.x=GetAttribute<float>(Reader, "x");
|
||||||
|
NewPos.y=GetAttribute<float>(Reader, "y");
|
||||||
|
NewPos.z=GetAttribute<float>(Reader, "z");
|
||||||
|
theSubMesh.Positions.push_back(NewPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Normal
|
||||||
|
else if(ReadNormals && Reader->getNodeName()==string("normal"))
|
||||||
|
{
|
||||||
|
aiVector3D NewNormal;
|
||||||
|
NewNormal.x=GetAttribute<float>(Reader, "x");
|
||||||
|
NewNormal.y=GetAttribute<float>(Reader, "y");
|
||||||
|
NewNormal.z=GetAttribute<float>(Reader, "z");
|
||||||
|
theSubMesh.Normals.push_back(NewNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tangent
|
||||||
|
else if(ReadTangents && Reader->getNodeName()==string("tangent"))
|
||||||
|
{
|
||||||
|
aiVector3D NewTangent;
|
||||||
|
NewTangent.x=GetAttribute<float>(Reader, "x");
|
||||||
|
NewTangent.y=GetAttribute<float>(Reader, "y");
|
||||||
|
NewTangent.z=GetAttribute<float>(Reader, "z");
|
||||||
|
theSubMesh.Tangents.push_back(NewTangent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Uv:
|
||||||
|
else if(ReadUvs && Reader->getNodeName()==string("texcoord"))
|
||||||
|
{
|
||||||
|
aiVector3D NewUv;
|
||||||
|
NewUv.x=GetAttribute<float>(Reader, "u");
|
||||||
|
NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
|
||||||
|
theSubMesh.Uvs.push_back(NewUv);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Attribute could not be read
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn(string("Attribute was not read: ")+Reader->getNodeName());
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRead(Reader);//Read the Vertex tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const
|
aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const
|
||||||
{
|
{
|
||||||
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
||||||
|
@ -418,8 +510,18 @@ aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vecto
|
||||||
NewAiMesh->mNumVertices=theSubMesh.Positions.size();
|
NewAiMesh->mNumVertices=theSubMesh.Positions.size();
|
||||||
|
|
||||||
//Normals
|
//Normals
|
||||||
NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()];
|
if(theSubMesh.HasNormals)
|
||||||
memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D));
|
{
|
||||||
|
NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()];
|
||||||
|
memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tangents
|
||||||
|
if(theSubMesh.HasTangents)
|
||||||
|
{
|
||||||
|
NewAiMesh->mTangents=new aiVector3D[theSubMesh.Tangents.size()];
|
||||||
|
memcpy(NewAiMesh->mTangents, &theSubMesh.Tangents[0], theSubMesh.Tangents.size()*sizeof(aiVector3D));
|
||||||
|
}
|
||||||
|
|
||||||
//Uvs
|
//Uvs
|
||||||
if(0!=theSubMesh.NumUvs)
|
if(0!=theSubMesh.NumUvs)
|
||||||
|
@ -816,12 +918,8 @@ void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode)
|
||||||
aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const
|
|
||||||
{
|
{
|
||||||
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
|
||||||
(void)m_CurrentScene;
|
|
||||||
|
|
||||||
//----Create the node for this bone and set its values-----
|
//----Create the node for this bone and set its values-----
|
||||||
aiNode* NewNode=new aiNode(Bones[BoneId].Name);
|
aiNode* NewNode=new aiNode(Bones[BoneId].Name);
|
||||||
NewNode->mParent=ParentNode;
|
NewNode->mParent=ParentNode;
|
||||||
|
|
|
@ -1,151 +1,159 @@
|
||||||
#include "BaseImporter.h"
|
#include "BaseImporter.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "OgreXmlHelper.h"
|
#include "OgreXmlHelper.hpp"
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//Forward declarations:
|
//Forward declarations:
|
||||||
struct SubMesh;
|
struct SubMesh;
|
||||||
struct Face;
|
struct Face;
|
||||||
struct Weight;
|
struct Weight;
|
||||||
struct Bone;
|
struct Bone;
|
||||||
struct Animation;
|
struct Animation;
|
||||||
struct Track;
|
struct Track;
|
||||||
struct Keyframe;
|
struct Keyframe;
|
||||||
|
|
||||||
///The Main Ogre Importer Class
|
///The Main Ogre Importer Class
|
||||||
class OgreImporter : public BaseImporter
|
class OgreImporter : public BaseImporter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
|
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
|
||||||
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||||
virtual void GetExtensionList(std::set<std::string>& extensions);
|
virtual void GetExtensionList(std::set<std::string>& extensions);
|
||||||
virtual void SetupProperties(const Importer* pImp);
|
virtual void SetupProperties(const Importer* pImp);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// Helper Functions to read parts of the XML File
|
/// Helper Functions to read parts of the XML File
|
||||||
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value
|
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value
|
||||||
|
|
||||||
/// writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
|
/// Reads a single Vertexbuffer and writes its data in the Submesh
|
||||||
void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
|
static void ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices);
|
||||||
|
|
||||||
/// converts the animations in aiAnimations and puts them into the scene
|
/// writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
|
||||||
void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
|
||||||
|
|
||||||
/// uses the bone data to convert a SubMesh into a aiMesh which will be created and returned
|
/// converts the animations in aiAnimations and puts them into the scene
|
||||||
aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones) const;
|
void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||||
|
|
||||||
//creates the aiskeleton in current scene
|
/// uses the bone data to convert a SubMesh into a aiMesh which will be created and returned
|
||||||
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones) const;
|
||||||
|
|
||||||
aiMaterial* LoadMaterial(const std::string MaterialName) const;
|
//creates the aiskeleton in current scene
|
||||||
|
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||||
///Recursivly creates a filled aiNode from a given root bone
|
|
||||||
aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const;
|
aiMaterial* LoadMaterial(const std::string MaterialName) const;
|
||||||
|
static void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial);
|
||||||
//Now we don't have to give theses parameters to all functions
|
|
||||||
std::string m_CurrentFilename;
|
///Recursivly creates a filled aiNode from a given root bone
|
||||||
std::string m_MaterialLibFilename;
|
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
|
||||||
IOSystem* m_CurrentIOHandler;
|
|
||||||
aiScene *m_CurrentScene;
|
//Now we don't have to give theses parameters to all functions
|
||||||
};
|
std::string m_CurrentFilename;
|
||||||
|
std::string m_MaterialLibFilename;
|
||||||
///A submesh from Ogre
|
IOSystem* m_CurrentIOHandler;
|
||||||
struct SubMesh
|
aiScene *m_CurrentScene;
|
||||||
{
|
};
|
||||||
std::string Name;
|
|
||||||
std::string MaterialName;
|
///A submesh from Ogre
|
||||||
std::vector<Face> FaceList;
|
struct SubMesh
|
||||||
std::vector<aiVector3D> Positions; bool HasPositions;
|
{
|
||||||
std::vector<aiVector3D> Normals; bool HasNormals;
|
std::string Name;
|
||||||
std::vector<aiVector3D> Uvs; unsigned int NumUvs;//nearly always 2d, but assimp has always 3d texcoords
|
std::string MaterialName;
|
||||||
std::vector< std::vector<Weight> > Weights;//a list of bones for each vertex
|
std::vector<Face> FaceList;
|
||||||
int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh
|
|
||||||
unsigned int BonesUsed;//the highest index of a bone from a bone weight, this is needed to create the assimp bone structur (converting from Vertex-Bones to Bone-Vertices)
|
std::vector<aiVector3D> Positions; bool HasPositions;
|
||||||
|
std::vector<aiVector3D> Normals; bool HasNormals;
|
||||||
SubMesh(): HasPositions(false), HasNormals(false), NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
|
std::vector<aiVector3D> Tangents; bool HasTangents;
|
||||||
};
|
std::vector<aiVector3D> Uvs; unsigned int NumUvs;//nearly always 2d, but assimp has always 3d texcoords
|
||||||
|
|
||||||
///For the moment just triangles, no other polygon types!
|
std::vector< std::vector<Weight> > Weights;//a list of bones for each vertex
|
||||||
struct Face
|
int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh
|
||||||
{
|
unsigned int BonesUsed;//the highest index of a bone from a bone weight, this is needed to create the assimp bone structur (converting from Vertex-Bones to Bone-Vertices)
|
||||||
unsigned int VertexIndices[3];
|
|
||||||
};
|
SubMesh(): HasPositions(false), HasNormals(false), HasTangents(false),
|
||||||
|
NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
|
||||||
struct BoneAssignment
|
};
|
||||||
{
|
|
||||||
unsigned int BoneId;//this is, what we get from ogre
|
///For the moment just triangles, no other polygon types!
|
||||||
std::string BoneName;//this is, what we need for assimp
|
struct Face
|
||||||
};
|
{
|
||||||
|
unsigned int VertexIndices[3];
|
||||||
///for a vertex->bone structur
|
};
|
||||||
struct Weight
|
|
||||||
{
|
struct BoneAssignment
|
||||||
unsigned int BoneId;
|
{
|
||||||
float Value;
|
unsigned int BoneId;//this is, what we get from ogre
|
||||||
};
|
std::string BoneName;//this is, what we need for assimp
|
||||||
|
};
|
||||||
|
|
||||||
/// Helper Class to describe an ogre-bone for the skeleton:
|
///for a vertex->bone structur
|
||||||
/** All Id's are signed ints, because than we have -1 as a simple INVALID_ID Value (we start from 0 so 0 is a valid bone ID!*/
|
struct Weight
|
||||||
struct Bone
|
{
|
||||||
{
|
unsigned int BoneId;
|
||||||
int Id;
|
float Value;
|
||||||
int ParentId;
|
};
|
||||||
std::string Name;
|
|
||||||
aiVector3D Position;
|
|
||||||
float RotationAngle;
|
/// Helper Class to describe an ogre-bone for the skeleton:
|
||||||
aiVector3D RotationAxis;
|
/** All Id's are signed ints, because than we have -1 as a simple INVALID_ID Value (we start from 0 so 0 is a valid bone ID!*/
|
||||||
std::vector<int> Children;
|
struct Bone
|
||||||
aiMatrix4x4 BoneToWorldSpace;
|
{
|
||||||
|
int Id;
|
||||||
///ctor
|
int ParentId;
|
||||||
Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
|
std::string Name;
|
||||||
///this operator is needed to sort the bones after Id's
|
aiVector3D Position;
|
||||||
bool operator<(const Bone& rval) const
|
float RotationAngle;
|
||||||
{return Id<rval.Id; }
|
aiVector3D RotationAxis;
|
||||||
///this operator is needed to find a bone by its name in a vector<Bone>
|
std::vector<int> Children;
|
||||||
bool operator==(const std::string& rval) const
|
aiMatrix4x4 BoneToWorldSpace;
|
||||||
{return Name==rval; }
|
|
||||||
bool operator==(const aiString& rval) const
|
///ctor
|
||||||
{return Name==std::string(rval.data); }
|
Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
|
||||||
|
///this operator is needed to sort the bones after Id's
|
||||||
void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones);
|
bool operator<(const Bone& rval) const
|
||||||
|
{return Id<rval.Id; }
|
||||||
};
|
///this operator is needed to find a bone by its name in a vector<Bone>
|
||||||
|
bool operator==(const std::string& rval) const
|
||||||
|
{return Name==rval; }
|
||||||
|
bool operator==(const aiString& rval) const
|
||||||
///Describes an Ogre Animation
|
{return Name==std::string(rval.data); }
|
||||||
struct Animation
|
|
||||||
{
|
void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones);
|
||||||
std::string Name;
|
|
||||||
float Length;
|
};
|
||||||
std::vector<Track> Tracks;
|
|
||||||
};
|
|
||||||
|
|
||||||
///a track (keyframes for one bone) from an animation
|
///Describes an Ogre Animation
|
||||||
struct Track
|
struct Animation
|
||||||
{
|
{
|
||||||
std::string BoneName;
|
std::string Name;
|
||||||
std::vector<Keyframe> Keyframes;
|
float Length;
|
||||||
};
|
std::vector<Track> Tracks;
|
||||||
|
};
|
||||||
/// keyframe (bone transformation) from a track from a animation
|
|
||||||
struct Keyframe
|
///a track (keyframes for one bone) from an animation
|
||||||
{
|
struct Track
|
||||||
float Time;
|
{
|
||||||
aiVector3D Position;
|
std::string BoneName;
|
||||||
aiQuaternion Rotation;
|
std::vector<Keyframe> Keyframes;
|
||||||
aiVector3D Scaling;
|
};
|
||||||
};
|
|
||||||
|
/// keyframe (bone transformation) from a track from a animation
|
||||||
}//namespace Ogre
|
struct Keyframe
|
||||||
}//namespace Assimp
|
{
|
||||||
|
float Time;
|
||||||
|
aiVector3D Position;
|
||||||
|
aiQuaternion Rotation;
|
||||||
|
aiVector3D Scaling;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace Ogre
|
||||||
|
}//namespace Assimp
|
|
@ -55,7 +55,7 @@ using namespace std;
|
||||||
//#include "boost/foreach.hpp"
|
//#include "boost/foreach.hpp"
|
||||||
//using namespace boost;
|
//using namespace boost;
|
||||||
|
|
||||||
#include "OgreImporter.h"
|
#include "OgreImporter.hpp"
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
#include "TinyFormatter.h"
|
#include "TinyFormatter.h"
|
||||||
|
|
||||||
|
@ -71,10 +71,6 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
||||||
(void)m_CurrentScene;
|
(void)m_CurrentScene;
|
||||||
|
|
||||||
aiMaterial *NewMaterial=new aiMaterial();
|
|
||||||
|
|
||||||
aiString ts(MaterialName.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_NAME);
|
|
||||||
/*For bettetr understanding of the material parser, here is a material example file:
|
/*For bettetr understanding of the material parser, here is a material example file:
|
||||||
|
|
||||||
material Sarg
|
material Sarg
|
||||||
|
@ -100,9 +96,39 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*and here is another one:
|
||||||
|
|
||||||
const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material";
|
import * from abstract_base_passes_depth.material
|
||||||
DefaultLogger::get()->info("Trying to load " +MaterialFileName);
|
import * from abstract_base.material
|
||||||
|
import * from mat_shadow_caster.material
|
||||||
|
import * from mat_character_singlepass.material
|
||||||
|
|
||||||
|
material hero/hair/caster : mat_shadow_caster_skin_areject
|
||||||
|
{
|
||||||
|
set $diffuse_map "hero_hair_alpha_c.dds"
|
||||||
|
}
|
||||||
|
|
||||||
|
material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights
|
||||||
|
{
|
||||||
|
set $diffuse_map "hero_hair_alpha_c.dds"
|
||||||
|
set $specular_map "hero_hair_alpha_s.dds"
|
||||||
|
set $normal_map "hero_hair_alpha_n.dds"
|
||||||
|
set $light_map "black_lightmap.dds"
|
||||||
|
|
||||||
|
set $shadow_caster_material "hero/hair/caster"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//the filename typically ends with .mesh or .mesh.xml
|
||||||
|
const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.rfind(".mesh"))+".material";
|
||||||
|
DefaultLogger::get()->info("Trying to load " + MaterialFileName);
|
||||||
|
|
||||||
|
|
||||||
|
aiMaterial *NewMaterial=new aiMaterial();
|
||||||
|
|
||||||
|
aiString ts(MaterialName.c_str());
|
||||||
|
NewMaterial->AddProperty(&ts, AI_MATKEY_NAME);
|
||||||
|
|
||||||
//Read the file into memory and put it in a stringstream
|
//Read the file into memory and put it in a stringstream
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
|
@ -110,11 +136,17 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
|
IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
|
||||||
if(NULL==MatFilePtr)
|
if(NULL==MatFilePtr)
|
||||||
{
|
{
|
||||||
MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
|
//try the default mat Library
|
||||||
if(NULL==MatFilePtr)
|
if(NULL==MatFilePtr)
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!");
|
|
||||||
return NewMaterial;
|
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!");
|
||||||
|
delete NewMaterial;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr);
|
boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr);
|
||||||
|
@ -135,7 +167,10 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
ss >> Line;
|
ss >> Line;
|
||||||
if(Line==MaterialName)//Load the next material
|
if(Line==MaterialName)//Load the next material
|
||||||
{
|
{
|
||||||
|
string RestOfLine;
|
||||||
|
getline(ss, RestOfLine);//ignore the rest of the line
|
||||||
ss >> Line;
|
ss >> Line;
|
||||||
|
|
||||||
if(Line!="{")
|
if(Line!="{")
|
||||||
throw DeadlyImportError("empty material!");
|
throw DeadlyImportError("empty material!");
|
||||||
|
|
||||||
|
@ -145,72 +180,9 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
ss >> Line;
|
ss >> Line;
|
||||||
if(Line=="technique")
|
if(Line=="technique")
|
||||||
{
|
{
|
||||||
ss >> Line;
|
ReadTechnique(ss, NewMaterial);
|
||||||
if(Line!="{")
|
|
||||||
throw DeadlyImportError("empty technique!");
|
|
||||||
while(Line!="}")//read until the end of the technique
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="pass")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line!="{")
|
|
||||||
throw DeadlyImportError("empty pass!");
|
|
||||||
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")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line!="{")
|
|
||||||
throw DeadlyImportError("empty texture unit!");
|
|
||||||
while(Line!="}")//read until the end of the texture_unit
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
if(Line=="texture")
|
|
||||||
{
|
|
||||||
ss >> Line;
|
|
||||||
aiString ts(Line.c_str());
|
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
|
||||||
}
|
|
||||||
}//end of texture unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//end of technique
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DefaultLogger::get()->info(Line);
|
DefaultLogger::get()->info(Line);
|
||||||
//read informations from a custom material:
|
//read informations from a custom material:
|
||||||
if(Line=="set")
|
if(Line=="set")
|
||||||
|
@ -237,6 +209,54 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
aiString ts(Line.c_str());
|
aiString ts(Line.c_str());
|
||||||
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
|
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
|
}//end of material
|
||||||
}
|
}
|
||||||
|
@ -248,6 +268,71 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
|
||||||
return NewMaterial;
|
return NewMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial)
|
||||||
|
{
|
||||||
|
string Line;
|
||||||
|
ss >> Line;
|
||||||
|
if(Line!="{")
|
||||||
|
throw DeadlyImportError("empty technique!");
|
||||||
|
while(Line!="}")//read until the end of the technique
|
||||||
|
{
|
||||||
|
ss >> Line;
|
||||||
|
if(Line=="pass")
|
||||||
|
{
|
||||||
|
ss >> Line;
|
||||||
|
if(Line!="{")
|
||||||
|
throw DeadlyImportError("empty pass!");
|
||||||
|
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")
|
||||||
|
{
|
||||||
|
ss >> Line;
|
||||||
|
if(Line!="{")
|
||||||
|
throw DeadlyImportError("empty texture unit!");
|
||||||
|
while(Line!="}")//read until the end of the texture_unit
|
||||||
|
{
|
||||||
|
ss >> Line;
|
||||||
|
if(Line=="texture")
|
||||||
|
{
|
||||||
|
ss >> Line;
|
||||||
|
aiString ts(Line.c_str());
|
||||||
|
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||||
|
}
|
||||||
|
}//end of texture unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end of technique
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}//namespace Ogre
|
}//namespace Ogre
|
||||||
|
|
|
@ -1,79 +1,79 @@
|
||||||
|
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
#include "fast_atof.h"
|
#include "fast_atof.h"
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef irr::io::IrrXMLReader XmlReader;
|
typedef irr::io::IrrXMLReader XmlReader;
|
||||||
|
|
||||||
|
|
||||||
//------------Helper Funktion to Get a Attribute Save---------------
|
//------------Helper Funktion to Get a Attribute Save---------------
|
||||||
template<typename t> inline t GetAttribute(XmlReader* Reader, std::string Name);
|
template<typename t> inline t GetAttribute(XmlReader* Reader, std::string Name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
BOOST_STATIC_ASSERT(false);
|
BOOST_STATIC_ASSERT(false);
|
||||||
return t();
|
return t();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<> inline int GetAttribute<int>(XmlReader* Reader, std::string Name)
|
template<> inline int GetAttribute<int>(XmlReader* Reader, 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
|
||||||
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name)
|
template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name)
|
||||||
{
|
{
|
||||||
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
|
||||||
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string GetAttribute<std::string>(XmlReader* Reader, std::string Name)
|
template<> inline std::string GetAttribute<std::string>(XmlReader* Reader, std::string Name)
|
||||||
{
|
{
|
||||||
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
|
||||||
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline bool GetAttribute<bool>(XmlReader* Reader, std::string Name)
|
template<> inline bool GetAttribute<bool>(XmlReader* Reader, std::string Name)
|
||||||
{
|
{
|
||||||
const char* Value=Reader->getAttributeValue(Name.c_str());
|
const char* Value=Reader->getAttributeValue(Name.c_str());
|
||||||
if(Value)
|
if(Value)
|
||||||
{
|
{
|
||||||
if(Value==std::string("true"))
|
if(Value==std::string("true"))
|
||||||
return true;
|
return true;
|
||||||
else if(Value==std::string("false"))
|
else if(Value==std::string("false"))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
throw DeadlyImportError(std::string("Bool value has invalid value: "+Name+" / "+Value+" / "+Reader->getNodeName()));
|
throw DeadlyImportError(std::string("Bool value has invalid value: "+Name+" / "+Value+" / "+Reader->getNodeName()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||||
}
|
}
|
||||||
//__________________________________________________________________
|
//__________________________________________________________________
|
||||||
|
|
||||||
inline bool XmlRead(XmlReader* Reader)
|
inline bool XmlRead(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace Ogre
|
}//namespace Ogre
|
||||||
}//namespace Assimp
|
}//namespace Assimp
|
|
@ -1457,9 +1457,10 @@ try to find the appendant material and skeleton file.
|
||||||
The skeleton file must have the same name as the mesh file, e.g. fish.mesh.xml and fish.skeleton.xml.
|
The skeleton file must have the same name as the mesh file, e.g. fish.mesh.xml and fish.skeleton.xml.
|
||||||
|
|
||||||
@subsection material Materials
|
@subsection material Materials
|
||||||
The material file can have the same name as the mesh file, or you can use
|
The material file can have the same name as the mesh file (if the file is model.mesh or model.mesh.xml the
|
||||||
Importer::Importer::SetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "materiafile.material") to specify
|
loader will try to load model.material),
|
||||||
the name of the material file. This is especially usefull if multiply materials a stored in a single file.
|
or you can use Importer::Importer::SetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "materiafile.material")
|
||||||
|
to specify the name of the material file. This is especially usefull if multiply materials a stored in a single file.
|
||||||
The importer will first try to load the material with the same name as the mesh and only if this can't be open try
|
The importer will first try to load the material with the same name as the mesh and only if this can't be open try
|
||||||
to load the alternate material file. The default material filename is "Scene.material".
|
to load the alternate material file. The default material filename is "Scene.material".
|
||||||
|
|
||||||
|
@ -1468,6 +1469,7 @@ should read the custom material sektion in the Ogre Blender exporter Help File,
|
||||||
can find in scripts/OgreImpoter/Assimp.tlp in the assimp source. If you don't set all values, don't worry, they will be ignored during import.
|
can find in scripts/OgreImpoter/Assimp.tlp in the assimp source. If you don't set all values, don't worry, they will be ignored during import.
|
||||||
|
|
||||||
If you want more properties in custom materials, you can easily expand the ogre material loader, it will be just a few lines for each property.
|
If you want more properties in custom materials, you can easily expand the ogre material loader, it will be just a few lines for each property.
|
||||||
|
Just look in OgreImporterMaterial.cpp
|
||||||
|
|
||||||
@subsection todo Todo
|
@subsection todo Todo
|
||||||
- Load colors in custom materials
|
- Load colors in custom materials
|
||||||
|
|
Loading…
Reference in New Issue