Game Development Community

dev|Pro Game Development Curriculum

Advanced Camera

by Thomas \"Man of Ice\" Lund · 04/03/2008 (11:57 am) · 480 comments

Download Code File

Description
Over time a lot of people have released camera resources, but some do not work anymore, others are hard to implement etc.

I've tried to assemble a single class to add to the engine that implements them all in one go using the same basic architecture. This enables minimum code bloat and makes it way easier to keep the code up to date.

Change log
March 3rd, 2005
Manoel made some changes to the orbit camera. Works in multiplayer now and is much nicer by using console variables

February 3rd, 2005
Fixed small big in interpolation.

February 2nd, 2005
Major changes in this one with various contributors.
* Static camera mode
* Smooth interpolation and transition between modes
* Smooth orbit camera!!!
* Vertical freedom mode when in 3rd person
* Better collision check with terrain and interiors
* Mouse control of orbit camera
* Totally reworked codebase and lots of cleanups. Much more readable now

Manoel Neto contributed the new orbit camera and the interpolation
Zik Saleeba contributed the vertical freedom mode and better collision check

Thanks a lot!!!!

I have marked changes with a New in the text below for those who upgrade

January 23rd, 2005
Minor changes. Larger update soon with new functionality
* Now takes GameBase objects as target + player
* Removed debug message in orbit camera
* Added getters for player and target object

June 25th, 2004
Updated the bindings for orbit camera. Switched left+right.

June 23rd, 2004
A big thanks to Stephen Zepp for contributing with an orbit camera mode. Its added to the resource, and is perfect for RTS games and action adventures. It allows for a camera to rotate around a user as if placed on a sphere. The user can zoom in/out, rotate and tilt the camera.

June 9th, 2004
Added getter/setter for the 3 offset values accessible from script
Added a "follow terrain" mode for the third person camera, so the camera follows the terrain slope - doesnt work perfectly

April 5th, 2004
All camera modes now use a raycast to not get hidden behind terrain or interiors

April 3rd, 2004
This release is the first release, and might not be as "advanced" as the author would like, but its time to release it and get some feedback to further enhance it down the road.

Camera Modes Implemented
The resource currently implements the following camera systems:
* Track Mode
This is the same as the tracking camera resource posted by Cory Osborn. A stationary camera tracks the player and keeps him in focus.

* New Static Mode
Camera stays in its position and rotation. Useful for e.g. scene based adventures where the camera doesnt move with the players

* Third Person Mode
The camera is placed at an offset behind the player and rotates with the player. The camera itself is not controllable

* Third Person Track Mode
The camera is placed in third person mode but rotated so it always looks at a specified object, but with the player in full view

* God View
Camera is placed at an offset from the player and does not rotate with the player. This is your typical "Diablo" kind of camera.

* New Orbit Mode
Camera is placed on a sphere looking at the player, and can rotate/tilt and zoom controlled by the player. There are bindings to the mouse when in single player game (server and client on same machine)

Movie
Here is a small movie displaying the different camera modes (3 MB)
www.codejar.com/advancedcamerademo.wmv

How to Add
First off all you need to take the attached advancedCamera.cc/h files and add to engine\game and add them to the project.

Then you need to expose the camera object in GameConnection as described in Cory's resource www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4720

I took the liberty to paste the relevant parts in here too

Exposing mCameraObject
The first thing you want to do is add console method's to access the GameConnection setCameraObject/getCameraObject methods. I added these to GameConnection.cc right after the console method for getControlObject:

ConsoleMethod( GameConnection, setCameraObject, bool, 3, 3, "(ShapeBase object)")
{
   ShapeBase *gb;
   if(!Sim::findObject(argv[2], gb))
      return false;

   object->setCameraObject(gb);
   return true;
}

ConsoleMethod( GameConnection, getCameraObject, S32, 2, 2, "")
{
   argv;
   SimObject* cp = object->getCameraObject();
   return cp ? cp->getId(): 0;
}

ConsoleMethod( GameConnection, clearCameraObject, void, 2, 2, "")
{
   object->setCameraObject(NULL);
}

After playing around with it, I also found you need some adjustments to the setCameraObject and setControlObject methods - otherwise the client connection can screw things up if you bounce the same object from your connection's control to camera or vice versa. Here is my GameConnection::setControlObject:

void GameConnection::setControlObject(ShapeBase *obj)
{
   if(mControlObject == obj)
      return;

   if(mControlObject && mControlObject != mCameraObject) 
      mControlObject->setControllingClient(0);
   
   if(obj)
   {
      // Nothing else is permitted to control this object.
      if (ShapeBase* coo = obj->getControllingObject())
         coo->setControlObject(0);
      if (GameConnection *con = obj->getControllingClient()) 
      {
         if (this != con) 
         {
            // was it controlled via camera or control?
            if (con->getControlObject() == obj)
               con->setControlObject(0);
            else
               con->setCameraObject(0);
         }
      }

      // We are now the controlling client of this object.
      obj->setControllingClient(this);
   }

   // Okay, set our control object.
   mControlObject = obj;
   if (mCameraObject.isNull())
      setScopeObject(mControlObject);
}


and here is my GameConnection::setCameraObject:

void GameConnection::setCameraObject(ShapeBase *obj)
{
   if(mCameraObject == obj)
      return;

   if(mCameraObject && mCameraObject != mControlObject) 
      mCameraObject->setControllingClient(0);
   
   if (obj) {
      // Nothing else is permitted to control this object.
      if (ShapeBase* coo = obj->getControllingObject())
         coo->setControlObject(0);
      if (GameConnection *con = obj->getControllingClient()) 
      {
         if (this != con) 
         {
            // was it controlled via camera or control?
            if (con->getControlObject() == obj)
               con->setControlObject(0);
            else
               con->setCameraObject(0);
         }
      }

      // We are now the controlling client of this object.
      obj->setControllingClient(this);
   }

   // Okay, set our camera object.

   mCameraObject = obj;

   if (mCameraObject.isNull()) {
      setScopeObject(mControlObject);
   } else {
      setScopeObject(mCameraObject);
      // if this is a client then set the fov and active image
      if(isServerConnection())
      {
         F32 fov = mCameraObject->getDefaultCameraFov();
         GameSetCameraFov(fov);
      }
   }
}

Camera read/write packets
None of this will work unless the client copy of the camera object gets packets updated. Here we're going to modify GameConnection::readPacket and GameConnection::writePacket.

In GameConnection::readPacket, find this block of code:

if (bstream->readFlag())
      {
         S32 gIndex = bstream->readInt(10);
         ShapeBase* obj = static_cast<ShapeBase*>(resolveGhost(gIndex));
         setCameraObject(obj);
      }
      else
         setCameraObject(0);

and change it to

if (bstream->readFlag()) 
      {
         S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
         ShapeBase* obj = static_cast<ShapeBase*>(resolveGhost(gIndex));
         setCameraObject(obj);
         obj->readPacketData(this, bstream);
      }
      else
         setCameraObject(0);


In GameConnection::writePacket, find this block of code:

if (!mCameraObject.isNull() && mCameraObject != mControlObject)
      {
         gIndex = getGhostIndex(mCameraObject);
         if (bstream->writeFlag(gIndex != -1))
            bstream->writeInt(gIndex, 10);
      }
      else
         bstream->writeFlag( false );

and change it to:

if (!mCameraObject.isNull() && mCameraObject != mControlObject) 
      {
         gIndex = getGhostIndex(mCameraObject);
         if (bstream->writeFlag(gIndex != -1)) {
            bstream->writeInt(gIndex, NetConnection::GhostIdBitSize);
            mCameraObject->writePacketData(this, bstream);
         }
      }
      else
         bstream->writeFlag( false );

Recompile it all and the engine is ready to go.

Script

To use the camera you need to follow some of Corys resource, but with some modifications. Datablock and naming has changed

First, add a datablock for the tracking camera to /fps/server/scripts/camera.cs:

...
datablock AdvancedCameraData(AdvCameraData)
{
   lookAtOffset = "0 0 2";
   thirdPersonOffset = "0 -3 3";
   godViewOffset = "0 -20 20";
   maxTerrainDiff = 2;
   orbitMinMaxZoom = "5 100";
   orbitMinMaxDeclination = "10 80";
   damping = 0.25;

};
...

Next, add it to the connection just like is currently done with the base camera class. Add this inside GameConnection::onClientEnterGame (/fps/server/scripts/game.cs), right after %this.camera is set up:

...
   // create advanced camera
      %this.advCamera = new AdvancedCamera() {
      dataBlock = AdvCameraData;
   };
   MissionCleanup.add(%this.advCamera);
   %this.advCamera.scopeToClient(%this);
...


We'll need to clean it up after the client leaves the game, so add this to GameConnection::onClientLeaveGame

...
   if (isObject(%this.advCamera))

      %this.advCamera.delete();
...


We need to tell it what to do when added and assign the connection's camera object, so add this to the end of GameConnection::createPlayer:

...
  // We set the camera system to run in 3rd person mode around the %player
  %this.advCamera.setPlayerObject(%player);
  %this.advCamera.setThirdPersonMode();
  %this.advCamera.setFollowTerrainMode(false);
  %this.advCamera.setVerticalFreedomMode(false);
  %this.setCameraObject(%this.advCamera);
...


And we'll want to unhook it when the player dies. Insert this at the beginning of GameConnection::onDeath:

...
   // clear connections camera
   %this.advCamera.clearPlayerObject();
   %this.advCamera.clearTargetObject();
   %this.clearCameraObject();
...

The last thing to know, is if you're in first-person mode, GameConnection automatically uses the control object to render the engine rather than the camera object. So if you don't see this working when you first enter a mission, toggle out of first-person.

Orbit mode
To use the orbit camera, one needs to add some key binds to manipulating the camera.

All you need to do, is add the following to your client\config.cs or better to your client\scripts\default.bind.cs

//------------------------------------------------------------------------------
// Advanced Camera Movement
//------------------------------------------------------------------------------

$cameraYawSpeed = -100.0;
$cameraPitchSpeed = -50.0;
$cameraZoomSpeed = -5.0;

function rotateCameraHorizontal(%val)
{
     $advCamera::Yaw = getMouseAdjustAmount(%val)*$cameraYawSpeed ;
}

function rotateCameraVertical(%val)
{
     $advCamera::Pitch = getMouseAdjustAmount(%val)*$cameraPitchSpeed;
}

function zoomCamera(%val)
{
     $advCamera::Zoom = getMouseAdjustAmount(%val)*$cameraZoomSpeed;
}

moveMap.bind( mouse, xaxis, rotateCameraHorizontal);
moveMap.bind( mouse, yaxis, rotateCameraVertical );
moveMap.bind( mouse, zaxis, zoomCamera );

Remember to comment out the mouse commands for the player movement, as these are overwritten by the orbit camera controls
//moveMap.bind( mouse, xaxis, yaw );
//moveMap.bind( mouse, yaxis, pitch );

Script API
To use the different camera modes you can use the following API
Selecting the camera mode is done with e.g.:
%this.advCamera.setTrackMode();
  %this.advCamera.setThirdPersonMode();
  %this.advCamera.setThirdPersonTargetMode();
  %this.advCamera.setGodViewMode();
  %this.advCamera.setOrbitMode();
  %this.advCamera.setStaticMode();

Prior to calling the above modes you have to set the PlayerObject using
setPlayerObject();

To use the 3rd person target mode you also need to set a TargetObject using
setTargetObject();

To use the static or tracking camera you need to set the position the camera should be placed suing
setCameraPosition(Point3F pos);

To use the follow terrain mode in 3rd person you give a bool to
setFollowTerrainMode(true/false);

To use the vertical freedom mode in 3rd person you give a bool to
setVerticalFreedomMode(true/false);
This only works if the player object is a Player, because it uses the head movement.

The offset values in the datablock can be changed for the camera object via script using
get/setLookAtOffset();
get/setThirdPersonOffset();
get/setGodViewOffset();
The setters take a Point3F as argument.

The orbit camera can be manipulated from script using
get/setOrbitMinMaxZoom()
get/setOrbitMinMaxDeclination()
The min/max take a Point2F

You can also manipulate the orbit camera directly by assigning values to the following variables
[code]
$advCamera::Yaw
$advCamera::Pitch
$advCamera::Zoom
$advCamera::azimuth
$advCamera::declination
$advCamera::zoomDistance
[code]

All camera modes coexist, so you can set the position, player object and target object once and then switch camera modes around as you see fit. Switching mode will not clear the old objects/positions.
#361
04/16/2007 (1:03 pm)
have you included the 2 camera files to your project properly and recompiled? If you did, try a full recompile.
#362
04/16/2007 (3:03 pm)
I forgot to copy the new .exe file to my work game folder. But here is a question how do I change the thirdPersonOffset when the game is running. Like I have few view that I want the player to be able to change in the game. Like a side view and a top down view.
#363
04/16/2007 (3:05 pm)
One way is to use the

get/setThirdPersonOffset();

script commands.
#364
04/16/2007 (3:46 pm)
OK here is what I have:

function SideView(%this)
{
%this.advCamera.setThirdPersonOffset("0 0 0");
}

and

moveMap.bind( keyboard, v, SideView);

but this dose not work.
#365
04/23/2007 (7:42 am)
If you're still having problems compiling, make sure that you aren't duplicating the methods:

ConsoleMethod( GameConnection, setCameraObject
ConsoleMethod( GameConnection, getCameraObject
ConsoleMethod( GameConnection, clearCameraObject

These have already been added to the gameconnection.cc at the bottom of the file.

The rest of the changes have already been made in 1.5 and 1.5.1. Just add the advanced camera files to the project and recompile, the rest is scripting. I just did another test with 1.5.1 and it works fine. 1.5 compiled fine as well, I didn't try out the scripting, but I see no reason why that shouldn't work as well.
#366
04/24/2007 (2:27 pm)
Thanks @Anderson.

I was duplicating these files you mentioned.

But now works great.

Works with TGEA too.

Thanks again.
#367
04/25/2007 (1:10 pm)
I have a problem here :(

Everything works fine but I can't control the camera in orbit mode...

My mouse don't affect the camera rotation.

Any help?
#368
05/01/2007 (12:22 pm)
Are you having problems with the adv camera in 1.5 or TGEA?
#369
05/02/2007 (7:16 am)
In both :(

But I just aready got it work. I just downloaded again the files and recompile. Works great. Verry odd.

Thanks.
#370
05/17/2007 (6:35 am)
Great Thomas! Thanks for the great stuff
#371
05/20/2007 (9:15 am)
Im using the GodViewMode camera from this resource however the camera is miles away from the character. I can change the rotation but how do I change the distance?
#372
05/23/2007 (1:34 am)
I'm having the same problem with Orbit mode as Outline above in 1.5. Orbit mode is acting more like the Diablo style camera for me. Anyone have any ideas?
#373
05/23/2007 (5:20 am)
@Andrew

I don't know exactly what I did... I just downloaded again the resource files and recompiled everthing. Works fine now with TGE1.5 and TGEA.
#374
05/23/2007 (7:22 am)
We have created a nice version of this camera code using the orbit code as our base. It's a 3rd person view, and in this view you can rotate around the character holding your right mouse button. You can also zoom in and out by scrolling. When you start walking, the camera will follow you nicely and also move back to behind the player if it wasn't allready. If people are interrested i'm willing to share. However keep in mind that by creating this, we didnt "worry" about torque multiplayer and networking issues. Our game runs loopback on the client and will connect to a seperate server with a costum TCPObject class. When you are creating something similar or just singleplayer.. this code will work great.
#375
05/23/2007 (8:12 am)
Hey Man! I'm working in a singleplayer game and I think your camera core could be very interesting.

I've implemented advanced camera but I don't have this "auto-back-smoothly-positioning" thing. It's more like a Zelda camera system and it's great!!!

Can you share it with me please?

Thanks in advance =D
#376
05/23/2007 (8:22 am)
Yes, i have received some emails about it to so i will go ahead and post it when i'm ready.

"I will add some comments to the source and look for all the changes we made (also to the script-base). It's a little more complated for us since we changed so much to the engine that we're using nothing but the rendering really. We are trying to get rid of the scripts completely. But anyway, i will try to get everything togetter and post it. It will also benefit us when people find improvements for it hopefully"
#377
05/24/2007 (5:35 am)
Thanks Robin!!!
#378
05/26/2007 (10:27 am)
(Robin Degen)

This sounds like somthing similar to what I am currently trying to do. I am looking for away to get the camera to rotate so that it is following the player when the player is moving.

i.e. you can freely rotate the camera but when you start to move the camera will rotate slowly to face the direction you are moving in.

I would be intrested to see how you whent about smothly adjusting the camera to move back behind the player.
#379
05/27/2007 (3:56 am)
The basic idea is that i use GuiShapeNameHud for the mouse "detection" by using onRightMouseUp, onRightMouseDown and onRightMouseDragged. And a couple of globals to pass that on to advancedcamera.cc. Because we are only working loopback or singleplayer in a way.. we dont have to worry about networking or other players so globals work fine.

In the advanced camera i got rid of nearly all console methods and added a 2, called ZoomIn and ZoomOut. I bound those to the scrollwheel.

This code is for our Alpha version of the game and offcourse by any means not final. But it does work and might give people a nice idea to improve it. I would really appreciate it if people can help us improve it aswell.

Here's our case OrbitMode in AdvancedCamera::interpolateTick and our defines and globals in that file. (I used that idea from a few posts above about moving it from processTick).

//Advanced Camera, based on code from Thomas "Man of Ice" Lund.
//----------------------------------------------------------------------------
// New Camera mode by Robin 'DGM' Degen and 'Captnoord'.
// This code is part of the Scattered Lands project
// See www.scatteredlands.com
// Do not use this without permission.
//
//----------------------------------------------------------------------------
// Make sure the script uses only the Orbit camera before using!
//----------------------------------------------------------------------------
// We are not responsible how this code works on any other computer
// then our own. Nor that it will compile on any other source-base 
// then our own. 
// We are also not responsible for any harm that it might cause.

#define ZOOM_MIN_DISTANCE 3
#define ZOOM_MAX_DISTANCE 30
// view defines
#define VIEW_MIN_ANGLE 2.5
#define VIEW_MAX_ANGLE 0.18
#define VIEW_VERTICAL_SPEED 100
#define VIEW_HORIZONTAL_SPEED 150
// Player defines
#define PLAYER_ROT_SPEED M_PI/500
#define PLAYER_CAM_HYS PLAYER_ROT_SPEED //0.1f

//For movement.
F32 MoveX=0;
F32 MoveY=0;
F32 ZoomDist=10;
bool CameraIsMoving=false;

case OrbitMode :
		{
			// Capt:
			// orbin mode:
			// these have 2 settings
			// 1. normal orbit mode, related to movement and stuff like that
			// 2. manual orbital view
			// these mode's are switched automaticly

			if ( playerObj != NULL)
			{
				Point3F mConvertedOrbitOffset;
				F32 mOffsetX;
				F32 mOffsetY;
				F32 mOffsetZ;

				MatrixF objToWorld = playerObj->getRenderTransform();
				objToWorld.mulP(mCurrentOrbitOffset, &cameraPosWorld);
				

				if((MoveX == 0) && (MoveY == 0))
				{
					//If the client isn't rotating and the player is walking
					//Move back to the "PlayerRot" setpoint slowly
					if(CameraIsMoving)
					{
						Player*	playerObjAsPlayer =	dynamic_cast<Player*>(playerObj);			
						Point3F	HeadRotation = playerObjAsPlayer->getRotation();

						// check for overflow
						if (mAzimuth > 2 * M_PI)
							mAzimuth -= 2 * M_PI;
						else if (mAzimuth < 0)
							mAzimuth += 2*M_PI;

						// Get the current cam offset related to the view orientation and the player orientation
						F32 CamOffset = mAzimuth - ((-HeadRotation.z) + (1.5 * M_PI));

						// here is where the magic happens
//Move back to behind the player... This is a constant speed for now..
						if (CamOffset > PLAYER_CAM_HYS && !(CamOffset > M_PI))
							mAzimuth = mAzimuth - PLAYER_ROT_SPEED;

						if (CamOffset < -PLAYER_CAM_HYS || CamOffset > M_PI)
							mAzimuth = mAzimuth + PLAYER_ROT_SPEED;
					}
				}else{
					//Vertical
					mDeclination = mDeclination - (MoveY/VIEW_VERTICAL_SPEED);

					//Horizontal
					mAzimuth = mAzimuth - (MoveX/VIEW_HORIZONTAL_SPEED);

					if(mAzimuth > 2 * M_PI)
					{
						mAzimuth = mAzimuth - 2 * M_PI;
					}
					else if(mAzimuth < 0)
					{
						mAzimuth = 2 * M_PI + mAzimuth;
					}

					//Limit the rotations and zooming
					if(mDeclination > VIEW_MIN_ANGLE)
						mDeclination = VIEW_MIN_ANGLE;

					if(mDeclination < VIEW_MAX_ANGLE)
						mDeclination = VIEW_MAX_ANGLE;
				}

				if(ZoomDist < ZOOM_MIN_DISTANCE)
					ZoomDist = ZOOM_MIN_DISTANCE;

				if(ZoomDist > ZOOM_MAX_DISTANCE)
					ZoomDist = ZOOM_MAX_DISTANCE;

				// use spherical to cartesian coord transforms to calculate offset
				mOffsetX = ZoomDist * sin(mDeclination) * cos(mAzimuth);
				mOffsetY = ZoomDist * sin(mDeclination) * sin(mAzimuth);
				mOffsetZ = ZoomDist * cos(mDeclination);

				mConvertedOrbitOffset.set(mOffsetX, mOffsetY, mOffsetZ);
				cameraPosWorld += mConvertedOrbitOffset;
			}
			break;
		}

ConsoleMethod( AdvancedCamera, ZoomIn, bool, 1, 1, "()") {   
	ZoomDist = ZoomDist - 1; //Make something smoother later
	return true;
}

ConsoleMethod( AdvancedCamera, ZoomOut, bool, 1, 1, "()") {   
	ZoomDist = ZoomDist + 1;
	return true;
}

And here's our GuiShapeNameHud

extern F32 MoveX;
extern F32 MoveY;
extern bool CameraIsMoving;

F32 mX=0;
F32 mY=0;

void GuiShapeNameHud::onRightMouseDragged(const GuiEvent &event)
{
	Point2I MousePos;

	MousePos.x = mX;
	MousePos.y = mY;
	
	MoveX = event.mousePoint.x - mX;
	MoveY = event.mousePoint.y - mY;

	Canvas->setCursorPos(MousePos);
}

void GuiShapeNameHud::onRightMouseDown(const GuiEvent &evt)
{
	Canvas->showCursor(false);
	mX = evt.mousePoint.x;
	mY = evt.mousePoint.y;

	CameraIsMoving = false;
}

void GuiShapeNameHud::onRightMouseUp(const GuiEvent &evt)
{
	Point2I MousePos;

	MoveX = 0;
	MoveY = 0;

	MousePos.x = mX;
	MousePos.y = mY;

	CameraIsMoving = true;

	Canvas->setCursorPos(MousePos);

	Canvas->showCursor(true);
}

Basicly what i'm doing in GuiShapeNameHud is when the user holds the right mousebutton and moves it.. the mousecursor will hide and keep moving back to where the user first held his mouse down. Then by looking only at the difference between the 2 points, we get an idea of how fast the mouse is moving. When the user releases the right mousebutton again, the mouse will be in the same position as where he first pressed it. Offcourse it's unhidden again when he does.

We are using this togetter with a click-to-walk resource somewhere else on here that we modified a little but it should work the same.

So yea.. bring the suggestions in :)
#380
05/27/2007 (6:48 am)
Got a nasty block of errors when compiling first time round, any ideas on how to fix this up?

c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C2556: 'S32 cGameConnectionsetCameraObject(GameConnection *,S32,const char **)' : overloaded function differs only by return type from 'bool cGameConnectionsetCameraObject(GameConnection *,S32,const char **)'
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'cGameConnectionsetCameraObject'
c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C2371: 'cGameConnectionsetCameraObject' : redefinition; different basic types
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'cGameConnectionsetCameraObject'
c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C2556: 'S32 cGameConnectionsetCameraObjectcaster(SimObject *,S32,const char **)' : overloaded function differs only by return type from 'bool cGameConnectionsetCameraObjectcaster(SimObject *,S32,const char **)'
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'cGameConnectionsetCameraObjectcaster'
c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C2371: 'cGameConnectionsetCameraObjectcaster' : redefinition; different basic types
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'cGameConnectionsetCameraObjectcaster'
c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C3861: 'cGameConnectionsetCameraObject': identifier not found
c:\torque\sdk\engine\game\gameconnection.cc(1505) : error C2374: 'GameConnectionsetCameraObjectobj' : redefinition; multiple initialization
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'GameConnectionsetCameraObjectobj'
c:\torque\sdk\engine\game\gameconnection.cc(1506) : error C2556: 'S32 cGameConnectionsetCameraObject(GameConnection *,S32,const char **)' : overloaded function differs only by return type from 'bool cGameConnectionsetCameraObject(GameConnection *,S32,const char **)'
        c:\torque\sdk\engine\game\gameconnection.cc(1291) : see declaration of 'cGameConnectionsetCameraObject'
c:\torque\sdk\engine\game\gameconnection.cc(1515) : error C2084: function 'S32 cGameConnectiongetCameraObjectcaster(SimObject *,S32,const char **)' already has a body
        c:\torque\sdk\engine\game\gameconnection.cc(1301) : see previous definition of 'cGameConnectiongetCameraObjectcaster'
c:\torque\sdk\engine\game\gameconnection.cc(1515) : error C2374: 'GameConnectiongetCameraObjectobj' : redefinition; multiple initialization
        c:\torque\sdk\engine\game\gameconnection.cc(1301) : see declaration of 'GameConnectiongetCameraObjectobj'
c:\torque\sdk\engine\game\gameconnection.cc(1516) : error C2084: function 'S32 cGameConnectiongetCameraObject(GameConnection *,S32,const char **)' already has a body
        c:\torque\sdk\engine\game\gameconnection.cc(1301) : see previous definition of 'cGameConnectiongetCameraObject'
c:\torque\sdk\engine\game\gameconnection.cc(1521) : error C2084: function 'void cGameConnectionclearCameraObjectcaster(SimObject *,S32,const char **)' already has a body
        c:\torque\sdk\engine\game\gameconnection.cc(1308) : see previous definition of 'cGameConnectionclearCameraObjectcaster'
c:\torque\sdk\engine\game\gameconnection.cc(1521) : error C2374: 'GameConnectionclearCameraObjectobj' : redefinition; multiple initialization
        c:\torque\sdk\engine\game\gameconnection.cc(1308) : see declaration of 'GameConnectionclearCameraObjectobj'
c:\torque\sdk\engine\game\gameconnection.cc(1522) : error C2084: function 'void cGameConnectionclearCameraObject(GameConnection *,S32,const char **)' already has a body
        c:\torque\sdk\engine\game\gameconnection.cc(1308) : see previous definition of 'cGameConnectionclearCameraObject'