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