Game Development Community

dev|Pro Game Development Curriculum

Mission Area Bounds

by Robert Blanchet Jr. · 06/12/2002 (9:57 am) · 32 comments

For some games you may wish to display visually to the player where the mission area begins and ends.

home.attbi.com/~xgalaxy/missionarea.jpg
This code snippet will show you how to do exactly that.

EDIT: As of June 15th I've made some major changes to the code necessary for this code to display properly when hosting both dedicated and non-dedicated servers. The code below reflects those changes.

Open up game.h and add the following:
void GameRenderMissionArea(F32 alpha, bool *sides);

Once that is done open up game.cc.
Add the following after all the includes:
#include "game/missionArea.h"

Now scroll down and find the function GameRenderWorld(). After the following lines:
dglSetCanonicalState();
gClientSceneGraph->renderScene();

Add this:
GameConnection* conn = GameConnection::getServerConnection();
MatrixF cam;
Point3F camPos;
conn->getControlCameraTransform(0,&cam);
cam.getColumn(3, &camPos);

const RectI &area = MissionArea::smMissionArea;
Point2F min(area.point.x, area.point.y);
Point2F max(area.point.x + area.extent.x, area.point.y + area.extent.y);

float distances[4];
distances[0] = camPos.x - min.x;
distances[1] = camPos.y - min.y;
distances[2] = max.x - camPos.x;
distances[3] = max.y - camPos.y;

bool renderSide[4] = {false, false, false, false};
float alpha = 0.0f;
float dist = 400.0f;
bool flag = false;
for(int side = 0; side < 4; side++)
{
   if(distances[side] < 0)
   {
      renderSide[0] = true;
      renderSide[1] = true;
      renderSide[2] = true;
      renderSide[3] = true;
      flag = true;
   }
   else if(distances[side] < 400)
   {
      renderSide[side] = true;
      if(distances[side] < dist)
      {
         dist = distances[side] < dist ? distances[side] : dist;
         alpha = 20/dist > 1.0 ? 1.0 : 20/dist;
      }
   }
   if(flag)
      alpha = 1.0f;
   GameRenderMissionArea(alpha, renderSide);

// rest of function

Ok now after that function add this function:
void GameRenderMissionArea(F32 alpha, bool *sides)
{
   TerrainBlock *terrain = gClientSceneGraph->getCurrentTerrain();  

   if(!terrain)
      return;

   GridSquare *gs = terrain->findSquare(TerrainBlock::BlockShift, Point2I(0,0));
   F32 height = F32(gs->maxHeight) * 0.03124f + 10.f;

   const RectI &area = MissionArea::smMissionArea;
   Point2F min(area.point.x, area.point.y);
   Point2F max(area.point.x + area.extent.x, area.point.y + area.extent.y);

   dglClearBitmapModulation();
   TextureHandle bitMap = TextureHandle("common/ui/grid.png", MeshTexture);
   
   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDisable(GL_LIGHTING);
   glColor4f(1.0, 1.0, 1.0, alpha);
   glEnable(GL_TEXTURE_2D);
   TextureObject* texture = (TextureObject*)bitMap;
   glBindTexture(GL_TEXTURE_2D, texture->texGLName);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   height *= 2;
   if (sides[1])
   {
      glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(0.0,0.0);
      glVertex3f(min.x, min.y, 0);
      glTexCoord2f((max.x - min.x)/5,0);
      glVertex3f(max.x, min.y, 0);
      glTexCoord2f((max.x - min.x)/5, height/5);
      glVertex3f(max.x, min.y, height);
      glTexCoord2f(0,height/5);
      glVertex3f(min.x, min.y, height);
      glEnd();
   }
   if (sides[3])
   {
      glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(0,0);
      glVertex3f(min.x, max.y, 0);
      glTexCoord2f((max.x - min.x)/5,0);
      glVertex3f(max.x, max.y, 0);
      glTexCoord2f((max.x - min.x)/5,height/5);
      glVertex3f(max.x, max.y, height);
      glTexCoord2f(0,height/5);
      glVertex3f(min.x, max.y, height);
      glEnd();
   }
   if (sides[0])
   {
      glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(0,0);
      glVertex3f(min.x, min.y, 0);
      glTexCoord2f((max.y-min.y)/5,0);
      glVertex3f(min.x, max.y, 0);
      glTexCoord2f((max.y-min.y)/5,height/5);
      glVertex3f(min.x, max.y, height);
      glTexCoord2f(0,height/5);
      glVertex3f(min.x, min.y, height);
      glEnd();
   }
   if (sides[2])
   {
      glBegin(GL_TRIANGLE_FAN);
      glTexCoord2f(0,0);
      glVertex3f(max.x, min.y, 0);
      glTexCoord2f((max.y-min.y)/5,0);
      glVertex3f(max.x, max.y, 0);
      glTexCoord2f((max.y-min.y)/5,height/5);
      glVertex3f(max.x, max.y, height);
      glTexCoord2f(0,height/5);
      glVertex3f(max.x, min.y, height);
      glEnd();
   }

   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
}

And there you have it. Just make sure to specify a location of a bitmap otherwise you'll just get the gridlike effect by using the one I gave (which the image doesnt exist I believe).
Page «Previous 1 2
#1
06/12/2002 (12:23 pm)
nevermind looks goood
#2
06/12/2002 (12:55 pm)
There I forgot to add a critical piece lol. Must have accidentally skipped over it.

The changes are in bold.
#3
06/12/2002 (1:25 pm)
had part of the code left in a wrong place :-) mybad
#4
06/12/2002 (1:32 pm)
I dont know why your getting cPanoramaScreenshot errors as my code doesn't even touch that stuff.

As far as GameRenderMissionArea error make sure your adding

void GameRenderMissionArea(F32 alpha, bool* sides);

To game.h right after the line of code that reads:
void GameRenderWorld();
#5
06/12/2002 (2:08 pm)
GameRenderMissionArea MUST BE BEFORE GameRenderWorld
and you need the part added to GameRenderWorld() to end like this:
alpha = 1.0f;
   GameRenderMissionArea(alpha, renderSide);
}
// rest of function
#6
06/12/2002 (2:19 pm)
Very useful addition. Good work!
#7
06/12/2002 (2:52 pm)
never mind except I 'm getting an odd effect from sun flare
#8
06/12/2002 (3:19 pm)
to solve sunflare problem be sure that in GameRenderWorlds() that the grid is rendered first THEN the sunflare
#9
06/12/2002 (6:48 pm)
I was having a problem where it was only drawing one of the mission area walls. I used this code to fix.

if(side == 0)
			{
				 glBegin(GL_TRIANGLE_FAN);
				 glTexCoord2f(0.0,0.0);
				 glVertex3f(min.x, min.y, 0);
				 glTexCoord2f((max.y - min.y)/5,0);
				 glVertex3f(min.x, max.y, 0);
				 glTexCoord2f((max.y - min.y)/5, height/5);
				 glVertex3f(min.x, max.y, height);
				 glTexCoord2f(0,height/5);
				 glVertex3f(min.x, min.y, height);
				 glEnd();
			}
			else if(side == 1)
			{
				 glBegin(GL_TRIANGLE_FAN);
				 glTexCoord2f(0.0,0.0);
				 glVertex3f(min.x, min.y, 0);
				 glTexCoord2f((max.x - min.x)/5,0);
				 glVertex3f(max.x, min.y, 0);
				 glTexCoord2f((max.x - min.x)/5, height/5);
				 glVertex3f(max.x, min.y, height);
				 glTexCoord2f(0,height/5);
				 glVertex3f(min.x, min.y, height);
				 glEnd();
			}
			if(side == 2)
			{
				 glBegin(GL_TRIANGLE_FAN);
				 glTexCoord2f(0.0,0.0);
				 glVertex3f(max.x, min.y, 0);
				 glTexCoord2f((max.y - min.y)/5,0);
				 glVertex3f(max.x, max.y, 0);
				 glTexCoord2f((max.y - min.y)/5, height/5);
				 glVertex3f(max.x, max.y, height);
				 glTexCoord2f(0,height/5);
				 glVertex3f(max.x, min.y, height);
				 glEnd();
			}
			if(side == 3)
			{
				 glBegin(GL_TRIANGLE_FAN);
				 glTexCoord2f(0.0,0.0);
				 glVertex3f(min.x, max.y, 0);
				 glTexCoord2f((max.x - min.x)/5,0);
				 glVertex3f(max.x, max.y, 0);
				 glTexCoord2f((max.x - min.x)/5, height/5);
				 glVertex3f(max.x, max.y, height);
				 glTexCoord2f(0,height/5);
				 glVertex3f(min.x, max.y, height);
				 glEnd();
			}
#10
06/12/2002 (10:00 pm)
Found a very large bug in this code. These functions are run by the server, not the client. This means that if a client connects to a server (not hosting his own server) he cannot see the grid.
#11
06/12/2002 (10:35 pm)
Thats interesting. And looking at it now that actually kind of makes sense..but how do you fix it? lol
I guess you could move the code into function gClientSceneGraph->renderScene() function but that seems kind of like a hack :/
#12
06/12/2002 (11:09 pm)
Would that work? I didnt realise myself until one of my beta testers reported the bug
#13
06/13/2002 (12:07 am)
Hmmm after some further testing. It runs clientside up until this line of code. This is obviously the issue here, how do we get around it?

TerrainBlock *terrain = dynamic_cast<TerrainBlock*>(Sim::findObject("Terrain"));
	if(!terrain)
	   return;
#14
06/13/2002 (7:39 am)
Hmm thats odd. Are you sure that:
MissionArea *missArea = dynamic_cast<MissionArea*>(Sim::findObject("MissionArea"));

isn't a problem as well? Seems like both would be equally of a problem to me :/

In any case try replacing:
TerrainBlock *terrain = dynamic_cast<TerrainBlock*>(Sim::findObject("Terrain"));

with this one instead:
TerrainBlock *terrain = gClientSceneGraph->getCurrentTerrain();

Looks prettier anyway :)
#15
06/13/2002 (2:08 pm)
I replaced it with this and it worked

TerrainBlock * terrain = NULL;
  	for (SimSetIterator itr(conn); *itr && !terrain; ++itr)
  		if ((*itr)->getType() & TerrainObjectType ) terrain = static_cast<TerrainBlock*>(*itr);

BUT

you are correct that this line will not work. Any ideas?

MissionArea *missArea = dynamic_cast<MissionArea*>(Sim::findObject("MissionArea"));
#16
06/14/2002 (1:54 am)
I'd put this code in a different place. I can't remember if sceneRenderImages can only be inserted for shapebase and its derivates but I'd just insert a sceneRenderImage on the missionArea class (and if that can't be done then change the missionArea class to shapebase).

For one thing you wouldn't be loading the texture every single frame and you wouldn't need the terrain at all (just use missionArea.mFlightCeiling for height).

You'd have no problems with making texture loading and area rendering only client side.
#17
06/15/2002 (10:44 am)
"For one thing you wouldn't be loading the texture every single frame and you wouldn't need the terrain at all (just use missionArea.mFlightCeiling for height). "

I don't think you really need to worry about that, because (if I remember correctly) the images are cached in the Res manager.
#18
06/15/2002 (2:36 pm)
Sigh, I'm confused as to why this wont render client side.
#19
06/15/2002 (4:13 pm)
Whoohoo.

Mission accomplished.
I got it to work !! I'm going to completely replace everything up there so watch out :)
#20
06/15/2002 (4:34 pm)
Ok I've reflected all the appropriate changes in the code.

PS:

I just wanted to appologize to everyone for provided a resource that barely worked at best with sloppy code to boot.

Hopefully the changes I've made work both when hosting a non-dedicated game, and in a dedicated -> client model as well.

I've fixed the code sloppyness as well as clean up code that wasn't even supposed to be there.

I've further tested the control both when hosting my own game and when connecting to a dedicated server (on the same machine) and the code has been working in both scenarios unlike before.

Thanks again for being patient.
Page «Previous 1 2