Improve speed for finalizing skinned meshes (removal of unnecessary frames after loading) (thx @ichtyander for the testmodel)
Down from ~20 seconds to ~0,5 seconds :-) git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4622 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
29faf510ac
commit
cc2b3716b7
|
@ -1,6 +1,7 @@
|
|||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
|
||||
- Improve speed for finalizing skinned meshes (removal of unnecessary frames after loading) (thx @ichtyander for the testmodel)
|
||||
- Collada loader now instantiates camera nodes which had been ignore so far (thx @NemoStein for the test .dae)
|
||||
- line2d::intersectWith has a new parameter to allow ignoring intersections with coincident lines
|
||||
- vector2d::equals now has an tolerance parameter for passing the epsilon (like vector3d had). Note that this changes the default
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace gui
|
|||
//! Validate when enter was pressed
|
||||
EGUI_SBV_ENTER = 2,
|
||||
//! Validate when the editbox loses the focus
|
||||
EGUI_SBV_LOSE_FOCUS = 4,
|
||||
EGUI_SBV_LOSE_FOCUS = 4
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,80 @@
|
|||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// Frames must always be increasing, so we remove objects where this isn't the case
|
||||
// return number of kicked keys
|
||||
template <class T> // T = objects containing a "frame" variable
|
||||
irr::u32 dropBadKeys(irr::core::array<T>& array)
|
||||
{
|
||||
if (array.size()<2)
|
||||
return 0;
|
||||
|
||||
irr::u32 n=1; // new index
|
||||
for(irr::u32 j=1;j<array.size();++j)
|
||||
{
|
||||
if (array[j].frame < array[j-1].frame)
|
||||
continue; //bad frame, unneeded and may cause problems
|
||||
if ( n != j )
|
||||
array[n] = array[j];
|
||||
++n;
|
||||
}
|
||||
irr::u32 d = array.size()-n; // remove already copied keys
|
||||
if ( d > 0 )
|
||||
{
|
||||
array.erase(n, d);
|
||||
}
|
||||
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
|
||||
irr::u32 dropMiddleKeys(irr::core::array<T>& array, Cmp & cmp)
|
||||
{
|
||||
if ( array.size() < 3 )
|
||||
return 0;
|
||||
|
||||
irr::u32 s = 0; // old index for current key
|
||||
irr::u32 n = 1; // new index for next key
|
||||
for(irr::u32 j=1;j<array.size();++j)
|
||||
{
|
||||
if ( cmp(array[j], array[s]) )
|
||||
continue; // same key, handle later
|
||||
|
||||
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;
|
||||
}
|
||||
if ( array.size() > s+1 ) // identical keys at the array end?
|
||||
array[n++] = array[array.size()-1]; // keep the last
|
||||
|
||||
irr::u32 d = array.size()-n; // remove already copied keys
|
||||
if ( d > 0 )
|
||||
{
|
||||
array.erase(n, d);
|
||||
}
|
||||
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
|
||||
{
|
||||
namespace scene
|
||||
|
@ -881,10 +955,10 @@ void CSkinnedMesh::checkForAnimation()
|
|||
SkinnedLastFrame=false;
|
||||
}
|
||||
|
||||
|
||||
//! called by loader after populating with mesh and bone data
|
||||
void CSkinnedMesh::finalize()
|
||||
{
|
||||
os::Printer::log("Skinned Mesh - finalize", ELL_DEBUG);
|
||||
u32 i;
|
||||
|
||||
// Make sure we recalc the next frame
|
||||
|
@ -939,8 +1013,6 @@ void CSkinnedMesh::finalize()
|
|||
Vertices_Moved[i].set_used(LocalBuffers[i]->getVertexCount());
|
||||
}
|
||||
|
||||
//Todo: optimise keys here...
|
||||
|
||||
checkForAnimation();
|
||||
|
||||
if (HasAnimation)
|
||||
|
@ -952,76 +1024,42 @@ void CSkinnedMesh::finalize()
|
|||
core::array<SScaleKey> &ScaleKeys = AllJoints[i]->ScaleKeys;
|
||||
core::array<SRotationKey> &RotationKeys = AllJoints[i]->RotationKeys;
|
||||
|
||||
if (PositionKeys.size()>2)
|
||||
// drop identical middle keys - we only need the first and last frame
|
||||
irr::u32 dropped = dropMiddleKeys<SPositionKey>(PositionKeys, identicalPos);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<PositionKeys.size()-2;++j)
|
||||
{
|
||||
if (PositionKeys[j].position == PositionKeys[j+1].position && PositionKeys[j+1].position == PositionKeys[j+2].position)
|
||||
{
|
||||
PositionKeys.erase(j+1); //the middle key is unneeded
|
||||
--j;
|
||||
}
|
||||
}
|
||||
os::Printer::log("Skinned Mesh - unneeded position frames kicked:", core::stringc(dropped).c_str(), ELL_DEBUG);
|
||||
}
|
||||
|
||||
if (PositionKeys.size()>1)
|
||||
|
||||
// drop frames with bad keys (frames out of order)
|
||||
dropped = dropBadKeys<SPositionKey>(PositionKeys);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<PositionKeys.size()-1;++j)
|
||||
{
|
||||
if (PositionKeys[j].frame >= PositionKeys[j+1].frame) //bad frame, unneed and may cause problems
|
||||
{
|
||||
PositionKeys.erase(j+1);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
irr::os::Printer::log("Skinned Mesh - bad position frames kicked:", irr::core::stringc(dropped).c_str(), irr::ELL_DEBUG);
|
||||
}
|
||||
|
||||
if (ScaleKeys.size()>2)
|
||||
|
||||
dropped = dropMiddleKeys<SScaleKey>(ScaleKeys, identicalScale);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<ScaleKeys.size()-2;++j)
|
||||
{
|
||||
if (ScaleKeys[j].scale == ScaleKeys[j+1].scale && ScaleKeys[j+1].scale == ScaleKeys[j+2].scale)
|
||||
{
|
||||
ScaleKeys.erase(j+1); //the middle key is unneeded
|
||||
--j;
|
||||
}
|
||||
}
|
||||
os::Printer::log("Skinned Mesh - unneeded scale frames kicked:", core::stringc(dropped).c_str(), ELL_DEBUG);
|
||||
}
|
||||
|
||||
if (ScaleKeys.size()>1)
|
||||
|
||||
dropped = dropBadKeys<SScaleKey>(ScaleKeys);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<ScaleKeys.size()-1;++j)
|
||||
{
|
||||
if (ScaleKeys[j].frame >= ScaleKeys[j+1].frame) //bad frame, unneed and may cause problems
|
||||
{
|
||||
ScaleKeys.erase(j+1);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
irr::os::Printer::log("Skinned Mesh - bad scale frames kicked:", irr::core::stringc(dropped).c_str(), irr::ELL_DEBUG);
|
||||
}
|
||||
|
||||
if (RotationKeys.size()>2)
|
||||
|
||||
dropped = dropMiddleKeys<SRotationKey>(RotationKeys, identicalRotation);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<RotationKeys.size()-2;++j)
|
||||
{
|
||||
if (RotationKeys[j].rotation == RotationKeys[j+1].rotation && RotationKeys[j+1].rotation == RotationKeys[j+2].rotation)
|
||||
{
|
||||
RotationKeys.erase(j+1); //the middle key is unneeded
|
||||
--j;
|
||||
}
|
||||
}
|
||||
os::Printer::log("Skinned Mesh - unneeded rotation frames kicked:", core::stringc(dropped).c_str(), ELL_DEBUG);
|
||||
}
|
||||
|
||||
if (RotationKeys.size()>1)
|
||||
|
||||
dropped = dropBadKeys<SRotationKey>(RotationKeys);
|
||||
if ( dropped > 0 )
|
||||
{
|
||||
for(u32 j=0;j<RotationKeys.size()-1;++j)
|
||||
{
|
||||
if (RotationKeys[j].frame >= RotationKeys[j+1].frame) //bad frame, unneed and may cause problems
|
||||
{
|
||||
RotationKeys.erase(j+1);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
irr::os::Printer::log("Skinned Mesh - bad rotation frames kicked:", irr::core::stringc(dropped).c_str(), irr::ELL_DEBUG);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue