diff --git a/changes.txt b/changes.txt index 1b66efb1..7dceeacb 100644 --- a/changes.txt +++ b/changes.txt @@ -3,6 +3,7 @@ Changes in 1.9 (not yet released) - Removed VS6 .dsw / .dsp project files - VS6 is no longer supported. - Added support for PVR textures. Loader offer support for compressed DXT1-5, PVRTC/PVRTC-II, ETC1/ETC2 texture formats. +- 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 diff --git a/include/IGUISpinBox.h b/include/IGUISpinBox.h index 4ce788ba..1c647627 100644 --- a/include/IGUISpinBox.h +++ b/include/IGUISpinBox.h @@ -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 }; diff --git a/source/Irrlicht/CD3D8Texture.cpp b/source/Irrlicht/CD3D8Texture.cpp index a01f8798..25ee12d5 100644 --- a/source/Irrlicht/CD3D8Texture.cpp +++ b/source/Irrlicht/CD3D8Texture.cpp @@ -384,11 +384,13 @@ bool CD3D8Texture::createMipMaps(u32 level) { if (upperDesc.Format == D3DFMT_A1R5G5B5) copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, + upperDesc.Width, upperDesc.Height, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else if (upperDesc.Format == D3DFMT_A8R8G8B8) copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, + upperDesc.Width, upperDesc.Height, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else @@ -440,65 +442,30 @@ ECOLOR_FORMAT CD3D8Texture::getColorFormatFromD3DFormat(D3DFORMAT format) void CD3D8Texture::copy16BitMipMap(char* src, char* tgt, - s32 width, s32 height, - s32 pitchsrc, s32 pitchtgt) const + const s32 srcWidth, const s32 srcHeight, + const s32 width, const s32 height, + const s32 pitchsrc, const s32 pitchtgt) const { - u16 c; - - for (int x=0; x>= 2; - r >>= 2; - g >>= 2; - b >>= 2; + a /= blockcount; + r /= blockcount; + g /= blockcount; + b /= blockcount; - c = ((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff); - *(u32*)((void*)&tgt[(x*4)+(y*pitchtgt)]) = c.color; + u16 c; + if (ColorFormat == ECF_A1R5G5B5) + c = RGBA16(r,g,b,a); + else + c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color); + *(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c; + } + } +} + + +void CD3D8Texture::copy32BitMipMap(char* src, char* tgt, + const s32 srcWidth, const s32 srcHeight, + const s32 width, const s32 height, + const s32 pitchsrc, const s32 pitchtgt) const +{ + const s32 dy_max = (srcHeight==1?1:2); + const s32 dx_max = (srcWidth==1?1:2); + const s32 blockcount= dx_max*dy_max; + for (s32 y=0; y // T = objects containing a "frame" variable + irr::u32 dropBadKeys(irr::core::array& array) + { + if (array.size()<2) + return 0; + + irr::u32 n=1; // new index + for(irr::u32 j=1;j 0 ) + { + array.erase(n, d); + } + return d; + } + + // drop identical middle keys - we only need the first and last + // return number of kicked keys + template // Cmp = comparison for keys of type T + irr::u32 dropMiddleKeys(irr::core::array& 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 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 &ScaleKeys = AllJoints[i]->ScaleKeys; core::array &RotationKeys = AllJoints[i]->RotationKeys; - if (PositionKeys.size()>2) + // drop identical middle keys - we only need the first and last frame + irr::u32 dropped = dropMiddleKeys(PositionKeys, identicalPos); + if ( dropped > 0 ) { - for(u32 j=0;j1) + + // drop frames with bad keys (frames out of order) + dropped = dropBadKeys(PositionKeys); + if ( dropped > 0 ) { - for(u32 j=0;j= 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(ScaleKeys, identicalScale); + if ( dropped > 0 ) { - for(u32 j=0;j1) + + dropped = dropBadKeys(ScaleKeys); + if ( dropped > 0 ) { - for(u32 j=0;j= 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(RotationKeys, identicalRotation); + if ( dropped > 0 ) { - for(u32 j=0;j1) + + dropped = dropBadKeys(RotationKeys); + if ( dropped > 0 ) { - for(u32 j=0;j= 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); } diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj b/source/Irrlicht/Irrlicht10.0.vcxproj index 6a352423..5243491b 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj +++ b/source/Irrlicht/Irrlicht10.0.vcxproj @@ -704,7 +704,7 @@ Level3 - FastCall + Cdecl NDEBUG;%(PreprocessorDefinitions)