Ogre Animations implemented but they don't work yet.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@485 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
49ff2e8c44
commit
449bff99be
|
@ -71,15 +71,30 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------Read all submeshs:-----------------------
|
//-------------------Read the submesh:-----------------------
|
||||||
|
SubMesh theSubMesh;
|
||||||
XmlRead(MeshFile);
|
XmlRead(MeshFile);
|
||||||
while(string(MeshFile->getNodeName())=="submesh")//read the index values (the faces):
|
if(MeshFile->getNodeName()==string("submesh"))
|
||||||
{
|
{
|
||||||
SubMesh NewSubMesh;
|
theSubMesh.MaterialName=GetAttribute<string>(MeshFile, "material");
|
||||||
NewSubMesh.MaterialName=GetAttribute<string>(MeshFile, "material");
|
DefaultLogger::get()->debug("Loading Submehs with Material: "+theSubMesh.MaterialName);
|
||||||
DefaultLogger::get()->debug("Loading Submehs with Material: "+NewSubMesh.MaterialName);
|
ReadSubMesh(theSubMesh, MeshFile);
|
||||||
ReadSubMesh(NewSubMesh, MeshFile);
|
|
||||||
|
//Load the Material:
|
||||||
|
aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
|
||||||
|
|
||||||
|
//Set the Material:
|
||||||
|
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;
|
||||||
|
theSubMesh.MaterialIndex=0;
|
||||||
}
|
}
|
||||||
|
//check for second root node:
|
||||||
|
if(MeshFile->getNodeName()==string("submesh"))
|
||||||
|
throw new ImportErrorException("more than one submesh in the file, abording!");
|
||||||
|
|
||||||
//____________________________________________________________
|
//____________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,16 +109,22 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
|
|
||||||
|
|
||||||
//----------------Load the skeleton: -------------------------------
|
//----------------Load the skeleton: -------------------------------
|
||||||
|
vector<Bone> Bones;
|
||||||
|
vector<Animation> Animations;
|
||||||
if(MeshFile->getNodeName()==string("skeletonlink"))
|
if(MeshFile->getNodeName()==string("skeletonlink"))
|
||||||
{
|
{
|
||||||
string SkeletonFile=GetAttribute<string>(MeshFile, "name");
|
string SkeletonFile=GetAttribute<string>(MeshFile, "name");
|
||||||
LoadSkeleton(SkeletonFile);
|
LoadSkeleton(SkeletonFile, Bones, Animations);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("No skeleton file will be loaded");
|
||||||
DefaultLogger::get()->warn(MeshFile->getNodeName());
|
DefaultLogger::get()->warn(MeshFile->getNodeName());
|
||||||
|
}
|
||||||
//__________________________________________________________________
|
//__________________________________________________________________
|
||||||
|
|
||||||
|
CreateAssimpSubMesh(theSubMesh, Bones);
|
||||||
|
CreateAssimpSkeleton(Bones, Animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,12 +142,6 @@ void OgreImporter::SetupProperties(const Importer* pImp)
|
||||||
|
|
||||||
void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
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
|
|
||||||
vector< vector<Weight> > Weights;
|
|
||||||
|
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
//TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, wenn the order
|
//TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, wenn the order
|
||||||
//of faces and geometry changed, and not if we habe more than one of one
|
//of faces and geometry changed, and not if we habe more than one of one
|
||||||
|
@ -149,7 +164,7 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
{
|
{
|
||||||
throw new ImportErrorException("Submesh has quads, only traingles are supported!");
|
throw new ImportErrorException("Submesh has quads, only traingles are supported!");
|
||||||
}
|
}
|
||||||
FaceList.push_back(NewFace);
|
theSubMesh.FaceList.push_back(NewFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
}//end of faces
|
}//end of faces
|
||||||
|
@ -166,13 +181,13 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
{
|
{
|
||||||
throw new ImportErrorException("vertexbuffer node is not first in geometry node!");
|
throw new ImportErrorException("vertexbuffer node is not first in geometry node!");
|
||||||
}
|
}
|
||||||
HasPositions=GetAttribute<bool>(Reader, "positions");
|
theSubMesh.HasPositions=GetAttribute<bool>(Reader, "positions");
|
||||||
HasNormals=GetAttribute<bool>(Reader, "normals");
|
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
|
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
|
||||||
NumUvs=0;
|
theSubMesh.NumUvs=0;
|
||||||
else
|
else
|
||||||
NumUvs=GetAttribute<int>(Reader, "texture_coords");
|
theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords");
|
||||||
if(NumUvs>1)
|
if(theSubMesh.NumUvs>1)
|
||||||
throw new ImportErrorException("too many texcoords (just 1 supported!)");
|
throw new ImportErrorException("too many texcoords (just 1 supported!)");
|
||||||
|
|
||||||
//read all the vertices:
|
//read all the vertices:
|
||||||
|
@ -182,35 +197,35 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
//read all vertex attributes:
|
//read all vertex attributes:
|
||||||
|
|
||||||
//Position
|
//Position
|
||||||
if(HasPositions)
|
if(theSubMesh.HasPositions)
|
||||||
{
|
{
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
aiVector3D NewPos;
|
aiVector3D NewPos;
|
||||||
NewPos.x=GetAttribute<float>(Reader, "x");
|
NewPos.x=GetAttribute<float>(Reader, "x");
|
||||||
NewPos.y=GetAttribute<float>(Reader, "y");
|
NewPos.y=GetAttribute<float>(Reader, "y");
|
||||||
NewPos.z=GetAttribute<float>(Reader, "z");
|
NewPos.z=GetAttribute<float>(Reader, "z");
|
||||||
Positions.push_back(NewPos);
|
theSubMesh.Positions.push_back(NewPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Normal
|
//Normal
|
||||||
if(HasNormals)
|
if(theSubMesh.HasNormals)
|
||||||
{
|
{
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
aiVector3D NewNormal;
|
aiVector3D NewNormal;
|
||||||
NewNormal.x=GetAttribute<float>(Reader, "x");
|
NewNormal.x=GetAttribute<float>(Reader, "x");
|
||||||
NewNormal.y=GetAttribute<float>(Reader, "y");
|
NewNormal.y=GetAttribute<float>(Reader, "y");
|
||||||
NewNormal.z=GetAttribute<float>(Reader, "z");
|
NewNormal.z=GetAttribute<float>(Reader, "z");
|
||||||
Normals.push_back(NewNormal);
|
theSubMesh.Normals.push_back(NewNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Uv:
|
//Uv:
|
||||||
if(1==NumUvs)
|
if(1==theSubMesh.NumUvs)
|
||||||
{
|
{
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
aiVector3D NewUv;
|
aiVector3D NewUv;
|
||||||
NewUv.x=GetAttribute<float>(Reader, "u");
|
NewUv.x=GetAttribute<float>(Reader, "u");
|
||||||
NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
|
NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
|
||||||
Uvs.push_back(NewUv);
|
theSubMesh.Uvs.push_back(NewUv);
|
||||||
}
|
}
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
}
|
}
|
||||||
|
@ -218,126 +233,168 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
}//end of "geometry
|
}//end of "geometry
|
||||||
else if(string(Reader->getNodeName())=="boneassignments")
|
else if(string(Reader->getNodeName())=="boneassignments")
|
||||||
{
|
{
|
||||||
Weights.resize(Positions.size());
|
theSubMesh.Weights.resize(theSubMesh.Positions.size());
|
||||||
while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
|
while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
|
||||||
{
|
{
|
||||||
Weight NewWeight;
|
Weight NewWeight;
|
||||||
unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
|
unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
|
||||||
NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
|
NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
|
||||||
NewWeight.Value=GetAttribute<float>(Reader, "weight");
|
NewWeight.Value=GetAttribute<float>(Reader, "weight");
|
||||||
|
theSubMesh.BonesUsed=max(theSubMesh.BonesUsed, NewWeight.BoneId+1);//calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0)
|
||||||
|
|
||||||
Weights[VertexId].push_back(NewWeight);
|
theSubMesh.Weights[VertexId].push_back(NewWeight);
|
||||||
|
|
||||||
//XmlRead(Reader);//Once i had this line, and than i got only every second boneassignment, but my first test models had even boneassignment counts, so i thougt, everything would work. And yes, i HATE irrXML!!!
|
//XmlRead(Reader);//Once i had this line, and than i got only every second boneassignment, but my first test models had even boneassignment counts, so i thougt, everything would work. And yes, i HATE irrXML!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
}//end of boneassignments
|
}//end of boneassignments
|
||||||
}
|
}
|
||||||
DefaultLogger::get()->debug(str(format("Positionen: %1% Normale: %2% TexCoords: %3%") % Positions.size() % Normals.size() % Uvs.size()));
|
DefaultLogger::get()->debug(str(format("Positionen: %1% Normale: %2% TexCoords: %3%") % theSubMesh.Positions.size() % theSubMesh.Normals.size() % theSubMesh.Uvs.size()));
|
||||||
DefaultLogger::get()->warn(Reader->getNodeName());
|
DefaultLogger::get()->warn(Reader->getNodeName());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------Make all Vertexes unique: (this is required by assimp)-----------------------
|
//---------------Make all Vertexes unique: (this is required by assimp)-----------------------
|
||||||
vector<Face> UniqueFaceList(FaceList.size());
|
vector<Face> UniqueFaceList(theSubMesh.FaceList.size());
|
||||||
vector<aiVector3D> UniquePositions(FaceList.size()*3);//*3 because each face consits 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> UniqueNormals(FaceList.size()*3);
|
vector<aiVector3D> UniquePositions(UniqueVertexCount);
|
||||||
vector<aiVector3D> UniqueUvs(FaceList.size()*3);
|
vector<aiVector3D> UniqueNormals(UniqueVertexCount);
|
||||||
vector< vector<Weight> > UniqueWeights(FaceList.size()*3);
|
vector<aiVector3D> UniqueUvs(UniqueVertexCount);
|
||||||
|
vector< vector<Weight> > UniqueWeights(UniqueVertexCount);
|
||||||
|
|
||||||
for(unsigned int i=0; i<FaceList.size(); ++i)
|
for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
|
||||||
{
|
{
|
||||||
UniquePositions[3*i+0]=Positions[FaceList[i].VertexIndices[0]];
|
//We precalculate the index vlaues her, because we need them in all vertex attributes
|
||||||
UniquePositions[3*i+1]=Positions[FaceList[i].VertexIndices[1]];
|
unsigned int Vertex1=theSubMesh.FaceList[i].VertexIndices[0];
|
||||||
UniquePositions[3*i+2]=Positions[FaceList[i].VertexIndices[2]];
|
unsigned int Vertex2=theSubMesh.FaceList[i].VertexIndices[1];
|
||||||
|
unsigned int Vertex3=theSubMesh.FaceList[i].VertexIndices[2];
|
||||||
|
|
||||||
UniqueNormals[3*i+0]=Normals[FaceList[i].VertexIndices[0]];
|
UniquePositions[3*i+0]=theSubMesh.Positions[Vertex1];
|
||||||
UniqueNormals[3*i+1]=Normals[FaceList[i].VertexIndices[1]];
|
UniquePositions[3*i+1]=theSubMesh.Positions[Vertex2];
|
||||||
UniqueNormals[3*i+2]=Normals[FaceList[i].VertexIndices[2]];
|
UniquePositions[3*i+2]=theSubMesh.Positions[Vertex3];
|
||||||
|
|
||||||
if(1==NumUvs)
|
UniqueNormals[3*i+0]=theSubMesh.Normals[Vertex1];
|
||||||
|
UniqueNormals[3*i+1]=theSubMesh.Normals[Vertex2];
|
||||||
|
UniqueNormals[3*i+2]=theSubMesh.Normals[Vertex3];
|
||||||
|
|
||||||
|
if(1==theSubMesh.NumUvs)
|
||||||
{
|
{
|
||||||
UniqueUvs[3*i+0]=Uvs[FaceList[i].VertexIndices[0]];
|
UniqueUvs[3*i+0]=theSubMesh.Uvs[Vertex1];
|
||||||
UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
|
UniqueUvs[3*i+1]=theSubMesh.Uvs[Vertex2];
|
||||||
UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
|
UniqueUvs[3*i+2]=theSubMesh.Uvs[Vertex3];
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueWeights[3*i+0]=UniqueWeights[FaceList[i].VertexIndices[0]];
|
UniqueWeights[3*i+0]=theSubMesh.Weights[Vertex1];
|
||||||
UniqueWeights[3*i+1]=UniqueWeights[FaceList[i].VertexIndices[1]];
|
UniqueWeights[3*i+1]=theSubMesh.Weights[Vertex2];
|
||||||
UniqueWeights[3*i+2]=UniqueWeights[FaceList[i].VertexIndices[2]];
|
UniqueWeights[3*i+2]=theSubMesh.Weights[Vertex3];
|
||||||
|
|
||||||
|
//The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...)
|
||||||
UniqueFaceList[i].VertexIndices[0]=3*i+0;
|
UniqueFaceList[i].VertexIndices[0]=3*i+0;
|
||||||
UniqueFaceList[i].VertexIndices[1]=3*i+1;
|
UniqueFaceList[i].VertexIndices[1]=3*i+1;
|
||||||
UniqueFaceList[i].VertexIndices[2]=3*i+2;
|
UniqueFaceList[i].VertexIndices[2]=3*i+2;
|
||||||
}
|
}
|
||||||
//_________________________________________________________________________________________
|
//_________________________________________________________________________________________
|
||||||
|
|
||||||
//----------------Load the Material:-------------------------------
|
//now we have the unique datas, but want them in the SubMesh, so we swap all the containers:
|
||||||
aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
|
theSubMesh.FaceList.swap(UniqueFaceList);
|
||||||
//_________________________________________________________________
|
theSubMesh.Positions.swap(UniquePositions);
|
||||||
|
theSubMesh.Normals.swap(UniqueNormals);
|
||||||
|
theSubMesh.Uvs.swap(UniqueUvs);
|
||||||
|
theSubMesh.Weights.swap(UniqueWeights);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones)
|
||||||
|
{
|
||||||
//Mesh is fully loaded, copy it into the aiScene:
|
//Mesh is fully loaded, copy it into the aiScene:
|
||||||
if(m_CurrentScene->mNumMeshes!=0)
|
if(m_CurrentScene->mNumMeshes!=0)
|
||||||
throw new ImportErrorException("Currently only one mesh per File is allowed!!");
|
throw new ImportErrorException("Currently only one mesh per File is allowed!!");
|
||||||
|
|
||||||
//---------------------Create the aiMesh:-----------------------
|
|
||||||
aiMesh* NewAiMesh=new 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
|
|
||||||
if(0!=NumUvs)
|
|
||||||
{
|
|
||||||
NewAiMesh->mNumUVComponents[0]=2;
|
|
||||||
NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
|
|
||||||
memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Bones
|
|
||||||
/*NewAiMesh->mNumBones=UniqueWeights.size();
|
|
||||||
NewAiMesh->mBones=new aiBone*[UniqueWeights.size()];
|
|
||||||
for(un*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//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:
|
//Attach the mesh to the scene:
|
||||||
m_CurrentScene->mNumMeshes=1;
|
m_CurrentScene->mNumMeshes=1;
|
||||||
m_CurrentScene->mMeshes=new aiMesh*;
|
m_CurrentScene->mMeshes=new aiMesh*;
|
||||||
m_CurrentScene->mMeshes[0]=NewAiMesh;
|
m_CurrentScene->mMeshes[0]=NewAiMesh;
|
||||||
|
|
||||||
|
|
||||||
|
//Positions
|
||||||
|
NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()];
|
||||||
|
memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D));
|
||||||
|
NewAiMesh->mNumVertices=theSubMesh.Positions.size();
|
||||||
|
|
||||||
|
//Normals
|
||||||
|
NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()];
|
||||||
|
memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D));
|
||||||
|
|
||||||
|
//Uvs
|
||||||
|
if(0!=theSubMesh.NumUvs)
|
||||||
|
{
|
||||||
|
NewAiMesh->mNumUVComponents[0]=2;
|
||||||
|
NewAiMesh->mTextureCoords[0]= new aiVector3D[theSubMesh.Uvs.size()];
|
||||||
|
memcpy(NewAiMesh->mTextureCoords[0], &theSubMesh.Uvs[0], theSubMesh.Uvs.size()*sizeof(aiVector3D));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------- Bones --------------------------------------------
|
||||||
|
//Copy the weights in in Bone-Vertices Struktur
|
||||||
|
//(we have them in a Vertex-Bones Struktur, this is much easier for making them unique, which is required by assimp
|
||||||
|
vector< vector<aiVertexWeight> > aiWeights(theSubMesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices
|
||||||
|
for(unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices
|
||||||
|
{
|
||||||
|
for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
|
||||||
|
{
|
||||||
|
aiVertexWeight NewWeight;
|
||||||
|
NewWeight.mVertexId=VertexId;//the current Vertex, we can't use the Id form the submehs weights, because they are bone id's
|
||||||
|
NewWeight.mWeight=theSubMesh.Weights[VertexId][BoneId].Value;
|
||||||
|
aiWeights[theSubMesh.Weights[VertexId][BoneId].BoneId].push_back(NewWeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<aiBone*> aiBones;
|
||||||
|
aiBones.reserve(theSubMesh.BonesUsed);//the vector might be smaller, because there might be empty bones (bones that are not attached to any vertex)
|
||||||
|
|
||||||
|
//create all the bones and fill them with informations
|
||||||
|
for(unsigned int i=0; i<theSubMesh.BonesUsed; ++i)
|
||||||
|
{
|
||||||
|
if(aiWeights[i].size()>0)
|
||||||
|
{
|
||||||
|
aiBone* NewBone=new aiBone();
|
||||||
|
NewBone->mNumWeights=aiWeights[i].size();
|
||||||
|
NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()];
|
||||||
|
memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size());
|
||||||
|
NewBone->mName=Bones[i].Name;//The bone list should be sorted after its ids, this was done in LoadSkeleton
|
||||||
|
NewBone->mOffsetMatrix=aiMatrix4x4(Bones[i].WorldToBoneSpace).Inverse();//we suggest, that the mesh space is the world space!
|
||||||
|
|
||||||
|
aiBones.push_back(NewBone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewAiMesh->mNumBones=aiBones.size();
|
||||||
|
NewAiMesh->mBones=new aiBone* [aiBones.size()];
|
||||||
|
memcpy(NewAiMesh->mBones, &(aiBones[0]), aiBones.size()*sizeof(aiBone*));
|
||||||
|
|
||||||
|
//______________________________________________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Faces
|
||||||
|
NewAiMesh->mFaces=new aiFace[theSubMesh.FaceList.size()];
|
||||||
|
for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
|
||||||
|
{
|
||||||
|
NewAiMesh->mFaces[i].mNumIndices=3;
|
||||||
|
NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
|
||||||
|
|
||||||
|
NewAiMesh->mFaces[i].mIndices[0]=theSubMesh.FaceList[i].VertexIndices[0];
|
||||||
|
NewAiMesh->mFaces[i].mIndices[1]=theSubMesh.FaceList[i].VertexIndices[1];
|
||||||
|
NewAiMesh->mFaces[i].mIndices[2]=theSubMesh.FaceList[i].VertexIndices[2];
|
||||||
|
}
|
||||||
|
NewAiMesh->mNumFaces=theSubMesh.FaceList.size();
|
||||||
|
|
||||||
|
//Link the material:
|
||||||
|
NewAiMesh->mMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName)
|
||||||
{
|
{
|
||||||
MaterialHelper *NewMaterial=new MaterialHelper();
|
MaterialHelper *NewMaterial=new MaterialHelper();
|
||||||
|
|
||||||
|
@ -501,7 +558,8 @@ aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
||||||
return NewMaterial;
|
return NewMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreImporter::LoadSkeleton(std::string FileName)
|
|
||||||
|
void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vector<Animation> &Animations)
|
||||||
{
|
{
|
||||||
//most likely the skeleton file will only end with .skeleton
|
//most likely the skeleton file will only end with .skeleton
|
||||||
//But this is a xml reader, so we need: .skeleton.xml
|
//But this is a xml reader, so we need: .skeleton.xml
|
||||||
|
@ -520,9 +578,6 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
if(!SkeletonFile)
|
if(!SkeletonFile)
|
||||||
throw new ImportErrorException(string("Failed to create XML Reader for ")+FileName);
|
throw new ImportErrorException(string("Failed to create XML Reader for ")+FileName);
|
||||||
|
|
||||||
//Variables to store the data from the skeleton file:
|
|
||||||
vector<Bone> Bones;
|
|
||||||
|
|
||||||
//Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
|
//Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!!
|
||||||
|
|
||||||
XmlRead(SkeletonFile);
|
XmlRead(SkeletonFile);
|
||||||
|
@ -618,11 +673,19 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
}
|
}
|
||||||
//_____________________________________________________________________________
|
//_____________________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
//--------- Calculate the WorldToBoneSpace Matrix recursivly for all bones: ------------------
|
||||||
|
BOOST_FOREACH(Bone theBone, Bones)
|
||||||
|
{
|
||||||
|
if(-1==theBone.ParentId) //the bone is a root bone
|
||||||
|
{
|
||||||
|
theBone.CalculateWorldToBoneSpaceMatrix(Bones);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//_______________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------load animations-----------------------------
|
//---------------------------load animations-----------------------------
|
||||||
vector<Animation> Animations;
|
|
||||||
if(string("animations")==SkeletonFile->getNodeName())//animations are optional values
|
if(string("animations")==SkeletonFile->getNodeName())//animations are optional values
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->debug("Loading Animations");
|
DefaultLogger::get()->debug("Loading Animations");
|
||||||
|
@ -697,10 +760,11 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
}
|
}
|
||||||
//_____________________________________________________________________________
|
//_____________________________________________________________________________
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
|
||||||
|
{
|
||||||
//-----------------skeleton is completly loaded, now but it in the assimp scene:-------------------------------
|
//-----------------skeleton is completly loaded, now but it in the assimp scene:-------------------------------
|
||||||
|
|
||||||
if(!m_CurrentScene->mRootNode)
|
if(!m_CurrentScene->mRootNode)
|
||||||
|
@ -708,7 +772,7 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
if(0!=m_CurrentScene->mRootNode->mNumChildren)
|
if(0!=m_CurrentScene->mRootNode->mNumChildren)
|
||||||
throw new ImportErrorException("Root Node already has childnodes!");
|
throw new ImportErrorException("Root Node already has childnodes!");
|
||||||
|
|
||||||
//--------------Creatre the assimp bone hierarchy-----------------
|
//--------------Createt the assimp bone hierarchy-----------------
|
||||||
DefaultLogger::get()->debug("Root Bones");
|
DefaultLogger::get()->debug("Root Bones");
|
||||||
vector<aiNode*> RootBoneNodes;
|
vector<aiNode*> RootBoneNodes;
|
||||||
BOOST_FOREACH(Bone theBone, Bones)
|
BOOST_FOREACH(Bone theBone, Bones)
|
||||||
|
@ -735,7 +799,7 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
aiAnimation* NewAnimation=new aiAnimation();
|
aiAnimation* NewAnimation=new aiAnimation();
|
||||||
NewAnimation->mName=Animations[i].Name;
|
NewAnimation->mName=Animations[i].Name;
|
||||||
NewAnimation->mDuration=Animations[i].Length;
|
NewAnimation->mDuration=Animations[i].Length;
|
||||||
NewAnimation->mTicksPerSecond=0.05f;
|
NewAnimation->mTicksPerSecond=1.0f;
|
||||||
|
|
||||||
//Create all tracks in this animation
|
//Create all tracks in this animation
|
||||||
NewAnimation->mNumChannels=Animations[i].Tracks.size();
|
NewAnimation->mNumChannels=Animations[i].Tracks.size();
|
||||||
|
@ -778,8 +842,7 @@ void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode)
|
||||||
aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* ParentNode)
|
|
||||||
{
|
{
|
||||||
//----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);
|
||||||
|
@ -794,7 +857,7 @@ aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* Parent
|
||||||
//__________________________________________________________
|
//__________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
//----recursivly create all children Nodes:------
|
//---------- recursivly create all children Nodes: ----------
|
||||||
NewNode->mNumChildren=Bones[BoneId].Children.size();
|
NewNode->mNumChildren=Bones[BoneId].Children.size();
|
||||||
NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
|
NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
|
||||||
for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
|
for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
|
||||||
|
@ -808,6 +871,31 @@ aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Bone::CalculateWorldToBoneSpaceMatrix(vector<Bone> &Bones)
|
||||||
|
{
|
||||||
|
//Calculate the matrix for this bone:
|
||||||
|
if(-1==ParentId)
|
||||||
|
{
|
||||||
|
WorldToBoneSpace= aiMatrix4x4::Translation(Position, aiMatrix4x4())
|
||||||
|
* aiMatrix4x4::Rotation(RotationAngle, RotationAxis, aiMatrix4x4())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WorldToBoneSpace= Bones[ParentId].WorldToBoneSpace
|
||||||
|
* aiMatrix4x4::Translation(Position, aiMatrix4x4())
|
||||||
|
* aiMatrix4x4::Rotation(RotationAngle, RotationAxis, aiMatrix4x4())
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//and recursivly for all children:
|
||||||
|
BOOST_FOREACH(int theChildren, Children)
|
||||||
|
{
|
||||||
|
Bones[theChildren].CalculateWorldToBoneSpaceMatrix(Bones);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}//namespace Ogre
|
}//namespace Ogre
|
||||||
}//namespace Assimp
|
}//namespace Assimp
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,19 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "OgreXmlHelper.h"
|
||||||
#include "irrXMLWrapper.h"
|
#include "irrXMLWrapper.h"
|
||||||
#include "fast_atof.h"
|
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef irr::io::IrrXMLReader XmlReader;
|
|
||||||
|
|
||||||
//Forward declarations:
|
//Forward declarations:
|
||||||
|
struct SubMesh;
|
||||||
struct Face;
|
struct Face;
|
||||||
struct Weight;
|
struct Weight;
|
||||||
struct SubMesh;
|
|
||||||
struct Bone;
|
struct Bone;
|
||||||
struct Animation;
|
struct Animation;
|
||||||
struct Track;
|
struct Track;
|
||||||
|
@ -32,10 +31,15 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
///Helper Functions to read parts of the XML File
|
///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);//the submesh reference is the result value
|
||||||
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);
|
void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations);///< writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it!
|
||||||
aiMaterial* LoadMaterial(std::string MaterialName);
|
void CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones);
|
||||||
void LoadSkeleton(std::string FileName);
|
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
|
||||||
|
|
||||||
|
aiMaterial* LoadMaterial(const std::string MaterialName);
|
||||||
|
|
||||||
|
///Recursivly creates a filled aiNode from a given root bone
|
||||||
|
aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
|
||||||
|
|
||||||
//Now we don't have to give theses parameters to all functions
|
//Now we don't have to give theses parameters to all functions
|
||||||
std::string m_CurrentFilename;
|
std::string m_CurrentFilename;
|
||||||
|
@ -44,71 +48,21 @@ private:
|
||||||
aiScene *m_CurrentScene;
|
aiScene *m_CurrentScene;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///A submesh from Ogre
|
||||||
|
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> 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
|
||||||
//------------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 new 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 new 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!
|
///For the moment just triangles, no other polygon types!
|
||||||
struct Face
|
struct Face
|
||||||
|
@ -116,22 +70,21 @@ struct Face
|
||||||
unsigned int VertexIndices[3];
|
unsigned int VertexIndices[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BoneAssignment
|
||||||
|
{
|
||||||
|
unsigned int BoneId;//this is, what we get from ogre
|
||||||
|
std::string BoneName;//this is, what we need for assimp
|
||||||
|
};
|
||||||
|
|
||||||
|
///for a vertex->bone structur
|
||||||
struct Weight
|
struct Weight
|
||||||
{
|
{
|
||||||
unsigned int BoneId;
|
unsigned int BoneId;
|
||||||
float Value;
|
float Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper Class to describe a complete SubMesh
|
|
||||||
struct SubMesh
|
|
||||||
{
|
|
||||||
std::string Name;
|
|
||||||
std::string MaterialName;
|
|
||||||
std::vector<Face> Faces;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/// Helper Class to describe an ogre-bone for the skeleton:
|
||||||
/// Helper Class to describe an ogre-bone
|
|
||||||
/** 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!*/
|
/** 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 Bone
|
struct Bone
|
||||||
{
|
{
|
||||||
|
@ -142,6 +95,7 @@ struct Bone
|
||||||
float RotationAngle;
|
float RotationAngle;
|
||||||
aiVector3D RotationAxis;
|
aiVector3D RotationAxis;
|
||||||
std::vector<int> Children;
|
std::vector<int> Children;
|
||||||
|
aiMatrix4x4 WorldToBoneSpace;
|
||||||
|
|
||||||
///ctor
|
///ctor
|
||||||
Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
|
Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
|
||||||
|
@ -151,11 +105,11 @@ struct Bone
|
||||||
///this operator is needed to find a bone by its name in a vector<Bone>
|
///this operator is needed to find a bone by its name in a vector<Bone>
|
||||||
bool operator==(const std::string& rval) const
|
bool operator==(const std::string& rval) const
|
||||||
{return Name==rval; }
|
{return Name==rval; }
|
||||||
|
|
||||||
|
void CalculateWorldToBoneSpaceMatrix(std::vector<Bone>& Bones);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///Recursivly creates a filled aiNode from a given root bone
|
|
||||||
aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* ParentNode);
|
|
||||||
|
|
||||||
|
|
||||||
///Describes an Ogre Animation
|
///Describes an Ogre Animation
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
#include "irrXMLWrapper.h"
|
||||||
|
#include "fast_atof.h"
|
||||||
|
|
||||||
|
namespace Assimp
|
||||||
|
{
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef irr::io::IrrXMLReader XmlReader;
|
||||||
|
|
||||||
|
|
||||||
|
//------------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 new 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 new 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace Ogre
|
||||||
|
}//namespace Assimp
|
|
@ -1461,5 +1461,6 @@ Material: The right material in the file will be searched, the importer should w
|
||||||
have 1 technique and 1 pass in this technique. From there, the texturename (for 1 color- and 1 normalmap) will be loaded. Also, the
|
have 1 technique and 1 pass in this technique. From there, the texturename (for 1 color- and 1 normalmap) will be loaded. Also, the
|
||||||
materialname will be set.
|
materialname will be set.
|
||||||
|
|
||||||
Skeleton: Skeleton with Bone hierarchie, names and transformations, but no animations.
|
Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in the skeleton is supported), names and transformations,
|
||||||
|
animations with rotation, translation and scaling keys.
|
||||||
*/
|
*/
|
|
@ -1946,6 +1946,10 @@
|
||||||
RelativePath="..\..\code\OgreImporter.h"
|
RelativePath="..\..\code\OgreImporter.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\OgreXmlHelper.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="collada"
|
Name="collada"
|
||||||
|
|
|
@ -1954,6 +1954,10 @@
|
||||||
RelativePath="..\..\code\OgreImporter.h"
|
RelativePath="..\..\code\OgreImporter.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\OgreXmlHelper.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
|
|
Loading…
Reference in New Issue