2D images with rotation

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
swesoulc
Posts: 17
Joined: Tue Apr 03, 2007 10:05 am

Re: 2D images with rotation

Post by swesoulc »

Your test contains just the .exe, but for anyone to debug this we would need code to reproduce it (and with code I mean certainly an example that is already reduced to just the problem, not some large project with all the code).
yes, my purpose with the exe, as i stated , Was to Just Display the result.
I've uploaded a small exe to demonstrate my problem.
i never even opted for anyone to bug search my code. Since the only thing i did was change my previous draw function to this one, and i have had no problem with the rest of the code for well about 2 years, my thoughts go to that the problem is somewhere within the newly added code. And since my project spans way, Way more then one file... To share the code would be quite tideus. Code that i myself have a hard time putting my head around at times. I would actually never request that of this community ( i have Some pride atleast )

I have mearly been asking if this issue have been know by the original coder.
If anyone hase had this problem before and found a work-around.
if anyone would like to declare me stupid and say that it is obviously the rect i toss to the function that is broken. ( i can go through those for a seventh time, if it would make anyone feel better )
If it is the recalculating of coordinates that gets screwed up because i havn't set a camera.
Basicly anything.

thank you though CuteAlien for your reply, however degrading it now was.
CuteAlien
Admin
Posts: 9634
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: 2D images with rotation

Post by CuteAlien »

Uhm, sorry, this wasn't meant to be degrading. I just wanted to tell you the fastest way to get better help, don't take this personal. This is pretty much the standard info we give out, the fact that it didn't tell me anything was more or less implicit already when I asked for sources. When you have the feeling that I'm describing it too detailed (the stuff about reducing it first) just put it to the fact that in a forum with many beginners 9 out of 10 just don't know this stuff (and the 10th is pissed of because he thinks we make fun of him telling him obvious stuff... that's life).

So, can't help - haven't seen a bug exactly like this with draw2DImage, but well - maybe someone else thinks this looks familiar from screenshots. But maybe post a little of your code around the trouble function in case it's something obvious which you just don't see because you stared at it too long already :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
swesoulc
Posts: 17
Joined: Tue Apr 03, 2007 10:05 am

Re: 2D images with rotation

Post by swesoulc »

Well thank you again cutealien

EDIT (entire post deleted )

Thanks for putting up with me. Problem solved. I have declared myself an idiot. draw2dimage works fine. The problem was that i had been staring at the code for too long, and forgot to look at the texture. Would you belive that a image not in 100x100 don't look too good when you try and put it out as such.

will be going back to my former post to remove images and links.
zhengxianfu
Posts: 16
Joined: Thu Apr 05, 2012 9:33 am

Re: 2D images with rotation

Post by zhengxianfu »

Lonesome Ducky wrote:I have written the completed version of this snippet. I have incorporated all fixes mentioned, and optimized it from 8 sin/cos calls to 2, so it is less computationally intensive. The code is also cleaned up a bit and should be easier to understand. Here you go! :D

Thanks very much.I use it into my project .Great Job!
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Re: 2D images with rotation

Post by Catprog »

I am getting a bit of jitter as well. BackOfMap,FrontMap are the two textures. left,right,top,bottom are where it is being drawn. frame is what step it is on.

Code: Select all

    void draw(irr::scene::ISceneManager* smgr )
    {
 
        core::dimension2d<u32> texSize = BackOfMap->getSize();
 
        cImage* mapFront;
 
 
        cImage* mapBack;
 
 
        bool needCleanup=false;
        if(Frame<=.99)
        {
 
 
            u32 diffrence = (right-left)*(Frame);
            u32 RightText = texSize.Width*(Frame);
            u32 revRightText = texSize.Width*(1-Frame);
 
            f32 halfOfRolling =texSize.Width*.1f/2;
 
            u32 WidthOfScreenScroll = (right-left)*.1f;
 
 
 
            mapFront=new cImage(FrontMap,
                                core::rect<s32>(left,top,left+diffrence,bottom),
                                core::rect<s32>(0,0,RightText ,texSize.Height));
 
 
            u32 rightOfMap = (right-left)*(.2+Frame);
            if(rightOfMap>=right) rightOfMap=right;
            s32 leftOfMap = rightOfMap-(right-left-diffrence);
            if(leftOfMap<left) leftOfMap=left;
 
            f32 SizeOfShownMap=(rightOfMap-leftOfMap);
 
            u32 RightTex  = ((SizeOfShownMap/(right-left)))*texSize.Width;
 
 
 
            mapBack=new cImage(BackOfMap,
                               core::rect<s32>(leftOfMap,top,rightOfMap,bottom),
                               core::rect<s32>(0,0, RightTex,texSize.Height));
 
 
            needCleanup=true;
        }
        else
        {
 
            mapFront=new cImage(FrontMap,
                                core::rect<s32>(left,top,right,bottom),
                                core::rect<s32>(0,0,texSize.Width,texSize.Height));
 
            needCleanup=false;
 
 
        }
 
        mapFront->Draw(smgr);
 
        if(Frame<=.99)       mapBack->Draw(smgr);
 
 
        if(needCleanup)        delete mapBack;
 
        delete mapFront;
    }
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Re: 2D images with rotation

Post by Lonesome Ducky »

Please make sure to use the code in the very first post in this thread. The code you're using is my first revision and is, quite frankly, terrible :lol:
arnir
Competition winner
Posts: 154
Joined: Sat Jan 20, 2007 4:36 pm
Location: Czech Republic

Re: 2D images with rotation

Post by arnir »

genial! really thanks!
programmer is bad designer
designer is bad programmer
cww
Posts: 27
Joined: Sun Jul 28, 2013 1:29 pm

Re: 2D images with rotation

Post by cww »

Hi,

Thanks for this code and definitely very useful to me. However, I am facing the 'rendered behind' problem with ZBuffer = false. I am using EDT_OGLES1 and testing on iOS. Any idea how to 'fix' this?

I can 'resolve' the problem by setting the z-position to 0 (or -1, original value in code is 1), but it seems more like a hack that can cause other problem down the road, so not sure if it is a good idea.

Code: Select all

 
// Convert pixels to world coordinates
    irr::core::vector2df screenSize(driver.getViewPort().getWidth(), driver.getViewPort().getHeight());
    for (irr::s32 i = 0; i < 4; i++) {
        // setting to z position to 0 or -1 solves the problem
        vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,0); 
 
Thanks!
cww
Posts: 27
Joined: Sun Jul 28, 2013 1:29 pm

Re: 2D images with rotation

Post by cww »

ignore my last question, managed to find the solution after some digging ;)

Code: Select all

 
material.ZBuffer = irr::video::ECFN_NEVER;
 
Akabane87
Posts: 50
Joined: Sat May 05, 2012 6:11 pm

Re: 2D images with rotation

Post by Akabane87 »

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).
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: 2D images with rotation

Post by hendu »

Just noting that CLAMP is wrong and will still cause artifacts (as it uses the border color, which is black if not set). You want CLAMP_TO_EDGE.
Akabane87
Posts: 50
Joined: Sat May 05, 2012 6:11 pm

Re: 2D images with rotation

Post by Akabane87 »

Mmh you're certainly right but it fixed in my case all these types of artifact so I didn't checked further for a properly working flag :roll: .
cww
Posts: 27
Joined: Sun Jul 28, 2013 1:29 pm

Re: 2D images with rotation

Post by cww »

Hi, I can't get alpha to work by using Vertices.Color.setAlpha(100). It is always solid, even if I set it to 0. I am using OGLES1Driver on iOS. Anyone has any idea how to fix or go about finding the fix? Thanks!

PS: the alpha embedded within the image itself is working correctly, but not the alpha I set to the Vertex.
Akabane87
Posts: 50
Joined: Sat May 05, 2012 6:11 pm

Re: 2D images with rotation

Post by Akabane87 »

Did you set useAlphaChannel to true ? Without it you will use the material type EMT_SOLID that only use alpha from texture and not pixel color's alpha.

Coming back to the original subject, I found some other artefacts with the screen projection calculation. Here is my latest version (with an additionnal flag to now use premultiplied alpha if my texture use it) :

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, bool useFiltering/* = true*/, bool usePremultipliedAlpha/* = false*/) 
{
      //irr::video::SMaterial material;
    irr::video::SMaterial& material = driver->getMaterial2D();
 
    if(usePremultipliedAlpha)
    {
        color.color = PremultiplyAlpha(color.color);
    }
 
    // Store and clear the world matrix
    irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
    // Store and clear the projection matrix
    irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION);
    // Store and clear the view matrix
    irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW);
 
    core::matrix4 m;
    // this fixes some problems with pixel exact rendering, but also breaks nice texturing
    driver->setTransform(irr::video::ETS_WORLD, mat);
 
    // adjust the view such that pixel center aligns with texels
    // Otherwise, subpixel artifacts will occur
    if(driver->getDriverType() == video::EDT_DIRECT3D9)
        m.setTranslation(core::vector3df(-0.5f,-0.5f,0));
    driver->setTransform(irr::video::ETS_VIEW, m);
 
    const core::dimension2d<u32>& renderTargetSize = driver->getCurrentRenderTargetSize();
    m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0);
    m.setTranslation(core::vector3df(-1,1,0));
    driver->setTransform(irr::video::ETS_PROJECTION, m);
 
    // Find the positions of corners
    irr::core::vector3df corner[4];
 
    f32 halfWidth = (f32)(sourceRect.getWidth())*0.5f;
    f32 halfHeight = (f32)(sourceRect.getHeight())*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);
 
 
    // 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);
    const irr::core::dimension2d<u32>& texSize = texture->getOriginalSize();
    for (int x = 0; x < 4; x++) 
    {
        float uvX = uvCorner[x].X/(float)texSize.Width;
        float uvY = uvCorner[x].Y/(float)texSize.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 };
 
    for (int x = 0; x < 4; x++) 
    {
        vertices[x].Pos = corner[x];
        vertices[x].TCoords = uvCorner[x];
        vertices[x].Color = color;
    }
 
    //driver->enableMaterial2D(true);
    material.Lighting = false;
    material.ZWriteEnable = false;
    material.ZBuffer = false;
    material.BackfaceCulling = false;
    //material.AntiAliasing = true;
    material.TextureLayer[0].Texture = texture;
    // Fix dark border appearance when texture scaled down with bilinear or trilinear filter on
    if(uvCorner[0].X >= 0.0f && uvCorner[3].X <= 1.0f)
        material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
    else
        material.TextureLayer[0].TextureWrapU = video::ETC_REPEAT;
    if(uvCorner[0].Y >= 0.0f && uvCorner[3].Y <= 1.0f)
        material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
    else
        material.TextureLayer[0].TextureWrapV = video::ETC_REPEAT;
 
    if(usePremultipliedAlpha)
        material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_ONE, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR);
    else
        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 = useFiltering;
 
    driver->setMaterial(material);
    //driver->draw2DVertexPrimitiveList(&vertices[0],4,&indices[0],2);
    driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
 
    //driver->enableMaterial2D(false);
 
    // Restore projection and view matrices
    driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);
    driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
    driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
}
 
edit : I edited the code since it was still incorrect on some points (blending method was ignored).
Post Reply