nuclear@0: #include "BaseImporter.h" nuclear@0: nuclear@0: #include nuclear@0: nuclear@0: #include "OgreXmlHelper.hpp" nuclear@0: #include "irrXMLWrapper.h" nuclear@0: nuclear@0: /// Ogre Importer TODO nuclear@0: /* - Read Vertex Colors nuclear@0: - Read multiple TexCoords nuclear@0: */ nuclear@0: nuclear@0: nuclear@0: nuclear@0: namespace Assimp nuclear@0: { nuclear@0: namespace Ogre nuclear@0: { nuclear@0: nuclear@0: nuclear@0: //Forward declarations: nuclear@0: struct Face; nuclear@0: struct Weight; nuclear@0: struct Bone; nuclear@0: struct Animation; nuclear@0: struct Track; nuclear@0: struct Keyframe; nuclear@0: nuclear@0: ///A submesh from Ogre nuclear@0: struct SubMesh nuclear@0: { nuclear@0: bool SharedData; nuclear@0: nuclear@0: std::string Name; nuclear@0: std::string MaterialName; nuclear@0: std::vector FaceList; nuclear@0: nuclear@0: std::vector Positions; bool HasPositions; nuclear@0: std::vector Normals; bool HasNormals; nuclear@0: std::vector Tangents; bool HasTangents; nuclear@0: std::vector > Uvs;//arbitrary number of texcoords, they are nearly always 2d, but assimp has always 3d texcoords, n vectors(outer) with texcoords for each vertex(inner) nuclear@0: nuclear@0: std::vector< std::vector > Weights;//a list(inner) of bones for each vertex(outer) nuclear@0: int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh nuclear@0: 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) nuclear@0: nuclear@0: SubMesh(): SharedData(false), HasPositions(false), HasNormals(false), HasTangents(false), nuclear@0: MaterialIndex(-1), BonesUsed(0) {}//initialize everything nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: ///The Main Ogre Importer Class nuclear@0: class OgreImporter : public BaseImporter nuclear@0: { nuclear@0: public: nuclear@0: virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; nuclear@0: virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); nuclear@0: virtual const aiImporterDesc* GetInfo () const; nuclear@0: virtual void SetupProperties(const Importer* pImp); nuclear@0: private: nuclear@0: nuclear@0: nuclear@0: //-------------------------------- OgreMesh.cpp ------------------------------- nuclear@0: /// Helper Functions to read parts of the XML File nuclear@0: void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value nuclear@0: nuclear@0: /// Reads a single Vertexbuffer and writes its data in the Submesh nuclear@0: static void ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices); nuclear@0: nuclear@0: /// Reads bone weights are stores them into the given submesh nuclear@0: static void ReadBoneWeights(SubMesh &theSubMesh, XmlReader *Reader); nuclear@0: nuclear@0: /// After Loading a SubMehs some work needs to be done (make all Vertexes unique, normalize weights) nuclear@0: static void ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometry); nuclear@0: nuclear@0: /// Uses the bone data to convert a SubMesh into a aiMesh which will be created and returned nuclear@0: aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector& Bones) const; nuclear@0: nuclear@0: nuclear@0: //-------------------------------- OgreSkeleton.cpp ------------------------------- nuclear@0: /// Writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it! nuclear@0: void LoadSkeleton(std::string FileName, std::vector &Bones, std::vector &Animations) const; nuclear@0: nuclear@0: /// Converts the animations in aiAnimations and puts them into the scene nuclear@0: void PutAnimationsInScene(const std::vector &Bones, const std::vector &Animations); nuclear@0: nuclear@0: /// Creates the aiskeleton in current scene nuclear@0: void CreateAssimpSkeleton(const std::vector &Bones, const std::vector &Animations); nuclear@0: nuclear@0: /// Recursivly creates a filled aiNode from a given root bone nuclear@0: static aiNode* CreateAiNodeFromBone(int BoneId, const std::vector &Bones, aiNode* ParentNode); nuclear@0: nuclear@0: nuclear@0: //-------------------------------- OgreMaterial.cpp ------------------------------- nuclear@0: aiMaterial* LoadMaterial(const std::string MaterialName) const; nuclear@0: void ReadTechnique(std::stringstream &ss, aiMaterial* NewMaterial) const; nuclear@0: nuclear@0: nuclear@0: nuclear@0: nuclear@0: //Now we don't have to give theses parameters to all functions nuclear@0: std::string m_CurrentFilename; nuclear@0: std::string m_MaterialLibFilename; nuclear@0: bool m_TextureTypeFromFilename; nuclear@0: IOSystem* m_CurrentIOHandler; nuclear@0: aiScene *m_CurrentScene; nuclear@0: SubMesh m_SharedGeometry;///< we will just use the vertexbuffers of the submesh nuclear@0: }; nuclear@0: nuclear@0: ///For the moment just triangles, no other polygon types! nuclear@0: struct Face nuclear@0: { nuclear@0: unsigned int VertexIndices[3]; nuclear@0: }; nuclear@0: nuclear@0: struct BoneAssignment nuclear@0: { nuclear@0: unsigned int BoneId;//this is, what we get from ogre nuclear@0: std::string BoneName;//this is, what we need for assimp nuclear@0: }; nuclear@0: nuclear@0: ///for a vertex->bone structur nuclear@0: struct Weight nuclear@0: { nuclear@0: unsigned int BoneId; nuclear@0: float Value; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: /// Helper Class to describe an ogre-bone for the skeleton: nuclear@0: /** 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!*/ nuclear@0: struct Bone nuclear@0: { nuclear@0: int Id; nuclear@0: int ParentId; nuclear@0: std::string Name; nuclear@0: aiVector3D Position; nuclear@0: float RotationAngle; nuclear@0: aiVector3D RotationAxis; nuclear@0: std::vector Children; nuclear@0: aiMatrix4x4 BoneToWorldSpace; nuclear@0: nuclear@0: ///ctor nuclear@0: Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {} nuclear@0: ///this operator is needed to sort the bones after Id's nuclear@0: bool operator<(const Bone& rval) const nuclear@0: {return Id nuclear@0: bool operator==(const std::string& rval) const nuclear@0: {return Name==rval; } nuclear@0: bool operator==(const aiString& rval) const nuclear@0: {return Name==std::string(rval.data); } nuclear@0: nuclear@0: // implemented in OgreSkeleton.cpp nuclear@0: void CalculateBoneToWorldSpaceMatrix(std::vector& Bones); nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: nuclear@0: ///Describes an Ogre Animation nuclear@0: struct Animation nuclear@0: { nuclear@0: std::string Name; nuclear@0: float Length; nuclear@0: std::vector Tracks; nuclear@0: }; nuclear@0: nuclear@0: ///a track (keyframes for one bone) from an animation nuclear@0: struct Track nuclear@0: { nuclear@0: std::string BoneName; nuclear@0: std::vector Keyframes; nuclear@0: }; nuclear@0: nuclear@0: /// keyframe (bone transformation) from a track from a animation nuclear@0: struct Keyframe nuclear@0: { nuclear@0: float Time; nuclear@0: aiVector3D Position; nuclear@0: aiQuaternion Rotation; nuclear@0: aiVector3D Scaling; nuclear@0: }; nuclear@0: nuclear@0: }//namespace Ogre nuclear@0: }//namespace Assimp