Commit 98f8e531 authored by lukeph's avatar lukeph

support for positioning joints at an absolute position. Without this support,...

support for positioning joints at an absolute position. Without this support, doing ragdolls would require the inverse of a matrix (slow)

I'll write a tutorial in the wiki for this.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1016 dfc29bdd-3216-0410-991c-e03cc46cb475
parent ebf823a8
......@@ -183,6 +183,8 @@ namespace scene
//! animates the joints in the mesh based on the current frame (also takes in to account transitions)
virtual void animateJoints() = 0;
//! render mesh ignoring it's transformation. Used with ragdolls. (culling is unaffected)
virtual void setRenderFromIdentity( bool On )=0;
};
} // end namespace scene
......
......@@ -28,6 +28,17 @@ namespace scene
};
enum E_BONE_SKINNING_SPACE
{
//! local skinning, standard
EBSS_LOCAL=0,
//! global skinning
EBSS_GLOBAL,
EBSS_COUNT
};
//! Names for bone animation modes
const c8* const BoneAnimationModeNames[] =
{
......@@ -51,7 +62,7 @@ namespace scene
//! Returns the index of the bone
virtual u32 getBoneIndex() const = 0;
//! Sets the animation mode of the bone. Returns true if successful.
//! Sets the animation mode of the bone. Returns true if successful. (Unused)
virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode) = 0;
//! Gets the current animation mode of the bone
......@@ -68,15 +79,17 @@ namespace scene
//! Does nothing as bones are not visible
virtual void render() { }
//! How the relative transformation of the bone is used
virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space ) =0;
virtual void setAbsoluteTransformation(const core::matrix4& transformation)
{
AbsoluteTransformation=transformation;
}
//! How the relative transformation of the bone is used
virtual E_BONE_SKINNING_SPACE getSkinningSpace() =0;
//! updates the absolute position based on the relative and the parents position
virtual void updateAbsolutePositionOfAllChildren()=0;
s32 positionHint;
s32 scaleHint;
s32 rotationHint;
......
......@@ -123,7 +123,7 @@ namespace scene
//! Joints
struct SJoint
{
SJoint() : UseAnimationFrom(0), LocalAnimatedMatrix_Animated(false),
SJoint() : UseAnimationFrom(0), LocalAnimatedMatrix_Animated(false), GlobalSkinningSpace(false),
positionHint(-1),scaleHint(-1),rotationHint(-1)
{
}
......@@ -160,6 +160,8 @@ namespace scene
core::vector3df Animatedscale;
core::quaternion Animatedrotation;
core::matrix4 GlobalInversedMatrix; //the x format pre-calculates this
private:
......@@ -169,6 +171,8 @@ namespace scene
SJoint *UseAnimationFrom;
bool LocalAnimatedMatrix_Animated;
bool GlobalSkinningSpace;
s32 positionHint;
s32 scaleHint;
s32 rotationHint;
......
......@@ -33,7 +33,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode*
CurrentFrameNr(0.f), JointMode(0), JointsUsed(false),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
Looping(true), ReadOnlyMaterials(false),
LoopCallBack(0), PassCount(0), Shadow(0)
LoopCallBack(0), PassCount(0), Shadow(0), RenderFromIdentity(0)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
......@@ -333,7 +333,9 @@ void CAnimatedMeshSceneNode::render()
{
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
if (Mesh->getMeshType() == EAMT_SKINNED)
if (RenderFromIdentity)
driver->setTransform(video::ETS_WORLD, core::matrix4() );
else if (Mesh->getMeshType() == EAMT_SKINNED)
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
......@@ -873,6 +875,14 @@ void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
TransitionTime = (u32)core::floor32(time*1000.0f);
}
//! render mesh ignoring it's transformation. Used with ragdolls. (culling is unaffected)
void CAnimatedMeshSceneNode::setRenderFromIdentity( bool On )
{
RenderFromIdentity=On;
}
//! updates the joint positions of this mesh
void CAnimatedMeshSceneNode::animateJoints()
{
......
......@@ -147,6 +147,9 @@ namespace scene
//! updates the joint positions of this mesh
virtual void animateJoints();
//! render mesh ignoring it's transformation. Used with ragdolls. (culling is unaffected)
virtual void setRenderFromIdentity( bool On );
private:
f32 buildFrameNr( u32 timeMs);
......@@ -182,6 +185,7 @@ namespace scene
core::array<IBoneSceneNode* > JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
bool RenderFromIdentity;
struct SMD3Special
{
......
......@@ -11,7 +11,7 @@ namespace scene
//! constructor
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
u32 boneIndex, const c8* boneName)
: IBoneSceneNode(parent, mgr, id), AnimationMode(EBAM_AUTOMATIC),
: IBoneSceneNode(parent, mgr, id), AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL),
BoneIndex(boneIndex), BoneName(boneName)
{
......
......@@ -54,11 +54,28 @@ namespace scene
//! Reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
//! How the relative transformation of the bone is used
virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space )
{
SkinningSpace=space;
}
virtual E_BONE_SKINNING_SPACE getSkinningSpace()
{
return SkinningSpace;
}
private:
E_BONE_ANIMATION_MODE AnimationMode;
E_BONE_SKINNING_SPACE SkinningSpace;
u32 BoneIndex;
core::stringc BoneName;
core::aabbox3d<f32> Box;
};
......
......@@ -77,6 +77,7 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
//! blend: {0-old position, 1-New position}
void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
{
if ( !HasAnimation || lastAnimatedFrame==frame)
return;
......@@ -158,6 +159,8 @@ void CSkinnedMesh::buildAll_LocalAnimatedMatrices()
Joint->LocalAnimatedMatrix.setTranslation(Joint->Animatedposition);
Joint->LocalAnimatedMatrix*=Joint->Animatedrotation.getMatrix();
Joint->GlobalSkinningSpace=false;
if (Joint->ScaleKeys.size())
{
//Joint->_LocalAnimatedMatrix.setScale(Joint->_Animatedscale);
......@@ -185,10 +188,11 @@ void CSkinnedMesh::buildAll_GlobalAnimatedMatrices(SJoint *Joint, SJoint *Parent
else
{
// Find global matrix...
if (!ParentJoint)
if (!ParentJoint || Joint->GlobalSkinningSpace)
Joint->GlobalAnimatedMatrix = Joint->LocalAnimatedMatrix;
else
Joint->GlobalAnimatedMatrix = ParentJoint->GlobalAnimatedMatrix * Joint->LocalAnimatedMatrix;
}
for (u32 j=0; j<Joint->Children.size(); ++j)
......@@ -1197,13 +1201,23 @@ void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode*> &Join
{
IBoneSceneNode* node=JointChildSceneNodes[i];
SJoint *joint=AllJoints[i];
joint->LocalAnimatedMatrix.setTranslation( node->getPosition() );
joint->LocalAnimatedMatrix.setRotationDegrees( node->getRotation() );
//joint->LocalAnimatedMatrix.setScale( node->getScale() );
joint->positionHint=node->positionHint;
joint->scaleHint=node->scaleHint;
joint->rotationHint=node->rotationHint;
if (node->getSkinningSpace()==EBSS_GLOBAL)
joint->GlobalSkinningSpace=true;
else
joint->GlobalSkinningSpace=false;
}
//Remove cache, temp...
lastAnimatedFrame=-1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment