// ============================================================== // This file is part of MegaGlest (www.glest.org) // // Md5Model.h -- Copyright (c) 2006 David Henry // changed for use with MegaGlest: Copyright (C) 2011- by Mark Vejvoda // // This code is licensed under the MIT license: // http://www.opensource.org/licenses/mit-license.php // // Open Source Initiative OSI - The MIT License (MIT):Licensing // // The MIT License (MIT) // Copyright (c) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE.// // // Declarations for MD5 Model Classes (object, mesh, animation and // skeleton). // ///////////////////////////////////////////////////////////////////////////// #ifndef __MD5_H__ #define __MD5_H__ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #endif // _WIN32 #include #include #include #include #include #if !defined(_WIN32) || defined(__MINGW32__) #include #endif #include #include "Mathlib.h" #include "md5Texture.h" namespace Shared { namespace Graphics { namespace md5 { using std::string; using std::vector; using std::map; #if defined(_WIN32) using std::tr1::shared_ptr; #endif // Forward declarations class Md5Skeleton; class Md5Mesh; class Md5Model; class Md5Animation; class Md5Object; class ShaderProgram; class ArbVertexProgram; class ArbFragmentProgram;; // MD5 Constants extern const int kMd5Version; // We can use a specific render path, depending on // which shader/program we want to use... enum render_path_e { R_normal, R_ARBfp_diffuse, R_ARBfp_diffuse_specular, R_ARBfp_ds_parallax, R_shader }; // Tangent uniform's location //extern GLint tangentLoc; // ARB program's tangent location #define TANGENT_LOC 6 // OpenGL vector types typedef GLfloat vec2_t[2]; typedef GLfloat vec3_t[3]; typedef GLfloat vec4_t[4]; struct Md5Joint_t { string name; int parent; Vector3f pos; Quaternionf orient; }; struct Md5Vertex_t { float st[2]; // Texture coordinates int startWeight; // Start index weights int countWeight; // Number of weights }; struct Md5Triangle_t { int index[3]; // Vertex indices }; struct Md5Weight_t { int joint; // Joint index float bias; Vector3f pos; Vector3f norm; Vector3f tan; }; struct BoundingBox_t { Vector3f min; Vector3f max; }; struct OBBox_t { Matrix4x4f world; Vector3f center; Vector3f extent; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Exception - Exception class for MD5 loader classes. // This acts like a standard runtime_error exception but // know which file or mesh has failed to be loaded. // ///////////////////////////////////////////////////////////////////////////// class Md5Exception : public std::runtime_error { public: // Constructors Md5Exception (const string &error) : std::runtime_error (error) { } Md5Exception (const string &error, const string &name) : std::runtime_error (error), _which (name) { } virtual ~Md5Exception () throw () { } public: // Public interface virtual const char *which () const throw () { return _which.c_str (); } private: // Member variables string _which; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Skeleton - Skeleton model data class. // ///////////////////////////////////////////////////////////////////////////// class Md5Skeleton { public: // Constructors/Destructor Md5Skeleton () { } Md5Skeleton (std::ifstream &file, int numJoints) throw (Md5Exception); ~Md5Skeleton (); private: // Internal types typedef shared_ptr Md5JointPtr; public: // Public interface void draw (const Matrix4x4f &modelView, bool labelJoints); void setNumJoints (int numJoints); void addJoint (Md5Joint_t *thisJoint); Md5Skeleton *clone () const; // Accessors int numJoints () const { return _joints.size (); } Md5Joint_t *joint (int index) const { return _joints[index].get (); } private: // Member variables vector _joints; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Mesh - Mesh data class. // ///////////////////////////////////////////////////////////////////////////// class Md5Mesh { public: // Public internal types enum { kHide, // Skip mesh kNoDraw, // Don't draw but prepare vertices kShow, // Draw mesh }; typedef shared_ptr Md5VertexPtr; typedef shared_ptr Md5TrianglePtr; typedef shared_ptr Md5WeightPtr; public: // Constructor/Destructor Md5Mesh (std::ifstream &ifs) throw (Md5Exception); ~Md5Mesh (); public: // Public interface void setupVertexArrays (Md5Skeleton *skel); void computeWeightNormals (Md5Skeleton *skel); void computeWeightTangents (Md5Skeleton *skel); void computeBoundingBox (Md5Skeleton *skel); void renderVertexArrays () const; void drawNormals () const; // Hide/NoDraw/Show state void setState (int state) { _renderState = state; } // Texture setters void setDecalMap (const Texture2D *tex) { _decal = tex; } void setSpecularMap (const Texture2D *tex) { _specMap = tex; } void setNormalMap (const Texture2D *tex) { _normalMap = tex; } void setHeightMap (const Texture2D *tex) { _heightMap = tex; } // Accessors const string &name () const { return _name; } const BoundingBox_t &boundingBox () const { return _boundingBox; } // Mesh render state bool hiden () const { return (_renderState == kHide); } bool noDraw () const { return (_renderState == kNoDraw); } bool show () const { return (_renderState == kShow); } private: // Internal functions void preRenderVertexArrays () const; void postRenderVertexArrays () const; void allocVertexArrays (); void setupTexCoordArray (); void setupTexture (const Texture2D *tex, GLenum texUnit) const; void resetReversedTexture(const Texture2D *tex, GLenum texUnit) const; private: // Member variables string _name; string _shader; int _renderState; BoundingBox_t _boundingBox; int _numVerts; int _numTris; int _numWeights; // Original mesh data vector _verts; vector _tris; vector _weights; // Final mesh data; vertex arrays for fast rendering vector _vertexArray; vector _normalArray; vector _tangentArray; vector _texCoordArray; vector _vertIndices; // Textures const Texture2D *_decal; const Texture2D *_specMap; const Texture2D *_normalMap; const Texture2D *_heightMap; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Model - MD5 Mesh Model class. // ///////////////////////////////////////////////////////////////////////////// class Md5Model { public: // Constructor/Destructor Md5Model (const string &filename) throw (Md5Exception); ~Md5Model (); public: // Internal type definitions typedef shared_ptr Md5SkeletonPtr; typedef shared_ptr Md5MeshPtr; typedef shared_ptr Md5AnimationPtr; typedef map AnimMap; public: // Public interface void prepare (Md5Skeleton *skel); void drawModel () const; bool addAnim (const string &filename); // Setters void setMeshRenderState (const string &name, int state); void setMeshDecalMap (const string &name, const Texture2D *tex); void setMeshSpecularMap (const string &name, const Texture2D *tex); void setMeshNormalMap (const string &name, const Texture2D *tex); void setMeshHeightMap (const string &name, const Texture2D *tex); // Accessors const Md5Animation *anim (const string &name) const; int numJoints () const { return _numJoints; } const Md5Skeleton *baseSkeleton () const { return _baseSkeleton.get (); } const AnimMap &anims () const { return _animList; } const BoundingBox_t &bindPoseBoundingBox () const { return _bindPoseBox; } static render_path_e renderPath; static ShaderProgram *shader; static ArbVertexProgram *vp; static ArbFragmentProgram *fp; static GLint tangentLoc; static bool bDrawNormals; private: // Internal functions void computeBindPoseBoundingBox (); // Check if an animation is valid for this model, // i.e. anim's skeleton matches with model's skeleton bool validityCheck (Md5Animation *anim) const; // Access to a mesh, given its name Md5Mesh *getMeshByName (const string &name) const; private: // Member variables int _numJoints; int _numMeshes; Md5SkeletonPtr _baseSkeleton; vector _meshes; AnimMap _animList; BoundingBox_t _bindPoseBox; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Animation - MD5 model animation class. // ///////////////////////////////////////////////////////////////////////////// class Md5Animation { public: // Constructor/Destructor Md5Animation (const string &filename) throw (Md5Exception); ~Md5Animation (); private: // Internal type struct JointInfo { string name; int parent; // NOTE: this structure is stored in // little-endian format union JointFlags { short value; struct { bool tx: 1; bool ty: 1; bool tz: 1; bool qx: 1; bool qy: 1; bool qz: 1; }; } flags; int startIndex; }; struct BaseFrameJoint { Vector3f pos; Quaternionf orient; }; typedef shared_ptr Md5SkeletonPtr; typedef shared_ptr BoundingBoxPtr; public: // Public interface void interpolate (int frameA, int frameB, float interp, Md5Skeleton *out) const; // Accessors int maxFrame () const { return _numFrames - 1; } int frameRate () const { return _frameRate; } const string &name () const { return _name; } Md5Skeleton *frame (int frame) const { return _skelframes[frame].get (); } const BoundingBox_t *frameBounds (int frame) const { return _bboxes[frame].get (); } private: // Internal functions void buildFrameSkeleton (vector &jointInfos, vector &baseFrame, vector &animFrameData); private: // Member variables int _numFrames; int _frameRate; string _name; // Store each frame as a skeleton vector _skelframes; // Bounding boxes for each frame vector _bboxes; }; ///////////////////////////////////////////////////////////////////////////// // // class Md5Object - MD5 object class. // ///////////////////////////////////////////////////////////////////////////// class Md5Object { public: // Public internal types/enums enum { kDrawModel = 1, kDrawSkeleton = 2, kDrawJointLabels = 4, }; public: // Contructor/Destructor Md5Object (Md5Model *model); virtual ~Md5Object (); public: // Public interface void animate (double dt); void computeBoundingBox (); void prepare (bool softwareTransformation); void render () const; // Setters void setMd5Model (Md5Model *model); void setAnim (const string &name); void setModelViewMatrix (const Matrix4x4f &mat) { _modelView = mat; } void setRenderFlags (int flags) { _renderFlags = flags; } // Accessors int renderFlags () const { return _renderFlags; } const Md5Model *getModelPtr () const { return _model; } const string currAnimName () const { return _currAnimName; } const OBBox_t &boundingBox () const { return _bbox; } protected: // Member variables; Md5Model *_model; Md5Skeleton *_animatedSkeleton; Matrix4x4f _modelView; bool _softwareTransformation; const Md5Animation *_currAnim; string _currAnimName; unsigned int _currFrame; unsigned int _nextFrame; double _last_time; double _max_time; int _renderFlags; OBBox_t _bbox; }; }}} //end namespace #endif // __MD5_H__