- Ogre Importer Beta
- Ogre Importer Documentation - Extended the general documentation at some points git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@476 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
a8ccd6fbd5
commit
8cfb2e26cf
|
@ -217,12 +217,8 @@ public:
|
|||
* The function is a request to the importer to update its configuration
|
||||
* basing on the Importer's configuration property list.
|
||||
* @param pImp Importer instance
|
||||
* @param ppFlags Post-processing steps to be executed on the data
|
||||
* returned by the loaders. This value is provided to allow some
|
||||
* internal optimizations.
|
||||
*/
|
||||
virtual void SetupProperties(const Importer* pImp /*,
|
||||
unsigned int ppFlags*/);
|
||||
virtual void SetupProperties(const Importer* pImp);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -192,6 +192,11 @@ SOURCE_GROUP( Obj FILES
|
|||
ObjTools.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP( Ogre FILES
|
||||
OgreImporter.h
|
||||
OgreImporter.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP( Ply FILES
|
||||
PlyLoader.cpp
|
||||
PlyLoader.h
|
||||
|
@ -472,6 +477,8 @@ ADD_LIBRARY( assimp SHARED
|
|||
ObjFileParser.cpp
|
||||
ObjFileParser.h
|
||||
ObjTools.h
|
||||
OgreImporter.h
|
||||
OgreImporter.cpp
|
||||
OptimizeGraph.cpp
|
||||
OptimizeGraph.h
|
||||
OptimizeMeshes.cpp
|
||||
|
|
|
@ -158,6 +158,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef AI_BUILD_NO_LWS_IMPORTER
|
||||
# include "LWSLoader.h"
|
||||
#endif
|
||||
#ifndef AI_BUILD_NO_OGRE_IMPORTER
|
||||
# include "OgreImporter.h"
|
||||
#endif
|
||||
|
||||
// .......................................................................................
|
||||
// PostProcess-Steps
|
||||
|
@ -360,6 +363,10 @@ Importer::Importer()
|
|||
#if (!defined AI_BUILD_NO_LWS_IMPORTER)
|
||||
pimpl->mImporter.push_back( new LWSImporter());
|
||||
#endif
|
||||
#if (!defined AI_BUILD_NO_OGRE_IMPORTER)
|
||||
pimpl->mImporter.push_back( new Ogre::OgreImporter());
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Add an instance of each post processing step here in the order
|
||||
|
|
|
@ -0,0 +1,425 @@
|
|||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include "boost/format.hpp"
|
||||
using namespace boost;
|
||||
|
||||
#include "OgreImporter.h"
|
||||
#include "irrXMLWrapper.h"
|
||||
|
||||
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Ogre
|
||||
{
|
||||
|
||||
|
||||
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
|
||||
{
|
||||
if(!checkSig)//Check File Extension
|
||||
{
|
||||
std::string extension("mesh.xml");
|
||||
int l=extension.length();
|
||||
return pFile.substr(pFile.length()-l, l)==extension;
|
||||
}
|
||||
else//Check file Header
|
||||
{
|
||||
const char* tokens[] = {"<mesh>"};
|
||||
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
|
||||
{
|
||||
m_CurrentFilename=pFile;
|
||||
m_CurrentIOHandler=pIOHandler;
|
||||
m_CurrentScene=pScene;
|
||||
|
||||
//Open the File:
|
||||
boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
|
||||
if( file.get() == NULL)
|
||||
throw new ImportErrorException("Failed to open file "+pFile+".");
|
||||
|
||||
//Read the Mesh File:
|
||||
boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
|
||||
XmlReader* MeshFile = irr::io::createIrrXMLReader(mIOWrapper.get());
|
||||
if(!MeshFile)//parse the xml file
|
||||
throw new ImportErrorException("Failed to create XML Reader for "+pFile);
|
||||
|
||||
|
||||
DefaultLogger::get()->info("Mesh File opened");
|
||||
|
||||
//Read root Node:
|
||||
if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="mesh"))
|
||||
{
|
||||
throw new ImportErrorException("Root Node is not <mesh>! "+pFile+" "+MeshFile->getNodeName());
|
||||
}
|
||||
|
||||
//Go to the submeshs:
|
||||
if(!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="submeshes"))
|
||||
{
|
||||
throw new ImportErrorException("No <submeshes> node in <mesh> node! "+pFile);
|
||||
}
|
||||
|
||||
|
||||
//-------------------Read all submeshs:-----------------------
|
||||
XmlRead(MeshFile);
|
||||
while(string(MeshFile->getNodeName())=="submesh")//read the index values (the faces):
|
||||
{
|
||||
SubMesh NewSubMesh;
|
||||
NewSubMesh.MaterialName=GetAttribute<string>(MeshFile, "material");
|
||||
DefaultLogger::get()->info("Loading Submehs with Material: "+NewSubMesh.MaterialName);
|
||||
ReadSubMesh(NewSubMesh, MeshFile);
|
||||
}
|
||||
//_______________________________________________________________-
|
||||
|
||||
|
||||
|
||||
//-----------------Read the skeleton:----------------------
|
||||
//Create the root node
|
||||
pScene->mRootNode=new aiNode("root");
|
||||
|
||||
//link the mesh with the root node:
|
||||
pScene->mRootNode->mMeshes=new unsigned int[1];
|
||||
pScene->mRootNode->mMeshes[0]=0;
|
||||
pScene->mRootNode->mNumMeshes=1;
|
||||
//_________________________________________________________
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OgreImporter::GetExtensionList(std::string &append)
|
||||
{
|
||||
append+="*.mesh.xml";
|
||||
}
|
||||
|
||||
|
||||
void OgreImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
|
||||
}
|
||||
|
||||
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||
{
|
||||
vector<Face> FaceList;
|
||||
vector<aiVector3D> Positions; bool HasPositions=false;
|
||||
vector<aiVector3D> Normals; bool HasNormals=false;
|
||||
vector<aiVector3D> Uvs; unsigned int NumUvs=0;//nearly always 2d, but assimp has always 3d texcoords
|
||||
|
||||
XmlRead(Reader);
|
||||
//TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work korrekt, wenn the order
|
||||
//of faces and geometry changed, and not if we habe more than one of one
|
||||
while(Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry")
|
||||
{
|
||||
if(string(Reader->getNodeName())=="faces")//Read the face list
|
||||
{
|
||||
//some info logging:
|
||||
unsigned int NumFaces=GetAttribute<int>(Reader, "count");
|
||||
stringstream ss; ss <<"Submesh has " << NumFaces << " Faces.";
|
||||
DefaultLogger::get()->info(ss.str());
|
||||
|
||||
while(XmlRead(Reader) && Reader->getNodeName()==string("face"))
|
||||
{
|
||||
Face NewFace;
|
||||
NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1");
|
||||
NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2");
|
||||
NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3");
|
||||
if(Reader->getAttributeValue("v4"))//this should be supported in the future
|
||||
{
|
||||
throw new ImportErrorException("Submesh has quads, only traingles are supported!");
|
||||
}
|
||||
FaceList.push_back(NewFace);
|
||||
}
|
||||
|
||||
}
|
||||
else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
|
||||
{
|
||||
//some info logging:
|
||||
unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
|
||||
stringstream ss; ss<<"VertexCount: "<<NumVertices;
|
||||
DefaultLogger::get()->info(ss.str());
|
||||
|
||||
//General Informations about vertices
|
||||
XmlRead(Reader);
|
||||
if(!(Reader->getNodeName()==string("vertexbuffer")))
|
||||
{
|
||||
throw new ImportErrorException("vertexbuffer node is not first in geometry node!");
|
||||
}
|
||||
HasPositions=GetAttribute<bool>(Reader, "positions");
|
||||
HasNormals=GetAttribute<bool>(Reader, "normals");
|
||||
NumUvs=GetAttribute<int>(Reader, "texture_coords");
|
||||
if(NumUvs>1)
|
||||
throw new ImportErrorException("too many texcoords (just 1 supported!)");
|
||||
|
||||
//read all the vertices:
|
||||
XmlRead(Reader);
|
||||
while(Reader->getNodeName()==string("vertex"))
|
||||
{
|
||||
//read all vertex attributes:
|
||||
|
||||
//Position
|
||||
if(HasPositions)
|
||||
{
|
||||
XmlRead(Reader);
|
||||
aiVector3D NewPos;
|
||||
NewPos.x=GetAttribute<float>(Reader, "x");
|
||||
NewPos.y=GetAttribute<float>(Reader, "y");
|
||||
NewPos.z=GetAttribute<float>(Reader, "z");
|
||||
Positions.push_back(NewPos);
|
||||
}
|
||||
|
||||
//Normal
|
||||
if(HasNormals)
|
||||
{
|
||||
XmlRead(Reader);
|
||||
aiVector3D NewNormal;
|
||||
NewNormal.x=GetAttribute<float>(Reader, "x");
|
||||
NewNormal.y=GetAttribute<float>(Reader, "y");
|
||||
NewNormal.z=GetAttribute<float>(Reader, "z");
|
||||
Normals.push_back(NewNormal);
|
||||
}
|
||||
|
||||
//Uv:
|
||||
if(1==NumUvs)
|
||||
{
|
||||
XmlRead(Reader);
|
||||
aiVector3D NewUv;
|
||||
NewUv.x=GetAttribute<float>(Reader, "u");
|
||||
NewUv.y=GetAttribute<float>(Reader, "v");
|
||||
Uvs.push_back(NewUv);
|
||||
}
|
||||
XmlRead(Reader);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->info(str(format("Positionen: %1% Normale: %2% TexCoords: %3%") % Positions.size() % Normals.size() % Uvs.size()));
|
||||
|
||||
|
||||
//Make all Vertexes unique: (this is required by assimp)
|
||||
vector<Face> UniqueFaceList(FaceList.size());
|
||||
vector<aiVector3D> UniquePositions(FaceList.size()*3);//*3 because each face consits of 3 vertexes, because we only support triangles^^
|
||||
vector<aiVector3D> UniqueNormals(FaceList.size()*3);
|
||||
vector<aiVector3D> UniqueUvs(FaceList.size()*3);
|
||||
|
||||
for(unsigned int i=0; i<FaceList.size(); ++i)
|
||||
{
|
||||
UniquePositions[3*i+0]=Positions[FaceList[i].VertexIndices[0]];
|
||||
UniquePositions[3*i+1]=Positions[FaceList[i].VertexIndices[1]];
|
||||
UniquePositions[3*i+2]=Positions[FaceList[i].VertexIndices[2]];
|
||||
|
||||
UniqueNormals[3*i+0]=Normals[FaceList[i].VertexIndices[0]];
|
||||
UniqueNormals[3*i+1]=Normals[FaceList[i].VertexIndices[1]];
|
||||
UniqueNormals[3*i+2]=Normals[FaceList[i].VertexIndices[2]];
|
||||
|
||||
UniqueUvs[3*i+0]=Uvs[FaceList[i].VertexIndices[0]];
|
||||
UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
|
||||
UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
|
||||
|
||||
UniqueFaceList[i].VertexIndices[0]=3*i+0;
|
||||
UniqueFaceList[i].VertexIndices[1]=3*i+1;
|
||||
UniqueFaceList[i].VertexIndices[2]=3*i+2;
|
||||
}
|
||||
|
||||
//----------------Load the Material:-------------------------------
|
||||
aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
|
||||
//_________________________________________________________________
|
||||
|
||||
//Mesh is fully loaded, copy it into the aiScene:
|
||||
if(m_CurrentScene->mNumMeshes!=0)
|
||||
throw new ImportErrorException("Currently only one mesh per File is allowed!!");
|
||||
|
||||
//---------------------Create the aiMesh:-----------------------
|
||||
aiMesh* NewAiMesh=new aiMesh();
|
||||
|
||||
//Positions
|
||||
NewAiMesh->mVertices=new aiVector3D[UniquePositions.size()];
|
||||
memcpy(NewAiMesh->mVertices, &UniquePositions[0], UniquePositions.size()*sizeof(aiVector3D));
|
||||
NewAiMesh->mNumVertices=UniquePositions.size();
|
||||
|
||||
//Normals
|
||||
NewAiMesh->mNormals=new aiVector3D[UniqueNormals.size()];
|
||||
memcpy(NewAiMesh->mNormals, &UniqueNormals[0], UniqueNormals.size()*sizeof(aiVector3D));
|
||||
|
||||
//Uvs
|
||||
NewAiMesh->mNumUVComponents[0]=2;
|
||||
//NewAiMesh->mTextureCoords=new aiVector3D*[1];
|
||||
NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
|
||||
memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
|
||||
|
||||
//Faces
|
||||
NewAiMesh->mFaces=new aiFace[UniqueFaceList.size()];
|
||||
for(unsigned int i=0; i<UniqueFaceList.size(); ++i)
|
||||
{
|
||||
NewAiMesh->mFaces[i].mNumIndices=3;
|
||||
NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
|
||||
|
||||
NewAiMesh->mFaces[i].mIndices[0]=UniqueFaceList[i].VertexIndices[0];
|
||||
NewAiMesh->mFaces[i].mIndices[1]=UniqueFaceList[i].VertexIndices[1];
|
||||
NewAiMesh->mFaces[i].mIndices[2]=UniqueFaceList[i].VertexIndices[2];
|
||||
}
|
||||
NewAiMesh->mNumFaces=UniqueFaceList.size();
|
||||
|
||||
//Set the Material:
|
||||
NewAiMesh->mMaterialIndex=0;
|
||||
if(m_CurrentScene->mMaterials)
|
||||
throw new ImportErrorException("only 1 material supported at this time!");
|
||||
m_CurrentScene->mMaterials=new aiMaterial*[1];
|
||||
m_CurrentScene->mNumMaterials=1;
|
||||
m_CurrentScene->mMaterials[0]=MeshMat;
|
||||
//________________________________________________________________
|
||||
|
||||
|
||||
//Attach the mesh to the scene:
|
||||
m_CurrentScene->mNumMeshes=1;
|
||||
m_CurrentScene->mMeshes=new aiMesh*;
|
||||
m_CurrentScene->mMeshes[0]=NewAiMesh;
|
||||
|
||||
|
||||
//stringstream ss; ss <<"Last Node: <" << Reader->getNodeName() << ">";
|
||||
//throw new ImportErrorException(ss.str());
|
||||
}
|
||||
|
||||
aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
||||
{
|
||||
MaterialHelper *NewMaterial=new MaterialHelper();
|
||||
NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);
|
||||
/*For bettetr understanding of the material parser, here is a material example file:
|
||||
|
||||
material Sarg
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 0.640000 0.640000 0.640000 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
emissive 0.000000 0.000000 0.000000 1.000000
|
||||
texture_unit
|
||||
{
|
||||
texture SargTextur.tga
|
||||
tex_address_mode wrap
|
||||
filtering linear linear none
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material";
|
||||
DefaultLogger::get()->info(str(format("Trying to load %1%") % MaterialFileName));
|
||||
|
||||
//Read the file into memory and put it in a stringstream
|
||||
stringstream ss;
|
||||
{// after this block, the temporarly loaded data will be released
|
||||
IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
|
||||
if(NULL==MatFilePtr)
|
||||
{
|
||||
MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
|
||||
if(NULL==MatFilePtr)
|
||||
{
|
||||
DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opned, Material will not be loaded!");
|
||||
return NewMaterial;
|
||||
}
|
||||
}
|
||||
scoped_ptr<IOStream> MaterialFile(MatFilePtr);
|
||||
vector<char> FileData(MaterialFile->FileSize());
|
||||
MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1);
|
||||
BaseImporter::ConvertToUTF8(FileData);
|
||||
|
||||
ss << &FileData[0];
|
||||
}
|
||||
|
||||
string Line;
|
||||
ss >> Line;
|
||||
unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another
|
||||
while(!ss.eof())
|
||||
{
|
||||
if(Line=="material")
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line==MaterialName)//Load the next material
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line!="{")
|
||||
throw new ImportErrorException("empty material!");
|
||||
|
||||
while(Line!="}")//read until the end of the material
|
||||
{
|
||||
//Proceed to the first technique
|
||||
ss >> Line;
|
||||
if(Line=="technique")
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line!="{")
|
||||
throw new ImportErrorException("empty technique!");
|
||||
while(Line!="}")//read until the end of the technique
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line=="pass")
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line!="{")
|
||||
throw new ImportErrorException("empty pass!");
|
||||
while(Line!="}")//read until the end of the pass
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line=="ambient")
|
||||
{
|
||||
//read the ambient light values:
|
||||
}
|
||||
else if(Line=="diffuse")
|
||||
{
|
||||
}
|
||||
else if(Line=="specular")
|
||||
{
|
||||
}
|
||||
else if(Line=="emmisive")
|
||||
{
|
||||
}
|
||||
else if(Line=="texture_unit")
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line!="{")
|
||||
throw new ImportErrorException("empty texture unit!");
|
||||
while(Line!="}")//read until the end of the texture_unit
|
||||
{
|
||||
ss >> Line;
|
||||
if(Line=="texture")
|
||||
{
|
||||
ss >> Line;
|
||||
NewMaterial->AddProperty(&aiString(Line.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
|
||||
}
|
||||
}//end of texture unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}//end of technique
|
||||
}
|
||||
|
||||
}//end of material
|
||||
}
|
||||
else {} //this is the wrong material, proceed the file until we reach the next material
|
||||
}
|
||||
ss >> Line;
|
||||
}
|
||||
|
||||
return NewMaterial;
|
||||
}
|
||||
|
||||
}//namespace Ogre
|
||||
}//namespace Assimp
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER
|
|
@ -0,0 +1,122 @@
|
|||
#include "BaseImporter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "irrXMLWrapper.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Ogre
|
||||
{
|
||||
|
||||
typedef irr::io::IrrXMLReader XmlReader;
|
||||
|
||||
//Forward declarations:
|
||||
struct Face;
|
||||
struct SubMesh;
|
||||
|
||||
///The Main Ogre Importer Class
|
||||
class OgreImporter : public BaseImporter
|
||||
{
|
||||
public:
|
||||
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 GetExtensionList(std::string& append);
|
||||
virtual void SetupProperties(const Importer* pImp);
|
||||
private:
|
||||
|
||||
///Helper Functions to read parts of the XML File
|
||||
/** @param Filename We need this to check for a material File with the same name.*/
|
||||
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);
|
||||
aiMaterial* LoadMaterial(std::string MaterialName);
|
||||
|
||||
//Now we don't have to give theses parameters to all functions
|
||||
std::string m_CurrentFilename;
|
||||
std::string m_MaterialLibFilename;
|
||||
IOSystem* m_CurrentIOHandler;
|
||||
aiScene *m_CurrentScene;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------Helper Funktion to Get a Attribute Save---------------
|
||||
template<typename t> inline t GetAttribute(XmlReader* Reader, std::string Name)
|
||||
{
|
||||
throw std::exception("unimplemented Funtcion used!");
|
||||
return t();
|
||||
}
|
||||
|
||||
template<> inline int GetAttribute<int>(XmlReader* Reader, std::string Name)
|
||||
{
|
||||
const char* Value=Reader->getAttributeValue(Name.c_str());
|
||||
if(Value)
|
||||
return atoi(Value);
|
||||
else
|
||||
throw ImportErrorException(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||
}
|
||||
|
||||
template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name)
|
||||
{
|
||||
const char* Value=Reader->getAttributeValue(Name.c_str());
|
||||
if(Value)
|
||||
return fast_atof(Value);
|
||||
else
|
||||
throw ImportErrorException(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||
}
|
||||
|
||||
template<> inline std::string GetAttribute<std::string>(XmlReader* Reader, std::string Name)
|
||||
{
|
||||
const char* Value=Reader->getAttributeValue(Name.c_str());
|
||||
if(Value)
|
||||
return std::string(Value);
|
||||
else
|
||||
throw new ImportErrorException(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||
}
|
||||
|
||||
template<> inline bool GetAttribute<bool>(XmlReader* Reader, std::string Name)
|
||||
{
|
||||
const char* Value=Reader->getAttributeValue(Name.c_str());
|
||||
if(Value)
|
||||
{
|
||||
if(Value==std::string("true"))
|
||||
return true;
|
||||
else if(Value==std::string("false"))
|
||||
return false;
|
||||
else
|
||||
throw new ImportErrorException(std::string("Bool value has invalid value: "+Name+" / "+Value+" / "+Reader->getNodeName()));
|
||||
}
|
||||
else
|
||||
throw new ImportErrorException(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
|
||||
}
|
||||
//__________________________________________________________________
|
||||
|
||||
inline bool XmlRead(XmlReader* Reader)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(!Reader->read())
|
||||
return false;
|
||||
}
|
||||
while(Reader->getNodeType()!=irr::io::EXN_ELEMENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///For the moment just triangles, no other polygon types!
|
||||
struct Face
|
||||
{
|
||||
unsigned int VertexIndices[3];
|
||||
};
|
||||
|
||||
/// Helper Class to describe a complete SubMesh
|
||||
struct SubMesh
|
||||
{
|
||||
std::string Name;
|
||||
std::string MaterialName;
|
||||
std::vector<Face> Faces;
|
||||
};
|
||||
|
||||
}//namespace Ogre
|
||||
}//namespace Assimp
|
55
doc/dox.h
55
doc/dox.h
|
@ -49,8 +49,11 @@ that it has not yet been implemented, and some formats have not completely been
|
|||
<b>Object File Format </b> ( <i>*.off</i> ). <br>
|
||||
<b>Terragen Terrain </b> ( <i>*.ter</i> ) <br>
|
||||
<b>3D GameStudio Model </b> ( <i>*.mdl</i> ) <br>
|
||||
<b>3D GameStudio Terrain</b> ( <i>*.hmp</i> )<br><br><br>
|
||||
<b>3D GameStudio Terrain</b> ( <i>*.hmp</i> )<br>
|
||||
<b>Ogre</b> (<i>.mesh.xml, .skeleton.xml, .material</i>)<br><br>
|
||||
</tt>
|
||||
See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not.<br>
|
||||
|
||||
<sup>3</sup>: These formats support animations, but ASSIMP doesn't yet support them (or they're buggy)
|
||||
<br>
|
||||
<hr>
|
||||
|
@ -778,7 +781,8 @@ OK, that sounds too easy :-). The whole procedure for a new loader merely looks
|
|||
|
||||
<ul>
|
||||
<li>Create a header (<tt><i>FormatName</i>Importer.h</tt>) and a unit (<tt><i>FormatName</i>Importer.cpp</tt>) in the <tt><root>/code/</tt> directory</li>
|
||||
<li>Add them to the following workspaces: vc8, vc9, CMAKE</li>
|
||||
<li>Add them to the following workspaces: vc8 and vc9 (the files are in the workspaces directory), CMAKE (code/CMakeLists.txt, create a new
|
||||
source group for your importer and put them also to ADD_LIBRARY( assimp SHARED))</li>
|
||||
<li>Include <i>AssimpPCH.h</i> - this is the PCH file, and it includes already most Assimp-internal stuff. </li>
|
||||
<li>Open Importer.cpp and include your header just below the <i>(include_new_importers_here)</i> line,
|
||||
guarded by a #define
|
||||
|
@ -789,7 +793,7 @@ guarded by a #define
|
|||
@endcode
|
||||
Wrap the same guard around your .cpp!</li>
|
||||
|
||||
<li>No advance to the <i>(register_new_importers_here)</i> line in the Importer.cpp and register your importer there - just like all the others do.</li>
|
||||
<li>Now advance to the <i>(register_new_importers_here)</i> line in the Importer.cpp and register your importer there - just like all the others do.</li>
|
||||
<li>Setup a suitable test environment (i.e. use AssimpView or your own application), make sure to enable
|
||||
the #aiProcess_ValidateDataStructure flag and enable verbose logging. That is, simply call before you import anything:
|
||||
@code
|
||||
|
@ -814,6 +818,14 @@ Done! Please, share your loader that everyone can profit from it!
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
@section properties Properties
|
||||
|
||||
You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify
|
||||
you custom properties in aiConfig.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works.
|
||||
|
||||
The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can
|
||||
store the properties as a member variable of your importer, they are thread safe.
|
||||
|
||||
@section tnote Notes for text importers
|
||||
|
||||
<ul>
|
||||
|
@ -865,6 +877,12 @@ MaterialHelper* mat = new MaterialHelper();
|
|||
|
||||
const float spec = 16.f;
|
||||
mat->AddProperty(&spec, 1, AI_MATKEY_SHININESS);
|
||||
|
||||
//set the name of the material:
|
||||
NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);//MaterialName is a std::string
|
||||
|
||||
//set the first diffuse texture
|
||||
NewMaterial->AddProperty(&aiString(Texturename.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));//again, Texturename is a std::string
|
||||
@endcode
|
||||
|
||||
@section boost Boost
|
||||
|
@ -1390,3 +1408,34 @@ Build: alles von CustomBuild + DirectX + MFC?
|
|||
|
||||
|
||||
|
||||
/**
|
||||
@page importer_notes Importer Notes
|
||||
|
||||
@section ogre Ogre
|
||||
Ogre importer is WIP and optimized for the Blender Ogre exporter!
|
||||
|
||||
XML Format: There is a binary and a XML mesh Format from Ogre. This loader can only
|
||||
Handle xml files, but don't panic, there is a command line converter, which you can use
|
||||
to create XML files from Binary Files. Just look on the Ogre page for it.
|
||||
|
||||
Currently you can only load meshes. So you will need to import the *.mesh.xml file, the loader will
|
||||
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 material file can have the same name as the mesh 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
|
||||
to load the alternate material file. The default material filename is "Scene.material".
|
||||
|
||||
What will be loaded?
|
||||
|
||||
Mesh: Faces, Positions, Normals and one Uv pair. The Materialname will be used to load the material
|
||||
|
||||
Material: The right material in the file will be searched, the importer should work with materials who
|
||||
have 1 technique and 1 pass in this technique. From there, the texturename will be loaded. Also, the
|
||||
materialname will be set.
|
||||
|
||||
Skeleton: Nothing, yet.
|
||||
*/
|
|
@ -552,6 +552,12 @@ enum aiComponent
|
|||
#define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
|
||||
"IMPORT_IRR_ANIM_FPS"
|
||||
|
||||
/// Ogre Importer will try to load this Materialfile
|
||||
/**
|
||||
Ogre Mehs contain only the MaterialName, not the MaterialFile. If there is no material file
|
||||
with the same name as the material, Ogre Importer will try to load this file and search the material in it.
|
||||
*/
|
||||
#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE "IMPORT_OGRE_MATERIAL_FILE"
|
||||
|
||||
|
||||
#endif // !! AI_CONFIG_H_INC
|
||||
|
|
|
@ -1935,6 +1935,18 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ogre"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\OgreImporter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\OgreImporter.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="collada"
|
||||
>
|
||||
|
|
|
@ -1943,6 +1943,18 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ogre"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\OgreImporter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\OgreImporter.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="process"
|
||||
|
|
Loading…
Reference in New Issue