Game Development Community

Stumped: Translating TGE Bitmap Texture alteration -> TSE

by Bryce "Cogburn" Weiner · in Torque Game Engine Advanced · 11/16/2005 (9:39 pm) · 12 replies

I'm working with some OLD TGE code that provides the ability to rotate a bitmap image within the control.

In the old skool, it was done this way:

glBegin(GL_TRIANGLE_FAN);
         glTexCoord2f(texLeft, texBottom);
         glVertex2f(lb.x, lb.y);

         glTexCoord2f(texRight, texBottom);
         glVertex2f(rb.x, rb.y);

         glTexCoord2f(texRight, texTop);
         glVertex2f(rt.x, rt.y);

         glTexCoord2f(texLeft, texTop);
         glVertex2f(lt.x, lt.y);
      glEnd();

For the life of me I cannot find how to duplicate this in TSE.

Any help would be appreciated.

EDIT: This is the original resource I'm working from: www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2387

#1
11/16/2005 (9:44 pm)
Hum maybe you can make a custom material and use this shader command

animFlags[0] = $rotate

Look in the demo at the cube code in the materials.cs file.
#2
11/16/2005 (11:52 pm)
That might be on the right track, but this is not a persistant animation. I would need to be able to say something along the lines of "rotate 15.3 degrees counterclockwise from the current position and stop" and I'm not sure that this method as it is would be sufficent.

This is for a replacement health indicator. It rotates between "alive" and "dead" based on the current health value.

How can you control the shader rotation that precisely?

EDIT: I'm also looking for an example of how to turn a texture into a material programmatically, or at least change the GuiBitmapCtrl to use a material instead of a bitmap...
#3
11/17/2005 (10:07 am)
For a first cut conversion, take a look at the PrimBuild namespace, it'll allow you to basically do a line by line conversion of the gl code above.

Then in the future, if you decide that this is a performance issue, you can convert it to use a static vertex buffer, and pass the rotation amount into a shader to rotate the texture coords.
#4
11/18/2005 (6:34 pm)
PrimBuild was the way to go... I have it working and 99% complete. I do have one problem that is directly related to my C++ noobishness.

new GuiBitmapCtrl(HDisc) {
         profile = "GuiDefaultProfile";
         horizSizing = "width";
         vertSizing = "height";
         position = "0 0";
         extent = "205 205";
         minExtent = "0 0";
         visible = "1";
         bitmap = "./HDisc.png";
         wrap = "0";
         Angle = "0";
         Pivot = "0 0";
      };
      new GuiBitmapCtrl(MDisc) {
         profile = "GuiDefaultProfile";
         horizSizing = "width";
         vertSizing = "height";
         position = "0 0";
         extent = "205 205";
         minExtent = "0 0";
         visible = "1";
         bitmap = "./MDisc.png";
         wrap = "0";
         Angle = "0";
         Pivot = "0 0";
      };
      new GuiBitmapCtrl(RDisc) {
         profile = "GuiDefaultProfile";
         horizSizing = "width";
         vertSizing = "height";
         position = "0 0";
         extent = "205 205";
         minExtent = "0 0";
         visible = "1";
         bitmap = "./RDisc.png";
         wrap = "0";
         Angle = "45";
         Pivot = "0 0";
      };

From the .h file:
/// Renders a bitmap.
class GuiBitmapCtrl : public GuiControl
{

private:
   typedef GuiControl Parent;
   F32     mAngle;
   Point2I mPivot; // relative to the center of the bitmap

Given the above, when I RDisc.setAngle(45), MDisc is the image that is affected. Similarly, when I MDisc.setAngle(45) HDisc is the image affected. When I HDisc.setAngle(45), nothing happens to any BitmapCtrl on the screen.

I'm sure that this is an easy C++ problem, but I'm stumped as to what it is. I guess I COULD work around it, but for my own knowledge I'd like to know what I did wrong.

TIA
#5
11/20/2005 (5:09 pm)
Ok so, I'm an idiot. :)

I wasn't doing a GFX->setTexture and it was using every bitmap on the screen when I added a new control.

Furthermore, I had a leftover GFX->drawBitmapStretch that was rendering ON TOP of the changes, so it looked like the underlying bitmap was being rotated.

Basically, I forgot to remove a line of code and made this more trouble than it should have been. :)
#6
07/05/2006 (12:20 am)
Could anyone explain or provide the resource to rotate a bitmap to use in TSE
#7
07/18/2006 (12:47 pm)
Bump..........
#8
02/13/2007 (5:54 am)
Re-bump

I didn't know I could use shaders on gui objects...
Anyway, i just need it to rotate and would appreciate any code.

This is what I got to draw a target reticule on the screen
void GuiTargetHud::drawTarget(Point2I offset, F32 opacity)
{

   //Used for rotating
   //F32 time = Platform::getVirtualMilliseconds() * 0.001f;

   if (!mTextureObject && mBitmapName && mBitmapName[0])
   {
      mTextureObject.set( mBitmapName, &GFXDefaultGUIProfile);
      if(!mTextureObject)
         return;
   }

   // Center the Image
   offset.x -= (mTextureObject->getWidth() / 2);
   offset.y -= (mTextureObject->getHeight() / 2);

   // Draw it.
   GFX->clearBitmapModulation();
   GFX->drawBitmap(mTextureObject,offset);
   
}

Now I want it to turn around the target...
TIA
#9
02/13/2007 (4:40 pm)
Around the target? Like a hula-hoop?

Why not just create an animated client-side object and mount it to the "targeted" object?
#10
02/14/2007 (12:57 am)
Hehe.... no man, not like a Hula-hoop. It needs to rotate.

I not using Clientside object since I like a bitmap more for this, and I dont want it to resize based on distance.
You said you've done it with the Pimbuilder... Can you please share that piece of code, Bryce?
#11
02/14/2007 (5:32 pm)
This was for a buddy of mine and I can't find the code. I did brush up on the concept enough to point you in the right direction.

Assuming the following: you are creating a "target lock" indicator that will consist of a rotating bitmap image. You're using a GUI element and have already calculated the X & Y coordinates and just need a bit to rotate the image. I'll also assume you're using something like iTicker for controlling the rotation.

PrimBuilder replaces the depreciated vector and color functions that the GL libraries used to provide.

Given the code in the original post, it would look like this:
void GuiBitmapCtrl::setAngle(F32 angle)
{
   mAngle = mFmod( angle, 360.0f );
}

Assuming you've set a pivot point, usually the center of the image... we'll call it mPivot... This goes near the top of your onRender

Point2I half( ( mBounds.extent.x >> 1)  - 1, 
                    ( mBounds.extent.y >> 1 ) - 1 );
      Point2I center( offset.x + half.x - mPivot.x, offset.y + half.y - mPivot.y );
      F32 texLeft   = 0.0f;
      F32 texRight  = 1.0f;
      F32 texTop    = 0.0f;
      F32 texBottom = 1.0f;

      // compute translation coordinate
      Point2F lb_t, rb_t, rt_t, lt_t;
      Point2I lb, rb, rt, lt;

      // left - bottom
      lb_t.x = -half.x + mPivot.x;
      lb_t.y = half.y + mPivot.y;

      // right - bottom
      rb_t.x = half.x + mPivot.x;
      rb_t.y = lb_t.y;

      // right - top
      rt_t.x = rb_t.x;
      rt_t.y = -half.y + mPivot.y;

      // left - top
      lt_t.x = lb_t.x;
      lt_t.y = rt_t.y;

      // rotate the 4 points
      F32 angle( mAngle / 180.0f * M_PI );
      F32 c, s;
      mSinCos( angle, s, c );

      // left - bottom
      lb.x = center.x + lb_t.x * c - lb_t.y * s;
      lb.y = center.y + lb_t.x * s + lb_t.y * c;

      // right - bottom
      rb.x = center.x + rb_t.x * c - rb_t.y * s;
      rb.y = center.y + rb_t.x * s + rb_t.y * c;

      // right - top
      rt.x = center.x + rt_t.x * c - rt_t.y * s;
      rt.y = center.y + rt_t.x * s + rt_t.y * c;

      // left - top
      lt.x = center.x + lt_t.x * c - lt_t.y * s;
      lt.y = center.y + lt_t.x * s + lt_t.y * c;

Now do what ever transformations you need to... and when you're ready to output it looks like this... notice this is the code from the original post above using the PrimBuild namespace functions.

PrimBuild::begin(GFXTriangleFan, 4);

	PrimBuild::texCoord2f(texLeft, texBottom);
	PrimBuild::vertex2f(lb.x,lb.y);
	
	PrimBuild::texCoord2f(texRight, texBottom);
	PrimBuild::vertex2f(rb.x, rb.y);

	PrimBuild::texCoord2f(texRight, texTop);
	PrimBuild::vertex2f(rt.x, rt.y);

	PrimBuild::texCoord2f(texLeft, texTop);
	PrimBuild::vertex2f(lt.x, lt.y);

	PrimBuild::end();

Now all you need are hooks into something like iTicker so you can control the rotation and I think that will work just nicely. :)

Take a look at the original GuiBitmapCtrlEx resource I mentioned and combine that with the info above and I think you'll have what you need.
#12
04/16/2007 (2:05 pm)
Dunno how I missed this post. Thanx Bryce...