Game Development Community

Icons that track world objects. Examples?

by Joachim Lous · in Technical Issues · 07/23/2005 (5:26 am) · 3 replies

I need to superimpose 2D icons in the hud, and have them follow the position of static world objects in the scene; sort of like tooltips for world objects, just using bitmaps. Preferably using scripting only.

billboards or particlles won't do: I don't want them scaling with distance,
they should be fixed-size 2D sprites in the HUD.

I've gathered that I probably need to use project()/unproject(), and to get those I need to use the GUI classes. I should probably just do my homework, but I'm a bit pressed for time, and I have a feeling someone must have done this before. Seeing how it's done would save me a bunch of time sorting out all the little problems you tend to encounter along the way when you're a noob like me. Anyone got any pointers?

#1
07/23/2005 (8:09 pm)
GuiShapeNameHud is where you should start. It took me a little under a day to hack in bitmap/icon support for ThinkTanks Xbox.
#2
07/27/2005 (4:30 am)
Turns out I had misunderstood: project/unproject aren't exposed to scripting, so there's no way to do this with scripts by default (except the hard way: doing the whole math in script code, including implementing your own matrix inverter. Not very tempting.).

The good news is that adding scripting support was really easy. To add GameTSCtrl::project and GameTSCtrl::unproject to the console, find engine/game/GameTSCtrl.cc simply add to the end of it something like:

ConsoleMethod( GameTSCtrl, project, const char *, 3, 3, "(Point3F WorldPos")
{
   Point3F src;
   Point3F dst;
   
   dSscanf(argv[2],"%f %f %f",&src.x,&src.y,&src.z);
   object->project(src, &dst);
   char* buff = Con::getReturnBuffer(100);
   dSprintf(buff, 100,"%i %i",(int)(dst.x),(int)(dst.y));
   return buff;
}


ConsoleMethod( GameTSCtrl, unproject, const char *, 3, 3, "(Point2F ScreenPos")
{
   Point3F src;
   Point3F dst;
   
   dSscanf(argv[2],"%f %f",&src.x,&src.y);
   src.z = -1;
   object->unproject(src, &dst);
   char* buff = Con::getReturnBuffer(100);
   dSprintf(buff, 100,"%g %g %g",dst.x,dst.y,dst.z);
   return buff;
}

Caveats:
o This code is not extensively tested; there may well be problems with it. I just wanted to show the general technique .
o I do no checking/odification of the results, so:
- your projected screen position may well be outside the screen if the target is
- if your world point is behind the projection plane "project" will return "0 0", so any such result should be interpreted as invalid.
#3
01/26/2007 (10:25 pm)
Here is my tested version:

ConsoleMethod(GuiTSCtrl, project, const char*, 3, 3, "GuiTSCtrl.project(point3F) returns screen space X,Y and Z for world space point")
{
   const Point3F pt;
   Point3F dest;
   char* destbuf = Con::getReturnBuffer(100);

   dSscanf(argv[2], "%f %f %f", &pt.x, &pt.y, &pt.z);

   object->project(pt, &dest);

   dSprintf(destbuf,sizeof(destbuf),"%i %i",(int)(dest.x),(int)(dest.y));
   return destbuf;
}
ConsoleMethod(GuiTSCtrl, unproject, const char*, 3, 3, "GuiTSCtrl.unproject(point3F) returns world space point for X, Y and Z")
{
   const Point3F pt;
   Point3F dest;
   char* destbuf = Con::getReturnBuffer(100);

   dSscanf(argv[2], "%f %f %f", &pt.x, &pt.y, &pt.z);

   object->unproject(pt, &dest);

   dSprintf(destbuf,sizeof(destbuf),"%g %g %g",dest.x,dest.y,dest.z);
   return destbuf;
}