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:
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:
and here is my GameConnection::setCameraObject:
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:
and change it to
In GameConnection::writePacket, find this block of code:
and change it to:
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:
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:
We'll need to clean it up after the client leaves the game, so add this to GameConnection::onClientLeaveGame
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:
And we'll want to unhook it when the player dies. Insert this at the beginning of GameConnection::onDeath:
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
Remember to comment out the mouse commands for the player movement, as these are overwritten by the orbit camera controls
Script API
To use the different camera modes you can use the following API
Selecting the camera mode is done with e.g.:
Prior to calling the above modes you have to set the PlayerObject using
To use the 3rd person target mode you also need to set a TargetObject using
To use the static or tracking camera you need to set the position the camera should be placed suing
To use the follow terrain mode in 3rd person you give a bool to
To use the vertical freedom mode in 3rd person you give a bool to
The offset values in the datablock can be changed for the camera object via script using
The orbit camera can be manipulated from script using
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.
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.
#122
...
collector.demo/server/scripts/camera.cs (0): Unable to instantiate non-conobject class AdvancedCameraData.
...
...
collector.demo/server/scripts/game.cs (215): Unable to instantiate non-conobject class AdvancedCamera.
Set::add: Object "0" doesn't exist
collector.demo/server/scripts/game.cs (217): Unable to find object: '0' attempting to call function 'scopeToClient'
collector.demo/server/scripts/game.cs (332): Unable to find object: '0' attempting to call function 'setPlayerObject'
collector.demo/server/scripts/game.cs (333): Unable to find object: '0' attempting to call function 'setThirdPersonMode'
collector.demo/server/scripts/game.cs (334): Unable to find object: '0' attempting to call function 'setFollowTerrainMode'
collector.demo/server/scripts/game.cs (335): Unable to find object: '0' attempting to call function 'setVerticalFreedomMode'
collector.demo/server/scripts/game.cs (336): Unknown command setCameraObject.
Object LocalClientConnection(1452) GameConnection -> NetConnection -> SimGroup -> SimSet -> SimObject
...
So there you have it. I am at my wits end here. If someone knows whats going on or can point me in the right direction or can sympathize feel free.
_Adam_
04/27/2005 (3:13 pm)
Hey. Yeah, i noticed no one responded to my post, and I had taken a break from the camera frustration. Unfortunately it is integral to the action game I am attempting to make so here it goes. I started with a fresh copy of the starter.fps and added all the code you said to, where you said to (i think). And I go to run it and nada. I am using version 1.3 of Torque. The log said this pertaining to the advCamera:...
collector.demo/server/scripts/camera.cs (0): Unable to instantiate non-conobject class AdvancedCameraData.
...
...
collector.demo/server/scripts/game.cs (215): Unable to instantiate non-conobject class AdvancedCamera.
Set::add: Object "0" doesn't exist
collector.demo/server/scripts/game.cs (217): Unable to find object: '0' attempting to call function 'scopeToClient'
collector.demo/server/scripts/game.cs (332): Unable to find object: '0' attempting to call function 'setPlayerObject'
collector.demo/server/scripts/game.cs (333): Unable to find object: '0' attempting to call function 'setThirdPersonMode'
collector.demo/server/scripts/game.cs (334): Unable to find object: '0' attempting to call function 'setFollowTerrainMode'
collector.demo/server/scripts/game.cs (335): Unable to find object: '0' attempting to call function 'setVerticalFreedomMode'
collector.demo/server/scripts/game.cs (336): Unknown command setCameraObject.
Object LocalClientConnection(1452) GameConnection -> NetConnection -> SimGroup -> SimSet -> SimObject
...
So there you have it. I am at my wits end here. If someone knows whats going on or can point me in the right direction or can sympathize feel free.
_Adam_
#123
The usual cause to this error message is, that you copied in the files but didnt add them to your project. Thus they didnt get compiled into the engine and the script cannot instantiate something that is not present
Check your project tree to add the files!
04/27/2005 (11:18 pm)
Hey AdamThe usual cause to this error message is, that you copied in the files but didnt add them to your project. Thus they didnt get compiled into the engine and the script cannot instantiate something that is not present
Check your project tree to add the files!
#124
Alright. I did have the files added to the project and compiled. But i was an idiot and didn't realize that you needed to run the torqueDemo_DEBUG.exe instead of the normal one. I feel like such a dumba$$.
04/28/2005 (11:25 am)
Thanks for the quick reply, Thomas. I thought i had added them to the VC7 solution, but I will go back and make sure they are there. Thanks again.Alright. I did have the files added to the project and compiled. But i was an idiot and didn't realize that you needed to run the torqueDemo_DEBUG.exe instead of the normal one. I feel like such a dumba$$.
#125
05/03/2005 (10:38 am)
Got this up and running, works great, thanks, but when i switch between objects the camera is tracking the cammera seems to roll over look up at the sky then switch, any idea what causes that and how i might fix it. I dont need transitions, would rather just have it switch instantly.
#126
Synapse Lighting Pack Beta 1.3.5
and the Torque Build Environment. Not VC7
Thanks
Thomas Cory, Adam and Harold. Reading and Re reading
convinced me this was possible.
Surge of MDNAMEDIA.com
05/17/2005 (8:41 pm)
This Worked For Me!!!Synapse Lighting Pack Beta 1.3.5
and the Torque Build Environment. Not VC7
Thanks
Thomas Cory, Adam and Harold. Reading and Re reading
convinced me this was possible.
Surge of MDNAMEDIA.com
#127
05/22/2005 (6:56 pm)
What advantage does this 3rd person camera have over the default stock 3rd person camera?
#128
05/22/2005 (10:40 pm)
@Chris: main advantage is that the position of the camera is controlled via script where the default one is controlled via nodes in the model. This makes it very hard to modify and adjust the camera ingame and/or dynamic.
#129
There are basically 3 cases for the camera, when it is inside a brush, when it is on a brush plane, and when it is outside a brush.
The problem was partially solved with a ray being cast from the player (plus the offset) to the camera and then determining if it was inside the brush. It is then offset from the collision point to put it back in a safe position.
The problem is that castRay appears to return false if you are on the brush plane and not technically inside of it. Since sitting on the brush plane is just as bad as being in a brush this is what needed to be addressed.
My fix seems to handle all cases because of the following:
The case where the camera is inside a brush is already taken care of with cast ray.
As far as I know we cant test for being on the brush plane or that would be the ideal condition to test for.
The player is always in a safe position (or should be) so moving the camera toward the player will always move the camera nearer to a safe position.
This makes the worst case scenario that the camera is sitting on a brush plane.
If we ALWAYS offset the camera towards the player when it has been determined that it is not inside a brush we can guarantee that it will be off the plane into a safe position.
The drawback of this is that the CurrentLookAtOffset that you define is never exactly what you set it to be. It will always that offset and the value set by DISTANCE_FROM_COLLISION that determines the final camera position, regardless if you are on a brush plane or not. In my opinion this is a small price to pay for the huge gain of not ending up looking at the exteriors.
Anyways onto the code. In the function AdvancedCamera::runCameraCollisionCheck in advancedCamera.cc change this:
to this:
I have tested this fairly extensively with the 3rd person camera and some fairly detailed interiors with lots of rooms. I have not tested the other camera modes though.
05/23/2005 (3:19 pm)
So I implemented the advanced camera resource yesterday and went about fixing the problem where the camera would draw the exterior outside of an interior.There are basically 3 cases for the camera, when it is inside a brush, when it is on a brush plane, and when it is outside a brush.
The problem was partially solved with a ray being cast from the player (plus the offset) to the camera and then determining if it was inside the brush. It is then offset from the collision point to put it back in a safe position.
The problem is that castRay appears to return false if you are on the brush plane and not technically inside of it. Since sitting on the brush plane is just as bad as being in a brush this is what needed to be addressed.
My fix seems to handle all cases because of the following:
The case where the camera is inside a brush is already taken care of with cast ray.
As far as I know we cant test for being on the brush plane or that would be the ideal condition to test for.
The player is always in a safe position (or should be) so moving the camera toward the player will always move the camera nearer to a safe position.
This makes the worst case scenario that the camera is sitting on a brush plane.
If we ALWAYS offset the camera towards the player when it has been determined that it is not inside a brush we can guarantee that it will be off the plane into a safe position.
The drawback of this is that the CurrentLookAtOffset that you define is never exactly what you set it to be. It will always that offset and the value set by DISTANCE_FROM_COLLISION that determines the final camera position, regardless if you are on a brush plane or not. In my opinion this is a small price to pay for the huge gain of not ending up looking at the exteriors.
Anyways onto the code. In the function AdvancedCamera::runCameraCollisionCheck in advancedCamera.cc change this:
// Cast ray and check for collision with terrain and interiors
if (!gClientContainer.castRay(startpos + mCurrentLookAtOffset, endpos, mask, &collisionInfo)) {
// No collision, so return endpos
return endpos;
}to this:
// Cast ray and check for collision with terrain and interiors
if (!gClientContainer.castRay(startpos + mCurrentLookAtOffset, endpos, mask, &collisionInfo))
{
// No collision, but we offset anyway because we could be on the brush plane
Point3F LookDir = startpos + mCurrentLookAtOffset - endpos;
LookDir.normalize();
Point3F AntiClippingOffset = LookDir * DISTANCE_FROM_COLLISION;
return endpos + AntiClippingOffset;
}I have tested this fairly extensively with the 3rd person camera and some fairly detailed interiors with lots of rooms. I have not tested the other camera modes though.
#130
any thoughts on how to correct this?
I imagine anyone who is using the unproject to find coordinates on the screen for an RTS style game would be having the same problem?
I will keep digging into it, but it may be beyond my current skill level.
As near as I can tell the story is that unproject is an OpenGL function that uses the current viewpoint as the source of the unproject. GUIControl stores this information in 3 Arrays of OpenGL doubles, and GameTSCtrl inherits it. However, how that information is updated is beyond me...
whoops... GUITSCtrl stores it, and then GameTSCTrl inherits it...
05/31/2005 (4:38 pm)
I am having a little difficulty with the camera. I am firing a projectile along a vector from the muzzlpoint to a point in the world where the cursor is located. I use the unproject function, and it works perfectly in 1st Person. The projectile strikes the mouse tip every time at any range, on any surface. However, when I switch to the camera's 3rd person mode, the unproject becomes innacurate. It gets worse the more the camera is offset from the first person POV, and is increased even more at the edges and corners of the screen.any thoughts on how to correct this?
I imagine anyone who is using the unproject to find coordinates on the screen for an RTS style game would be having the same problem?
I will keep digging into it, but it may be beyond my current skill level.
As near as I can tell the story is that unproject is an OpenGL function that uses the current viewpoint as the source of the unproject. GUIControl stores this information in 3 Arrays of OpenGL doubles, and GameTSCtrl inherits it. However, how that information is updated is beyond me...
whoops... GUITSCtrl stores it, and then GameTSCTrl inherits it...
#131
The bit I am having trouble with is once the tut starts talking about script API? The resource starts off hot for a beginner and then just drops you in the shit!
06/03/2005 (12:47 am)
Has anyone had any recent success with this? I can compile it no worries but nothing changes... Its a real bummer cos it looks sweet!The bit I am having trouble with is once the tut starts talking about script API? The resource starts off hot for a beginner and then just drops you in the shit!
#132
I got this to work about 2 weeks ago. Did you switch out of first person mode?
06/03/2005 (7:41 am)
@EuanI got this to work about 2 weeks ago. Did you switch out of first person mode?
#133
I had a similiar problem to this, where mouse picking with the advanced camera would get weird as the mouse got further from the player. I noticed this specifically when I would zoom out a lot and try to mouse pick. From what I remember, the problem in my build was the zoom functionality. I customized a lot of things in the advanced camera, though, so I'm not sure if this will apply to your build, but I'll briefly outline my problem anyway in case it helps.
What was happening was my server and client positions of the adv camera were off. The zoom values, controlled by the user, were being reflected and viewed on the client, but not being updated on the server. Then, in server updates, the server would send a new zoom or position value that would overwrite the client. The result was basically, the client looked normal still, but the server was overwriting key values with outdated information. Since the mouse picking code (based on the GG resource) uses server values to function, I was getting bad mouse picking results. The solution was to just cut off those server updates. I figured the camera is kind of like a predicted control object, so the client should have the authoritative decision anyway.
@All,
I made a little script to get around the snag of switching from the advanced camera to the free flying TGE cam.
What this basically does is, if you set the control object to the player, it will turn on the advanced camera. If you set the control object to something else (like the flying camera via alt-c) it will turn off the advanced camera. You could probably customize it some more to do what you need.
In /server/scripts/game.cs, at the end of the file:
In gameConnection.cc, where the other adv camera changes are:
06/03/2005 (8:34 am)
@Brent:I had a similiar problem to this, where mouse picking with the advanced camera would get weird as the mouse got further from the player. I noticed this specifically when I would zoom out a lot and try to mouse pick. From what I remember, the problem in my build was the zoom functionality. I customized a lot of things in the advanced camera, though, so I'm not sure if this will apply to your build, but I'll briefly outline my problem anyway in case it helps.
What was happening was my server and client positions of the adv camera were off. The zoom values, controlled by the user, were being reflected and viewed on the client, but not being updated on the server. Then, in server updates, the server would send a new zoom or position value that would overwrite the client. The result was basically, the client looked normal still, but the server was overwriting key values with outdated information. Since the mouse picking code (based on the GG resource) uses server values to function, I was getting bad mouse picking results. The solution was to just cut off those server updates. I figured the camera is kind of like a predicted control object, so the client should have the authoritative decision anyway.
@All,
I made a little script to get around the snag of switching from the advanced camera to the free flying TGE cam.
What this basically does is, if you set the control object to the player, it will turn on the advanced camera. If you set the control object to something else (like the flying camera via alt-c) it will turn off the advanced camera. You could probably customize it some more to do what you need.
In /server/scripts/game.cs, at the end of the file:
// ----------------------
// CAMERA FUNCTIONS
// ----------------------
// Some support functions for the adv Camera --drew
function GameConnection::disableAdvCamera (%this)
{
%client = %this;
%client.clearCameraObject();
}
function GameConnection::enableAdvCamera (%this)
{
%client = %this;
%client.setCameraObject (%client.advCamera);
}
function GameConnection::toggleAdvCamera (%this)
{
%client = %this;
if (%client.isAdvCameraEnabled())
%this.disableAdvCamera();
else
%this.enableAdvCamera();
}
//-----------------------------------------------------------------------------
// Package overrides to help advanaced camera
//-----------------------------------------------------------------------------
package AdvCameraPackage {
//-----------------------------------------------------------------------------
// Intercept the engine call with a script function,
// so we can do some more processing before it goes
// to the engine.
function GameConnection::setControlObject(%this, %obj)
{
echo ("GameConnection::setControlObject Package Override");
// Since adv Camera has problems when trying to switch to a
// different camera, turn it off when setting the control
// object to something else.
if (%obj == %this.player)
%this.enableAdvCamera ();
else
%this.disableAdvCamera ();
// Now make the real call to the engine.
Parent::setControlObject(%this, %obj);
}
};
// Packages work like a stack. Popping off a package on the bottom of the
// stack will pop all the ones above. Calling activatePackage(AdvCameraPackage) here, then
// popping it later causes the common/client/cursor.cs defined package
// to be popped, breaking the mouse cursor. To get around this, activate this package later on.
ActivatePackage(AdvCameraPackage);In gameConnection.cc, where the other adv camera changes are:
ConsoleMethod( GameConnection, isAdvCameraEnabled, bool, 2, 2, "()" "")
{
ShapeBase * cam = object->getCameraObject();
const char *className = cam->getClassName();
if (!dStrcmp (className, "AdvancedCamera"))
return true;
else
return false;
}
#134
Thanks for the reply. I have been mucking around with this for a week now, and I am pretty sure I know what the problem is. Unproject is giving me bad world coordinates. In first person mode I click on a spot on the terrain, switch to 3rd person and click on the exact same spot on the terrain and I get different world coordinates, than those I get in first person (this shouldn't happen, right?). I am unable to correlate the difference in the coordinates to anything in particular with the camera (IE. they aren't consistent except in their inconsistency). I will definetely take note of the problem you outlined, since I will eventually implement the Object selection stuff and it is nice to have a heads up on that. In fact that may be where I head next since this issue has reached an impass for me.
@Back to All
I have finally settled on what the difficulty is (95%-ish sure). OpenGL unproject relies on 3 matrices to help it determine world coordinates from screen coordinates: Projection Matrix, Model View Matrix, and ViewPort Matrix. I think the Advanced camera needs to be pushing relevent matrix information to the stacks (similar to Debris::renderObject) so that OpenGL has the information it needs to give accurate world coordinates given the mouse location on the screen, and the camera's current transform and rotation.
Unfortunately for me, resolving this is well beyond my current Torque and OpenGL skills. Far enough beyond in fact to account for a 5% unsureness in correct diagnosis of the problem. I will have to leave it to the benevolence of one of the more savvy community memebers. Pretty please with sugar on top....
If anyone does have any questions about this, feel free to contact me at the email addy in my profile.
Brent
@Thomas
Additional Note: I was experiencing a jitter with only one camera in 3rd Person when my player was moving uphill (oddly enough that was the only condition and it was extremely subtle). Getting rid of the interpolation code corrected that problem, however commenting out the processAfter made it do the jitterbug!
06/03/2005 (11:47 am)
@DrewThanks for the reply. I have been mucking around with this for a week now, and I am pretty sure I know what the problem is. Unproject is giving me bad world coordinates. In first person mode I click on a spot on the terrain, switch to 3rd person and click on the exact same spot on the terrain and I get different world coordinates, than those I get in first person (this shouldn't happen, right?). I am unable to correlate the difference in the coordinates to anything in particular with the camera (IE. they aren't consistent except in their inconsistency). I will definetely take note of the problem you outlined, since I will eventually implement the Object selection stuff and it is nice to have a heads up on that. In fact that may be where I head next since this issue has reached an impass for me.
@Back to All
I have finally settled on what the difficulty is (95%-ish sure). OpenGL unproject relies on 3 matrices to help it determine world coordinates from screen coordinates: Projection Matrix, Model View Matrix, and ViewPort Matrix. I think the Advanced camera needs to be pushing relevent matrix information to the stacks (similar to Debris::renderObject) so that OpenGL has the information it needs to give accurate world coordinates given the mouse location on the screen, and the camera's current transform and rotation.
Unfortunately for me, resolving this is well beyond my current Torque and OpenGL skills. Far enough beyond in fact to account for a 5% unsureness in correct diagnosis of the problem. I will have to leave it to the benevolence of one of the more savvy community memebers. Pretty please with sugar on top....
If anyone does have any questions about this, feel free to contact me at the email addy in my profile.
Brent
@Thomas
Additional Note: I was experiencing a jitter with only one camera in 3rd Person when my player was moving uphill (oddly enough that was the only condition and it was extremely subtle). Getting rid of the interpolation code corrected that problem, however commenting out the processAfter made it do the jitterbug!
#135
)
The bug or a similar bug still exists when you move off the terrain block to another. The vehicle I was driving just vanished beneath me, leaving me feeling a bit exposed.
06/03/2005 (1:34 pm)
Regarding an ealier posting (Manoel Neto (Mar 07, 2005 at 19:27 UTC) )
The bug or a similar bug still exists when you move off the terrain block to another. The vehicle I was driving just vanished beneath me, leaving me feeling a bit exposed.
#136
I have changed all the code. Copleted all the changes and edited and then I just get lost at the heading which says "Script API". I dont understand what to do there?
If anyone could please help me with that I would be most appreciative. I find the last part of the resource jumps around a bit?
Is the bit about the "Script API" just commands manually put in to the console?
Do I press alt-c and then put these commands in?
Oh one other thing. I am trying use this on the starter.racing mod. Would that be a problem?
06/03/2005 (4:27 pm)
@ Todd D. Degani and anyone elseI have changed all the code. Copleted all the changes and edited and then I just get lost at the heading which says "Script API". I dont understand what to do there?
If anyone could please help me with that I would be most appreciative. I find the last part of the resource jumps around a bit?
Is the bit about the "Script API" just commands manually put in to the console?
Do I press alt-c and then put these commands in?
Oh one other thing. I am trying use this on the starter.racing mod. Would that be a problem?
#137
The script API is just showing you how to use the advanced camera. You can use the commands listed there in your own scripts to directly manipulate the camera or its modes.
I don't see a problem with using this with the racing mod.
06/03/2005 (5:07 pm)
@EuanThe script API is just showing you how to use the advanced camera. You can use the commands listed there in your own scripts to directly manipulate the camera or its modes.
I don't see a problem with using this with the racing mod.
#138
I have done the code from scratch to make sure I wasnt doing something wrong. So I have done it in FPS. I break out of First Person view (by pressing tab) and put in the command
%this.advCamera.setGodViewMode();
and it comes back with
(0): Unable to find object: ' ' attempting to call function 'setGodViewMode'
which is what I was getting in the racer as well.
I am sure its just something simple I am doing. But I just dont know!
Any suggestions?
It seems like it cant find the advancedcamera.h or advancedcamera.cc ? But I have included it into the project under Torque Demo\Source Files\Game (is that right) and it compiles under Visual Studio 2003 with no errors. I have also copied the files under "C:\Torque\SDK\engine\game" ?
Thanks for your help.
06/03/2005 (5:44 pm)
@ Todd D. Degani (Or if anyone else can help ?)I have done the code from scratch to make sure I wasnt doing something wrong. So I have done it in FPS. I break out of First Person view (by pressing tab) and put in the command
%this.advCamera.setGodViewMode();
and it comes back with
(0): Unable to find object: ' ' attempting to call function 'setGodViewMode'
which is what I was getting in the racer as well.
I am sure its just something simple I am doing. But I just dont know!
Any suggestions?
It seems like it cant find the advancedcamera.h or advancedcamera.cc ? But I have included it into the project under Torque Demo\Source Files\Game (is that right) and it compiles under Visual Studio 2003 with no errors. I have also copied the files under "C:\Torque\SDK\engine\game" ?
Thanks for your help.
#139
By putting in your desired camera type in to the game.cs file it works like a charm. I am very sorry for my stupidity.
Thanks Todd and everyones helpful posts.
06/03/2005 (6:32 pm)
Oh I feel like such an idiot. I am really sorry to all those who read my embarressing post. I just figured out how it works.By putting in your desired camera type in to the game.cs file it works like a charm. I am very sorry for my stupidity.
Thanks Todd and everyones helpful posts.
#140
Glad you got it figured out. Everything seems easier once you figure it out :)
06/03/2005 (8:13 pm)
@EuanGlad you got it figured out. Everything seems easier once you figure it out :)

Torque Owner Thomas \"Man of Ice\" Lund