(C++) draw2DImage with rotation (OpenGL)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Andi|xng
Posts: 83
Joined: Thu Mar 24, 2005 10:49 pm
Location: Schrobenhausen, Germany
Contact:

(C++) draw2DImage with rotation (OpenGL)

Post by Andi|xng »

Since I [got no answer] if this here is also the right place for suggestions how to improve the Irrlicht engine itself, I use this forum now to share a method with you that I have written for my game.

It is an improvement of the draw2DImage-method, that allows also rotation. Since I only use OpenGL, I have only written it for the COpenGLDriver:

Code: Select all

//rotation is given in radians, clockwise.

void COpenGLDriver::draw2DImageRotation(video::ITexture* texture, const core::rect<s32>& destRect, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, const f32 rotation, SColor color, bool useAlphaChannelOfTexture) 
{ 
  
   if (!texture) 
      return; 

   core::rect<s32> trgRect=destRect; 
   core::rect<s32> srcRect=sourceRect; 

   core::dimension2d<s32> currentRendertargetSize = getCurrentRenderTargetSize();
   const core::dimension2d<s32> targetSurfaceSize=currentRendertargetSize; 

   const core::dimension2d<s32> ss = texture->getOriginalSize(); 
   float ssw=1.0f/ss.Width; 
   float ssh=1.0f/ss.Height; 

   core::rect<f32> tcoords; 
   tcoords.UpperLeftCorner.X = (((f32)srcRect.UpperLeftCorner.X)+0.5f) * ssw ;
   tcoords.UpperLeftCorner.Y = (((f32)srcRect.UpperLeftCorner.Y)+0.5f) * ssh; 
   tcoords.LowerRightCorner.X = (((f32)srcRect.UpperLeftCorner.X +0.5f + (f32)srcRect.getWidth())) * ssw; 
   tcoords.LowerRightCorner.Y = (((f32)srcRect.UpperLeftCorner.Y +0.5f + (f32)srcRect.getHeight())) * ssh; 

   s32 xPlus = -(currentRendertargetSize.Width>>1); 
   f32 xFact = 1.0f / (currentRendertargetSize.Width>>1); 

   s32 yPlus = currentRendertargetSize.Height-(currentRendertargetSize.Height>>1); 
   f32 yFact = 1.0f / (currentRendertargetSize.Height>>1); 

   //rotate the points
   //center point
   float cx = (trgRect.UpperLeftCorner.X + trgRect.LowerRightCorner.X) / 2;
   float cy = (trgRect.UpperLeftCorner.Y + trgRect.LowerRightCorner.Y) / 2;
   //rotate x axis
   float cosr = cos(rotation);
   float sinr = sin(rotation);
   float x_x = cosr * (trgRect.LowerRightCorner.X - cx);
   float x_y = sinr * (trgRect.LowerRightCorner.X - cx);
   //rotate y axis
   float y_x = sinr * (trgRect.LowerRightCorner.Y - cy);
   float y_y = cosr * (trgRect.LowerRightCorner.Y - cy);
   //points
   float p1x = cx - x_x + y_x; float p1y = cy - x_y - y_y;
   float p2x = cx + x_x + y_x; float p2y = cy + x_y - y_y;
   float p3x = cx + x_x - y_x; float p3y = cy + x_y + y_y;
   float p4x = cx - x_x - y_x; float p4y = cy - x_y + y_y;
   //transform points
   p1x = (p1x + xPlus + 0.5f) * xFact;
   p1y = (yPlus - p1y + 0.5f) * yFact; 
   p2x = (p2x + xPlus + 0.5f) * xFact;
   p2y = (yPlus - p2y + 0.5f) * yFact;
   p3x = (p3x + xPlus + 0.5f) * xFact;
   p3y = (yPlus - p3y + 0.5f) * yFact;
   p4x = (p4x + xPlus + 0.5f) * xFact;
   p4y = (yPlus - p4y + 0.5f) * yFact;


   setTexture(0, texture);    

   if (useAlphaChannelOfTexture) 
      setRenderStates2DMode(false, true, true); 
   else 
      setRenderStates2DMode(false, true, false); 

   bool bTempColors=false;
   

   glBegin(GL_QUADS); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); 
   glVertex2f(p1x, p1y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); 
   glVertex2f(p2x, p2y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); 
   glVertex2f(p3x, p3y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
   glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); 
   glVertex2f(p4x, p4y);

   glEnd(); 

}
Andi|xng
Posts: 83
Joined: Thu Mar 24, 2005 10:49 pm
Location: Schrobenhausen, Germany
Contact:

Post by Andi|xng »

And here is an extension that rotates the image not around its center point, but around the given point rotationPos:

Code: Select all

void COpenGLDriver::draw2DImageRotation(video::ITexture* texture, const core::rect<s32>& destRect, 
                   const core::rect<s32>& sourceRect, const core::position2d<s32>& rotationPos, 
                   const f32 rotation, SColor color, bool useAlphaChannelOfTexture) 
{ 
  
   if (!texture) 
      return; 

   core::rect<s32> trgRect=destRect; 
   core::rect<s32> srcRect=sourceRect; 

   core::dimension2d<s32> currentRendertargetSize = getCurrentRenderTargetSize();
   const core::dimension2d<s32> targetSurfaceSize=currentRendertargetSize; 

   const core::dimension2d<s32> ss = texture->getOriginalSize(); 
   float ssw=1.0f/ss.Width; 
   float ssh=1.0f/ss.Height; 

   core::rect<f32> tcoords; 
   tcoords.UpperLeftCorner.X = (((f32)srcRect.UpperLeftCorner.X)+0.5f) * ssw ;
   tcoords.UpperLeftCorner.Y = (((f32)srcRect.UpperLeftCorner.Y)+0.5f) * ssh; 
   tcoords.LowerRightCorner.X = (((f32)srcRect.UpperLeftCorner.X +0.5f + (f32)srcRect.getWidth())) * ssw; 
   tcoords.LowerRightCorner.Y = (((f32)srcRect.UpperLeftCorner.Y +0.5f + (f32)srcRect.getHeight())) * ssh; 

   s32 xPlus = -(currentRendertargetSize.Width>>1); 
   f32 xFact = 1.0f / (currentRendertargetSize.Width>>1); 

   s32 yPlus = currentRendertargetSize.Height-(currentRendertargetSize.Height>>1); 
   f32 yFact = 1.0f / (currentRendertargetSize.Height>>1); 

   //ANDI: rotate the points
   float cosr = cos(rotation);
   float sinr = sin(rotation);
   //points
   float p1x = cosr * (trgRect.UpperLeftCorner.X - rotationPos.X) -
     sinr * (trgRect.UpperLeftCorner.Y - rotationPos.Y) + rotationPos.X;
   float p1y = sinr * (trgRect.UpperLeftCorner.X - rotationPos.X) +
     cosr * (trgRect.UpperLeftCorner.Y - rotationPos.Y) + rotationPos.Y;
   float p2x = cosr * (trgRect.LowerRightCorner.X - rotationPos.X) -
     sinr * (trgRect.UpperLeftCorner.Y - rotationPos.Y) + rotationPos.X;
   float p2y = sinr * (trgRect.LowerRightCorner.X - rotationPos.X) +
     cosr * (trgRect.UpperLeftCorner.Y - rotationPos.Y) + rotationPos.Y;
   float p3x = cosr * (trgRect.LowerRightCorner.X - rotationPos.X) -
     sinr * (trgRect.LowerRightCorner.Y - rotationPos.Y) + rotationPos.X;
   float p3y = sinr * (trgRect.LowerRightCorner.X - rotationPos.X) +
     cosr * (trgRect.LowerRightCorner.Y - rotationPos.Y) + rotationPos.Y;
   float p4x = cosr * (trgRect.UpperLeftCorner.X - rotationPos.X) -
     sinr * (trgRect.LowerRightCorner.Y - rotationPos.Y) + rotationPos.X;
   float p4y = sinr * (trgRect.UpperLeftCorner.X - rotationPos.X) +
     cosr * (trgRect.LowerRightCorner.Y - rotationPos.Y) + rotationPos.Y;
   //transform points
   p1x = (p1x + xPlus + 0.5f) * xFact;
   p1y = (yPlus - p1y + 0.5f) * yFact; 
   p2x = (p2x + xPlus + 0.5f) * xFact;
   p2y = (yPlus - p2y + 0.5f) * yFact;
   p3x = (p3x + xPlus + 0.5f) * xFact;
   p3y = (yPlus - p3y + 0.5f) * yFact;
   p4x = (p4x + xPlus + 0.5f) * xFact;
   p4y = (yPlus - p4y + 0.5f) * yFact;


   setTexture(0, texture);    

   if (useAlphaChannelOfTexture) 
      setRenderStates2DMode(false, true, true); 
   else 
      setRenderStates2DMode(false, true, false); 

   bool bTempColors=false;
   

   glBegin(GL_QUADS); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); 
   glVertex2f(p1x, p1y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); 
   glVertex2f(p2x, p2y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); 
   glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); 
   glVertex2f(p3x, p3y); 

   glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
   glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); 
   glVertex2f(p4x, p4y);

   glEnd(); 

}
Sinsemilla

OpenGL class?

Post by Sinsemilla »

Hi

you wrote that only for the COpenGL class like i see. Can you show a way how to implement this in the main function? which means how to make it work from when everything is wrote in irr namespace?

many thanks for future reply
Sinsemilla

COpenGLDriver class

Post by Sinsemilla »

sorry its COpenGLDriver class.
Andi|xng
Posts: 83
Joined: Thu Mar 24, 2005 10:49 pm
Location: Schrobenhausen, Germany
Contact:

Re: COpenGLDriver class

Post by Andi|xng »

I declared the function of course also in the super class (I think it is the null device class), so it is always visible. The directx "implementation" is simply empty and does nothing.
Post Reply