Merge r4618-4629 from trunk. Branch has now catched up to trunk again :-)

Fix memory access in d3dx mipmap generation. Thanks to hellflip for the hint.
Developer documentation - adding a release checklist.
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 :-)
Minor bugfix for my last check-in. dropBadKeys now finds some more broken frames.
Changing calling convention for static lib release fast CPU to Cdecl because FastCall did not actually compile (conflicts with pnglib). Also the same setting is used when compiling as dll, so I guess this setting was simply not tested. Thanks @AReich for reporting. See thread for more info:  http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=49462


git-svn-id: http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4651 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2014-01-08 00:09:09 +00:00
parent 51e6ac4493
commit 36fc52fa0e
8 changed files with 215 additions and 144 deletions

View File

@ -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

View File

@ -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
};

View File

@ -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<width; ++x)
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<height; ++y)
{
for (int y=0; y<height; ++y)
for (s32 x=0; x<width; ++x)
{
s32 a=0, r=0, g=0, b=0;
for (int dx=0; dx<2; ++dx)
u32 a=0, r=0, g=0, b=0;
for (s32 dy=0; dy<dy_max; ++dy)
{
for (int dy=0; dy<2; ++dy)
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<dx_max; ++dx)
{
int tgx = (x*2)+dx;
int tgy = (y*2)+dy;
const s32 tgx = (x*2)+dx;
c = *(u16*)((void*)&src[(tgx*2)+(tgy*pitchsrc)]);
a += getAlpha(c);
r += getRed(c);
g += getGreen(c);
b += getBlue(c);
}
}
a /= 4;
r /= 4;
g /= 4;
b /= 4;
c = ((a & 0x1) <<15) | ((r & 0x1F)<<10) | ((g & 0x1F)<<5) | (b & 0x1F);
*(u16*)((void*)&tgt[(x*2)+(y*pitchtgt)]) = c;
}
}
}
void CD3D8Texture::copy32BitMipMap(char* src, char* tgt,
s32 width, s32 height,
s32 pitchsrc, s32 pitchtgt) const
{
SColor c;
for (int x=0; x<width; ++x)
{
for (int y=0; y<height; ++y)
{
s32 a=0, r=0, g=0, b=0;
for (int dx=0; dx<2; ++dx)
{
for (int dy=0; dy<2; ++dy)
{
int tgx = (x*2)+dx;
int tgy = (y*2)+dy;
c = *(u32*)((void*)&src[(tgx<<2)+(tgy*pitchsrc)]);
SColor c;
if (ColorFormat == ECF_A1R5G5B5)
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
else
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
a += c.getAlpha();
r += c.getRed();
@ -507,13 +474,60 @@ void CD3D8Texture::copy32BitMipMap(char* src, char* tgt,
}
}
a >>= 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<height; ++y)
{
for (s32 x=0; x<width; ++x)
{
u32 a=0, r=0, g=0, b=0;
SColor c;
for (s32 dy=0; dy<dy_max; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<dx_max; ++dx)
{
const s32 tgx = (x*2)+dx;
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
a += c.getAlpha();
r += c.getRed();
g += c.getGreen();
b += c.getBlue();
}
}
a /= blockcount;
r /= blockcount;
g /= blockcount;
b /= blockcount;
c.set(a, r, g, b);
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
}
}
}

View File

@ -91,10 +91,15 @@ private:
bool createMipMaps(u32 level=1);
void 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;
//! Helper function for mipmap generation.
void copy32BitMipMap(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;
IDirect3DDevice8* Device;
IDirect3DTexture8* Texture;

View File

@ -245,11 +245,13 @@ bool CD3D9Texture::createMipMaps(u32 level)
{
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
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
@ -565,19 +567,22 @@ bool CD3D9Texture::hasMipMaps() const
void CD3D9Texture::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
{
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<height; ++y)
{
for (s32 x=0; x<width; ++x)
{
u32 a=0, r=0, g=0, b=0;
for (s32 dy=0; dy<2; ++dy)
for (s32 dy=0; dy<dy_max; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<2; ++dx)
for (s32 dx=0; dx<dx_max; ++dx)
{
const s32 tgx = (x*2)+dx;
@ -594,10 +599,10 @@ void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
}
}
a /= 4;
r /= 4;
g /= 4;
b /= 4;
a /= blockcount;
r /= blockcount;
g /= blockcount;
b /= blockcount;
u16 c;
if (ColorFormat == ECF_A1R5G5B5)
@ -611,9 +616,13 @@ void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
void CD3D9Texture::copy32BitMipMap(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
{
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<height; ++y)
{
for (s32 x=0; x<width; ++x)
@ -621,10 +630,10 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
u32 a=0, r=0, g=0, b=0;
SColor c;
for (s32 dy=0; dy<2; ++dy)
for (s32 dy=0; dy<dy_max; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<2; ++dx)
for (s32 dx=0; dx<dx_max; ++dx)
{
const s32 tgx = (x*2)+dx;
@ -637,10 +646,10 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
}
}
a /= 4;
r /= 4;
g /= 4;
b /= 4;
a /= blockcount;
r /= blockcount;
g /= blockcount;
b /= blockcount;
c.set(a, r, g, b);
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;

View File

@ -94,11 +94,15 @@ private:
//! Helper function for mipmap generation.
void 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;
//! Helper function for mipmap generation.
void copy32BitMipMap(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;
//! set Pitch based on the d3d format
void setPitch(D3DFORMAT d3dformat);

View File

@ -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[n-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);
}

View File

@ -704,7 +704,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>
</DebugInformationFormat>
<CallingConvention>FastCall</CallingConvention>
<CallingConvention>Cdecl</CallingConvention>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>