--- Irrlicht.old/include/IAnimatedMesh.h 2004-08-29 11:27:34.000000000 +0200 +++ Irrlicht/include/IAnimatedMesh.h 2005-01-18 13:28:58.000000000 +0100 @@ -21,6 +21,9 @@ //! Quake 2 MD2 model file EAMT_MD2, + //! Quake 3 .md3 model file + EAMT_MD3, + //! Milkshape 3d skeletal animation file EAMT_MS3D, --- Irrlicht.old/include/IAnimatedMeshMD3.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/include/IAnimatedMeshMD3.h 2004-07-16 16:48:28.000000000 +0200 @@ -0,0 +1,50 @@ +// Copyright (C) 2003 Fabio Concas +// as an extension of the "Irrlicht Engine" +// which is Copyright (C) 2002-2003 Nikolaus Gebhardt + +#ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__ +#define __I_ANIMATED_MESH_MD3_H_INCLUDED__ + +#include + +namespace irr +{ +namespace scene +{ + + //! Interface for using some special functions of MD3 meshes + class IAnimatedMeshMD3 : public IAnimatedMesh + { + public: + //! Returns the amount of tags in an md3 mesh + virtual s32 getTagCount () const = 0; + + //! Returns the position of the tag relateively to its mesh + virtual core::vector3df getTagOrigin (const char* Name) = 0; + + //! Returns the position of the tag relateively to its mesh + virtual core::vector3df getTagOrigin (s32 Number) = 0; + + //! Returns a 3x3 (non orthogonal) rotation matrix + virtual const core::vector3df* getTagRotation (const char* Name) = 0; + + //! Returns a 3x3 (non orthogonal) rotation matrix + virtual const core::vector3df* getTagRotation (s32 Number) = 0; + + //! Returns the name of the tag indexed by Number + virtual const c8* getTagName (s32 Number) = 0; + + //! Returns the zero based index of the tag provided its name + virtual s32 getTagNumber (const char* Name) = 0; + + //! Returns the relative transformation matrix for a tag. + //! This is useful for attaching the parts of a complete md3 model, + //! or even attach an object to a part of a mesh. + virtual core::matrix4* getMatrixOfTags (s32 tagNumber, s32 frame = -1) = 0; + }; + +} // end namespace scene +} // end namespace irr + +#endif + --- Irrlicht.old/include/IAnimatedMeshSceneNode.h 2003-12-20 15:21:46.000000000 +0100 +++ Irrlicht/include/IAnimatedMeshSceneNode.h 2004-07-16 17:48:28.000000000 +0200 @@ -85,6 +85,38 @@ //! ms3d mesh or the name of the joint could not be found. virtual ISceneNode* getMS3DJointNode(const c8* jointName) = 0; + //! Returns a pointer to a child node, wich has the same transformation as + //! the corrsesponding tag, if the mesh in this scene node is a md3 mesh. + //! Otherwise 0 is returned. With this method it is possible to + //! attach scene nodes to joints more easily. In this way, it is + //! for example possible to attach a weapon to the left hand of an + //! animated model. This example shows how: + //! \code + //! ISceneNode* tag_weapon = + //! yourMD3AnimatedMeshSceneNode->getMD3TagNode("tag_weapon"); + //! tag_weapon->addChild(weaponSceneNode); + //! \endcode + //! Please note that the SceneNode returned by this method may not exist + //! before this call and is created by it. + //! \param tagName: Name of the md3 tag. + //! \return Returns a pointer to the scene node which represents the tag + //! with the specified name. Returns 0 if the contained mesh is not an + //! md3 mesh or the name of the tag could not be found. + virtual ISceneNode* getMD3TagNode(const c8* tagName) = 0; + + + //********** Madinitaly's code for linked animations ********** + //! Starts an MD3 animation. + virtual bool setAnimation (u16 animIdx) = 0; + + //! Adds an MD3 animation. + virtual s32 addAnimation (u16 firstFrame, u16 lastFrame, u8 FPS) = 0; + + //! Links anim to linkedAnim. + virtual bool linkAnimation (u16 anim, u16 linkedAnim) = 0; + //************************************************************* + + //! Starts a default MD2 animation. //! With this method it is easily possible to start a Run, Attack, //! Die or whatever animation, if the mesh contained in this scene --- Irrlicht.old/include/irrlicht.h 2004-09-25 12:34:08.000000000 +0200 +++ Irrlicht/include/irrlicht.h 2005-01-18 13:32:06.000000000 +0100 @@ -38,6 +38,7 @@ #include "heapsort.h" #include "IAnimatedMesh.h" #include "IAnimatedMeshMD2.h" +#include "IAnimatedMeshMD3.h" #include "IAnimatedMeshMS3D.h" #include "IAnimatedMeshX.h" #include "IAnimatedMeshSceneNode.h" --- Irrlicht.old/CAnimatedMeshMD3.cpp 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/CAnimatedMeshMD3.cpp 2005-01-18 18:09:04.000000000 +0100 @@ -0,0 +1,580 @@ +// Copyright (C) 2003-2004 Fabio Concas +// as an extension of the "Irrlicht Engine" +// which is Copyright (C) 2002-2003 Nikolaus Gebhardt + +#include "CAnimatedMeshMD3.h" +#include "os.h" +#include "SColor.h" +#include "IReadFile.h" +#include + + + +namespace irr +{ +namespace scene +{ + + +#ifdef _MSC_VER +# pragma pack( push, packing ) +# pragma pack( 1 ) +# define PACK_STRUCT +#elif defined( __GNUC__ ) +# define PACK_STRUCT __attribute__((packed)) +#else +# error compiler not supported +#endif + + + +#define S3DVERTEX_CLOSE_ENOUGH(v1, v2, e) ((v1.Pos.X <= v2.Pos.X + e && v1.Pos.X >= v2.Pos.X - e) && \ + (v1.Pos.Y <= v2.Pos.Y + e && v1.Pos.Y >= v2.Pos.Y - e) && \ + (v1.Pos.Z <= v2.Pos.Z + e && v1.Pos.Z >= v2.Pos.Z - e) && \ + (v1.TCoords.X <= v2.TCoords.X + e && v1.TCoords.X >= v2.TCoords.X - e) && \ + (v1.TCoords.Y <= v2.TCoords.Y + e && v1.TCoords.Y >= v2.TCoords.Y - e)) + + + + const c8 *MAGIC_NUMBER = "IDP3"; + const s32 MD3_VERSION = 15; + const s32 MAX_FRAMES = 1024; + const s32 MAX_TAGS = 16; + const s32 MAX_SURFACES = 32; + const s32 MAX_SHADERS = 256; + const s32 MAX_VERTICES = 4096; + const s32 MAX_TRIANGLES = 8192; + + + struct SMD3_Header { + c8 magicNumber[4]; + s32 Version; + c8 fileName[64]; + s32 Flags; + s32 numFrames; + s32 numTags; + s32 numSurfaces; + s32 numSkins; + s32 ofsFrames; + s32 ofsTags; + s32 ofsSurfaces; + s32 ofsEOF; + } PACK_STRUCT; + + struct SMD3_Frame { + f32 minBounds[3]; + f32 maxBounds[3]; + f32 Translate[3]; + f32 Scale; + c8 Name[16]; + } PACK_STRUCT; + + struct SMD3_Tag { + c8 Name[64]; + f32 Origin[3]; + f32 Rotation[3][3]; + } PACK_STRUCT; + + struct SMD3_Surface { + c8 magicNumber[4]; + c8 Name[64]; + s32 Flags; + s32 numFrames; + s32 numShaders; + s32 numVertices; + s32 numTriangles; + s32 ofsTriangles; + s32 ofsShaders; + s32 ofsTexels; + s32 ofsVertices; + s32 Size; + } PACK_STRUCT; + + struct SMD3_Shader { + c8 fileName[64]; + s32 Index; + } PACK_STRUCT; + + struct SMD3_Triangle { + s32 vIndex[3]; + } PACK_STRUCT; + + struct SMD3_Texel { + f32 S; + f32 T; + } PACK_STRUCT; + + struct SMD3_Vertex { + s16 X, Y, Z; + s16 encNormal; + } PACK_STRUCT; + + +// Default alignment +#ifdef _MSC_VER +# pragma pack( pop, packing ) +#endif + +#undef PACK_STRUCT + + +//! Constructor +CAnimatedMeshMD3::CAnimatedMeshMD3 () : + FrameCount (0), curFrame (0), TagCount (0), TagData (0) +{ + #ifdef _DEBUG + IAnimatedMesh::setDebugName("CAnimatedMeshMD3 IAnimatedMesh"); + IMesh::setDebugName("CAnimatedMeshMD3 IMesh"); + IMeshBuffer::setDebugName("CAnimatedMeshMD3 IMeshBuffer"); + #endif +} + + + +//! Destructor +CAnimatedMeshMD3::~CAnimatedMeshMD3() +{ + if (FrameList) + delete[] FrameList; + if (Vertices) + delete[] Vertices; + if (Normals) + delete[] Normals; + if (TagData) + delete[] TagData; +} + + + +//! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. +s32 CAnimatedMeshMD3::getFrameCount() +{ + return FrameCount; +} + + + +//! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. +// (this type of meshe will ignore the detail level). +IMesh* CAnimatedMeshMD3::getMesh (s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) +{ + if ((u32)frame > (FrameCount)) + frame = (frame % (FrameCount)); + + if (startFrameLoop == -1 && endFrameLoop == -1) + { + startFrameLoop = 0; + endFrameLoop = FrameCount; + } + + Animate (frame); + return this; +} + + + +//! Returns pointer to a mesh buffer +IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer (s32 nr) +{ + return this; +} + + + +//! Returns the material of this meshbuffer +const video::SMaterial& CAnimatedMeshMD3::getMaterial () const +{ + return Material; +} + + + +//! Returns the material of this meshbuffer +video::SMaterial& CAnimatedMeshMD3::getMaterial () +{ + return Material; +} + + + +//! Returns pointer to vertices +const void* CAnimatedMeshMD3::getVertices () const +{ + return FrameList[curFrame].const_pointer (); +} + + +//! Returns pointer to vertices +void* CAnimatedMeshMD3::getVertices() +{ + return FrameList[curFrame].pointer (); +} + + + +//! Returns which type of vertex data is stored. +video::E_VERTEX_TYPE CAnimatedMeshMD3::getVertexType () const +{ + return video::EVT_STANDARD; +} + + + +//! Returns amount of vertices +s32 CAnimatedMeshMD3::getVertexCount () const +{ + return FrameList[0].size (); +} + + + +//! Returns pointer to Indices +const u16* CAnimatedMeshMD3::getIndices () const +{ + return Indices.const_pointer (); +} + + + +//! Returns pointer to Indices +u16* CAnimatedMeshMD3::getIndices () +{ + return Indices.pointer (); +} + + + +//! Returns amount of indices +s32 CAnimatedMeshMD3::getIndexCount () const +{ + return Indices.size(); +} + + + +void CAnimatedMeshMD3::Animate (u32 frame) +{ + curFrame = frame; +} + + + +//! Loads an md3 file +// Many thanks to r2d2 for the multiple surfaces fix! +bool CAnimatedMeshMD3::loadFile (io::IReadFile* file) +{ + if (!file) + return false; + + SMD3_Header Header; + SMD3_Tag Tags; + SMD3_Frame Bones; + SMD3_Surface MeshH; + + s32 totalVertices = 0, totalTriangles = 0; + + file->seek (0); + file->read (&Header, sizeof(SMD3_Header)); + + // Check file header + if (strncmp (Header.magicNumber, MAGIC_NUMBER, 4) || Header.Version != MD3_VERSION) { + os::Printer::log ("MD3 Loader: Wrong file header", file->getFileName (), ELL_WARNING); + return false; + } + + // Read boneframes + BoxList.reallocate (Header.numFrames); + file->seek (Header.ofsFrames); + for (int Cnt = 0; Cnt < Header.numFrames; Cnt++) + { + file->read (&Bones, sizeof (SMD3_Frame)); + BoxList.push_back (core::aabbox3d ( + Bones.minBounds[0], Bones.minBounds[1], Bones.minBounds[2], + Bones.maxBounds[0], Bones.maxBounds[1], Bones.maxBounds[2])); + } + + // Let's handle tags now + TagData = new core::array[Header.numTags]; + STagData TD; + // Read tags, frame by frame + file->seek (Header.ofsTags); + if (Header.numTags > 0) + { + for (int frameCnt = 0; frameCnt < Header.numFrames; frameCnt++) + { + for (int tagCnt = 0; tagCnt < Header.numTags; tagCnt++) + { + file->read (&Tags, sizeof (SMD3_Tag)); + TD.Name = Tags.Name; + TD.Origin = core::vector3df (Tags.Origin[0], Tags.Origin[1], Tags.Origin[2]); + TD.Rotation[0] = core::vector3df (Tags.Rotation[0][0], Tags.Rotation[0][1], Tags.Rotation[0][2]); + TD.Rotation[1] = core::vector3df (Tags.Rotation[1][0], Tags.Rotation[1][1], Tags.Rotation[1][2]); + TD.Rotation[2] = core::vector3df (Tags.Rotation[2][0], Tags.Rotation[2][1], Tags.Rotation[2][2]); + + // Build transformation matrix for every frame + TD.Transformation.makeIdentity (); + TD.Transformation (0, 0) = TD.Rotation[0].X; + TD.Transformation (0, 1) = TD.Rotation[1].X; + TD.Transformation (0, 2) = TD.Rotation[2].X; + TD.Transformation (0, 3) = TD.Origin.X; + + TD.Transformation (1, 0) = TD.Rotation[0].Y; + TD.Transformation (1, 1) = TD.Rotation[1].Y; + TD.Transformation (1, 2) = TD.Rotation[2].Y; + TD.Transformation (1, 3) = TD.Origin.Y; + + TD.Transformation (2, 0) = TD.Rotation[0].Z; + TD.Transformation (2, 1) = TD.Rotation[1].Z; + TD.Transformation (2, 2) = TD.Rotation[2].Z; + TD.Transformation (2, 3) = TD.Origin.Z; + + TD.Transformation (3, 0) = 0; + TD.Transformation (3, 1) = 0; + TD.Transformation (3, 2) = 0; + TD.Transformation (3, 3) = 1; + + TagData[tagCnt].push_back (TD); + } + } + } // finished reading tags + TagCount = Header.numTags; + + // Read skins, surfaces, texture coordinates + FrameList = new core::array[Header.numFrames]; + FrameCount = Header.numFrames; + + s32 offset = Header.ofsSurfaces; + + for (s32 srfCnt = 0; srfCnt < Header.numSurfaces; ++srfCnt) + { + SMD3_Shader *Skins; + SMD3_Triangle *Triangles; + SMD3_Vertex Vertex; + SMD3_Texel Tex; + + core::array TexCoords; + + // Read surface structure + file->seek (offset); + file->read (&MeshH, sizeof (SMD3_Surface)); + if (MeshH.numFrames != Header.numFrames) + { + os::Printer::log ("MD3Loader", "Mesh frame count mismatch, skipping surface!", ELL_WARNING); + break; + } + + // Read skins + Skins = new SMD3_Shader[MeshH.numShaders]; + file->seek (offset + MeshH.ofsShaders); + file->read (Skins, sizeof (SMD3_Shader) * MeshH.numShaders); + + // Read triangles + Triangles = new SMD3_Triangle[MeshH.numTriangles]; + file->seek (offset + MeshH.ofsTriangles); + file->read (Triangles, sizeof (SMD3_Triangle) * MeshH.numTriangles); + + // Read texture coordinates + TexCoords.reallocate (MeshH.numVertices); + core::vector2df vec2d; + file->seek (offset + MeshH.ofsTexels); + for(s32 texCnt = 0; texCnt < MeshH.numVertices; ++texCnt) + { + file->read (&Tex, sizeof(SMD3_Texel)); + vec2d.X = Tex.S; + vec2d.Y = Tex.T; + TexCoords.push_back (vec2d); + } + + // Read vertices, read and decode normals, read triangles and animation frames... + Vertices = new core::array[Header.numFrames]; + Normals = new core::array[Header.numFrames]; + core::vector3df Vec; + for (s32 frameCnt = 0; frameCnt < Header.numFrames; ++frameCnt) + { + Vertices[frameCnt].reallocate (MeshH.numVertices); + Normals[frameCnt].reallocate (MeshH.numVertices); + for (s32 vertCnt = 0; vertCnt < MeshH.numVertices; ++vertCnt) + { + file->read (&Vertex, sizeof (SMD3_Vertex)); + Vec.X = Vertex.X / 64.0f; + Vec.Y = Vertex.Y / 64.0f; + Vec.Z = Vertex.Z / 64.0f; + Vertices[frameCnt].push_back (Vec); + Normals[frameCnt].push_back (calculateNormal (Vertex.encNormal)); + } + } + + video::S3DVertex Vtx; + Vtx.Color = video::SColor (0xFF, 0xFF, 0xFF, 0xFF); + for (s32 frameCnt = 0; frameCnt < Header.numFrames; ++frameCnt) + { + for (s32 triCnt = 0; triCnt < MeshH.numTriangles; ++triCnt) + for (s32 tn = 0; tn < 3; ++tn) + { + Vtx.Pos = Vertices[frameCnt][Triangles[triCnt].vIndex[tn]]; + Vtx.Normal = Normals[frameCnt][Triangles[triCnt].vIndex[tn]]; + Vtx.TCoords.X = TexCoords[Triangles[triCnt].vIndex[tn]].X; + Vtx.TCoords.Y = TexCoords[Triangles[triCnt].vIndex[tn]].Y; + FrameList[frameCnt].push_back (Vtx); + } + } + + // Update offset, vertices and triangles count + offset += MeshH.Size; + totalVertices += MeshH.numFrames * MeshH.numVertices; + totalTriangles += MeshH.numTriangles; + + // Clean up + delete[] Skins; + delete[] Triangles; + } + + TriangleCount = totalTriangles; + + // Finally, set indices + Indices.reallocate (totalVertices); + for (s32 idxCnt = 0; idxCnt < (totalTriangles * 3); idxCnt += 3) + { + Indices.push_back (idxCnt + 2); + Indices.push_back (idxCnt + 1); + Indices.push_back (idxCnt); + } + + return true; +} + + + +/*! Calculates the bounding box +void CAnimatedMeshMD3::calculateBoundingBox() +{ + BoundingBox.reset(0,0,0); + + if (FrameCount) + { + u32 defaultFrame = 1; + + if (defaultFrame>=FrameCount) + defaultFrame = 0; + + for (u32 j=0; j& CAnimatedMeshMD3::getBoundingBox() const +{ + return BoxList[curFrame]; +} + + +//! returns an axis aligned bounding box +core::aabbox3d& CAnimatedMeshMD3::getBoundingBox() +{ + return BoxList[curFrame]; +} + + + +//! Decodes a normal +core::vector3df CAnimatedMeshMD3::calculateNormal(s16 encNormal) +{ + core::vector3df V; + + f32 Lat = ((f32)(encNormal & 0xFF)) * (2 * core::PI) / (f32)255, + Lng = ((f32)((encNormal >> 8) & 0xFF)) * (2 * core::PI) / (f32)255; + + V = core::vector3df ( + cosf (Lat) * sinf (Lng), + sinf (Lat) * sin (Lng), + cosf (Lng)); + + return V; +} + + + +//! Returns the type of the animated mesh. +E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const +{ + return EAMT_MD3; +} + + + +//! Retrieves a tag number by its name +s32 CAnimatedMeshMD3::getTagNumber (const char* Name) +{ + if (TagCount == 1) return 0; + + for (int Cnt = 0; Cnt < TagCount; Cnt++) { + if (strcmp (Name, TagData[Cnt][0].Name.c_str ()) == 0) { + return Cnt; + } + } + + return -1; // No tag by that name +} + + + +//! Returns tag relative position +core::vector3df CAnimatedMeshMD3::getTagOrigin (const char* Name) +{ + s32 Num; + if ((Num = getTagNumber (Name)) != -1) + return TagData[Num][curFrame].Origin; + + return core::vector3df (0, 0, 0); +} + + + +core::vector3df CAnimatedMeshMD3::getTagOrigin (s32 Number) +{ + return TagData[Number][curFrame].Origin; +} + + + +//! Returns relative tag orientation +const core::vector3df* CAnimatedMeshMD3::getTagRotation (const char* Name) +{ + s32 Num; + if (Num = getTagNumber (Name) > -1) + return (const core::vector3df*)TagData[Num][curFrame].Rotation; + return 0; +} + + + +const core::vector3df* CAnimatedMeshMD3::getTagRotation (s32 Number) +{ + return (const core::vector3df*)TagData[Number][curFrame].Rotation; +} + + + +//! Returns name of tag indexed by Number +const c8* CAnimatedMeshMD3::getTagName (s32 Number) +{ + if (Number >= TagCount) return NULL; + return (const char*)TagData[Number][0].Name.c_str (); +} + + + +} // end namespace scene +} // end namespace irr + --- Irrlicht.old/CAnimatedMeshMD3.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/CAnimatedMeshMD3.h 2005-01-18 18:08:52.000000000 +0100 @@ -0,0 +1,154 @@ +// Copyright (C) 2003 Fabio Concas +// as an extension of the "Irrlicht Engine" +// which is Copyright (C) 2002-2003 Nikolaus Gebhardt + +#ifndef __C_ANIMATED_MESH_MD3_H_INCLUDED__ +#define __C_ANIMATED_MESH_MD3_H_INCLUDED__ + +#include + +#include "IAnimatedMeshMD3.h" +#include "IReadFile.h" +#include "S3DVertex.h" +#include "irrArray.h" +#include "irrString.h" + + +namespace irr +{ +namespace scene +{ + + class CAnimatedMeshMD3 : public IAnimatedMeshMD3, IMesh, IMeshBuffer + { + public: + + //! constructor + CAnimatedMeshMD3(); + + //! destructor + virtual ~CAnimatedMeshMD3(); + + //! loads an md2 file + virtual bool loadFile(io::IReadFile* file); + + //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. + virtual s32 getFrameCount(); + + //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. + virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); + + //! returns amount of mesh buffers. + virtual s32 getMeshBufferCount() { return 1; } + + //! returns pointer to a mesh buffer + virtual IMeshBuffer* getMeshBuffer(s32 nr); + + //! returns the material of this meshbuffer + virtual const video::SMaterial& getMaterial() const; + + //! returns the material of this meshbuffer + virtual video::SMaterial& getMaterial(); + + //! returns pointer to vertices + virtual const void* getVertices() const; + + //! returns pointer to vertices + virtual void* getVertices(); + + //! returns which type of vertex data is stored. + virtual video::E_VERTEX_TYPE getVertexType() const; + + //! returns amount of vertices + virtual s32 getVertexCount() const; + + //! returns pointer to Indices + virtual const u16* getIndices() const; + + //! returns pointer to Indices + virtual u16* getIndices(); + + //! returns amount of indices + virtual s32 getIndexCount() const; + + //! returns an axis aligned bounding box + virtual const core::aabbox3d& getBoundingBox() const; + + //! returns an axis aligned bounding box + virtual core::aabbox3d& getBoundingBox(); + + //! sets a flag of all contained materials to a new value + virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); + + //! Returns the type of the animated mesh. + virtual E_ANIMATED_MESH_TYPE getMeshType() const; + + //! Returns number of tags in md3 file + virtual s32 getTagCount () const { + return TagCount; + } + + //! Retrieves a tag number by its name + virtual inline s32 getTagNumber (const char* Name); + + //! Returns tag relative position + virtual inline core::vector3df getTagOrigin (const char* Name); + + virtual inline core::vector3df getTagOrigin (s32 Number); + + //! Returns relative tag orientation + virtual inline const core::vector3df* getTagRotation (const char* Name); + + virtual inline const core::vector3df* getTagRotation (s32 Number); + + //! Returns name of tag indexed by Number + virtual inline const c8* getTagName (s32 Number); + + //! Return a pointer to a transformation matrix of a tag. + // Useful for attaching objects to an MD3 model + virtual core::matrix4* getMatrixOfTags (s32 tagNumber, s32 frame = -1) { + if (tagNumber >= TagCount) return 0; + if (frame == -1 || frame >= FrameCount) + frame = curFrame; + + return &TagData[tagNumber][frame].Transformation; + } + + private: + //! animates one frame + inline void Animate (u32 frame); + + //! calculates the bounding box + //virtual void calculateBoundingBox(); + + //! Decodes a normal + core::vector3df calculateNormal(s16 encNormal); + + core::array Indices; + core::array *FrameList; + core::array *Vertices; + core::array *Normals; + core::array< core::aabbox3d > BoxList; + u32 FrameCount; + u32 TagCount; + s32 TriangleCount; + video::SMaterial Material; + + u32 curFrame; + //core::aabbox3d BoundingBox; + + struct STagData { + core::stringc Name; + core::vector3df Origin; + core::vector3df Rotation[3]; + core::matrix4 Transformation; // Orthogonal transoformation matrix (Rotation matrix * Translation matrix) + }; + + core::array* TagData; // Tags x Frames + }; + +} // end namespace scene +} // end namespace irr + +#endif + --- Irrlicht.old/CAnimatedMeshSceneNode.cpp 2004-02-22 20:10:16.000000000 +0100 +++ Irrlicht/CAnimatedMeshSceneNode.cpp 2004-07-16 18:15:44.000000000 +0200 @@ -12,6 +12,7 @@ #include "ICameraSceneNode.h" #include "IAnimatedMeshMS3D.h" #include "IAnimatedMeshX.h" +#include "IAnimatedMeshMD3.h" #include "IDummyTransformationSceneNode.h" #include "IMaterialRenderer.h" @@ -27,7 +28,8 @@ const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(mesh), BeginFrameTime(0), StartFrame(0), EndFrame(0), FramesPerSecond(100), - Shadow(0), Looping(true), LoopCallBack(0) + Shadow(0), Looping(true), LoopCallBack(0), + curAnim (-1) //<--------- Madinitaly added this ********** { #ifdef _DEBUG setDebugName("CAnimatedMeshSceneNode"); @@ -79,6 +81,10 @@ for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i) if (JointChildSceneNodes[i]) JointChildSceneNodes[i]->drop(); + + for (s32 i=0; i<(s32)TagChildSceneNodes.size(); ++i) + if (TagChildSceneNodes[i]) + TagChildSceneNodes[i]->drop(); if (LoopCallBack) LoopCallBack->drop(); @@ -96,6 +102,11 @@ for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i) if (JointChildSceneNodes[i]) JointChildSceneNodes[i]->OnPreRender(); + + if (IsVisible) + for (s32 i=0; i<(s32)TagChildSceneNodes.size(); ++i) + if (TagChildSceneNodes[i]) + TagChildSceneNodes[i]->OnPreRender(); } @@ -144,7 +155,22 @@ JointChildSceneNodes[i]->getRelativeTransformationMatrix() = *mat; } } - + + // do the same for md3 tags + if (!TagChildSceneNodes.empty () && Mesh && Mesh->getMeshType() == EAMT_MD3) + { + IAnimatedMeshMD3* amm = (IAnimatedMeshMD3*)Mesh; + core::matrix4* mat; + + for (s32 i=0; i<(s32)TagChildSceneNodes.size(); ++i) + if (TagChildSceneNodes[i]) + { + mat = amm->getMatrixOfTags (i, frameNr); + if (mat) + TagChildSceneNodes[i]->getRelativeTransformationMatrix() = *mat; + } + } + core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnPostRender(timeMs); @@ -164,6 +190,22 @@ s32 frame = getFrameNr(); + //********** Madinitaly's code for linked animations ********** + // Check linked animations + if (curAnim > -1 && + frame >= (Animations[curAnim].lastFrame - 1) && + Animations[curAnim].linkedAnim > -1) + { + // Switch to the linked animation + curAnim = Animations[curAnim].linkedAnim; + // ...and start it + StartFrame = Animations[curAnim].firstFrame; + EndFrame = Animations[curAnim].lastFrame; + FramesPerSecond = Animations[curAnim].FPS; + BeginFrameTime = os::Timer::getTime(); + } + //********************************************************** + scene::IMesh* m = Mesh->getMesh(frame, 255, StartFrame, EndFrame); if (m) @@ -324,6 +366,43 @@ +//! Returns a pointer to a child node, wich has the same transformation as +//! the corrsesponding joint, if the mesh in this scene node is a ms3d mesh. +ISceneNode* CAnimatedMeshSceneNode::getMD3TagNode(const c8* tagName) +{ + if (!Mesh || Mesh->getMeshType() != EAMT_MD3) + return 0; + + IAnimatedMeshMD3* amm = (IAnimatedMeshMD3*)Mesh; + s32 tagCount = amm->getTagCount(); + s32 number = amm->getTagNumber(tagName); + + if (number == -1) + { + os::Printer::log("Tag with specified name not found in md3 mesh.", tagName, ELL_WARNING); + return 0; + } + + if (TagChildSceneNodes.empty()) + { + // allocate joints for the first time. + TagChildSceneNodes.set_used(tagCount); + for (s32 i=0; iaddDummyTransformationSceneNode(this); + TagChildSceneNodes[number]->grab(); + } + + return TagChildSceneNodes[number]; +} + + + //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. @@ -346,6 +425,14 @@ return true; } + for (s32 i=0; i<(s32)TagChildSceneNodes.size(); ++i) + if (TagChildSceneNodes[i] == child) + { + TagChildSceneNodes[i]->drop(); + TagChildSceneNodes[i] = 0; + return true; + } + return true; } @@ -353,6 +440,65 @@ } + + //********** Madinitaly's code for MD3 animations ********** + +//! Starts an animation. +bool CAnimatedMeshSceneNode::setAnimation (u16 animIdx) +{ + if (!Mesh || Animations.size () < animIdx) + return false; + + // Set current animation index + curAnim = animIdx; + + // Jump to current animation first frame + StartFrame = Animations[curAnim].firstFrame; + EndFrame = Animations[curAnim].lastFrame; + BeginFrameTime = os::Timer::getTime(); + + // Set frames per second + FramesPerSecond = Animations[curAnim].FPS; + + return true; +} + + + +//! Adds an animation. +// Returns index of the new animation +s32 CAnimatedMeshSceneNode::addAnimation (u16 firstFrame, u16 lastFrame, u8 FPS) +{ + if (!Mesh) + return -1; + + SAnimData tmpAnim; + tmpAnim.firstFrame = firstFrame; + tmpAnim.lastFrame = lastFrame; + tmpAnim.FPS = FPS; + + Animations.push_back (tmpAnim); + return Animations.size () - 1; +} + + + +//! Links anim to linkedAnim. +bool CAnimatedMeshSceneNode::linkAnimation (u16 anim, u16 linkedAnim) +{ + if (!Mesh || + Animations.size () < anim || + Animations.size () < linkedAnim) + return false; + + Animations[anim].linkedAnim = linkedAnim; + + return true; +} + //********************************************************** + + + //! Starts a MD2 animation. bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim) { --- Irrlicht.old/CAnimatedMeshSceneNode.h 2003-12-20 15:21:50.000000000 +0100 +++ Irrlicht/CAnimatedMeshSceneNode.h 2004-07-16 17:48:28.000000000 +0200 @@ -68,11 +68,28 @@ //! the corrsesponding joint, if the mesh in this scene node is a ms3d mesh. virtual ISceneNode* getMS3DJointNode(const c8* jointName); + //! Returns a pointer to a child node, wich has the same transformation as + //! the corrsesponding tag, if the mesh in this scene node is a md3 mesh. + virtual ISceneNode* getMD3TagNode(const c8* tagName); + //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); + + //********** Madinitaly's code for linked animations ********** + //! Starts an MD3 animation. + virtual bool setAnimation (u16 animIdx); + + //! Adds an MD3 animation. + virtual s32 addAnimation (u16 firstFrame, u16 lastFrame, u8 FPS); + + //! Links anim to linkedAnim. + virtual bool linkAnimation (u16 anim, u16 linkedAnim); + //************************************************************* + + //! Starts a MD2 animation. virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim); @@ -94,6 +111,25 @@ IShadowVolumeSceneNode* Shadow; core::array JointChildSceneNodes; + core::array TagChildSceneNodes; + + //! Animation data + struct SAnimData { + //wchar_t Name[32]; + u16 firstFrame; + u16 lastFrame; + u8 FPS; + s32 linkedAnim; + + SAnimData () : firstFrame (0), lastFrame (0), FPS (25), linkedAnim (-1) + { + } + }; + + //! Animations of this mesh + core::array Animations; + //! Current animation (index in Animations array) + s32 curAnim; }; } // end namespace scene --- Irrlicht.old/CMD3MeshFileLoader.cpp 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/CMD3MeshFileLoader.cpp 2003-12-12 19:51:16.000000000 +0100 @@ -0,0 +1,71 @@ +#include "CMD3MeshFileLoader.h" +#include "CAnimatedMeshMD3.h" +#include + +namespace irr +{ +namespace scene +{ + +//! Constructor +CMD3MeshFileLoader::CMD3MeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) +: FileSystem(fs), Driver(driver) +{ + if (FileSystem) + FileSystem->grab(); + + if (Driver) + Driver->grab(); +} + + + +//! destructor +CMD3MeshFileLoader::~CMD3MeshFileLoader() +{ + if (FileSystem) + FileSystem->drop(); + + if (Driver) + Driver->drop(); +} + + + +//! returns true if the file maybe is able to be loaded by this class +//! based on the file extension (e.g. ".bsp") +bool CMD3MeshFileLoader::isALoadableFileExtension(const c8* filename) +{ + return (strstr(filename, ".md3")); +} + + + +//! creates/loads an animated mesh from the file. +//! \return Pointer to the created mesh. Returns 0 if loading failed. +//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). +//! See IUnknown::drop() for more information. +IAnimatedMesh* CMD3MeshFileLoader::createMesh(irr::io::IReadFile* file) +{ + IAnimatedMesh* msh = 0; + + // This method loads a mesh if it cans. + + bool success = false; + + // load quake 3 md3 model + file->seek(0); + + msh = new CAnimatedMeshMD3(); + success = ((CAnimatedMeshMD3*)msh)->loadFile(file); + if (success) + return msh; + + msh->drop(); + + return 0; +} + +} // end namespace scene +} // end namespace irr + --- Irrlicht.old/CMD3MeshFileLoader.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht/CMD3MeshFileLoader.h 2003-12-12 20:51:16.000000000 +0100 @@ -0,0 +1,44 @@ +#ifndef __C_MD3_MESH_FILE_LOADER_H_INCLUDED__ +#define __C_MD3_MESH_FILE_LOADER_H_INCLUDED__ + +#include "IMeshLoader.h" +#include "IFileSystem.h" +#include "IVideoDriver.h" + +namespace irr +{ +namespace scene +{ + +//! Meshloader capable of loading md3 files. +class CMD3MeshFileLoader : public IMeshLoader +{ +public: + + //! Constructor + CMD3MeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver); + + //! destructor + virtual ~CMD3MeshFileLoader(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".bsp") + virtual bool isALoadableFileExtension(const c8* fileName); + + //! creates/loads an animated mesh from the file. + //! \return Pointer to the created mesh. Returns 0 if loading failed. + //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). + //! See IUnknown::drop() for more information. + virtual IAnimatedMesh* createMesh(irr::io::IReadFile* file); + +private: + + io::IFileSystem* FileSystem; + video::IVideoDriver* Driver; +}; + +} // end namespace scene +} // end namespace irr + +#endif + --- Irrlicht.old/CSceneManager.cpp 2004-08-29 15:07:04.000000000 +0200 +++ Irrlicht/CSceneManager.cpp 2005-01-18 13:33:48.000000000 +0100 @@ -16,6 +16,7 @@ #include "CDefaultMeshFormatLoader.h" #include "C3DSMeshFileLoader.h" #include "CXMeshFileLoader.h" +#include "CMD3MeshFileLoader.h" #include "COCTLoader.h" #include "CCSMLoader.h" #include "CLMTSMeshFileLoader.h" @@ -101,6 +102,7 @@ MeshLoaderList.push_back(new CDefaultMeshFormatLoader(FileSystem, Driver)); MeshLoaderList.push_back(new C3DSMeshFileLoader(FileSystem, Driver)); MeshLoaderList.push_back(new CXMeshFileLoader(MeshManipulator, Driver)); + MeshLoaderList.push_back(new CMD3MeshFileLoader(FileSystem, Driver)); MeshLoaderList.push_back(new COCTLoader(Driver)); MeshLoaderList.push_back(new CCSMLoader(this, FileSystem)); MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, %Parameters));