2
0
Эх сурвалжийг харах

- 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-9d2fd5bffc1f

jonathanklein 16 жил өмнө
parent
commit
8cfb2e26cf

+ 1 - 5
code/BaseImporter.h

@@ -217,12 +217,8 @@ public:
 	 * The function is a request to the importer to update its configuration
 	 * The function is a request to the importer to update its configuration
 	 * basing on the Importer's configuration property list.
 	 * basing on the Importer's configuration property list.
 	 * @param pImp Importer instance
 	 * @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:
 protected:
 
 

+ 7 - 0
code/CMakeLists.txt

@@ -192,6 +192,11 @@ SOURCE_GROUP( Obj FILES
 	ObjTools.h
 	ObjTools.h
 )
 )
 
 
+SOURCE_GROUP( Ogre FILES
+	OgreImporter.h
+	OgreImporter.cpp
+)
+
 SOURCE_GROUP( Ply FILES
 SOURCE_GROUP( Ply FILES
 	PlyLoader.cpp
 	PlyLoader.cpp
 	PlyLoader.h
 	PlyLoader.h
@@ -472,6 +477,8 @@ ADD_LIBRARY( assimp SHARED
 	ObjFileParser.cpp
 	ObjFileParser.cpp
 	ObjFileParser.h
 	ObjFileParser.h
 	ObjTools.h
 	ObjTools.h
+	OgreImporter.h
+	OgreImporter.cpp
 	OptimizeGraph.cpp
 	OptimizeGraph.cpp
 	OptimizeGraph.h
 	OptimizeGraph.h
 	OptimizeMeshes.cpp
 	OptimizeMeshes.cpp

+ 7 - 0
code/Importer.cpp

@@ -158,6 +158,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BUILD_NO_LWS_IMPORTER
 #ifndef AI_BUILD_NO_LWS_IMPORTER
 #	include "LWSLoader.h"
 #	include "LWSLoader.h"
 #endif
 #endif
+#ifndef AI_BUILD_NO_OGRE_IMPORTER
+#	include "OgreImporter.h"
+#endif
 
 
 // .......................................................................................
 // .......................................................................................
 // PostProcess-Steps
 // PostProcess-Steps
@@ -360,6 +363,10 @@ Importer::Importer()
 #if (!defined AI_BUILD_NO_LWS_IMPORTER)
 #if (!defined AI_BUILD_NO_LWS_IMPORTER)
 	pimpl->mImporter.push_back( new LWSImporter());
 	pimpl->mImporter.push_back( new LWSImporter());
 #endif
 #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 
 	// Add an instance of each post processing step here in the order 

+ 425 - 0
code/OgreImporter.cpp

@@ -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

+ 122 - 0
code/OgreImporter.h

@@ -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

+ 52 - 3
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>Object File Format </b> ( <i>*.off</i> ). <br>	
 <b>Terragen Terrain </b> ( <i>*.ter</i> ) <br>
 <b>Terragen Terrain </b> ( <i>*.ter</i> ) <br>
 <b>3D GameStudio Model </b> ( <i>*.mdl</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>
 </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)
 <sup>3</sup>: These formats support animations, but ASSIMP doesn't yet support them (or they're buggy)
 <br>
 <br>
 <hr>
 <hr>
@@ -778,7 +781,8 @@ OK, that sounds too easy :-). The whole procedure for a new loader merely looks
 
 
 <ul>
 <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>&lt;root&gt;/code/</tt> directory</li>
 <li>Create a header (<tt><i>FormatName</i>Importer.h</tt>) and a unit (<tt><i>FormatName</i>Importer.cpp</tt>) in the <tt>&lt;root&gt;/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>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, 
 <li>Open Importer.cpp and include your header just below the <i>(include_new_importers_here)</i> line, 
 guarded by a #define 
 guarded by a #define 
@@ -789,7 +793,7 @@ guarded by a #define
 @endcode
 @endcode
 Wrap the same guard around your .cpp!</li>
 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 
 <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:
 the #aiProcess_ValidateDataStructure flag and enable verbose logging. That is, simply call before you import anything:
 @code
 @code
@@ -814,6 +818,14 @@ Done! Please, share your loader that everyone can profit from it!
 </li>
 </li>
 </ul>
 </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
 @section tnote Notes for text importers
 
 
 <ul>
 <ul>
@@ -865,6 +877,12 @@ MaterialHelper* mat = new MaterialHelper();
 
 
 const float spec = 16.f;
 const float spec = 16.f;
 mat->AddProperty(&spec, 1, AI_MATKEY_SHININESS);
 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
 @endcode
 
 
 @section boost Boost
 @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.
+*/

+ 6 - 0
include/aiConfig.h

@@ -552,6 +552,12 @@ enum aiComponent
 #define AI_CONFIG_IMPORT_IRR_ANIM_FPS				\
 #define AI_CONFIG_IMPORT_IRR_ANIM_FPS				\
 	"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
 #endif // !! AI_CONFIG_H_INC

+ 12 - 0
workspaces/vc8/assimp.vcproj

@@ -1935,6 +1935,18 @@
 						>
 						>
 					</File>
 					</File>
 				</Filter>
 				</Filter>
+				<Filter
+					Name="ogre"
+					>
+					<File
+						RelativePath="..\..\code\OgreImporter.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\code\OgreImporter.h"
+						>
+					</File>
+				</Filter>
 				<Filter
 				<Filter
 					Name="collada"
 					Name="collada"
 					>
 					>

+ 12 - 0
workspaces/vc9/assimp.vcproj

@@ -1943,6 +1943,18 @@
 						>
 						>
 					</File>
 					</File>
 				</Filter>
 				</Filter>
+				<Filter
+					Name="ogre"
+					>
+					<File
+						RelativePath="..\..\code\OgreImporter.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\code\OgreImporter.h"
+						>
+					</File>
+				</Filter>
 			</Filter>
 			</Filter>
 			<Filter
 			<Filter
 				Name="process"
 				Name="process"