2D image rotation?

Post your questions, suggestions and experiences regarding to Image manipulation, 3d modeling and level editing for the Irrlicht engine here.
Post Reply
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

2D image rotation?

Post by RdR »

Hello,

What is the best and easiest way to rotate and or scale a 2D image?
I want to create a HUD and need to rotate some images on the fly.
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Post by hendu »

By using an image library intended for the purpose, like devil or imlib2 ;)
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Post by RdR »

hendu wrote:By using an image library intended for the purpose, like devil or imlib2 ;)
I dont really want to create more dependencies, is there a good alternative when only using Irrilcht?
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

RdR wrote:is there a good alternative when only using Irrilcht?
Yes. You can create plane and set texture. You can rotate plane, zooming is also will be a piece of cake if you use perspective camera. You should draw this UI after your main "smgr->drawAll()" call, to make UI to be always on top of 3d objects.
Last edited by greenya on Mon Apr 11, 2011 1:42 am, edited 1 time in total.
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Post by RdR »

greenya wrote:
RdR wrote:is there a good alternative when only using Irrilcht?
Yes. You can create plane and set texture. You can rotate place, zooming is also will be a piece of cake if you use perspective camera. You should draw this UI after your main "smgr->drawAll()" call, to make UI to be always on top of 3d objects.
Thanks for your comment, but do you have a simple example?
cobra
Posts: 371
Joined: Fri Jan 23, 2009 2:56 am
Location: United States
Contact:

Post by cobra »

I believe this is under the zlib license.

Code: Select all

// draw2DImage source from Lonesome Ducky
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.
   //material.TextureLayer[0].TextureWrapU = irr::video::ETC_CLAMP;
   //material.TextureLayer[0].TextureWrapV = 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);

} 
Josiah Hartzell
Image
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Post by RdR »

Thanks cobra, I used this function instead because the above function had a weird problem aswell.

Somehow it looks like its behind everything in the world.
Here some screenshots:

Image

If I look a bit up, so there is nothing between de camera and the image it looks good:
Image

If I draw a normal 2D image using driver->draw2DImage() ( which I cant rotate ), everything works fine.[/url]
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Post by shadowslair »

You need to draw the turret image after drawing the terrain. If you need to draw another turret over this one, you need to draw it after etc. In this case the draw call sequence matters.
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Post by RdR »

shadowslair wrote:You need to draw the turret image after drawing the terrain. If you need to draw another turret over this one, you need to draw it after etc. In this case the draw call sequence matters.
I am, else the other 2D images won't be visible right?
I'm drawing all the 2D images (not visible in this screenshot) after the terrain, and everything is displayed correctly except the one which i'm trying to rotate (with the above function)

Edit:
The right image is using the standard draw2Image() method, they are both drawed at the same time (same method)
Image
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

Sorry for the very late reply, but you should make it completely disregard the zbuffer. Here's the updated code:

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);
}
RdR
Competition winner
Posts: 273
Joined: Tue Mar 29, 2011 2:58 pm
Contact:

Post by RdR »

Lonesome Ducky, thanks!
Disableing Zbuffer did the trick 8)
Post Reply