Page 1 of 1

Displaying flipped StaticImage.

Posted: Wed Oct 09, 2013 11:05
by Yevgeny
Hello All,

My post is related to CEGUI 0.7.7.
Don't know if this is a frequent problem, but in our project we need to display some pictures with opposite orientation (it's a game battle screen with character icons at the left and mirrored icons at the right). So I used CEGUI layout containing StaticImage's with

Code: Select all

 <Property Name="Rotation" Value="x:0 y:180 z:0" />


It worked fine, but with full set of icons I noticed memory consumption, because, as I understand, CEGUI creates new render-to-texture for each window with "Rotation" property. Moreover, texture dimensions are set to the nearest higher power-of-two, i.e. for the 600x600 pixels window it creates 1024x1024 texture.
To avoid this consumption I wrote a routine, which sets a rotation directly to the window GeometryBuffer, something like this:

Code: Select all

 
void MainMenuWindow::SetStaticImageHorizontalFlip(CEGUI::Window *win, bool flip) {
 
  // Here we determine names of ImageSet and Image of the StaticImage.
  // I use Ogre::StringUtils to parse strings, you can use any other string-processing library.
  std::string set_name, image_name;
  std::string s = win->getProperty("Image").c_str();
  Ogre::StringVector params;
  params = Ogre::StringUtil::split(s, " ");

  Ogre::StringVector subparams;
  subparams = Ogre::StringUtil::split(params[0], ":");
  if (subparams[0] == "set") set_name = subparams[1];
  else if (subparams[0] == "image") image_name = subparams[1];

  subparams = Ogre::StringUtil::split(params[1], ":");
  if (subparams[0] == "set") set_name = subparams[1];
  else if (subparams[0] == "image") image_name = subparams[1];

  // Determine image width (we need it to perform correct transformation).
  CEGUI::Imageset& imageset = CEGUI::ImagesetManager::getSingleton().get(set_name);
  // Why it returns HALF a width?..
  float width = imageset.getImageWidth(image_name) * 2;
 
  // Move pivot to the right, so the image will not go out of clipping area after rotation.
  win->getGeometryBuffer().setPivot(CEGUI::Vector3(width, 0.0f, 0.0f));
 
  // Horizontal flipping is equivalent to 180-degree rotation around Y.
  float angle = flip ? 180.0f : 0.0f;
 // Vector components represent rotation angles in degrees around corresponding axes.
  win->getGeometryBuffer().setRotation(CEGUI::Vector3(0.0f, angle, 0.0f));

}


Of course, it's not a full replacement for the "Rotation" property, because it rotates only an image, not a whole window contents. Also maybe there is a simplier way to manipulate images in latter versions of CEGUI.

Is it correct to do so? Now I'm in doubt, because I read "the content of that(GeometryBuffer) is reset when CEGUI decides that a redraw is needed" on this forum.

Re: Displaying flipped StaticImage.

Posted: Thu Oct 10, 2013 08:04
by Yevgeny
A little correction: I realised that there is no need to get image width, we need to know corresponding window width in pixels. So, the function now looks much simplier:

Code: Select all

void MainMenuWindow::SetStaticImageHorizontalFlip(CEGUI::Window *win, bool flip) {
 
  float width = win->getPixelSize().d_width;
 
  // Move pivot to the center of the window, so the image will not go out of clipping area after rotation.
  win->getGeometryBuffer().setPivot(CEGUI::Vector3(width/2.0f, 0.0f, 0.0f));
 
  // Horizontal flipping is equivalent to 180-degree rotation around Y.
  float angle = flip ? 180.0f : 0.0f;
 // Vector components represent rotation angles in degrees around corresponding axes.
  win->getGeometryBuffer().setRotation(CEGUI::Vector3(0.0f, angle, 0.0f));
}

Re: Displaying flipped StaticImage.

Posted: Thu Oct 10, 2013 09:17
by Kulik
Hi, the reason why we do rotated windows using RTT is clipping. Clipping gets very complex with perspective rotated windows, we would have to use stencil buffer and that would make all renderers more complex. It might happen at some point though.