irrlicht/source/Irrlicht/CXAnimationPlayer.h

219 lines
5.7 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
#ifndef __C_X_ANIMATION_PLAYER_H_INCLUDED__
#define __C_X_ANIMATION_PLAYER_H_INCLUDED__
#include "IAnimatedMeshX.h"
#include "CXFileReader.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
namespace irr
{
namespace video
{
class IVideoDriver;
}
namespace scene
{
class IMeshManipulator;
class CXAnimationPlayer : public IAnimatedMeshX
{
public:
//! constructor
CXAnimationPlayer(CXFileReader* reader,
video::IVideoDriver* driver,
IMeshManipulator* manip,
const c8* filename);
//! destructor
virtual ~CXAnimationPlayer();
//! Gets the frame count of the animated mesh.
virtual s32 getFrameCount();
//! Returns the IMesh interface for a frame.
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1);
//! Returns an axis aligned bounding box of the mesh.
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! Returns the type of the animated mesh.
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
//! Returns a pointer to a transformation matrix
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;
//! Returns a pointer to list of points containing the skeleton.
virtual const core::array<core::vector3df>* getDrawableSkeleton(s32 frame);
//! Returns amount of animations in .X-file.
virtual s32 getAnimationCount() const;
//! Returns the name of an animation.
virtual const c8* getAnimationName(s32 idx) const;
//! Sets an animation as animation to play back.
virtual void setCurrentAnimation(s32 idx);
//! Sets an animation as animation to play back.
virtual bool setCurrentAnimation(const c8* name);
private:
struct SWeightData
{
SWeightData() {};
SWeightData(const SWeightData& other)
: buffer(other.buffer), vertex(other.vertex), weight(other.weight)
{}
SWeightData(s32 b, s32 v, f32 w)
: buffer(b), vertex(v), weight(w)
{}
s32 buffer;
s32 vertex;
f32 weight;
bool operator <(const SWeightData& other) const
{
return (buffer < other.buffer ||
(buffer == other.buffer &&
vertex < other.vertex) ||
(buffer == other.buffer &&
vertex == other.vertex &&
weight < other.weight));
}
};
struct SVertexWeight
{
SVertexWeight() : weightCount(0) {}
// weight per vertex, at maximum, 4 joints per vertex
f32 weight[4];
s32 joint[4];
s32 weightCount;
void add(f32 _weight, s32 _joint)
{
if (weightCount == 4)
return;
weight[weightCount] = _weight;
joint[weightCount] = _joint;
++weightCount;
}
};
struct SJoint
{
s32 Parent; // index of parent
core::array<SWeightData> Weights;
core::matrix4 MatrixOffset;
core::matrix4 LocalMatrix;
core::matrix4 GlobalMatrix;
core::matrix4 AnimatedMatrix;
core::matrix4 LocalAnimatedMatrix;
core::matrix4 CombinedAnimationMatrix; // for faster computing
core::stringc Name;
bool IsVirtualJoint; // for in .x file not weighted vertices
bool WasAnimatedThisFrame; // used by animateSkeleton()
};
void createAnimationData();
void createJointData(const CXFileReader::SXFrame& f, s32 JointParent);
void createMeshData();
void addFrameToMesh(CXFileReader::SXFrame& frame);
video::SMaterial getMaterialFromXMaterial(const CXFileReader::SXMaterial& xmat);
void addFacesToBuffer(s32 meshbuffernr, CXFileReader::SXMesh& mesh, s32 matnr, const CXFileReader::SXFrame& frame);
core::stringc getTextureFileName(const core::stringc& texture);
s32 getJointNumberFromName(const core::stringc& name) const;
//! prepares animation data which was read in from the .x file
void prepareAnimationData();
//! animates the skeleton based on the animation data
void animateSkeleton();
//! modifies the skin based on the animated skeleton
void modifySkin();
void updateBoundingBoxFromAnimation();
void addVirtualWeight(s32 meshbuffernr, s32 vtxidx, CXFileReader::SXMesh& mesh,
const CXFileReader::SXFrame& frame);
CXFileReader* Reader;
video::IVideoDriver* Driver;
scene::SMesh OriginalMesh;
scene::SMesh *AnimatedMesh;
core::aabbox3df Box;
core::stringc FileName;
IMeshManipulator* Manipulator;
core::array<core::vector3df> DebugSkeleton;
bool IsAnimatedSkinnedMesh;
core::array<SJoint> Joints;
f32 CurrentAnimationTime;
f32 LastAnimationTime;
s32 CurrentAnimationSet;
f32 DebugSkeletonCrossSize;
// one array of weights per mesh buffer
core::array< core::array<SVertexWeight> > Weights;
// data for animations
struct SXAnimationTrack
{
s32 jointNr;
s32 keyType; // 0=rotation, 1=scale, 2=position, 3=matrix
core::array<core::quaternion> Quaternions;
core::array<core::vector3df> Vectors;
core::array<core::matrix4> Matrices;
core::array<f32> Times;
bool operator <(SXAnimationTrack& other) const
{
if (jointNr != other.jointNr)
return (jointNr < other.jointNr);
return keyType > other.keyType;
}
};
struct SXAnimationSet
{
core::stringc AnimationName;
core::array<SXAnimationTrack> Animations;
};
core::array<SXAnimationSet> AnimationSets;
};
} // end namespace scene
} // end namespace irr
#endif