1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
#include "BaseImporter.h"
#include <vector>
#include "OgreXmlHelper.hpp"
#include "irrXMLWrapper.h"
/// Ogre Importer TODO
/* - Read Vertex Colors
- Read multiple TexCoords
*/
namespace Assimp
{
namespace Ogre
{
//Forward declarations:
struct Face;
struct Weight;
struct Bone;
struct Animation;
struct Track;
struct Keyframe;
///A submesh from Ogre
struct SubMesh
{
bool SharedData;
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(): SharedData(false), HasPositions(false), HasNormals(false), HasTangents(false),
NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
};
///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::set<std::string>& extensions);
virtual void SetupProperties(const Importer* pImp);
private:
//-------------------------------- OgreMesh.cpp -------------------------------
/// 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);
/// Reads bone weights are stores them into the given submesh
static void ReadBoneWeights(SubMesh &theSubMesh, XmlReader *Reader);
/// After Loading a SubMehs some work needs to be done (make all Vertexes unique, normalize weights)
static void ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometry);
/// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned
aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones) const;
//-------------------------------- OgreSkeleton.cpp -------------------------------
/// 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;
/// Converts the animations in aiAnimations and puts them into the scene
void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
/// Creates the aiskeleton in current scene
void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations);
/// Recursivly creates a filled aiNode from a given root bone
static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode);
//-------------------------------- OgreMaterial.cpp -------------------------------
aiMaterial* LoadMaterial(const std::string MaterialName) const;
static void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial);
//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;
SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh
};
///For the moment just triangles, no other polygon types!
struct Face
{
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
{
unsigned int BoneId;
float Value;
};
/// Helper Class to describe an ogre-bone for the skeleton:
/** 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;
aiMatrix4x4 BoneToWorldSpace;
///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) const
{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) const
{return Name==rval; }
bool operator==(const aiString& rval) const
{return Name==std::string(rval.data); }
// implemented in OgreSkeleton.cpp
void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones);
};
///Describes an Ogre Animation
struct Animation
{
std::string Name;
float Length;
std::vector<Track> Tracks;
};
///a track (keyframes for one bone) from an animation
struct Track
{
std::string BoneName;
std::vector<Keyframe> Keyframes;
};
/// keyframe (bone transformation) from a track from a animation
struct Keyframe
{
float Time;
aiVector3D Position;
aiQuaternion Rotation;
aiVector3D Scaling;
};
}//namespace Ogre
}//namespace Assimp
|