Ogre Importer now loads the skeleton, animation loading will be available soon
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@478 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
3cb336ff7d
commit
d4d8c290db
|
@ -7,6 +7,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include "boost/format.hpp"
|
#include "boost/format.hpp"
|
||||||
|
#include "boost/foreach.hpp"
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
#include "OgreImporter.h"
|
#include "OgreImporter.h"
|
||||||
|
@ -79,19 +80,28 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
||||||
DefaultLogger::get()->debug("Loading Submehs with Material: "+NewSubMesh.MaterialName);
|
DefaultLogger::get()->debug("Loading Submehs with Material: "+NewSubMesh.MaterialName);
|
||||||
ReadSubMesh(NewSubMesh, MeshFile);
|
ReadSubMesh(NewSubMesh, MeshFile);
|
||||||
}
|
}
|
||||||
//_______________________________________________________________-
|
//____________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------Create the root node-----------------------
|
||||||
//-----------------Read the skeleton:----------------------
|
|
||||||
//Create the root node
|
|
||||||
pScene->mRootNode=new aiNode("root");
|
pScene->mRootNode=new aiNode("root");
|
||||||
|
|
||||||
//link the mesh with the root node:
|
//link the mesh with the root node:
|
||||||
pScene->mRootNode->mMeshes=new unsigned int[1];
|
pScene->mRootNode->mMeshes=new unsigned int[1];
|
||||||
pScene->mRootNode->mMeshes[0]=0;
|
pScene->mRootNode->mMeshes[0]=0;
|
||||||
pScene->mRootNode->mNumMeshes=1;
|
pScene->mRootNode->mNumMeshes=1;
|
||||||
//_________________________________________________________
|
//____________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
//----------------Load the skeleton: -------------------------------
|
||||||
|
if(MeshFile->getNodeName()==string("skeletonlink"))
|
||||||
|
{
|
||||||
|
string SkeletonFile=GetAttribute<string>(MeshFile, "name");
|
||||||
|
LoadSkeleton(SkeletonFile);
|
||||||
|
}
|
||||||
|
//__________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,11 +123,12 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
vector<aiVector3D> Positions; bool HasPositions=false;
|
vector<aiVector3D> Positions; bool HasPositions=false;
|
||||||
vector<aiVector3D> Normals; bool HasNormals=false;
|
vector<aiVector3D> Normals; bool HasNormals=false;
|
||||||
vector<aiVector3D> Uvs; unsigned int NumUvs=0;//nearly always 2d, but assimp has always 3d texcoords
|
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 korrekt, 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
|
||||||
while(Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry")
|
while(Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry" || Reader->getNodeName()==string("boneassignments"))
|
||||||
{
|
{
|
||||||
if(string(Reader->getNodeName())=="faces")//Read the face list
|
if(string(Reader->getNodeName())=="faces")//Read the face list
|
||||||
{
|
{
|
||||||
|
@ -139,7 +150,7 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
FaceList.push_back(NewFace);
|
FaceList.push_back(NewFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}//end of faces
|
||||||
else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
|
else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
|
||||||
{
|
{
|
||||||
//some info logging:
|
//some info logging:
|
||||||
|
@ -199,16 +210,36 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
XmlRead(Reader);
|
XmlRead(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}//end of "geometry
|
||||||
|
else if(string(Reader->getNodeName())=="boneassignments")
|
||||||
|
{
|
||||||
|
Weights.resize(Positions.size());
|
||||||
|
XmlRead(Reader);
|
||||||
|
while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
|
||||||
|
{
|
||||||
|
Weight NewWeight;
|
||||||
|
unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
|
||||||
|
NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
|
||||||
|
NewWeight.Value=GetAttribute<float>(Reader, "weight");
|
||||||
|
|
||||||
|
Weights[VertexId].push_back(NewWeight);
|
||||||
|
|
||||||
|
XmlRead(Reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}//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%") % Positions.size() % Normals.size() % Uvs.size()));
|
||||||
|
DefaultLogger::get()->debug(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(FaceList.size());
|
||||||
vector<aiVector3D> UniquePositions(FaceList.size()*3);//*3 because each face consits of 3 vertexes, because we only support triangles^^
|
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> UniqueNormals(FaceList.size()*3);
|
||||||
vector<aiVector3D> UniqueUvs(FaceList.size()*3);
|
vector<aiVector3D> UniqueUvs(FaceList.size()*3);
|
||||||
|
vector< vector<Weight> > UniqueWeights(FaceList.size()*3);
|
||||||
|
|
||||||
for(unsigned int i=0; i<FaceList.size(); ++i)
|
for(unsigned int i=0; i<FaceList.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -224,15 +255,21 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
|
UniqueUvs[3*i+1]=Uvs[FaceList[i].VertexIndices[1]];
|
||||||
UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
|
UniqueUvs[3*i+2]=Uvs[FaceList[i].VertexIndices[2]];
|
||||||
|
|
||||||
|
UniqueWeights[3*i+0]=UniqueWeights[FaceList[i].VertexIndices[0]];
|
||||||
|
UniqueWeights[3*i+1]=UniqueWeights[FaceList[i].VertexIndices[1]];
|
||||||
|
UniqueWeights[3*i+2]=UniqueWeights[FaceList[i].VertexIndices[2]];
|
||||||
|
|
||||||
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:-------------------------------
|
//----------------Load the Material:-------------------------------
|
||||||
aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
|
aiMaterial* MeshMat=LoadMaterial(theSubMesh.MaterialName);
|
||||||
//_________________________________________________________________
|
//_________________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
//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!!");
|
||||||
|
@ -255,6 +292,11 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
|
NewAiMesh->mTextureCoords[0]= new aiVector3D[UniqueUvs.size()];
|
||||||
memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
|
memcpy(NewAiMesh->mTextureCoords[0], &UniqueUvs[0], UniqueUvs.size()*sizeof(aiVector3D));
|
||||||
|
|
||||||
|
//Bones
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Faces
|
//Faces
|
||||||
NewAiMesh->mFaces=new aiFace[UniqueFaceList.size()];
|
NewAiMesh->mFaces=new aiFace[UniqueFaceList.size()];
|
||||||
for(unsigned int i=0; i<UniqueFaceList.size(); ++i)
|
for(unsigned int i=0; i<UniqueFaceList.size(); ++i)
|
||||||
|
@ -275,17 +317,13 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
|
||||||
m_CurrentScene->mMaterials=new aiMaterial*[1];
|
m_CurrentScene->mMaterials=new aiMaterial*[1];
|
||||||
m_CurrentScene->mNumMaterials=1;
|
m_CurrentScene->mNumMaterials=1;
|
||||||
m_CurrentScene->mMaterials[0]=MeshMat;
|
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;
|
||||||
|
|
||||||
|
|
||||||
//stringstream ss; ss <<"Last Node: <" << Reader->getNodeName() << ">";
|
|
||||||
//throw new ImportErrorException(ss.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
||||||
|
@ -447,6 +485,179 @@ aiMaterial* OgreImporter::LoadMaterial(std::string MaterialName)
|
||||||
return NewMaterial;
|
return NewMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OgreImporter::LoadSkeleton(std::string FileName)
|
||||||
|
{
|
||||||
|
//most likely the skeleton file will only end with .skeleton
|
||||||
|
//But this is a xml reader, so we need: .skeleton.xml
|
||||||
|
FileName+=".xml";
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName);
|
||||||
|
|
||||||
|
//Open the File:
|
||||||
|
boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName));
|
||||||
|
if(NULL==File.get())
|
||||||
|
throw new ImportErrorException("Failed to open skeleton file "+FileName+".");
|
||||||
|
|
||||||
|
//Read the Mesh File:
|
||||||
|
boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
|
||||||
|
XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
|
||||||
|
if(!SkeletonFile)
|
||||||
|
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!!!
|
||||||
|
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
if(string("skeleton")!=SkeletonFile->getNodeName())
|
||||||
|
throw new ImportErrorException("No <skeleton> node in SkeletonFile: "+FileName);
|
||||||
|
|
||||||
|
//load bones
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
if(string("bones")==SkeletonFile->getNodeName())
|
||||||
|
{
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
while(string("bone")==SkeletonFile->getNodeName())
|
||||||
|
{
|
||||||
|
//TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appera, so what....
|
||||||
|
|
||||||
|
//read a new bone:
|
||||||
|
Bone NewBone;
|
||||||
|
NewBone.Id=GetAttribute<int>(SkeletonFile, "id");
|
||||||
|
NewBone.Name=GetAttribute<string>(SkeletonFile, "name");
|
||||||
|
|
||||||
|
//load the position:
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
if(string("position")!=SkeletonFile->getNodeName())
|
||||||
|
throw new ImportErrorException("Position is not first node in Bone!");
|
||||||
|
NewBone.Position.x=GetAttribute<float>(SkeletonFile, "x");
|
||||||
|
NewBone.Position.y=GetAttribute<float>(SkeletonFile, "y");
|
||||||
|
NewBone.Position.z=GetAttribute<float>(SkeletonFile, "z");
|
||||||
|
|
||||||
|
//Rotation:
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
if(string("rotation")!=SkeletonFile->getNodeName())
|
||||||
|
throw new ImportErrorException("Rotation is not the second node in Bone!");
|
||||||
|
NewBone.RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
if(string("axis")!=SkeletonFile->getNodeName())
|
||||||
|
throw new ImportErrorException("No axis specified for bone rotation!");
|
||||||
|
NewBone.RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
|
||||||
|
NewBone.RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
|
||||||
|
NewBone.RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
|
||||||
|
|
||||||
|
//append the newly loaded bone to the bone list
|
||||||
|
Bones.push_back(NewBone);
|
||||||
|
|
||||||
|
//Proceed to the next bone:
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//The bones in the file a not neccesarly ordered by there id's so we do it now:
|
||||||
|
sort(Bones.begin(), Bones.end());
|
||||||
|
//now the id of each bone should be equal to its position in the vector:
|
||||||
|
//so we do a simple check:
|
||||||
|
{
|
||||||
|
bool IdsOk=true;
|
||||||
|
for(int i=0; i<static_cast<signed int>(Bones.size()); ++i)//i is signed, because all Id's are also signed!
|
||||||
|
{
|
||||||
|
if(Bones[i].Id!=i)
|
||||||
|
IdsOk=false;
|
||||||
|
}
|
||||||
|
if(!IdsOk)
|
||||||
|
throw new ImportErrorException("Bone Ids are not valid!"+FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultLogger::get()->debug(str(format("Number of bones: %1%") % Bones.size()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//load bonehierarchy
|
||||||
|
if(string("bonehierarchy")==SkeletonFile->getNodeName())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->debug("loading bonehierarchy...");
|
||||||
|
XmlRead(SkeletonFile);
|
||||||
|
while(string("boneparent")==SkeletonFile->getNodeName())
|
||||||
|
{
|
||||||
|
string Child, Parent;
|
||||||
|
Child=GetAttribute<string>(SkeletonFile, "bone");
|
||||||
|
Parent=GetAttribute<string>(SkeletonFile, "parent");
|
||||||
|
|
||||||
|
unsigned int ChildId, ParentId;
|
||||||
|
ChildId=find(Bones.begin(), Bones.end(), Child)->Id;
|
||||||
|
ParentId=find(Bones.begin(), Bones.end(), Parent)->Id;
|
||||||
|
|
||||||
|
Bones[ChildId].ParentId=ParentId;
|
||||||
|
Bones[ParentId].Children.push_back(ChildId);
|
||||||
|
|
||||||
|
XmlRead(SkeletonFile);//i once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks??
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//load animations
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------skeleton is completly loaded, now but it in the assimp scene:-------------------------------
|
||||||
|
|
||||||
|
if(!m_CurrentScene->mRootNode)
|
||||||
|
throw new ImportErrorException("No root node exists!!");
|
||||||
|
if(0!=m_CurrentScene->mRootNode->mNumChildren)
|
||||||
|
throw new ImportErrorException("Root Node already has childnodes!");
|
||||||
|
|
||||||
|
//create a node for all root bones:
|
||||||
|
DefaultLogger::get()->debug("Root Bones");
|
||||||
|
vector<aiNode*> RootBoneNodes;
|
||||||
|
BOOST_FOREACH(Bone theBone, Bones)
|
||||||
|
{
|
||||||
|
if(-1==theBone.ParentId) //the bone is a root bone
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->debug(theBone.Name);
|
||||||
|
RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size();
|
||||||
|
m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
|
||||||
|
memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* ParentNode)
|
||||||
|
{
|
||||||
|
//----Create the node for this bone and set its values-----
|
||||||
|
aiNode* NewNode=new aiNode(Bones[BoneId].Name);
|
||||||
|
NewNode->mParent=ParentNode;
|
||||||
|
//create a matrix from the transformation values of the ogre bone
|
||||||
|
NewNode->mTransformation=aiMatrix4x4::Translation(Bones[BoneId].Position, aiMatrix4x4())
|
||||||
|
*
|
||||||
|
aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, aiMatrix4x4())
|
||||||
|
;
|
||||||
|
//__________________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
//----recursivly create all children Nodes:------
|
||||||
|
NewNode->mNumChildren=Bones[BoneId].Children.size();
|
||||||
|
NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
|
||||||
|
for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
|
||||||
|
{
|
||||||
|
NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode);
|
||||||
|
}
|
||||||
|
//____________________________________________________
|
||||||
|
|
||||||
|
|
||||||
|
return NewNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}//namespace Ogre
|
}//namespace Ogre
|
||||||
}//namespace Assimp
|
}//namespace Assimp
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,12 @@ typedef irr::io::IrrXMLReader XmlReader;
|
||||||
|
|
||||||
//Forward declarations:
|
//Forward declarations:
|
||||||
struct Face;
|
struct Face;
|
||||||
|
struct Weight;
|
||||||
struct SubMesh;
|
struct SubMesh;
|
||||||
|
struct Bone;
|
||||||
|
struct Animation;
|
||||||
|
struct Track;
|
||||||
|
struct Keyframe;
|
||||||
|
|
||||||
///The Main Ogre Importer Class
|
///The Main Ogre Importer Class
|
||||||
class OgreImporter : public BaseImporter
|
class OgreImporter : public BaseImporter
|
||||||
|
@ -30,6 +35,7 @@ private:
|
||||||
/** @param Filename We need this to check for a material File with the same name.*/
|
/** @param Filename We need this to check for a material File with the same name.*/
|
||||||
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);
|
void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);
|
||||||
aiMaterial* LoadMaterial(std::string MaterialName);
|
aiMaterial* LoadMaterial(std::string MaterialName);
|
||||||
|
void LoadSkeleton(std::string FileName);
|
||||||
|
|
||||||
//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;
|
||||||
|
@ -110,6 +116,12 @@ struct Face
|
||||||
unsigned int VertexIndices[3];
|
unsigned int VertexIndices[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Weight
|
||||||
|
{
|
||||||
|
unsigned int BoneId;
|
||||||
|
float Value;
|
||||||
|
};
|
||||||
|
|
||||||
/// Helper Class to describe a complete SubMesh
|
/// Helper Class to describe a complete SubMesh
|
||||||
struct SubMesh
|
struct SubMesh
|
||||||
{
|
{
|
||||||
|
@ -118,5 +130,50 @@ struct SubMesh
|
||||||
std::vector<Face> Faces;
|
std::vector<Face> Faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// 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!*/
|
||||||
|
struct Bone
|
||||||
|
{
|
||||||
|
int Id;
|
||||||
|
int ParentId;
|
||||||
|
std::string Name;
|
||||||
|
aiVector3D Position;
|
||||||
|
float RotationAngle;
|
||||||
|
aiVector3D RotationAxis;
|
||||||
|
std::vector<int> Children;
|
||||||
|
|
||||||
|
///ctor
|
||||||
|
Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {}
|
||||||
|
///this operator is needed to sort the bones after Id's
|
||||||
|
bool operator<(const Bone& rval)
|
||||||
|
{return Id<rval.Id; }
|
||||||
|
///this operator is needed to find a bone by its name in a vector<Bone>
|
||||||
|
bool operator==(const std::string& rval)
|
||||||
|
{return Name==rval; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
///Recursivly creates a filled aiNode from a given root bone
|
||||||
|
aiNode* CreateAiNodeFromBone(int BoneId, std::vector<Bone> Bones, aiNode* ParentNode);
|
||||||
|
|
||||||
|
|
||||||
|
///Describes an Ogre Animation
|
||||||
|
struct Animation
|
||||||
|
{
|
||||||
|
std::string Name;
|
||||||
|
float Length;
|
||||||
|
};
|
||||||
|
|
||||||
|
///a track (keyframes for one bone) from an animation
|
||||||
|
struct Track
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/// keyframe (bone transformation) from a track from a animation
|
||||||
|
struct Keyframe
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
}//namespace Ogre
|
}//namespace Ogre
|
||||||
}//namespace Assimp
|
}//namespace Assimp
|
|
@ -1440,11 +1440,11 @@ If you want more propertiesin custom materials, you can easily expand the ogre m
|
||||||
|
|
||||||
What will be loaded?
|
What will be loaded?
|
||||||
|
|
||||||
Mesh: Faces, Positions, Normals and one Uv pair. The Materialname will be used to load the material
|
Mesh: Faces, Positions, Normals and one Uv pair. The Materialname will be used to load the material. No Bone-Assignments yet.
|
||||||
|
|
||||||
Material: The right material in the file will be searched, the importer should work with materials who
|
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 (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: Nothing, yet.
|
Skeleton: Skeleton with Bone hierarchie, names and transformations, but no animations.
|
||||||
*/
|
*/
|
Loading…
Reference in New Issue