Implement smooth frame transition for animated mesh
This commit is contained in:
parent
01de29670a
commit
fa4318b6ad
@ -61,7 +61,8 @@ void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame)
|
||||
// if you pass an out of range value, we just clamp it
|
||||
CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame );
|
||||
|
||||
beginTransition(); //transit to this frame if enabled
|
||||
// STK calls setCurrentFrame each frame for steering animation
|
||||
//beginTransition(); //transit to this frame if enabled
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +83,7 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
|
||||
{
|
||||
Transiting=0.f;
|
||||
TransitingBlend=0.f;
|
||||
setTransitionTime(0.f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,6 +191,8 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
return 0;
|
||||
#else
|
||||
if (Transiting != 0.0f)
|
||||
animateJoints(false);
|
||||
|
||||
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
||||
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
||||
@ -804,9 +808,12 @@ void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
|
||||
return;
|
||||
TransitionTime = ttime;
|
||||
if (ttime != 0)
|
||||
{
|
||||
setJointMode(EJUOR_CONTROL);
|
||||
beginTransition();
|
||||
}
|
||||
else
|
||||
setJointMode(EJUOR_NONE);
|
||||
setJointMode(EJUOR_READ);
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,7 +71,7 @@ struct Armature
|
||||
|
||||
std::vector<core::matrix4> m_joint_matrices;
|
||||
|
||||
std::vector<core::matrix4> m_interpolated_matrices;
|
||||
std::vector<LocRotScale> m_interpolated_matrices;
|
||||
|
||||
std::vector<std::pair<core::matrix4, bool> > m_world_matrices;
|
||||
|
||||
@ -140,9 +140,27 @@ struct Armature
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/* Because matrix4 in windows is not 64 bytes */
|
||||
void getPose(float frame, std::array<float, 16>* dest)
|
||||
void getPose(float frame, std::array<float, 16>* dest,
|
||||
float frame_interpolating = -1.0f, float rate = -1.0f)
|
||||
{
|
||||
getInterpolatedMatrices(frame);
|
||||
if (frame_interpolating != -1.0f && rate != -1.0f)
|
||||
{
|
||||
auto copied = m_interpolated_matrices;
|
||||
getInterpolatedMatrices(frame_interpolating);
|
||||
for (unsigned i = 0; i < m_interpolated_matrices.size(); i++)
|
||||
{
|
||||
m_interpolated_matrices[i].m_loc =
|
||||
copied[i].m_loc.getInterpolated(
|
||||
m_interpolated_matrices[i].m_loc, rate);
|
||||
m_interpolated_matrices[i].m_rot =
|
||||
m_interpolated_matrices[i].m_rot.slerp(
|
||||
m_interpolated_matrices[i].m_rot, copied[i].m_rot, rate);
|
||||
m_interpolated_matrices[i].m_scale =
|
||||
copied[i].m_scale.getInterpolated(
|
||||
m_interpolated_matrices[i].m_scale, rate);
|
||||
}
|
||||
}
|
||||
for (auto& p : m_world_matrices)
|
||||
{
|
||||
p.second = false;
|
||||
@ -178,8 +196,8 @@ struct Armature
|
||||
{
|
||||
m_interpolated_matrices[i] =
|
||||
frame >= float(m_frame_pose_matrices.back().first) ?
|
||||
m_frame_pose_matrices.back().second[i].toMatrix() :
|
||||
m_frame_pose_matrices.front().second[i].toMatrix();
|
||||
m_frame_pose_matrices.back().second[i] :
|
||||
m_frame_pose_matrices.front().second[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -215,14 +233,14 @@ struct Armature
|
||||
interpolated.m_scale =
|
||||
m_frame_pose_matrices[frame_2].second[i].m_scale.getInterpolated
|
||||
(m_frame_pose_matrices[frame_1].second[i].m_scale, interpolation);
|
||||
m_interpolated_matrices[i] = interpolated.toMatrix();
|
||||
m_interpolated_matrices[i] = interpolated;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
core::matrix4 getWorldMatrix(const std::vector<core::matrix4>& matrix,
|
||||
core::matrix4 getWorldMatrix(const std::vector<LocRotScale>& lrs,
|
||||
unsigned id)
|
||||
{
|
||||
core::matrix4 mat = matrix[id];
|
||||
core::matrix4 mat = lrs[id].toMatrix();
|
||||
int parent_id = m_parent_infos[id];
|
||||
if (parent_id == -1)
|
||||
{
|
||||
@ -232,7 +250,7 @@ struct Armature
|
||||
if (!m_world_matrices[parent_id].second)
|
||||
{
|
||||
m_world_matrices[parent_id] = std::make_pair
|
||||
(getWorldMatrix(matrix, parent_id), true);
|
||||
(getWorldMatrix(lrs, parent_id), true);
|
||||
}
|
||||
m_world_matrices[id] =
|
||||
std::make_pair(m_world_matrices[parent_id].first * mat, true);
|
||||
|
@ -119,12 +119,14 @@ s32 SPMesh::getJointIDWithArm(const c8* name, unsigned* arm_id) const
|
||||
} // getJointIDWithArm
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SPMesh::getSkinningMatrices(f32 frame, std::array<float, 16>* dest)
|
||||
void SPMesh::getSkinningMatrices(f32 frame, std::array<float, 16>* dest,
|
||||
float frame_interpolating, float rate)
|
||||
{
|
||||
unsigned accumulated_joints = 0;
|
||||
for (unsigned i = 0; i < m_all_armatures.size(); i++)
|
||||
{
|
||||
m_all_armatures[i].getPose(frame, &dest[accumulated_joints]);
|
||||
m_all_armatures[i].getPose(frame, &dest[accumulated_joints],
|
||||
frame_interpolating, rate);
|
||||
accumulated_joints += m_all_armatures[i].m_joint_used;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<Armature>& getArmatures() { return m_all_armatures; }
|
||||
// ------------------------------------------------------------------------
|
||||
void getSkinningMatrices(f32 frame, std::array<float, 16>* dest);
|
||||
void getSkinningMatrices(f32 frame, std::array<float, 16>* dest,
|
||||
float frame_interpolating = -1.0f, float rate = -1.0f);
|
||||
// ------------------------------------------------------------------------
|
||||
s32 getJointIDWithArm(const c8* name, unsigned* arm_id) const;
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -48,6 +48,7 @@ SPMeshNode::SPMeshNode(IAnimatedMesh* mesh, ISceneNode* parent,
|
||||
m_first_render_info = render_info;
|
||||
m_animated = false;
|
||||
m_skinning_offset = -32768;
|
||||
m_saved_transition_frame = -1.0f;
|
||||
m_is_in_shadowpass = true;
|
||||
} // SPMeshNode
|
||||
|
||||
@ -83,6 +84,7 @@ void SPMeshNode::setMesh(irr::scene::IAnimatedMesh* mesh)
|
||||
{
|
||||
m_glow_color = video::SColorf(0.0f, 0.0f, 0.0f);
|
||||
m_skinning_offset = -32768;
|
||||
m_saved_transition_frame = -1.0f;
|
||||
m_animated = false;
|
||||
m_mesh = static_cast<SPMesh*>(mesh);
|
||||
CAnimatedMeshSceneNode::setMesh(mesh);
|
||||
@ -167,7 +169,8 @@ IMesh* SPMeshNode::getMeshForCurrentFrame()
|
||||
{
|
||||
return m_mesh;
|
||||
}
|
||||
m_mesh->getSkinningMatrices(getFrameNr(), m_skinning_matrices.data());
|
||||
m_mesh->getSkinningMatrices(getFrameNr(), m_skinning_matrices.data(),
|
||||
m_saved_transition_frame, TransitingBlend);
|
||||
updateAbsolutePosition();
|
||||
|
||||
for (Armature& arm : m_mesh->getArmatures())
|
||||
@ -211,4 +214,22 @@ SPShader* SPMeshNode::getShader(unsigned mesh_buffer_id) const
|
||||
return NULL;
|
||||
} // getShader
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void SPMeshNode::setTransitionTime(f32 Time)
|
||||
{
|
||||
if (Time == 0.0f)
|
||||
{
|
||||
TransitingBlend = TransitionTime = Transiting = 0;
|
||||
m_saved_transition_frame = -1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 ttime = (u32)core::floor32(Time * 1000.0f);
|
||||
TransitionTime = ttime;
|
||||
Transiting = core::reciprocal((f32)TransitionTime);
|
||||
TransitingBlend = 0.0f;
|
||||
m_saved_transition_frame = getFrameNr();
|
||||
}
|
||||
} // setTransitionTime
|
||||
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ private:
|
||||
|
||||
bool m_is_in_shadowpass;
|
||||
|
||||
float m_saved_transition_frame;
|
||||
|
||||
std::vector<std::array<float, 16> > m_skinning_matrices;
|
||||
|
||||
video::SColorf m_glow_color;
|
||||
@ -167,6 +169,8 @@ public:
|
||||
assert(mb_id < m_texture_matrices.size());
|
||||
m_texture_matrices[mb_id] = tm;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setTransitionTime(f32 Time);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user