Fix skinned meshes not playing their last frame.
Also clarified animation documentation to describe current behavior more exactly. CSkinnedMesh had returned the last key instead of the number of keys. Thx to whoever mentioned to me once that our example dwarf is not playing his full animation in the meshviewer. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5118 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
44e73315e9
commit
125e73ef55
|
@ -1,6 +1,7 @@
|
|||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
|
||||
- Fix skinned meshes not playing their last frame. Also clarified animation documentation to describe current behavior more exactly.
|
||||
- Add IWriteFile::flush interface (thx @ JLouisB for the patch).
|
||||
- CLightSceneNode::updateAbsolutePosition does now light recalculations. This is to fix using animators with lights.
|
||||
- Fix collada export for objects with rotations around more than 1 axis.
|
||||
|
|
|
@ -22,8 +22,9 @@ namespace scene
|
|||
public:
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \return The amount of frames. If the amount is 1,
|
||||
it is a static, non animated mesh. */
|
||||
/** Note that the play-time is usually getFrameCount()-1 as it stops as soon as the last frame-key is reached.
|
||||
\return The amount of frames. If the amount is 1,
|
||||
it is a static, non animated mesh. */
|
||||
virtual u32 getFrameCount() const = 0;
|
||||
|
||||
//! Gets the animation speed of the animated mesh.
|
||||
|
|
|
@ -72,7 +72,11 @@ namespace scene
|
|||
virtual void setCurrentFrame(f32 frame) = 0;
|
||||
|
||||
//! Sets the frame numbers between the animation is looped.
|
||||
/** The default is 0 - MaximalFrameCount of the mesh.
|
||||
/** The default is 0 to getFrameCount()-1 of the mesh.
|
||||
Number of played frames is end-start.
|
||||
It interpolates toward the last frame but stops when it is reached.
|
||||
It does not interpolate back to start even when looping.
|
||||
Looping animations should ensure last and first frame-key are identical.
|
||||
\param begin: Start frame number of the loop.
|
||||
\param end: End frame number of the loop.
|
||||
\return True if successful, false if not. */
|
||||
|
|
|
@ -850,7 +850,7 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
|
|||
|
||||
// get start and begin time
|
||||
setAnimationSpeed(Mesh->getAnimationSpeed()); // NOTE: This had been commented out (but not removed!) in r3526. Which caused meshloader-values for speed to be ignored unless users specified explicitly. Missing a test-case where this could go wrong so I put the code back in.
|
||||
setFrameLoop(0, Mesh->getFrameCount());
|
||||
setFrameLoop(0, Mesh->getFrameCount()-1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace
|
|||
irr::u32 n=1; // new index
|
||||
for(irr::u32 j=1;j<array.size();++j)
|
||||
{
|
||||
if (array[j].frame < array[n-1].frame)
|
||||
if (array[j].frame < array[n-1].frame)
|
||||
continue; //bad frame, unneeded and may cause problems
|
||||
if ( n != j )
|
||||
array[n] = array[j];
|
||||
|
@ -36,7 +36,7 @@ namespace
|
|||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
// drop identical middle keys - we only need the first and last
|
||||
// return number of kicked keys
|
||||
template <class T, typename Cmp> // Cmp = comparison for keys of type T
|
||||
|
@ -55,7 +55,7 @@ namespace
|
|||
if ( j > s+1 ) // had there been identical keys?
|
||||
array[n++] = array[j-1]; // keep the last
|
||||
array[n++] = array[j]; // keep the new one
|
||||
s = j;
|
||||
s = j;
|
||||
}
|
||||
if ( array.size() > s+1 ) // identical keys at the array end?
|
||||
array[n++] = array[array.size()-1]; // keep the last
|
||||
|
@ -67,21 +67,21 @@ namespace
|
|||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
bool identicalPos(const irr::scene::ISkinnedMesh::SPositionKey& a, const irr::scene::ISkinnedMesh::SPositionKey& b)
|
||||
{
|
||||
return a.position == b.position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool identicalScale(const irr::scene::ISkinnedMesh::SScaleKey& a, const irr::scene::ISkinnedMesh::SScaleKey& b)
|
||||
{
|
||||
return a.scale == b.scale;
|
||||
}
|
||||
}
|
||||
|
||||
bool identicalRotation(const irr::scene::ISkinnedMesh::SRotationKey& a, const irr::scene::ISkinnedMesh::SRotationKey& b)
|
||||
{
|
||||
return a.rotation == b.rotation;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace irr
|
||||
|
@ -92,7 +92,7 @@ namespace scene
|
|||
|
||||
//! constructor
|
||||
CSkinnedMesh::CSkinnedMesh()
|
||||
: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
|
||||
: SkinningBuffers(0), EndFrame(0.f), FramesPerSecond(25.f),
|
||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||
InterpolationMode(EIM_LINEAR),
|
||||
HasAnimation(false), PreparedForSkinning(false),
|
||||
|
@ -124,7 +124,7 @@ CSkinnedMesh::~CSkinnedMesh()
|
|||
//! If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CSkinnedMesh::getFrameCount() const
|
||||
{
|
||||
return core::floor32(AnimationFrames);
|
||||
return core::floor32(EndFrame+1.f);
|
||||
}
|
||||
|
||||
|
||||
|
@ -878,22 +878,22 @@ void CSkinnedMesh::checkForAnimation()
|
|||
if (HasAnimation)
|
||||
{
|
||||
//--- Find the length of the animation ---
|
||||
AnimationFrames=0;
|
||||
EndFrame=0;
|
||||
for(i=0;i<AllJoints.size();++i)
|
||||
{
|
||||
if (AllJoints[i]->UseAnimationFrom)
|
||||
{
|
||||
if (AllJoints[i]->UseAnimationFrom->PositionKeys.size())
|
||||
if (AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame > AnimationFrames)
|
||||
AnimationFrames=AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame;
|
||||
if (AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame > EndFrame)
|
||||
EndFrame=AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame;
|
||||
|
||||
if (AllJoints[i]->UseAnimationFrom->ScaleKeys.size())
|
||||
if (AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame > AnimationFrames)
|
||||
AnimationFrames=AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame;
|
||||
if (AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame > EndFrame)
|
||||
EndFrame=AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame;
|
||||
|
||||
if (AllJoints[i]->UseAnimationFrom->RotationKeys.size())
|
||||
if (AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame > AnimationFrames)
|
||||
AnimationFrames=AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame;
|
||||
if (AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame > EndFrame)
|
||||
EndFrame=AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -958,7 +958,7 @@ void CSkinnedMesh::checkForAnimation()
|
|||
//! called by loader after populating with mesh and bone data
|
||||
void CSkinnedMesh::finalize()
|
||||
{
|
||||
os::Printer::log("Skinned Mesh - finalize", ELL_DEBUG);
|
||||
os::Printer::log("Skinned Mesh - finalize", ELL_DEBUG);
|
||||
u32 i;
|
||||
|
||||
// Make sure we recalc the next frame
|
||||
|
@ -1023,7 +1023,7 @@ void CSkinnedMesh::finalize()
|
|||
irr::u32 unorderedScaleKeys = 0;
|
||||
irr::u32 redundantRotationKeys = 0;
|
||||
irr::u32 unorderedRotationKeys = 0;
|
||||
|
||||
|
||||
//--- optimize and check keyframes ---
|
||||
for(i=0;i<AllJoints.size();++i)
|
||||
{
|
||||
|
@ -1053,11 +1053,11 @@ void CSkinnedMesh::finalize()
|
|||
}
|
||||
|
||||
Key=&PositionKeys.getLast();
|
||||
if (Key->frame!=AnimationFrames)
|
||||
if (Key->frame!=EndFrame)
|
||||
{
|
||||
PositionKeys.push_back(*Key);
|
||||
Key=&PositionKeys.getLast();
|
||||
Key->frame=AnimationFrames;
|
||||
Key->frame=EndFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1073,11 +1073,11 @@ void CSkinnedMesh::finalize()
|
|||
}
|
||||
|
||||
Key=&ScaleKeys.getLast();
|
||||
if (Key->frame!=AnimationFrames)
|
||||
if (Key->frame!=EndFrame)
|
||||
{
|
||||
ScaleKeys.push_back(*Key);
|
||||
Key=&ScaleKeys.getLast();
|
||||
Key->frame=AnimationFrames;
|
||||
Key->frame=EndFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,11 +1093,11 @@ void CSkinnedMesh::finalize()
|
|||
}
|
||||
|
||||
Key=&RotationKeys.getLast();
|
||||
if (Key->frame!=AnimationFrames)
|
||||
if (Key->frame!=EndFrame)
|
||||
{
|
||||
RotationKeys.push_back(*Key);
|
||||
Key=&RotationKeys.getLast();
|
||||
Key->frame=AnimationFrames;
|
||||
Key->frame=EndFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1108,7 +1108,7 @@ void CSkinnedMesh::finalize()
|
|||
}
|
||||
if ( unorderedPosKeys > 0 )
|
||||
{
|
||||
irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked:", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG);
|
||||
irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked:", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG);
|
||||
}
|
||||
if ( redundantScaleKeys > 0 )
|
||||
{
|
||||
|
|
|
@ -194,7 +194,7 @@ private:
|
|||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
f32 AnimationFrames;
|
||||
f32 EndFrame;
|
||||
f32 FramesPerSecond;
|
||||
|
||||
f32 LastAnimatedFrame;
|
||||
|
|
Loading…
Reference in New Issue