499 lines
13 KiB
C++
499 lines
13 KiB
C++
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
|
// This file is part of the "Irrlicht Engine".
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
|
|
//B3D file loader by Luke Hoschke, File format by Mark Sibly
|
|
|
|
#ifndef __C_ANIMATED_MESH_B3D_H_INCLUDED__
|
|
#define __C_ANIMATED_MESH_B3D_H_INCLUDED__
|
|
|
|
#include "IAnimatedMeshB3d.h"
|
|
#include "IMesh.h"
|
|
#include "IReadFile.h"
|
|
|
|
#include "SMeshBuffer.h"
|
|
#include "S3DVertex.h"
|
|
|
|
#include "irrString.h"
|
|
#include "matrix4.h"
|
|
#include "quaternion.h"
|
|
|
|
namespace irr
|
|
{
|
|
namespace video
|
|
{
|
|
class IVideoDriver;
|
|
} // end namespace video
|
|
namespace scene
|
|
{
|
|
class CAnimatedMeshB3d : public IAnimatedMeshB3d, public IMesh
|
|
{
|
|
public:
|
|
|
|
//! constructor
|
|
CAnimatedMeshB3d(video::IVideoDriver* driver);
|
|
|
|
//! destructor
|
|
virtual ~CAnimatedMeshB3d();
|
|
|
|
//! loads an B3d 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 u32 getMeshBufferCount() const;
|
|
|
|
//! returns pointer to a mesh buffer
|
|
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
|
|
|
|
//! Returns pointer to a mesh buffer which fits a material
|
|
/** \param material: material to search for
|
|
\return Returns the pointer to the mesh buffer or
|
|
NULL if there is no such mesh buffer. */
|
|
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const;
|
|
|
|
//! returns an axis aligned bounding box
|
|
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
|
|
|
//! set user axis aligned bounding box
|
|
virtual void setBoundingBox( const core::aabbox3df& box);
|
|
|
|
//! 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 a pointer to a transformation matrix of a part of the
|
|
//! mesh based on a frame time.
|
|
virtual core::matrix4* getMatrixOfJoint(s32 jointNumber, s32 frame);
|
|
|
|
//! Gets joint count.
|
|
virtual s32 getJointCount() const;
|
|
|
|
//! Gets the name of a joint.
|
|
virtual const c8* getJointName(s32 number) const;
|
|
|
|
//! Gets a joint number from its name
|
|
virtual s32 getJointNumber(const c8* name) const;
|
|
|
|
|
|
virtual core::matrix4* getLocalMatrixOfJoint(s32 jointNumber);
|
|
|
|
virtual core::matrix4* getMatrixOfJointUnanimated(s32 jointNumber);
|
|
|
|
virtual void setJointAnimation(s32 jointNumber, bool On);
|
|
|
|
//!Update Normals when Animating
|
|
//!False= Don't (default)
|
|
//!True= Update normals, slower
|
|
virtual void updateNormalsWhenAnimating(bool on);
|
|
|
|
|
|
//!Sets Interpolation Mode
|
|
//!0- Constant
|
|
//!1- Linear (default)
|
|
virtual void setInterpolationMode(s32 mode);
|
|
|
|
//!Want should happen on when animating
|
|
//!0-Nothing
|
|
//!1-Update nodes only
|
|
//!2-Update skin only
|
|
//!3-Update both nodes and skin (default)
|
|
virtual void setAnimateMode(s32 mode);
|
|
|
|
|
|
//!Convert all mesh buffers to use tangent vertices
|
|
virtual void convertToTangents();
|
|
|
|
|
|
|
|
//New Animation System Stuff (WIP)...
|
|
virtual void recoverJointsFromMesh(core::array<ISceneNode*> &JointChildSceneNodes);
|
|
virtual void tranferJointsToMesh(core::array<ISceneNode*> &JointChildSceneNodes);
|
|
virtual void createJoints(core::array<ISceneNode*> &JointChildSceneNodes, ISceneNode* AnimatedMeshSceneNode, ISceneManager* SceneManager);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
struct SB3DMeshBuffer : public IMeshBuffer
|
|
{
|
|
SB3DMeshBuffer()
|
|
{
|
|
#ifdef _DEBUG
|
|
setDebugName("SSkinMeshBuffer");
|
|
#endif
|
|
}
|
|
|
|
~SB3DMeshBuffer() {};
|
|
|
|
virtual const video::SMaterial& getMaterial() const
|
|
{
|
|
return Material;
|
|
}
|
|
|
|
virtual video::SMaterial& getMaterial()
|
|
{
|
|
return Material;
|
|
}
|
|
|
|
virtual video::S3DVertex *getVertex(u32 index)
|
|
{
|
|
if (VertexType==video::EVT_STANDARD) return &Vertices_Standard[index];
|
|
if (VertexType==video::EVT_TANGENTS) return (video::S3DVertex*)&Vertices_Tangents[index];
|
|
return (video::S3DVertex*)&Vertices_2TCoords[index];
|
|
}
|
|
|
|
virtual const void* getVertices() const
|
|
{
|
|
if (VertexType==video::EVT_STANDARD) return Vertices_Standard.const_pointer();
|
|
if (VertexType==video::EVT_TANGENTS) return Vertices_Tangents.const_pointer();
|
|
return Vertices_2TCoords.const_pointer();
|
|
}
|
|
|
|
virtual void* getVertices()
|
|
{
|
|
if (VertexType==video::EVT_STANDARD) return Vertices_Standard.pointer();
|
|
if (VertexType==video::EVT_TANGENTS) return Vertices_Tangents.pointer();
|
|
return Vertices_2TCoords.pointer();
|
|
}
|
|
|
|
virtual u32 getVertexCount() const
|
|
{
|
|
if (VertexType==video::EVT_STANDARD) return Vertices_Standard.size();
|
|
if (VertexType==video::EVT_TANGENTS) return Vertices_Tangents.size();
|
|
return Vertices_2TCoords.size();
|
|
}
|
|
|
|
virtual const u16* getIndices() const
|
|
{
|
|
return Indices.const_pointer();
|
|
}
|
|
|
|
virtual u16* getIndices()
|
|
{
|
|
return Indices.pointer();
|
|
}
|
|
|
|
virtual u32 getIndexCount() const
|
|
{
|
|
return Indices.size();
|
|
}
|
|
|
|
virtual const core::aabbox3d<f32>& getBoundingBox() const
|
|
{
|
|
return BoundingBox;
|
|
}
|
|
|
|
virtual void setBoundingBox( const core::aabbox3df& box)
|
|
{
|
|
BoundingBox = box;
|
|
}
|
|
|
|
virtual void recalculateBoundingBox()
|
|
{
|
|
if (VertexType==video::EVT_STANDARD)
|
|
{
|
|
if (Vertices_Standard.empty())
|
|
BoundingBox.reset(0,0,0);
|
|
else
|
|
{
|
|
BoundingBox.reset(Vertices_Standard[0].Pos);
|
|
for (u32 i=1; i<Vertices_Standard.size(); ++i)
|
|
BoundingBox.addInternalPoint(Vertices_Standard[i].Pos);
|
|
}
|
|
}
|
|
else if (VertexType==video::EVT_2TCOORDS)
|
|
{
|
|
if (Vertices_2TCoords.empty())
|
|
BoundingBox.reset(0,0,0);
|
|
else
|
|
{
|
|
BoundingBox.reset(Vertices_2TCoords[0].Pos);
|
|
for (u32 i=1; i<Vertices_2TCoords.size(); ++i)
|
|
BoundingBox.addInternalPoint(Vertices_2TCoords[i].Pos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Vertices_Tangents.empty())
|
|
BoundingBox.reset(0,0,0);
|
|
else
|
|
{
|
|
BoundingBox.reset(Vertices_Tangents[0].Pos);
|
|
for (u32 i=1; i<Vertices_Tangents.size(); ++i)
|
|
BoundingBox.addInternalPoint(Vertices_Tangents[i].Pos);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
virtual video::E_VERTEX_TYPE getVertexType() const
|
|
{
|
|
return VertexType;
|
|
}
|
|
|
|
//! returns the byte size (stride, pitch) of the vertex
|
|
virtual u32 getVertexPitch() const
|
|
{
|
|
if (VertexType==video::EVT_STANDARD) return sizeof ( video::S3DVertex );
|
|
if (VertexType==video::EVT_TANGENTS) return sizeof ( video::S3DVertexTangents );
|
|
return sizeof ( video::S3DVertex2TCoords );
|
|
}
|
|
|
|
virtual void MoveTo_2TCoords()
|
|
{
|
|
if (VertexType==video::EVT_STANDARD)
|
|
{
|
|
|
|
for(u32 n=0;n<Vertices_Standard.size();++n)
|
|
{
|
|
video::S3DVertex2TCoords Vertex;
|
|
Vertex.Color=Vertices_Standard[n].Color;
|
|
Vertex.Pos=Vertices_Standard[n].Pos;
|
|
Vertex.Normal=Vertices_Standard[n].Normal;
|
|
Vertex.TCoords=Vertices_Standard[n].TCoords;
|
|
Vertices_2TCoords.push_back(Vertex);
|
|
}
|
|
Vertices_Standard.clear();
|
|
|
|
VertexType=video::EVT_2TCOORDS;
|
|
}
|
|
}
|
|
|
|
virtual void MoveTo_Tangents()
|
|
{
|
|
if (VertexType==video::EVT_STANDARD)
|
|
{
|
|
|
|
for(u32 n=0;n<Vertices_Standard.size();++n)
|
|
{
|
|
video::S3DVertexTangents Vertex;
|
|
Vertex.Color=Vertices_Standard[n].Color;
|
|
Vertex.Pos=Vertices_Standard[n].Pos;
|
|
Vertex.Normal=Vertices_Standard[n].Normal;
|
|
Vertex.TCoords=Vertices_Standard[n].TCoords;
|
|
Vertices_Tangents.push_back(Vertex);
|
|
}
|
|
|
|
Vertices_Standard.clear();
|
|
|
|
VertexType=video::EVT_TANGENTS;
|
|
}
|
|
else if (VertexType==video::EVT_2TCOORDS)
|
|
{
|
|
|
|
for(u32 n=0;n<Vertices_2TCoords.size();++n)
|
|
{
|
|
video::S3DVertexTangents Vertex;
|
|
Vertex.Color=Vertices_2TCoords[n].Color;
|
|
Vertex.Pos=Vertices_2TCoords[n].Pos;
|
|
Vertex.Normal=Vertices_2TCoords[n].Normal;
|
|
Vertex.TCoords=Vertices_2TCoords[n].TCoords;
|
|
//Vertex.TCoords2=Vertices_2TCoords[n].TCoords2;
|
|
Vertices_Tangents.push_back(Vertex);
|
|
|
|
}
|
|
|
|
Vertices_2TCoords.clear();
|
|
|
|
VertexType=video::EVT_TANGENTS;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
video::SMaterial Material;
|
|
video::E_VERTEX_TYPE VertexType;
|
|
|
|
core::array<video::S3DVertexTangents> Vertices_Tangents;
|
|
core::array<video::S3DVertex2TCoords> Vertices_2TCoords;
|
|
core::array<video::S3DVertex> Vertices_Standard;
|
|
core::array<u16> Indices;
|
|
core::aabbox3d<f32> BoundingBox;
|
|
};
|
|
|
|
struct B3dChunk
|
|
{
|
|
c8 name[4];
|
|
s32 length;
|
|
s32 startposition;
|
|
};
|
|
|
|
s32 AnimFlags;
|
|
s32 AnimFrames; //how many frames in anim
|
|
f32 AnimFPS;
|
|
|
|
struct SB3dBone
|
|
{
|
|
s32 vertex_id;
|
|
f32 weight;
|
|
core::vector3df pos;
|
|
core::vector3df normal;
|
|
video::S3DVertex *vertex;
|
|
};
|
|
|
|
struct SB3dPositionKey
|
|
{
|
|
s32 frame;
|
|
core::vector3df position;
|
|
};
|
|
|
|
struct SB3dScaleKey
|
|
{
|
|
s32 frame;
|
|
core::vector3df scale;
|
|
};
|
|
|
|
struct SB3dRotationKey
|
|
{
|
|
s32 frame;
|
|
core::quaternion rotation;
|
|
};
|
|
|
|
struct SB3dNode
|
|
{
|
|
core::stringc Name;
|
|
|
|
core::vector3df position;
|
|
core::vector3df scale;
|
|
core::quaternion rotation;
|
|
|
|
core::vector3df Animatedposition;
|
|
core::vector3df Animatedscale;
|
|
core::quaternion Animatedrotation;
|
|
|
|
core::matrix4 GlobalAnimatedMatrix;
|
|
core::matrix4 LocalAnimatedMatrix;
|
|
|
|
core::matrix4 LocalMatrix;
|
|
core::matrix4 GlobalMatrix;
|
|
core::matrix4 GlobalInversedMatrix;
|
|
|
|
bool Animate; //Move this nodes local matrix when animating?
|
|
bool AnimatingPositionKeys;
|
|
bool AnimatingScaleKeys;
|
|
bool AnimatingRotationKeys;
|
|
|
|
bool HasScaleAnimation;
|
|
|
|
core::array<SB3dPositionKey> PositionKeys;
|
|
core::array<SB3dScaleKey> ScaleKeys;
|
|
core::array<SB3dRotationKey> RotationKeys;
|
|
|
|
core::array<SB3dBone> Bones;
|
|
|
|
core::array<SB3dNode*> Nodes;
|
|
|
|
};
|
|
|
|
core::array<SB3dNode*> Nodes;
|
|
|
|
core::array<SB3dNode*> RootNodes;
|
|
|
|
struct SB3dTexture
|
|
{
|
|
irr::video::ITexture* Texture;
|
|
s32 Flags;
|
|
s32 Blend;
|
|
f32 Xpos;
|
|
f32 Ypos;
|
|
f32 Xscale;
|
|
f32 Yscale;
|
|
f32 Angle;
|
|
};
|
|
|
|
struct SB3dMaterial
|
|
{
|
|
irr::video::SMaterial* Material;
|
|
f32 red, green, blue, alpha;
|
|
f32 shininess;
|
|
s32 blend,fx;
|
|
SB3dTexture *Textures[2];
|
|
|
|
};
|
|
|
|
bool ReadChunkTEXS(io::IReadFile* file);
|
|
bool ReadChunkBRUS(io::IReadFile* file);
|
|
bool ReadChunkMESH(io::IReadFile* file, SB3dNode *InNode);
|
|
bool ReadChunkVRTS(io::IReadFile* file, SB3dNode *InNode, SB3DMeshBuffer *MeshBuffer, s32 Vertices_Start);
|
|
bool ReadChunkTRIS(io::IReadFile* file, SB3dNode *InNode, SB3DMeshBuffer *MeshBuffer, s32 Vertices_Start);
|
|
bool ReadChunkNODE(io::IReadFile* file, SB3dNode *InNode);
|
|
bool ReadChunkBONE(io::IReadFile* file, SB3dNode *InNode);
|
|
bool ReadChunkKEYS(io::IReadFile* file, SB3dNode *InNode);
|
|
bool ReadChunkANIM(io::IReadFile* file, SB3dNode *InNode);
|
|
|
|
void normalizeWeights();
|
|
void animate(s32 frame,s32 startFrameLoop, s32 endFrameLoop);
|
|
void CalculateGlobalMatrixes(SB3dNode *Node,SB3dNode *ParentNode);
|
|
void animateSkin(f32 frame,f32 startFrame, f32 endFrame,SB3dNode *InNode,SB3dNode *ParentNode);
|
|
void getNodeAnimation(f32 frame,SB3dNode *Node,core::vector3df &position, core::vector3df &scale, core::quaternion &rotation);
|
|
void animateNodes(f32 frame,f32 startFrame, f32 endFrame);
|
|
void slerp(core::quaternion A,core::quaternion B,core::quaternion &C,f32 t);
|
|
|
|
void calculateTangents(core::vector3df& normal,
|
|
core::vector3df& tangent, core::vector3df& binormal,
|
|
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3,
|
|
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3);
|
|
|
|
|
|
void createSkelton_Helper(ISceneManager* SceneManager, core::array<ISceneNode*> &JointChildSceneNodes, ISceneNode *AnimatedMeshSceneNode, ISceneNode* ParentNode, SB3dNode *ParentB3dNode, SB3dNode *B3dNode);
|
|
|
|
|
|
|
|
core::array<B3dChunk> B3dStack;
|
|
|
|
f32 totalTime;
|
|
bool HasAnimation;
|
|
bool HasBones;
|
|
|
|
s32 lastCalculatedFrame;
|
|
s32 lastAnimateMode;
|
|
|
|
bool NormalsInFile;
|
|
bool AnimateNormals;
|
|
|
|
//0- Constant 1- Linear
|
|
s32 InterpolationMode;
|
|
|
|
//0-None 1-Update nodes only 2-Update skin only 3-Update both nodes and skin
|
|
s32 AnimateMode;
|
|
|
|
core::stringc readString(io::IReadFile* file);
|
|
core::stringc stripPathString(core::stringc oldstring, bool keepPath);
|
|
void readFloats(io::IReadFile* file, f32* vec, u32 count);
|
|
|
|
core::aabbox3d<f32> BoundingBox;
|
|
core::array<SB3dMaterial> Materials;
|
|
core::array<SB3dTexture> Textures;
|
|
|
|
core::array<video::S3DVertex2TCoords*> BaseVertices;
|
|
|
|
core::array<bool> Vertices_Moved;
|
|
core::array<f32> Vertices_Alpha;
|
|
core::array<s32> AnimatedVertices_VertexID;
|
|
core::array<SB3DMeshBuffer*> AnimatedVertices_MeshBuffer;
|
|
core::array<SB3DMeshBuffer*> Buffers;
|
|
|
|
video::IVideoDriver* Driver;
|
|
};
|
|
|
|
} // end namespace scene
|
|
} // end namespace irr
|
|
|
|
#endif
|
|
|
|
|