2007-05-20 11:03:49 -07:00
|
|
|
// Copyright (C) 2002-2007 Nikolaus Gebhardt / Thomas Alten
|
|
|
|
// This file is part of the "Irrlicht Engine".
|
|
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
|
|
|
|
#ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__
|
|
|
|
#define __I_ANIMATED_MESH_MD3_H_INCLUDED__
|
|
|
|
|
|
|
|
#include "IAnimatedMesh.h"
|
|
|
|
#include "IQ3Shader.h"
|
|
|
|
#include "quaternion.h"
|
|
|
|
|
|
|
|
namespace irr
|
|
|
|
{
|
|
|
|
namespace scene
|
|
|
|
{
|
|
|
|
|
|
|
|
enum eMD3Models
|
|
|
|
{
|
|
|
|
EMD3_HEAD = 0,
|
|
|
|
EMD3_UPPER,
|
|
|
|
EMD3_LOWER,
|
|
|
|
EMD3_WEAPON,
|
|
|
|
EMD3_NUMMODELS
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Animation list
|
|
|
|
enum EMD3_ANIMATION_TYPE
|
|
|
|
{
|
|
|
|
// Animations for both lower and upper parts of the player
|
|
|
|
EMD3_BOTH_DEATH_1 = 0,
|
|
|
|
EMD3_BOTH_DEAD_1,
|
|
|
|
EMD3_BOTH_DEATH_2,
|
|
|
|
EMD3_BOTH_DEAD_2,
|
|
|
|
EMD3_BOTH_DEATH_3,
|
|
|
|
EMD3_BOTH_DEAD_3,
|
|
|
|
|
|
|
|
// Animations for the upper part
|
|
|
|
EMD3_TORSO_GESTURE,
|
|
|
|
EMD3_TORSO_ATTACK_1,
|
|
|
|
EMD3_TORSO_ATTACK_2,
|
|
|
|
EMD3_TORSO_DROP,
|
|
|
|
EMD3_TORSO_RAISE,
|
|
|
|
EMD3_TORSO_STAND_1,
|
|
|
|
EMD3_TORSO_STAND_2,
|
|
|
|
|
|
|
|
// Animations for the lower part
|
|
|
|
EMD3_LEGS_WALK_CROUCH,
|
|
|
|
EMD3_LEGS_WALK,
|
|
|
|
EMD3_LEGS_RUN,
|
|
|
|
EMD3_LEGS_BACK,
|
|
|
|
EMD3_LEGS_SWIM,
|
|
|
|
EMD3_LEGS_JUMP_1,
|
|
|
|
EMD3_LEGS_LAND_1,
|
|
|
|
EMD3_LEGS_JUMP_2,
|
|
|
|
EMD3_LEGS_LAND_2,
|
|
|
|
EMD3_LEGS_IDLE,
|
|
|
|
EMD3_LEGS_IDLE_CROUCH,
|
|
|
|
EMD3_LEGS_TURN,
|
|
|
|
|
|
|
|
//! Not an animation, but amount of animation types.
|
|
|
|
EMD3_ANIMATION_COUNT
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SMD3AnimationInfo
|
|
|
|
{
|
|
|
|
s32 first; // First frame
|
|
|
|
s32 num; // Last frame
|
|
|
|
s32 looping; // Looping frames
|
|
|
|
s32 fps; // Frames per second
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// byte-align structures
|
|
|
|
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
|
|
|
# pragma pack( push, packing )
|
|
|
|
# pragma pack( 1 )
|
|
|
|
# define PACK_STRUCT
|
|
|
|
#elif defined( __GNUC__ )
|
|
|
|
# define PACK_STRUCT __attribute__((packed))
|
|
|
|
#else
|
|
|
|
# error compiler not supported
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// this holds the header info of the MD3 file
|
|
|
|
struct SMD3Header
|
|
|
|
{
|
|
|
|
c8 headerID[4]; //id of file, always "IDP3"
|
|
|
|
s32 Version; //this is a version number, always 15
|
|
|
|
s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars
|
|
|
|
s32 numFrames; //number of KeyFrames
|
|
|
|
s32 numTags; //number of 'tags' per frame
|
|
|
|
s32 numMeshes; //number of meshes/skins
|
|
|
|
s32 numMaxSkins; //maximum number of unique skins used in md3 file
|
|
|
|
s32 headerSize; //always equal to the length of this header
|
|
|
|
s32 tagStart; //starting position of tag-structures
|
|
|
|
s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures
|
|
|
|
s32 fileSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SMD3MeshHeader
|
|
|
|
{
|
|
|
|
c8 meshID[4]; //id, must be IDP3
|
|
|
|
c8 meshName[68]; //name of mesh 65 chars, 32 bit aligned == 68 chars
|
|
|
|
|
|
|
|
s32 numFrames; //number of meshframes in mesh
|
|
|
|
s32 numShader; //number of skins in mesh
|
|
|
|
s32 numVertices; //number of vertices
|
|
|
|
s32 numTriangles; //number of Triangles
|
|
|
|
|
|
|
|
s32 offset_triangles; //starting position of Triangle data, relative to start of Mesh_Header
|
|
|
|
s32 offset_shaders; //size of header
|
|
|
|
s32 offset_st; //starting position of texvector data, relative to start of Mesh_Header
|
|
|
|
s32 vertexStart; //starting position of vertex data,relative to start of Mesh_Header
|
|
|
|
s32 offset_end;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//! Compressed Vertex Data
|
|
|
|
struct SMD3Vertex
|
|
|
|
{
|
|
|
|
s16 position[3];
|
|
|
|
u8 normal[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Texure Coordinate
|
|
|
|
struct SMD3TexCoord
|
|
|
|
{
|
|
|
|
f32 u;
|
|
|
|
f32 v;
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Triangle Index
|
|
|
|
struct SMD3Face
|
|
|
|
{
|
|
|
|
s32 Index[3];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Default alignment
|
|
|
|
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
|
|
|
# pragma pack( pop, packing )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef PACK_STRUCT
|
|
|
|
|
|
|
|
//! Holding Frame Data for a Mesh
|
2007-09-06 23:11:47 -07:00
|
|
|
struct SMD3MeshBuffer : public IReferenceCounted
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
SMD3MeshHeader MeshHeader;
|
|
|
|
|
|
|
|
core::array < core::stringc > Shader;
|
|
|
|
core::array < s32 > Indices;
|
|
|
|
core::array < SMD3Vertex > Vertices;
|
|
|
|
core::array < SMD3TexCoord > Tex;
|
|
|
|
};
|
|
|
|
|
|
|
|
//! hold a tag info for connecting meshes
|
|
|
|
//! basically its an alternate way to describe a transformation
|
|
|
|
struct SMD3QuaterionTag
|
|
|
|
{
|
|
|
|
SMD3QuaterionTag() {}
|
|
|
|
|
|
|
|
SMD3QuaterionTag( const core::stringc& name )
|
|
|
|
: Name ( name ) {}
|
|
|
|
|
|
|
|
// construct from a matrix
|
|
|
|
SMD3QuaterionTag ( const core::stringc& name, const core::matrix4 &m )
|
|
|
|
{
|
|
|
|
Name = name;
|
|
|
|
position = m.getTranslation ();
|
|
|
|
rotation = m;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set to matrix
|
|
|
|
void setto ( core::matrix4 &m )
|
|
|
|
{
|
|
|
|
rotation.getMatrix ( m );
|
|
|
|
m.setTranslation ( position );
|
|
|
|
}
|
|
|
|
|
|
|
|
// construct from a position and euler angles in degrees
|
2007-09-08 15:37:57 -07:00
|
|
|
SMD3QuaterionTag ( const core::vector3df &pos, const core::vector3df &angle )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
position = pos;
|
2007-09-08 15:37:57 -07:00
|
|
|
rotation.set ( angle * core::DEGTORAD );
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-27 22:10:23 -07:00
|
|
|
bool operator == ( const SMD3QuaterionTag &other ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-27 22:10:23 -07:00
|
|
|
return Name == other.Name;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
2007-09-09 15:40:28 -07:00
|
|
|
|
|
|
|
core::stringc Name;
|
|
|
|
core::vector3df position;
|
|
|
|
core::quaternion rotation;
|
2007-05-20 11:03:49 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// holds a assoziative list of named quaternions
|
2007-09-06 23:11:47 -07:00
|
|
|
struct SMD3QuaterionTagList : public virtual IReferenceCounted
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
SMD3QuaterionTag* get ( const core::stringc& name )
|
|
|
|
{
|
|
|
|
SMD3QuaterionTag search ( name );
|
|
|
|
s32 index = Container.linear_search ( search );
|
|
|
|
if ( index >= 0 )
|
|
|
|
return &Container[index];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 size () const
|
|
|
|
{
|
|
|
|
return Container.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
SMD3QuaterionTag& operator[] (u32 index )
|
|
|
|
{
|
|
|
|
return Container[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
core::array < SMD3QuaterionTag > Container;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//! Holding Frames Buffers and Tag Infos
|
2007-09-06 23:11:47 -07:00
|
|
|
struct SMD3Mesh: public IReferenceCounted
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-08-13 16:53:12 -07:00
|
|
|
~SMD3Mesh()
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
for (u32 i=0; i<Buffer.size(); ++i)
|
|
|
|
Buffer[i]->drop();
|
|
|
|
};
|
|
|
|
|
|
|
|
SMD3Header MD3Header;
|
|
|
|
core::stringc Name;
|
|
|
|
core::array < SMD3MeshBuffer * > Buffer;
|
|
|
|
SMD3QuaterionTagList TagList;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//! Interface for using some special functions of MD3 meshes
|
|
|
|
class IAnimatedMeshMD3 : public IAnimatedMesh
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
//! tune how many frames you want to render inbetween
|
|
|
|
virtual void setInterpolationShift ( u32 shift, u32 loopMode ) = 0;
|
|
|
|
|
|
|
|
virtual SMD3QuaterionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) = 0;
|
|
|
|
|
|
|
|
virtual SMD3Mesh * getOriginalMesh () = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace scene
|
|
|
|
} // end namespace irr
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|