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