- better support for OgreXmlConverter generated files

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1177 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/5/head
jonathanklein 2012-02-20 10:27:27 +00:00
parent 37fb338c1f
commit 521088e134
7 changed files with 566 additions and 372 deletions

View File

@ -326,7 +326,8 @@ SET( Obj_SRCS
SOURCE_GROUP( Obj FILES ${Obj_SRCS})
SET( Ogre_SRCS
OgreImporter.h
OgreImporter.hpp
OgreXmlHelper.hpp
OgreImporter.cpp
OgreImporterMaterial.cpp
)

View File

@ -140,7 +140,7 @@ corresponding preprocessor flag to selectively disable formats.
# include "LWSLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
# include "OgreImporter.h"
# include "OgreImporter.hpp"
#endif
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
# include "MS3DLoader.h"

View File

@ -54,7 +54,7 @@ using namespace std;
#include "TinyFormatter.h"
#include "OgreImporter.h"
#include "OgreImporter.hpp"
#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)
{
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)
{
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");
}
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
{
XmlRead(Reader);
@ -242,63 +241,28 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
{
//some info logging:
unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
ostringstream ss; ss<<"VertexCount: "<<NumVertices;
ostringstream ss; ss<<"VertexCount: " << NumVertices;
DefaultLogger::get()->debug(ss.str());
//General Informations about vertices
XmlRead(Reader);
if(!(Reader->getNodeName()==string("vertexbuffer")))
while(Reader->getNodeName()==string("vertexbuffer"))
{
throw DeadlyImportError("vertexbuffer node is not first in geometry node!");
}
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:
XmlRead(Reader);
while(Reader->getNodeName()==string("vertex"))
{
//read all vertex attributes:
//Position
if(theSubMesh.HasPositions)
{
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);
ReadVertexBuffer(theSubMesh, Reader, NumVertices);
}
//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);
}
//some error checking on the loaded data
if(!theSubMesh.HasPositions)
throw DeadlyImportError("No positions could be loaded!");
//Uv:
if(1==theSubMesh.NumUvs)
{
XmlRead(Reader);
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);
}
XmlRead(Reader);
}
if(theSubMesh.HasNormals && theSubMesh.Normals.size() != NumVertices)
throw DeadlyImportError("Wrong Number of Normals loaded!");
if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices)
throw DeadlyImportError("Wrong Number of Tangents loaded!");
if(theSubMesh.NumUvs==1 && theSubMesh.Uvs.size() != NumVertices)
throw DeadlyImportError("Wrong Number of Uvs loaded!");
}//end of "geometry
@ -324,7 +288,8 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
DefaultLogger::get()->debug((Formatter::format(),
"Positionen: ",theSubMesh.Positions.size(),
" Normale: ",theSubMesh.Normals.size(),
" TexCoords: ",theSubMesh.Uvs.size()
" TexCoords: ",theSubMesh.Uvs.size(),
" Tantents: ",theSubMesh.Tangents.size()
));
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^^
vector<aiVector3D> UniquePositions(UniqueVertexCount);
vector<aiVector3D> UniqueNormals(UniqueVertexCount);
vector<aiVector3D> UniqueTangents(UniqueVertexCount);
vector<aiVector3D> UniqueUvs(UniqueVertexCount);
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+2]=theSubMesh.Positions[Vertex3];
if(theSubMesh.HasNormals)
{
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)
{
@ -360,7 +336,8 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
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+1]=theSubMesh.Weights[Vertex2];
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:
//if we don't have one of them, we just swap empty containers, so everything is ok
theSubMesh.FaceList.swap(UniqueFaceList);
theSubMesh.Positions.swap(UniquePositions);
theSubMesh.Normals.swap(UniqueNormals);
theSubMesh.Tangents.swap(UniqueTangents);
theSubMesh.Uvs.swap(UniqueUvs);
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
{
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();
//Normals
if(theSubMesh.HasNormals)
{
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
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) const
aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode)
{
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-----
aiNode* NewNode=new aiNode(Bones[BoneId].Name);
NewNode->mParent=ParentNode;

View File

@ -2,7 +2,7 @@
#include <vector>
#include "OgreXmlHelper.h"
#include "OgreXmlHelper.hpp"
#include "irrXMLWrapper.h"
namespace Assimp
@ -33,6 +33,9 @@ private:
/// Helper Functions to read parts of the XML File
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value
/// Reads a single Vertexbuffer and writes its data in the Submesh
static void ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices);
/// writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const;
@ -46,9 +49,10 @@ private:
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
aiMaterial* LoadMaterial(const std::string MaterialName) const;
static void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial);
///Recursivly creates a filled aiNode from a given root bone
aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const;
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
//Now we don't have to give theses parameters to all functions
std::string m_CurrentFilename;
@ -63,14 +67,18 @@ struct SubMesh
std::string Name;
std::string MaterialName;
std::vector<Face> FaceList;
std::vector<aiVector3D> Positions; bool HasPositions;
std::vector<aiVector3D> Normals; bool HasNormals;
std::vector<aiVector3D> Tangents; bool HasTangents;
std::vector<aiVector3D> Uvs; unsigned int NumUvs;//nearly always 2d, but assimp has always 3d texcoords
std::vector< std::vector<Weight> > Weights;//a list of bones for each vertex
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)
SubMesh(): HasPositions(false), HasNormals(false), NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
SubMesh(): HasPositions(false), HasNormals(false), HasTangents(false),
NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
};
///For the moment just triangles, no other polygon types!

View File

@ -55,7 +55,7 @@ using namespace std;
//#include "boost/foreach.hpp"
//using namespace boost;
#include "OgreImporter.h"
#include "OgreImporter.hpp"
#include "irrXMLWrapper.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
(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:
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";
DefaultLogger::get()->info("Trying to load " +MaterialFileName);
import * from abstract_base_passes_depth.material
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
stringstream ss;
@ -110,11 +136,17 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName);
if(NULL==MatFilePtr)
{
//try the default mat Library
if(NULL==MatFilePtr)
{
MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename);
if(NULL==MatFilePtr)
{
DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!");
return NewMaterial;
delete NewMaterial;
return NULL;
}
}
}
boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr);
@ -135,7 +167,10 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
ss >> Line;
if(Line==MaterialName)//Load the next material
{
string RestOfLine;
getline(ss, RestOfLine);//ignore the rest of the line
ss >> Line;
if(Line!="{")
throw DeadlyImportError("empty material!");
@ -145,6 +180,97 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
ss >> Line;
if(Line=="technique")
{
ReadTechnique(ss, NewMaterial);
}
DefaultLogger::get()->info(Line);
//read informations from a custom material:
if(Line=="set")
{
ss >> Line;
if(Line=="$specular")//todo load this values:
{
}
if(Line=="$diffuse")
{
}
if(Line=="$ambient")
{
}
if(Line=="$colormap")
{
ss >> Line;
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
if(Line=="$normalmap")
{
ss >> Line;
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
if(Line=="$shininess_strength")
{
ss >> Line;
float Shininess=fast_atof(Line.c_str());
NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
}
if(Line=="$shininess_exponent")
{
ss >> Line;
float Shininess=fast_atof(Line.c_str());
NewMaterial->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
}
//Properties from Venetica:
if(Line=="$diffuse_map")
{
ss >> Line;
if(Line[0]=='"')// "file" -> file
Line=Line.substr(1, Line.size()-2);
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
if(Line=="$specular_map")
{
ss >> Line;
if(Line[0]=='"')// "file" -> file
Line=Line.substr(1, Line.size()-2);
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
}
if(Line=="$normal_map")
{
ss >> Line;
if(Line[0]=='"')// "file" -> file
Line=Line.substr(1, Line.size()-2);
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
if(Line=="$light_map")
{
ss >> Line;
if(Line[0]=='"')// "file" -> file
Line=Line.substr(1, Line.size()-2);
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
}
}
}//end of material
}
else {} //this is the wrong material, proceed the file until we reach the next material
}
ss >> Line;
}
return NewMaterial;
}
void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial)
{
string Line;
ss >> Line;
if(Line!="{")
throw DeadlyImportError("empty technique!");
@ -206,50 +332,9 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
}
}
}//end of technique
}
DefaultLogger::get()->info(Line);
//read informations from a custom material:
if(Line=="set")
{
ss >> Line;
if(Line=="$specular")//todo load this values:
{
}
if(Line=="$diffuse")
{
}
if(Line=="$ambient")
{
}
if(Line=="$colormap")
{
ss >> Line;
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
if(Line=="$normalmap")
{
ss >> Line;
aiString ts(Line.c_str());
NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
}
}//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

View File

@ -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.
@subsection material Materials
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 material file can have the same name as the mesh file (if the file is model.mesh or model.mesh.xml the
loader will try to load model.material),
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".
@ -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.
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
- Load colors in custom materials