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.

Postby Lonesome Ducky » Wed Sep 08, 2010 12:14 am

I actually have much better code for accomplishing this if you're still interested:
Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture , irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, 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::vector2df corner[4];

   corner[0] = irr::core::vector2df(position.X,position.Y);
   corner[1] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y);
   corner[2] = irr::core::vector2df(position.X,position.Y+sourceRect.getHeight()*scale.Y);
   corner[3] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y+sourceRect.getHeight()*scale.Y);

   // Rotate corners
   if (rotation != 0.0f)
      for (int x = 0; x < 4; x++)
         corner[x].rotateBy(rotation,irr::core::vector2df(rotationPoint.X, rotationPoint.Y));


   // Find the uv coordinates of the sourceRect
   irr::core::vector2df uvCorner[4];
   uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
   uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,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 = driver->getScreenSize().Width;
   float screenHeight = driver->getScreenSize().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,1);
      vertices[x].TCoords = uvCorner[x];
      vertices[x].Color = color;
   }
   material.Lighting = false;
   material.ZWriteEnable = false;
   material.TextureLayer[0].Texture = texture;
   //material.TextureLayer[0].TextureWrap = irr::video::ETC_CLAMP;

   if (useAlphaChannel)
      material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
   else
      material.MaterialType = irr::video::EMT_SOLID;

   driver->setMaterial(material);
   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);

}
User avatar
Lonesome Ducky
Competition winner
 
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Postby arnir » Sun Nov 21, 2010 10:17 am

wow great, excellent!
finally working code for me :D
programmer is bad designer
designer is bad programmer
arnir
Competition winner
 
Posts: 154
Joined: Sat Jan 20, 2007 4:36 pm
Location: Czech Republic

Postby Josh1billion » Wed Mar 09, 2011 4:20 am

I'm trying to use this new draw2DImage() function in conjunction with rendering-to-texture, but they're not entirely compatible, so many weird glitches are arising. Can anyone (with more Irrlicht experience than me) try and update it? Thanks in advance if so.
www.JoshForde.com

Latest release: Super Orbulite World.
In development: Season of Dreams and others
User avatar
Josh1billion
 
Posts: 125
Joined: Thu Dec 11, 2008 9:50 pm
Location: Wisconsin

Postby Josh1billion » Tue Mar 15, 2011 7:38 pm

Sorry for the double-post, but does anyone at least have any idea on what would need to be changed to make this render-to-texture compatible?

So far, I've changed this:

Code: Select all
   float screenWidth = driver->getScreenSize().Width;
   float screenHeight = driver->getScreenSize().Height;


to the width and height of the render-to-texture texture, i.e.:

Code: Select all
   float screenWidth = 200;
   float screenHeight = 200;


I don't have any experience in this sort of low[er]-level stuff, so I have no idea what else needs to be changed for it to be render-to-texture compatible... Any help at all would be greatly appreciated, as this is a very important feature in my game, and I'm very stuck on it. :) Thanks.
www.JoshForde.com

Latest release: Super Orbulite World.
In development: Season of Dreams and others
User avatar
Josh1billion
 
Posts: 125
Joined: Thu Dec 11, 2008 9:50 pm
Location: Wisconsin

Postby Josh1billion » Wed Mar 16, 2011 6:35 am

Got it! A render-to-texture compatible version of the draw2DImage function that Lonesome Ducky posted earlier.

Many thanks to Keless for helping me over IM to figure out what the RTT incompatibility was.

Replace RTT_WIDTH and RTT_HEIGHT to the width and height of the texture that is being rendered to (not the width and height of the image being drawn, but of the texture onto which it is being drawn).

Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture , irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, 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());

   // Store and clear the world matrix
   irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
   driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());

   // Find the positions of corners
   irr::core::vector2df corner[4];

   corner[0] = irr::core::vector2df(position.X,position.Y);
   corner[1] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y);
   corner[2] = irr::core::vector2df(position.X,position.Y+sourceRect.getHeight()*scale.Y);
   corner[3] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y+sourceRect.getHeight()*scale.Y);


   // Rotate corners
   if (rotation != 0.0f)
      for (int x = 0; x < 4; x++)
         corner[x].rotateBy(rotation,irr::core::vector2df(rotationPoint.X, rotationPoint.Y));


   // Find the uv coordinates of the sourceRect
   irr::core::vector2df uvCorner[4];
   uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
   uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,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 = RTT_WIDTH;
   float screenHeight = RTT_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,1);
      vertices[x].TCoords = uvCorner[x];
      vertices[x].Color = color;
   }
   material.Lighting = false;
   material.ZWriteEnable = false;
   material.TextureLayer[0].Texture = texture;
   //material.TextureLayer[0].TextureWrap = irr::video::ETC_CLAMP;

   if (useAlphaChannel)
      material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
   else
      material.MaterialType = irr::video::EMT_SOLID;

   driver->setMaterial(material);
   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);
   driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);

}


www.JoshForde.com

Latest release: Super Orbulite World.
In development: Season of Dreams and others
User avatar
Josh1billion
 
Posts: 125
Joined: Thu Dec 11, 2008 9:50 pm
Location: Wisconsin

Postby mrdoubleb » Tue Apr 12, 2011 1:15 pm

This works great only problem i have no i that it gets drawn behind other things. So when i have a map/terrain i cant see it because its behind it. How can i fix that?
mrdoubleb
 
Posts: 9
Joined: Tue Apr 12, 2011 1:10 pm

Postby Masterhawk » Tue Apr 12, 2011 1:51 pm

what about calling it after "smgr->drawAll()" ?
Image
User avatar
Masterhawk
 
Posts: 299
Joined: Mon Nov 27, 2006 6:52 pm
Location: GERMANY

Postby mrdoubleb » Tue Apr 12, 2011 3:21 pm

Masterhawk wrote:what about calling it after "smgr->drawAll()" ?


its already called after smgr->drawAll() its part of a HUD in game.

I draw another image that works fine with the normal. (driver->draw2DImage)

below that image i use the function suplyed above it draws but it appears behind everything.
mrdoubleb
 
Posts: 9
Joined: Tue Apr 12, 2011 1:10 pm

Postby Lonesome Ducky » Tue Apr 12, 2011 9:38 pm

I've fixed it getting drawn behind things it shouldn't (by disabling zbuffer for it, which I should have done already in hindsight) and made it be able to use the texture's alpha and combine it with the alpha you supply through the color value.
Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture , irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, 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::vector2df corner[4];

   corner[0] = irr::core::vector2df(position.X,position.Y);
   corner[1] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y);
   corner[2] = irr::core::vector2df(position.X,position.Y+sourceRect.getHeight()*scale.Y);
   corner[3] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y+sourceRect.getHeight()*scale.Y);

   // Rotate corners
   if (rotation != 0.0f)
      for (int x = 0; x < 4; x++)
         corner[x].rotateBy(rotation,irr::core::vector2df(rotationPoint.X, rotationPoint.Y));


   // Find the uv coordinates of the sourceRect
   irr::core::vector2df uvCorner[4];
   uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
   uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,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 = driver->getScreenSize().Width;
   float screenHeight = driver->getScreenSize().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,1);
      vertices[x].TCoords = uvCorner[x];
      vertices[x].Color = color;
   }

   material.Lighting = false;
   material.ZWriteEnable = false;
   material.ZBuffer = false;
   material.TextureLayer[0].Texture = texture;
   material.MaterialTypeParam = irr::video::pack_texureBlendFunc(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;

   driver->setMaterial(material);
   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);
}
User avatar
Lonesome Ducky
Competition winner
 
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Postby mrdoubleb » Tue Apr 12, 2011 10:49 pm

Lonesome Ducky wrote:I've fixed it getting drawn behind things it shouldn't (by disabling zbuffer for it, which I should have done already in hindsight) and made it be able to use the texture's alpha and combine it with the alpha you supply through the color value. //Code//


Great! thanks.

i had to add somethings though:

at top:
Code: Select all
// Store and clear the world matrix
   irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
   driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());   


Bottom:
Code: Select all
driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);


like mentioned in posts aboved but it works now! Thanks!

My code now:

Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture , irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, 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());

   // Store and clear the world matrix
   irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
   driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());

   // Find the positions of corners
   irr::core::vector2df corner[4];

   corner[0] = irr::core::vector2df(position.X,position.Y);
   corner[1] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y);
   corner[2] = irr::core::vector2df(position.X,position.Y+sourceRect.getHeight()*scale.Y);
   corner[3] = irr::core::vector2df(position.X+sourceRect.getWidth()*scale.X,position.Y+sourceRect.getHeight()*scale.Y);

   // Rotate corners
   if (rotation != 0.0f)
      for (int x = 0; x < 4; x++)
         corner[x].rotateBy(rotation,irr::core::vector2df(rotationPoint.X, rotationPoint.Y));


   // Find the uv coordinates of the sourceRect
   irr::core::vector2df uvCorner[4];
   uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
   uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
   uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,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 = driver->getScreenSize().Width;
   float screenHeight = driver->getScreenSize().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,1);
      vertices[x].TCoords = uvCorner[x];
      vertices[x].Color = color;
   }

   material.Lighting = false;
   material.ZWriteEnable = false;
   material.ZBuffer = false;
   material.TextureLayer[0].Texture = texture;
   material.MaterialTypeParam = irr::video::pack_texureBlendFunc(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;

   driver->setMaterial(material);
   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);
   driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);
}
mrdoubleb
 
Posts: 9
Joined: Tue Apr 12, 2011 1:10 pm

Re: 2D images with rotation

Postby Lonesome Ducky » Wed Oct 12, 2011 7:59 pm

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

cpp Code: Select all
void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect<irr::s32> sourceRect, irr::core::position2d<irr::s32> position, irr::core::position2d<irr::s32> rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color) {
 
        // 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());
 
        // Store and clear the world matrix
        irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);
        driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4());
 
        // Find horizontal and vertical axes after rotation
        irr::f32 c = cos(-rotation*irr::core::DEGTORAD);
        irr::f32 s = sin(-rotation*irr::core::DEGTORAD);
        irr::core::vector2df horizontalAxis(c,s);
        irr::core::vector2df verticalAxis(s,-c);
 
        // First, we'll find the offset of the center and then where the center would be after rotation
        irr::core::vector2df centerOffset(position.X+sourceRect.getWidth()/2.0f*scale.X-rotationPoint.X,position.Y+sourceRect.getHeight()/2.0f*scale.Y-rotationPoint.Y);
        irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis;
        center.X += rotationPoint.X;
        center.Y += rotationPoint.Y;
 
        // Now find the corners based off the center
        irr::core::vector2df cornerOffset(sourceRect.getWidth()*scale.X/2.0f,sourceRect.getHeight()*scale.Y/2.0f);
        verticalAxis *= cornerOffset.Y;
        horizontalAxis *= cornerOffset.X;
        irr::core::vector2df corner[4];
        corner[0] = center + verticalAxis - horizontalAxis;
        corner[1] = center + verticalAxis + horizontalAxis;
        corner[2] = center - verticalAxis - horizontalAxis;
        corner[3] = center - verticalAxis + horizontalAxis;
 
        // Find the uv coordinates of the sourceRect
        irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height);
        irr::core::vector2df uvCorner[4];
        uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y);
        uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y);
        uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y);
        uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y);
        for (irr::s32 i = 0; i < 4; i++)
                uvCorner[i] /= textureSize;
               
        // Vertices for the image
        irr::video::S3DVertex vertices[4];
        irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 };
 
        // Convert pixels to world coordinates
        irr::core::vector2df screenSize(driver->getViewPort().getWidth(), driver->getViewPort().getHeight());
        for (irr::s32 i = 0; i < 4; i++) {
                vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1);
                vertices[i].TCoords = uvCorner[i];
                vertices[i].Color = color;
        }
 
        // Create the material
        // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE:
        // material.BlendOperation = irr::video::EBO_ADD;
        irr::video::SMaterial material;
        material.Lighting = false;
        material.ZWriteEnable = false;
        material.ZBuffer = false;
        material.BackfaceCulling = false;
        material.TextureLayer[0].Texture = texture;
        material.MaterialTypeParam = irr::video::pack_texureBlendFunc(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);
        //material.BlendOperation = irr::video::EBO_ADD;
        if (useAlphaChannel)
                material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND;
        else
                material.MaterialType = irr::video::EMT_SOLID;
 
        driver->setMaterial(material);
        driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2);
 
        // Restore projection, world, and view matrices
        driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat);
        driver->setTransform(irr::video::ETS_VIEW,oldViewMat);
        driver->setTransform(irr::video::ETS_WORLD,oldWorldMat);
}
 
 
User avatar
Lonesome Ducky
Competition winner
 
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Re: 2D images with rotation

Postby SGH » Sat Oct 15, 2011 11:51 pm

Got tired to have a lot of warnings in the console and to have to "using" every namespace. I want to share the final file with you:
cpp Code: Select all
#include <irrlicht.h>
class cImage {
        irr::core::recti ImageRect, OrigImageRect, TextureRect, BoundRect;
        irr::core::position2di RotationPoint;
        irr::f32 Rotation, OldRotation;
        irr::video::ITexture* Texture;
        irr::core::aabbox3df Box;
        irr::video::S3DVertex Vertices[4];
        irr::video::SMaterial Material;
        bool Transparent;
        irr::video::SColor TransColor;
        irr::video::SColor Color;
        irr::core::vector2df Scale;
public:
        cImage(irr::video::ITexture* texture, irr::core::recti nsize, irr::core::recti texpos)
        {
                Color = irr::video::SColor(0,255,255,255);
                Rotation = 0.f;
                OldRotation = 1.f;
                Scale = irr::core::vector2df(1,1);
                Texture = texture;
                Material.Wireframe = false;
                Material.Lighting = false;
                Material.ZBuffer = 0;
                Material.TextureLayer[0].Texture = Texture;
                ImageRect = nsize;
                OrigImageRect = ImageRect;
                TextureRect = texpos;
                irr::core::position2di ulc = texpos.UpperLeftCorner;
                irr::core::position2di lrc = texpos.LowerRightCorner;
                irr::core::dimension2du td = texture->getSize();
 
                Vertices[0] = irr::video::S3DVertex(-0.5,0.5,0, 1,1,0,
                        irr::video::SColor(255,255,255,255), (irr::f32)ulc.X/(irr::f32)td.Width, (irr::f32)ulc.Y/(irr::f32)td.Height);
                Vertices[1] = irr::video::S3DVertex(0.5,0.5,0, 1,0,0,
                        irr::video::SColor(255,255,255,255), (irr::f32)lrc.X/(irr::f32)td.Width, (irr::f32)ulc.Y/(irr::f32)td.Height);
                Vertices[2] = irr::video::S3DVertex(-0.5,-0.5,0, 0,1,1,
                        irr::video::SColor(255,255,255,255), (irr::f32)ulc.X/(irr::f32)td.Width, (irr::f32)lrc.Y/(irr::f32)td.Height);
                Vertices[3] = irr::video::S3DVertex(0.5,-0.5,0, 0,0,1,
                        irr::video::SColor(255,255,255,255), (irr::f32)lrc.X/(irr::f32)td.Width, (irr::f32)lrc.Y/(irr::f32)td.Height);
 
                Box.reset(Vertices[0].Pos);
                for (irr::u32 i=1; i<4; ++i)
                        Box.addInternalPoint(Vertices[i].Pos);
                OrigImageRect = ImageRect;
                switch(texture->getColorFormat())
                {
                case irr::video::ECF_A1R5G5B5:
                case irr::video::ECF_A8R8G8B8:
                case irr::video::ECF_A16B16G16R16F:
                case irr::video::ECF_A32B32G32R32F:
                        this->SetTransparent(true);
                        break;
                default:
                        this->SetTransparent(false);
                        break;
                }
        }
        void Draw(irr::scene::ISceneManager* SceneManager) {
                irr::u16 indices[] = {  0,1,23,2,1};
                irr::video::IVideoDriver* driver = SceneManager->getVideoDriver();
                irr::core::line3df rays[4];
                irr::core::position2di pos[4];
                irr::core::position2di imagpos[4];
                imagpos[0] = ImageRect.UpperLeftCorner;
                imagpos[1] = irr::core::position2di(ImageRect.LowerRightCorner.X, ImageRect.UpperLeftCorner.Y);
                imagpos[2] = irr::core::position2di(ImageRect.UpperLeftCorner.X,ImageRect.LowerRightCorner.Y);
                imagpos[3] = irr::core::position2di(ImageRect.LowerRightCorner);
                irr::f32 gx, gy, lx, ly;
                gx = (irr::f32)imagpos[0].X;
                gy = (irr::f32)imagpos[0].Y;
                lx = (irr::f32)imagpos[0].X;
                ly = (irr::f32)imagpos[0].Y;
                for (irr::u16 x = 0; x < 4; x++) {
                        if (imagpos[x].X > gx)
                                gx = (irr::f32)imagpos[x].X;
                        if (imagpos[x].X < lx)
                                lx = (irr::f32)imagpos[x].X;
                        if (imagpos[x].Y > gy)
                                gy = (irr::f32)imagpos[x].Y;
                        if (imagpos[x].Y < ly)
                                ly = (irr::f32)imagpos[x].Y;
                }
                RotationPoint.X = (irr::s32)(lx+gx)/2;
                RotationPoint.Y = (irr::s32)(ly+gy)/2;         
                irr::f32 angles[4];
                irr::f32 ed[4];
                for (irr::u16 x = 0; x < 4; x++) {
                        angles[x] = atan2((irr::f32)imagpos[x].Y-RotationPoint.Y,(irr::f32)imagpos[x].X-RotationPoint.X);
                        ed[x] = sqrt((irr::f32)((RotationPoint.X-imagpos[x].X)*(RotationPoint.X-imagpos[x].X)) + ((RotationPoint.Y-imagpos[x].Y)*(RotationPoint.Y-imagpos[x].Y)));
                        irr::f32 realang = angles[x] + Rotation*irr::core::DEGTORAD;
                        imagpos[x].X = RotationPoint.X+(irr::s32)(cos(realang)*ed[x]);
                        imagpos[x].Y = RotationPoint.Y+(irr::s32)(sin(realang)*ed[x]);
                }
                gx = (irr::f32)imagpos[0].X;
                gy = (irr::f32)imagpos[0].Y;
                lx = (irr::f32)imagpos[0].X;
                ly = (irr::f32)imagpos[0].Y;
                for (irr::u16 x = 0; x < 4; x++) {
                        if (imagpos[x].X > gx)
                                gx = (irr::f32)imagpos[x].X;
                        if (imagpos[x].X < lx)
                                lx = (irr::f32)imagpos[x].X;
                        if (imagpos[x].Y > gy)
                                gy = (irr::f32)imagpos[x].Y;
                        if (imagpos[x].Y < ly)
                                ly = (irr::f32)imagpos[x].Y;
                }
                BoundRect = irr::core::recti((irr::s32)lx,(irr::s32)ly,(irr::s32)gx,(irr::s32)gy);
                rays[0] = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(imagpos[0],SceneManager->getActiveCamera());
                rays[1] = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(imagpos[1],SceneManager->getActiveCamera());
                rays[2] = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(imagpos[2],SceneManager->getActiveCamera());
                rays[3] = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(imagpos[3],SceneManager->getActiveCamera());
                irr::f32 dist = rays[0].end.getDistanceFrom(SceneManager->getActiveCamera()->getPosition());
                irr::f32 div = dist/((SceneManager->getActiveCamera()->getNearValue()+1)*(SceneManager->getActiveCamera()->getNearValue()+1));         
                for (irr::u16 x = 0; x < 4; x++) {
                        irr::f32 xd,yd,zd;
                        xd = rays[x].end.X - rays[x].start.X;
                        yd = rays[x].end.Y - rays[x].start.Y;
                        zd = rays[x].end.Z - rays[x].start.Z;
 
                        rays[x].start.X += (xd/div);
                        rays[x].start.Y += (yd/div);
                        rays[x].start.Z += (zd/div);
                        Vertices[x].Pos = rays[x].start;
                }
                driver->setMaterial(Material);
                irr::core::matrix4 mat;
                driver->setTransform(irr::video::ETS_WORLD, mat);
                driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);      
        }
        void SetTransparent(bool trans) {
                Transparent = trans;
                if (Transparent)
                        Material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
                else
                        Material.MaterialType = irr::video::EMT_SOLID;
        };
        bool GetTransparent() { return Transparent; };
        void SetTransparentColor(irr::video::SColor trans, irr::video::IVideoDriver *driver) {
                TransColor = trans;
                driver->makeColorKeyTexture(Texture,TransColor);
        };
        void SetPosition(irr::core::position2di newpos) {
                irr::f32 xd, yd;
                xd = irr::f32(newpos.X - ImageRect.UpperLeftCorner.X);
                yd = irr::f32(newpos.Y - ImageRect.UpperLeftCorner.Y);
                ImageRect = irr::core::recti(ImageRect.UpperLeftCorner.X+(irr::s32)xd,ImageRect.UpperLeftCorner.Y+(irr::s32)yd,ImageRect.LowerRightCorner.X+(irr::s32)xd,ImageRect.LowerRightCorner.Y+(irr::s32)yd);
                OrigImageRect = irr::core::recti(OrigImageRect.UpperLeftCorner.X+(irr::s32)xd,OrigImageRect.UpperLeftCorner.Y+(irr::s32)yd,OrigImageRect.LowerRightCorner.X+(irr::s32)xd,OrigImageRect.LowerRightCorner.Y+(irr::s32)yd);       
        }
        void SetColor(irr::video::SColor newc) {
                Color = newc;
                for (irr::u16 x = 0; x < 4; x++) {
                        Vertices[x].Color = Color;
                }
        }
        irr::video::SColor GetColor() { return Color; };
        irr::video::SColor GetTransparentColor() { return TransColor; };
        void SetBilinearFilter(bool on) { Material.TextureLayer[0].BilinearFilter = on; };
        void SetTrilinearFilter(bool on) { Material.TextureLayer[0].TrilinearFilter = on; };
        void SetAnisotropicFilter(bool on) { Material.TextureLayer[0].AnisotropicFilter = on; };
        bool GetBilinearFilter() { return Material.TextureLayer[0].BilinearFilter; };
        bool GetTrilinearFilter() { return Material.TextureLayer[0].TrilinearFilter; };
        bool GetAnisotropicFilter() { return Material.TextureLayer[0].AnisotropicFilter > 0; };
        void SetRotation(irr::f32 newrot) { Rotation = newrot; };
        irr::f32 GetRotation() { return Rotation; };
        int GetWidth() { return ImageRect.UpperLeftCorner.X-ImageRect.LowerRightCorner.X; };
        int GetHeight() { return ImageRect.UpperLeftCorner.Y-ImageRect.LowerRightCorner.Y; };
        int GetOrigWidth() { return OrigImageRect.UpperLeftCorner.X-ImageRect.LowerRightCorner.X; };
        int GetOrigHeight() { return OrigImageRect.UpperLeftCorner.Y-ImageRect.LowerRightCorner.Y; };
        void SetTexture(irr::video::ITexture* tex) { Texture = tex; Material.TextureLayer[0].Texture = Texture; };
        irr::core::recti GetBoundRect() { return BoundRect; };
        void SetScale(irr::core::vector2df news) {
                Scale = news;
                ImageRect = irr::core::recti(OrigImageRect.UpperLeftCorner.X, OrigImageRect.UpperLeftCorner.Y, OrigImageRect.UpperLeftCorner.X+(irr::s32)(this->GetOrigWidth()*news.X), OrigImageRect.UpperLeftCorner.Y+(irr::s32)(this->GetOrigHeight()*news.Y));
        }
        irr::video::ITexture *GetTexture() { return Texture; };
};

I didn't "Fix" the eventual crash, because i don't notice it. Dunno.

EDIT: Damn, didn't notice the second page D: I leave the code in case you want to use it.
SGH
 
Posts: 13
Joined: Wed Aug 24, 2011 2:53 pm

Re: 2D images with rotation

Postby kiel814 » Tue Oct 25, 2011 11:56 pm

I started developing a 2D game and I wanted to flip characters horizontally without having to have 2 images of every character (looking to the right and looking to the left).
I thought that the code in this post would do the trick if I used negative values for the scale.
At first it didn't, but after a simple modification I was able to solve it.
If you are interested, here's the link:
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=45051&p=258661#p258661

Regards!
kiel814
 
Posts: 37
Joined: Mon May 23, 2011 4:30 pm

Re: 2D images with rotation

Postby swesoulc » Sun May 27, 2012 5:28 pm

So i've been having a wee bit of a problem here.
Been folling around with the draw2DImage function here to enhance my sprite animator with.

aaand i got , some kind of anomily happening. it's Always at the same frames.
So what it does is that it draws the square quite allright, the jagged edges i'd assume is from my laptops crappy grapics card ( then again, if i am wrong and that is something that is out of order as well, please do let me know how to adress it ) then on a few frames, it , jumpes sizes. And i will frace myself as that cause it's the best description. Now i've monitored the process and written out all screen cords, all vertices cords, all texture cords on each frame. And the SOB's are always 1-1. As they should. But darnit that dont stop me from seeing with my very eyes that the bloody Y cord likes to skip up a bit. Enough to grab a bit of the next frames texture coordinates.

So, any idea what this might be? I myself will go through the sprite animations code for getting texture co-ords but they have been working perfectly for quite a long while, and the only modification have been the addidtion of the draw2DImage as the primary rendering function. And that was just pasted in and given the needed variables.
Small notes.
i have not specified a camera, mipmap settings have not been set, AA is on. I have had same result with two versions of the draw2DImage , i am now on the latest one you posted.

EDIT

ok so I did some digging and the jaggedness is gone ( a small 1 instead of a 0 at the wrong place as usuall )
but the other problem still lingers. I've gone through each frame size and they are fixed at 100 - 100 px
I've uploaded a small exe to demonstrate my problem.
Last edited by swesoulc on Tue May 29, 2012 11:08 am, edited 1 time in total.
swesoulc
 
Posts: 17
Joined: Tue Apr 03, 2007 10:05 am

Re: 2D images with rotation

Postby CuteAlien » Mon May 28, 2012 2:28 pm

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).
IRC: #irrlicht on irc.freenode.net
Code snippets, patches&stuff: http://www.michaelzeilfelder.de/irrlicht.htm
Free racer created with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
User avatar
CuteAlien
Admin
 
Posts: 8322
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany

PreviousNext

Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 1 guest