Game Development Community

Camera avoiding structures/buildings

by NighTerrorX · in RTS Starter Kit · 10/12/2006 (6:21 am) · 2 replies

Hey guys,

I have tried searching for this, but I am not getting any useful bites -- so I turn to you guys for a some help.

I am trying to make the camera avoid structures/buildings. When the camera comes in contact with a structure it just goes right through it.

Is there a way to prevent this from happening? In my RTS project I am going to have some buildings/structures higher than normal, and cameras going inside the structure is not going to look cool.

Is there a certain type they have to be to prevent this. I am using the default FPS building from the Orc town for my test and the camera still goes through the walls

Sorry if this is a 19 second search...but at the time of writing this the search is a bit off.

Thanks for your help.

#1
10/12/2006 (6:27 am)
Hey, I am rather interested in this too, you could put a collision mesh on the camera object or somthing..
#2
12/07/2006 (1:44 pm)
Here's how I solved this, with a ray cast. This code won't work with the stock RTS kit, but I still thought I'd share it so you at least have an idea. To get it working with the stock kit, you would have to do some minor changes.

In RTSCamera.cc:
validatePoint() -
bool RTSCamera::validatePoint(Point3F pos, bool useEnd, Point3F end)
{
   // What do we want to collide with?
   U32 mask = StaticObjectType |
	          InteriorObjectType |
			  WaterObjectType |
			  ShapeBaseObjectType |
			  StaticShapeObjectType |
			  ItemObjectType |
			  TerrainObjectType |
			  StaticTSObjectType;
   RayInfo rInfo;

   if(!useEnd){
      F32 tempXY = mCos(getPitchAngle()) * mDataBlock->getZoomStep(); // What direction do we cast?
      
      end.x = pos.x + (mCos(getYawAngle() * -1 + M_PI2) * tempXY); // M_PI2 = 1.57079632679489661923 radians = 90 degrees
      end.y = pos.y + (mSin(getYawAngle() * -1 + M_PI2) * tempXY);
      end.z = pos.z - (mSin(getPitchAngle()) * mDataBlock->getZoomStep());

      if(mCurrentContainer->castRay(pos, end, mask, &rInfo))
         return false;

      // We have the front and back collision detected, so now all we need to do is worry about left and right.
      end.x = pos.x + (mSin(getYawAngle() * -1 + M_PI2) * tempXY);
      end.y = pos.y + (mCos(getYawAngle() * -1 + M_PI2) * tempXY);
   }
   if(mCurrentContainer->castRay(pos, end, mask, &rInfo))
      return false;

   return true;
}

I put this code after interpolateTick. Then in RTSCamera.h you need to add:
bool validatePoint(Point3F pos, bool useEnd = false, Point3F end = Point3F(0,0,0));

Then within processTick of RTSCamera.cc, I have (don't replace all of processTick with this, just starting with if(move)):
if (move){
      // Move based on our direction
      F32 tempX, tempY;
      tempX = move->x * TickSec * mDataBlock->getMovementSpeed();
      tempY = move->y * TickSec * mDataBlock->getMovementSpeed();
      mCurrPos.x += ((tempX * mCos(-1 * getYawAngle())) - (tempY * mSin(-1 * getYawAngle())));
      mCurrPos.y += ((tempY * mCos(-1 * getYawAngle())) + (tempX * mSin(-1 * getYawAngle())));

      // Need to use validatePoint two times so that a collision will still be detected when looking straight down.
      if(validatePoint(mCurrPos) && validatePoint(mPrevPos, true, mCurrPos)){

            // Position has changed, cast the ray.
            if(!posDiff && mCurrPos != mPrevPos)
                  castRay();
            mTargetPos = mCurrPos;
         
            // Tell the server what we are doing
            if(isClientObject()){
                  GameConnection *conn = GameConnection::getConnectionToServer();
                  if(conn)
                        conn->postNetEvent(new RTSCameraUpdate(this, false));
            }
      }
      else
            mCurrPos = mTargetPos;
}

Again, you aren't going to be able to just copy and paste, but this should at least give you an idea.

Edit: fixed some formatting issues.