Game Development Community

dev|Pro Game Development Curriculum

FuelOMeter, SpeedOMeter like control

by Frank Bignone · 05/13/2002 (10:54 am) · 20 comments

Download Code File

[EDIT]
Here is the latest zip file www.darkhand.dnsalias.com/files/code/meters.zip
[/EDIT]

Here is a simple new control for all of those are working with vehicles : whatever o meter (speed, fuel, throttle, ...).

First, you need to download the code provided and :
- put the file guiMeter.cc & guiMeter.h in your gui directory.
- put the file dgl.cc & dgl.h in your engine/dgl directory (I have modified the dglDrawBitmapRotated func)

Then you can add the following control in your GUI:
new GuiMeterCtrl() {
      profile = "GuiDefaultProfile";
      horizSizing = "relative";
      vertSizing = "relative";
      position = "349 120";
      extent = "83 81";
      minExtent = "8 8";
      visible = "1";
      helpTag = "0";
      lockMouse = "0";
      bitmap = "~/fuel/panel.png";
      wrap = "0";
      spinBitmap = "~/fuel/spin.png";
      color = "1.000000 1.000000 1.000000 1.000000";
      angle = "50";
      spinAngle = "0.000000 180.000000";
      spinOffset = "2.000000 3.000000";
   };

In the zip file, I put the panel.png & spin.png file. Be careful that the spin.png file should have a square size.

The important vars & funcs are :
- bitmap : frame of your speedometer
- spinBitmap : the nice arrow
- spinAngle : range of the arrow
- spinOffset : offset for the rotation
- setAngle(val) : set the angle of rotation relative to angular range ( 0 <= val <= 100)

That's all folks

About the author

Real programmers don't waste time recompiling; they patch the binary files... ... Real programmers don't waste time patching binary files; they patch memory.


#1
05/08/2002 (6:53 am)
Ugly picture..... should not have been resized as it was smaller than what is required.

BTW, change dlg.cc (line 218 to 240) by the following code. It will allow rectangular image for the rotation and also it applies the offset where it should.

Point2F screenPoint(X,Y); 

   F32 width = dstRect.extent.x;
   width *= 0.5;
	F32 height = dstRect.extent.y;
	height *= 0.5;

   MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );

   Point3F offset( screenPoint.x+spinOffset.x, screenPoint.y+spinOffset.y, 0.0 );
   Point3F points[4];
   
   points[0] = Point3F(-width, -height, 0.0);
   points[1] = Point3F(-width,  height, 0.0);
   points[2] = Point3F( width,  height, 0.0);
   points[3] = Point3F( width, -height, 0.0);

   for( int i=0; i<4; i++ )
   {
      rotMatrix.mulP( points[i] );
      points[i] += offset;
   }

   glBegin(GL_TRIANGLE_FAN);

Another point, your arrow picture should have the rotation point exactly at the center of the image (center of rotation) (which is not the case in the pic I provided :()
#2
05/13/2002 (4:23 pm)
OK, I've finally figured it out. You guys DON'T WANT me to release my next BETA version of TubettiWorld, right ? That's why you keep popping up with these yummy new little (and big) features to distract me from my mission. I agree with Melvyn. It's a conspiracy !

:-)

Oh yes: nice control there, Frank. Well done ! I'll add it to my shopping cart...
#3
05/14/2002 (10:40 am)
I want to try out tubetti world! you say there's a beta? :))

Phil.
#4
05/14/2002 (7:41 pm)
Yes Phil. We have 28 people in closed BETA, currently at v1.2. After I throw 1.3 BETA over the wall at that lunging, snapping and growling pack of testers, then I will be adding more people. I'll let you know when the time comes.

I'm planning that for BETA 1.5 (mid to late summer) to throw the closed doors open briefly to GG people only, to stress the higher level game management parts...
#5
05/15/2002 (3:56 pm)
the zip isnt working
#6
05/16/2002 (2:27 am)
I have put another zip file with latest code in it.
#7
05/16/2002 (6:56 am)
thanks
#8
06/21/2002 (7:24 am)
both links are dead???!!
#9
06/21/2002 (7:29 am)
i will check my computer tonight. It may have reboot ;)
#10
06/21/2002 (7:36 am)
my wife reboot my computer, should work now.
#11
06/21/2002 (7:38 am)
OMG, that was fast!!! Thanks a lot, Frank! :-))
#12
10/28/2002 (10:41 am)
I have installed it. I see the meter and spin object but I just cannot figure how to make it rotate with the speed. Any tips ? :) Thanks
#13
10/29/2002 (10:56 pm)
Send me an email to explain exactly what you want at sage-team@wanadoo.fr, and I will try to help you.
#14
09/07/2005 (5:53 pm)
only the original distrib.zip link is working.. the latest one is dead link.... any way to get that fixed?
#15
12/21/2005 (4:07 am)
Great job !! With this exemple I manage to begin program with torque !!
#16
02/04/2006 (12:18 pm)
So anyone got this resource to work with TGE 1.4?
#17
03/21/2006 (8:56 am)
#18
10/13/2006 (11:16 pm)
Just got it going in Torque 1.4
Instead of replacing the files dgl.cc and dgl.h, just add the following code.

In dgl.h insert the following above all the #if statements
#ifndef _MPOINT_H_
#include "math/mPoint.h"
#endif

Again in dgl.h, insert the following dec after the void dglDrawBitmap dec.
void dglDrawBitmapRotated(TextureObject *texObject,
                          const RectI&   in_rStretch,
                            const RectI&   in_rSubRegion,
                            const U32      in_flip = GFlip_None,
                            const F32 spinAngle = 0.0f,
							const Point2F spinOffset = Point2F(0,0) );

In dgl.cc, insert the following function after the dglDrawBitmap function.
void dglDrawBitmapRotated(TextureObject *texture,const RectI& dstRect,const RectI& srcRect,const U32 in_flip,F32 spinAngle, const Point2F spinOffset)
{
   AssertFatal(texture != NULL, "GSurface::drawBitmapStretchSR: NULL Handle");
   if(!dstRect.isValidRect())
      return;
   AssertFatal(srcRect.isValidRect() == true,
               "GSurface::drawBitmapRotated: routines assume normal rects");

   glEnable(GL_TEXTURE_2D);
   glBindTexture(GL_TEXTURE_2D, texture->texGLName);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   glDisable(GL_LIGHTING);

   F32 texLeft   = F32(srcRect.point.x)                    / F32(texture->texWidth);
   F32 texRight  = F32(srcRect.point.x + srcRect.extent.x) / F32(texture->texWidth);
   F32 texTop    = F32(srcRect.point.y)                    / F32(texture->texHeight);
   F32 texBottom = F32(srcRect.point.y + srcRect.extent.y) / F32(texture->texHeight);

   F32 screenLeft   = dstRect.point.x;
   F32 screenRight  = dstRect.point.x + dstRect.extent.x;
   F32 screenTop    = dstRect.point.y;
   F32 screenBottom = dstRect.point.y + dstRect.extent.y;

   if(in_flip & GFlip_X)
   {
      F32 temp = texLeft;
      texLeft = texRight;
      texRight = temp;
   }
   if(in_flip & GFlip_Y)
   {
      F32 temp = texTop;
      texTop = texBottom;
      texBottom = temp;
   }
   
   glColor4ub(sg_bitmapModulation.red,
             sg_bitmapModulation.green,
             sg_bitmapModulation.blue,
             sg_bitmapModulation.alpha);
  
   F32 X = 0;

   // calculate the centroid of the rectangle (to use as rotation pivot)
   if (screenLeft < screenRight)
   {
        X = screenLeft + ((screenRight - screenLeft)*0.5f);
   }
   else
   {
        X = screenRight + ((screenLeft - screenRight)*0.5f);
   };

   F32 Y = 0;

   if (screenTop < screenBottom)
   {
        Y = screenTop + ((screenBottom - screenTop)*0.5f);
   }
   else
   {
        Y = screenBottom + ((screenTop - screenBottom)*0.5f);
   };
   
   // spin angle is in degree's so convert to radians..radians = degrees * pi /180
   spinAngle = spinAngle * 3.14 / 180.0f;

   Point2F screenPoint(X,Y); 

   F32 width = dstRect.extent.x;
   width *= 0.5;

   MatrixF rotMatrix( EulerF( 0.0, 0.0, spinAngle ) );

   Point3F offset( screenPoint.x, screenPoint.y, 0.0 );
   Point3F points[4];
   
   points[0] = Point3F(-width+spinOffset.x, -width+spinOffset.y, 0.0);
   points[1] = Point3F(-width+spinOffset.x,  width+spinOffset.y, 0.0);
   points[2] = Point3F( width+spinOffset.x,  width+spinOffset.y, 0.0);
   points[3] = Point3F( width+spinOffset.x, -width+spinOffset.y, 0.0);

   for( int i=0; i<4; i++ )
   {
      rotMatrix.mulP( points[i] );
      points[i] += offset;
   }

   glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(texLeft,texTop);
      glVertex2fv(points[0]);

      glTexCoord2f(texLeft, texBottom);
      glVertex2fv(points[1]);

      glTexCoord2f(texRight, texBottom);
      glVertex2fv(points[2]);

      glTexCoord2f(texRight, texTop);
      glVertex2fv(points[3]);
   glEnd();
   
      
   /*
   glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(0.0, 0.0);
      glVertex2fv(points[0]);

      glTexCoord2f(0.0, 1.0);
      glVertex2fv(points[1]);

      glTexCoord2f(1.0, 1.0);
      glVertex2fv(points[2]);

      glTexCoord2f(1.0, 0.0);
      glVertex2fv(points[3]);
   glEnd();
*/


   glDisable(GL_BLEND);
   glDisable(GL_TEXTURE_2D);



}

in guiMeterCtrl.h change the line
#include "gui/guiBitmapCtrl.h"
to
#include "gui/controls/guiBitmapCtrl.h"

Import the guiMeterCtrl.cc and guiMeterCtrl.h into your compiler and recompile.

All you have to do then in create your guiMeterCtrl in your Gui and set the relevant file paths for the bitmaps.

All seems to work fine.
Great little control.
May use it to make a checkpoint arrow that points contantly towards the next checkpoint.
Nice work Frank Bignone.
:+}

NOTE: If you don't put the guiMeterCtrl.cc and guiMeterCtrl.h in the engine/gui folder you will need to change the following line in guiMeterCtrl.cc to correct the path.
#include "gui/guiMeterCtrl.h"
I put mine the the engine/gui/controls folder so changed it to the following.
#include "gui/controls/guiMeterCtrl.h"
#19
08/09/2008 (8:41 pm)
@Frank: Hey the link to the latest code is broken. Any chance you could put it back up somewhere? E-:
#20
12/05/2010 (4:04 pm)
Hey Frank,there are some differencies campared to TGE (despite the fact that I have never worked with TGE),I had to swap the vertex positions:

points[0] = Point3F(-width, -height, 0.0); 
points[1] = Point3F( width, -height, 0.0);
points[2] = Point3F(-width,  height, 0.0);  
points[3] = Point3F( width,  height, 0.0);

Thanks for this resource.