Thanks for the snipet
.
Because I wanted to be a little more free with the order of transformations applied, I made my own one passing a matrix transform instead of angles, scales and translations.
Here is the function I use (in my case I never change the World, view and projection matrix so I commented this stuff : feel free to uncomment it if needed) :
Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect<irr::s32> sourceRect, const core::matrix4& mat, bool useAlphaChannel, irr::video::SColor color)
{
irr::video::SMaterial material;
// Store and clear the projection matrix
// irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
// driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4());
//
// // Store and clear the view matrix
// irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
// driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4());
// Find the positions of corners
irr::core::vector3df corner[4];
f32 halfWidth = (f32)(sourceRect.getWidth()/*-1*/)*0.5f;
f32 halfHeight = (f32)(sourceRect.getHeight()/*-1*/)*0.5f;
corner[0] = irr::core::vector3df(0.0f - halfWidth, 0.0f - halfHeight, 0.0f);
corner[1] = irr::core::vector3df(0.0f + halfWidth, 0.0f - halfHeight, 0.0f);
corner[2] = irr::core::vector3df(0.0f - halfWidth, 0.0f + halfHeight, 0.0f);
corner[3] = irr::core::vector3df(0.0f + halfWidth, 0.0f + halfHeight, 0.0f);
// transform corners
for (int x = 0; x < 4; x++)
{
mat.transformVect(corner[x]);
// uncomment this if you want the image to be centered on left top corner instead of the center
//corner[x] += irr::core::vector3df(halfWidth, halfHeight, 0.0f);
}
// Find the uv coordinates of the sourceRect
irr::core::vector2df uvCorner[4];
uvCorner[0] = irr::core::vector2df((f32)sourceRect.UpperLeftCorner.X,(f32)sourceRect.UpperLeftCorner.Y);
uvCorner[1] = irr::core::vector2df((f32)sourceRect.LowerRightCorner.X,(f32)sourceRect.UpperLeftCorner.Y);
uvCorner[2] = irr::core::vector2df((f32)sourceRect.UpperLeftCorner.X,(f32)sourceRect.LowerRightCorner.Y);
uvCorner[3] = irr::core::vector2df((f32)sourceRect.LowerRightCorner.X,(f32)sourceRect.LowerRightCorner.Y);
for (int x = 0; x < 4; x++)
{
float uvX = uvCorner[x].X/(float)texture->getSize().Width;
float uvY = uvCorner[x].Y/(float)texture->getSize().Height;
uvCorner[x] = irr::core::vector2df(uvX,uvY);
}
// Vertices for the image
irr::video::S3DVertex vertices[4];
irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 };
// Convert pixels to world coordinates
float screenWidth = (f32)driver->getCurrentRenderTargetSize().Width;
float screenHeight = (f32)driver->getCurrentRenderTargetSize().Height;
for (int x = 0; x < 4; x++)
{
float screenPosX = ((corner[x].X/screenWidth)-0.5f)*2.0f;
float screenPosY = ((corner[x].Y/screenHeight)-0.5f)*-2.0f;
vertices[x].Pos = irr::core::vector3df(screenPosX,screenPosY,0);
vertices[x].TCoords = uvCorner[x];
vertices[x].Color = color;
}
material.Lighting = false;
material.ZWriteEnable = false;
material.ZBuffer = false;
material.TextureLayer[0].Texture = texture;
// Fix dark border appearance when texture scaled down with bilinear or trilinear filter on
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP;
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP;
material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR);
if (useAlphaChannel)
material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND;
else
material.MaterialType = irr::video::EMT_SOLID;
material.TextureLayer[0].BilinearFilter = false;
material.TextureLayer[0].TrilinearFilter = true;
driver->setMaterial(material);
//driver->draw2DVertexPrimitiveList(&vertices[0],4,&indices[0],2);
driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
// Restore projection and view matrices
// driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
// driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
}
And here is an example of use :
Code: Select all
// Scale first, then rotate from center and then translate.
core::matrix4 mat = core::matrix4().setTranslation(core::vector3df((f32)pos.X, (f32)pos.Y, 0.0f)) *
core::matrix4().setRotationAxisRadians(rotation*core::DEGTORAD, core::vector3df(0.0f, 0.0f, 1.0f)) *
core::matrix4().setScale(core::vector3df((f32)scale, (f32)scale, 0.0f));
draw2DImage(driver, texture, srcRect, mat, true, tint);
Notice that I fixed some jerks with alpha blending when scaling down with bilinear or trilinear filter (appearance of dark borders).