1 // Copyright (C) 2007-2012 Nikolaus Gebhardt / Thomas Alten 2 // This file is part of the "Irrlicht Engine". 3 // For conditions of distribution and use, see copyright notice in irrlicht.h 4 5 #ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__ 6 #define __I_ANIMATED_MESH_MD3_H_INCLUDED__ 7 8 #include "IAnimatedMesh.h" 9 #include "IQ3Shader.h" 10 #include "quaternion.h" 11 12 namespace irr 13 { 14 namespace scene 15 { 16 17 enum eMD3Models 18 { 19 EMD3_HEAD = 0, 20 EMD3_UPPER, 21 EMD3_LOWER, 22 EMD3_WEAPON, 23 EMD3_NUMMODELS 24 }; 25 26 //! Animation list 27 enum EMD3_ANIMATION_TYPE 28 { 29 // Animations for both lower and upper parts of the player 30 EMD3_BOTH_DEATH_1 = 0, 31 EMD3_BOTH_DEAD_1, 32 EMD3_BOTH_DEATH_2, 33 EMD3_BOTH_DEAD_2, 34 EMD3_BOTH_DEATH_3, 35 EMD3_BOTH_DEAD_3, 36 37 // Animations for the upper part 38 EMD3_TORSO_GESTURE, 39 EMD3_TORSO_ATTACK_1, 40 EMD3_TORSO_ATTACK_2, 41 EMD3_TORSO_DROP, 42 EMD3_TORSO_RAISE, 43 EMD3_TORSO_STAND_1, 44 EMD3_TORSO_STAND_2, 45 46 // Animations for the lower part 47 EMD3_LEGS_WALK_CROUCH, 48 EMD3_LEGS_WALK, 49 EMD3_LEGS_RUN, 50 EMD3_LEGS_BACK, 51 EMD3_LEGS_SWIM, 52 EMD3_LEGS_JUMP_1, 53 EMD3_LEGS_LAND_1, 54 EMD3_LEGS_JUMP_2, 55 EMD3_LEGS_LAND_2, 56 EMD3_LEGS_IDLE, 57 EMD3_LEGS_IDLE_CROUCH, 58 EMD3_LEGS_TURN, 59 60 //! Not an animation, but amount of animation types. 61 EMD3_ANIMATION_COUNT 62 }; 63 64 struct SMD3AnimationInfo 65 { 66 //! First frame 67 s32 first; 68 //! Last frame 69 s32 num; 70 //! Looping frames 71 s32 looping; 72 //! Frames per second 73 s32 fps; 74 }; 75 76 77 // byte-align structures 78 #include "irrpack.h" 79 80 //! this holds the header info of the MD3 file 81 struct SMD3Header 82 { 83 c8 headerID[4]; //id of file, always "IDP3" 84 s32 Version; //this is a version number, always 15 85 s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars 86 s32 numFrames; //number of KeyFrames 87 s32 numTags; //number of 'tags' per frame 88 s32 numMeshes; //number of meshes/skins 89 s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2 90 s32 frameStart; //starting position of frame-structur 91 s32 tagStart; //starting position of tag-structures 92 s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures 93 s32 fileSize; 94 } PACK_STRUCT; 95 96 //! this holds the header info of an MD3 mesh section 97 struct SMD3MeshHeader 98 { 99 c8 meshID[4]; //id, must be IDP3 100 c8 meshName[68]; //name of mesh 65 chars, 32 bit aligned == 68 chars 101 102 s32 numFrames; //number of meshframes in mesh 103 s32 numShader; //number of skins in mesh 104 s32 numVertices; //number of vertices 105 s32 numTriangles; //number of Triangles 106 107 s32 offset_triangles; //starting position of Triangle data, relative to start of Mesh_Header 108 s32 offset_shaders; //size of header 109 s32 offset_st; //starting position of texvector data, relative to start of Mesh_Header 110 s32 vertexStart; //starting position of vertex data,relative to start of Mesh_Header 111 s32 offset_end; 112 } PACK_STRUCT; 113 114 115 //! Compressed Vertex Data 116 struct SMD3Vertex 117 { 118 s16 position[3]; 119 u8 normal[2]; 120 } PACK_STRUCT; 121 122 //! Texture Coordinate 123 struct SMD3TexCoord 124 { 125 f32 u; 126 f32 v; 127 } PACK_STRUCT; 128 129 //! Triangle Index 130 struct SMD3Face 131 { 132 s32 Index[3]; 133 } PACK_STRUCT; 134 135 136 // Default alignment 137 #include "irrunpack.h" 138 139 //! Holding Frame Data for a Mesh 140 struct SMD3MeshBuffer : public IReferenceCounted 141 { 142 SMD3MeshHeader MeshHeader; 143 144 core::stringc Shader; 145 core::array < s32 > Indices; 146 core::array < SMD3Vertex > Vertices; 147 core::array < SMD3TexCoord > Tex; 148 }; 149 150 //! hold a tag info for connecting meshes 151 /** Basically its an alternate way to describe a transformation. */ 152 struct SMD3QuaternionTag 153 { ~SMD3QuaternionTagSMD3QuaternionTag154 virtual ~SMD3QuaternionTag() 155 { 156 position.X = 0.f; 157 } 158 159 // construct copy constructor SMD3QuaternionTagSMD3QuaternionTag160 SMD3QuaternionTag( const SMD3QuaternionTag & copyMe ) 161 { 162 *this = copyMe; 163 } 164 165 // construct for searching SMD3QuaternionTagSMD3QuaternionTag166 SMD3QuaternionTag( const core::stringc& name ) 167 : Name ( name ) {} 168 169 // construct from a position and euler angles in degrees SMD3QuaternionTagSMD3QuaternionTag170 SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle ) 171 : position(pos), rotation(angle * core::DEGTORAD) {} 172 173 // set to matrix settoSMD3QuaternionTag174 void setto ( core::matrix4 &m ) 175 { 176 rotation.getMatrix ( m, position ); 177 } 178 179 bool operator == ( const SMD3QuaternionTag &other ) const 180 { 181 return Name == other.Name; 182 } 183 184 SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe ) 185 { 186 Name = copyMe.Name; 187 position = copyMe.position; 188 rotation = copyMe.rotation; 189 return *this; 190 } 191 192 core::stringc Name; 193 core::vector3df position; 194 core::quaternion rotation; 195 }; 196 197 //! holds a associative list of named quaternions 198 struct SMD3QuaternionTagList 199 { SMD3QuaternionTagListSMD3QuaternionTagList200 SMD3QuaternionTagList() 201 { 202 Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE); 203 } 204 205 // construct copy constructor SMD3QuaternionTagListSMD3QuaternionTagList206 SMD3QuaternionTagList(const SMD3QuaternionTagList& copyMe) 207 { 208 *this = copyMe; 209 } 210 ~SMD3QuaternionTagListSMD3QuaternionTagList211 virtual ~SMD3QuaternionTagList() {} 212 getSMD3QuaternionTagList213 SMD3QuaternionTag* get(const core::stringc& name) 214 { 215 SMD3QuaternionTag search ( name ); 216 s32 index = Container.linear_search ( search ); 217 if ( index >= 0 ) 218 return &Container[index]; 219 return 0; 220 } 221 sizeSMD3QuaternionTagList222 u32 size () const 223 { 224 return Container.size(); 225 } 226 set_usedSMD3QuaternionTagList227 void set_used(u32 new_size) 228 { 229 s32 diff = (s32) new_size - (s32) Container.allocated_size(); 230 if ( diff > 0 ) 231 { 232 SMD3QuaternionTag e(""); 233 for ( s32 i = 0; i < diff; ++i ) 234 Container.push_back(e); 235 } 236 } 237 238 const SMD3QuaternionTag& operator[](u32 index) const 239 { 240 return Container[index]; 241 } 242 243 SMD3QuaternionTag& operator[](u32 index) 244 { 245 return Container[index]; 246 } 247 push_backSMD3QuaternionTagList248 void push_back(const SMD3QuaternionTag& other) 249 { 250 Container.push_back(other); 251 } 252 253 SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe) 254 { 255 Container = copyMe.Container; 256 return *this; 257 } 258 259 private: 260 core::array < SMD3QuaternionTag > Container; 261 }; 262 263 264 //! Holding Frames Buffers and Tag Infos 265 struct SMD3Mesh: public IReferenceCounted 266 { SMD3MeshSMD3Mesh267 SMD3Mesh () 268 { 269 MD3Header.numFrames = 0; 270 } 271 ~SMD3MeshSMD3Mesh272 virtual ~SMD3Mesh() 273 { 274 for (u32 i=0; i<Buffer.size(); ++i) 275 Buffer[i]->drop(); 276 } 277 278 core::stringc Name; 279 core::array<SMD3MeshBuffer*> Buffer; 280 SMD3QuaternionTagList TagList; 281 SMD3Header MD3Header; 282 }; 283 284 285 //! Interface for using some special functions of MD3 meshes 286 class IAnimatedMeshMD3 : public IAnimatedMesh 287 { 288 public: 289 290 //! tune how many frames you want to render inbetween. 291 virtual void setInterpolationShift(u32 shift, u32 loopMode) =0; 292 293 //! get the tag list of the mesh. 294 virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) =0; 295 296 //! get the original md3 mesh. 297 virtual SMD3Mesh* getOriginalMesh() =0; 298 }; 299 300 } // end namespace scene 301 } // end namespace irr 302 303 #endif 304 305