Game Development Community

Call for Advanced Camera new features/changes/fixes

by Thomas \"Man of Ice\" Lund · in Torque Game Engine · 01/16/2005 (3:55 am) · 65 replies

I'm going to give the advanced camera resource another update soon, and from what I hear a lot of people are using it (nice)

Thus I would like to call out to you all and ask you to dig into your modifications and new features + consider if you would like to contribute those to the general public.

Anything goes, so feel free to send anything you have. I'll update the resource and give proper credit naturally.

From my own hand I'm considering working on:
* general code cleanup - removing unused code
* API cleanup and renaming - e.g. changing the setTargetObject to setLookAtObject and other API changes that make it more intuitive to use. This will most likely break your code unless I put in some deprecation warnings in the old methods and keep them there
* make it possible to use GameBase objects instead of ShapeBase objects as "Look At" and "Tracking" objects - for vehicles, projectiles and similar
* client side orbit camera instead of current server side

Hope to recieve a lot of great additions :-)

If you have general ideas, those are also welcome

My email is in my profile
#41
02/16/2005 (5:24 am)
I try to change this properties of my vehicle:

// 3rd person camera settings
cameraRoll = true; // Roll the camera with the vehicle
cameraMaxDist = 6; // Far distance from vehicle
cameraOffset = 1.5; // Vertical offset from camera mount point
cameraLag = 0.1; // Velocity lag of camera
cameraDecay = 0.75; // Decay per sec. rate of velocity lag

And nothing happens, why?
#42
02/16/2005 (1:41 pm)
Josh,

I'm interested in your 3rd person "lag" code. Any chance you could post it here? If its too much to post, you could email it to me and I'll dig through it. Thanks in advance.
#43
02/18/2005 (2:40 pm)
@Juan - those 3rd person settings are for the stock TGE 3rd person camera, and have nothing to do with the advanced camera resource. Thats why nothing happens

The shaking can be because you mount the player to the bike. If one of those objects gets updated before/after the camera, then it would look like a shaking motion. You can play around with the updateAfter() methods in the engine code. At some point I will do that myself - but I do not have the need myself at the moment. Feel free to report back if you have a success with that
#44
03/07/2005 (12:32 am)
No, i can't Thomas. I'm newbie and don't understand how to do that.

And my player is a bycicle alone, not a player mounted in a bike. Tha camera always shakes. It seems to run under the bycicle. I don't know why.

Thanks a lot.
#45
04/05/2005 (2:12 pm)
Juan,
There is a good chance you are seeing what I was seeing attaching the camera to my car. (It looked really choppy/jerky.)
I believe what was causing this was that the camera was interpolating ticks from the server and animating based of of a time delta (the "dt" passed in to InterpolateTick/ProcessTick is not delta time but actually a 'delta tick').

Its been awhile since I've looked at the advanced camera (my current version is pretty modded):
----------------------------------------------
void gameCamera::processTick(const Move* move)
{
// I think this is a server-side thing
Parent::processTick(move);
if (move)
{
if(gEditingMission && mMode != FreeFlyMode)
mMode = FreeFlyMode;
}

interpolateTick(0.32f);
}

void gameCamera::interpolateTick(F32 dt)
{
Parent::interpolateTick(dt);

if (getControllingClient() && mContainer)
updateContainer();
}

void gameCamera::advanceTime(F32 dt)
{
// should only be client side
Parent::advanceTime(dt);
updateMovementValues(dt);
}

void gameCamera::updateMovementValues(F32 dt)
{
// this should only happen client side
switch(mMode)
{
case FollowMode:
ModeFollow(dt);
break;
case OrbitMode:
ModeOrbit(dt);
break;
case FreeFlyMode:
ModeFreeFly(dt);
break;
case FirstPersonMode:
ModeFirstPerson(dt);
break;
default:
ModeFollow(dt);
break;
}
}
-----------------------------------------------------

Dunno if it helps but this is a good chunk of what I have. (Minus all the Mode*() calls)
#46
04/06/2005 (1:06 am)
Thank's Gamer XYZ, but sorry, i don't understand what i have to do in updateMovementValues(F32 dt). Could you explain you better?

:-D
#47
04/06/2005 (8:18 am)
UpdateMovementValues() is where you can modify the client-side camera. (at least that's what I'm doing.)

I have my camera broken down into various "modes" and call the appropriate function depending on the mode.

Here's one of them...
void gameCamera::ModeFirstPerson(F32 dt)
{
GameBase* body = getPlayerObject();
if (!body)
return;

Point3F loc, up, at, rt;
MatrixF bMtx = body->getRenderTransform(); // vehicle orientation
MatrixF cMtx = getTransform(); // camera orientation

setTransform(bMtx);

bMtx.getPosition(&loc);
bMtx.getAt(&at);
bMtx.getUp(&up);
bMtx.getRight(&rt);

loc += (1.1f*up) + (-0.15*at) + (-0.2*rt);
setPosition(loc);
}

setTransform() is just a "set the orientation of the camera" call. I suppose I could simplify my function by calculating the position, then throwing it into the bMtx before setting the transform, but oh well.

setPosition() does well, sets to position. In this case, an offset from the player's body for what would normally be a 3rd person view but my offset is still within the body (I am looking out a window of a large body).

On a side note, I changed the MatrixF class so that mtx.setColumn(3,&pos) is now mtx.setPosition(&pos); That way, its much easier [for me] to see what's going on at a quick glance.
#48
04/10/2005 (4:35 am)
OK - I just got the jittering removed in my game by removing the interpolation + commenting out the sections where it says processAfter(mTargetObj)

Camera runs fine in tracking mode and third person mode, where it until now jittered a lot
#49
05/16/2005 (12:37 am)
@Thomas
How did you remove this interpolation? I have been trying to remove the jitter when strafing in 3rd person mode and cannot figure out the right way to do this.

Thx
#50
05/17/2005 (12:42 pm)
Hey I'm trying to do something w/ the camera that i would think is simple, but is driving me crazy. I want to make the camera work as it normally would in a non-modified game except i want it to "point"/"be facing" 90degrees to the models right or left e.g. when the game starts (or when i toggle to 3rd person) i don't want to see what's in front of the model, i want to see what is to his right or left. The reason i want to do this is because i am working on a project that will run 3 clients/games on 3 monitors such that there will be a monitor in front of the player, one to his right and one to his left. The idea is that the front screen will be running the "normal" game, the right screen will be running the game w/ the camera rotated to the model's right, and left...left. Once i get all that working I am going to bind the side clients to the "main"/front facing client so that when the main client moves, the other screens will move with him and continue to provide the correct "side" view that he should see. My latest attemp my work...I am thinking i'll just spawn three players(front,left,right) in the same spot w/ right and left facing right and left of main client, somehow make the "side" ones appear invisible and w/o collision (probably need a special model), finally I think i'll just map the controls for side guys to move w/ the main players control e.g. move forward for front facing client will work normal, but move forward for right facing client will actuall be side step. I think this will make the game do what i want...what do you guys think? Thanks for reading this and if you help or don't it's cool i understand...thanks anyway

Opps...I forgot to mention...I am aware of the FOV control and the fact that i could just run one game w/ 3 screens and 180 FOV, for my project it must be 3 seperate games running...just to avoid extra typing :)
#51
05/17/2005 (1:33 pm)
@Geo

I simply commented out all of these:

//	if(bool(mTargetObject)) {
//		processAfter(mTargetObject);
//		deleteNotify(mTargetObject);
//	}

and then did this:

// Sets the position and calculates rotation
void AdvancedCamera::setPosition(const Point3F& pos) {

	//Interpolate the camera position
	//(warning, framerate-dependant, must be improved later)
	Point3F tPos = getPosition();
//	F32 tInterpolation = 0.333333f;
//	tPos = pos*tInterpolation + tPos*(1.0-tInterpolation);

	tPos = pos;

That works for me. Post or email your results on this too.
#52
05/17/2005 (3:57 pm)
Question:

If someone alt-tabs out of the game, the game seems to go back to the old camera - and you can't get back into the advanced-camera mode until you alt-tab again. Any clue on how to suppress this?
#53
05/17/2005 (10:22 pm)
What happens is that Torque is detecting the tab part of the alt-tab. You might try finding a way to detect if alt is also pressed, and ignore it in that case. Or just bind to a different, non-system-critical key...
#54
05/23/2005 (3:21 pm)
I implemented the advanced camera resource yesterday and went about fixing the problem where the camera would draw the exterior outside of an interior so I expanded on the issue that Zik was tackling with his code.

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 room. I have not tested the other camera modes though.
#55
05/23/2005 (3:30 pm)
Nice work Todd!

B--
#56
05/24/2005 (7:49 am)
Great work - thanks!
#57
07/07/2005 (8:17 pm)
Anyone got this working sending a rotation as well as position??

I added setCameraPosWithRotation
ConsoleMethod( AdvancedCamera, setCameraPosWithRotation, void, 4, 4, "(Point3F pos, rot)"
              "Set the position w/ rotation of the camera for tracking mode.\n\n") {
   AdvancedCamera *camObj = (AdvancedCamera *) object;

   Point3F pos;
   dSscanf( argv[2], "%f %f %f", &pos.x, &pos.y, &pos.z );
   Point3F rot;
   dSscanf( argv[3], "%f %f %f", &rot.x, &rot.y, &rot.z );
   Con::errorf("setCameraPosWithRotation:%s,%s",argv[2],argv[3]);
   camObj->setCameraPosition(pos,rot);
}

Im getting the correct values in the console but the camera always points in the wrong direction..has anyone had any experience with something like this?

edit: here are some relevant snipplets
void AdvancedCamera::setCameraPosition(const Point3F& pos,const Point3F& rot) {

	mCameraPos = pos;
	mRot = rot;
	setPosition(mCameraPos,rot);
	Con::errorf("AdvancedCamera::setCameraPosition:%f,%f,%f,%f,%f,%f",pos.x,pos.y,pos.z,rot.x,rot.y,rot.z);
}

void AdvancedCamera::setPosition(const Point3F& pos,const Point3F& rot)
{
   MatrixF xRot, zRot;
   xRot.set(EulerF(rot.x, 0, 0));
   zRot.set(EulerF(0, 0, rot.z));
   MatrixF temp;
   temp.mul(zRot, xRot);
   temp.setColumn(3, pos);
   Parent::setTransform(temp);
   mRot = rot;
}
#58
09/09/2005 (9:59 am)
I am also having trouble getting the rotation working, and the camera still swivels from 0,0,0
#59
10/25/2005 (12:29 am)
Great Resource to adventure games. Thanks a Lot to Thomas, Cory Osborn, Zik Saleeba and Manoel Neto.

Now, a question:

How can I change the inicial values of the Orbit Camera?

I want to start with the camera right behind the player.
#60
03/08/2006 (4:32 pm)
I'm trying to get the orbit camera to face the same direction as the player on command... Does this make sense or am I complicating things too much?

void AdvancedCamera::faceFront()
{
	Point3F	cameraPosWorld;   // x y z of world coordinates
	Point3F mConvertedOrbitOffset;  
	Point3F	playerRotation;

	MatrixF	objToWorld;       

	F32 mOffsetX;
	F32 mOffsetY;
	F32 mOffsetZ;
	F32	playerAzimuth;
	
	// Grab the player
	GameBase *castObj = mPlayerObject;
	ShapeBase* playerObj = dynamic_cast<ShapeBase*>(castObj);

	if(	playerObj != NULL )	
	{
		Player*	playerObjAsPlayer =	dynamic_cast<Player*>(playerObj);	
	
		playerRotation = playerObjAsPlayer->getRotation();
		playerAzimuth =	playerRotation.z; 
			
		objToWorld = playerObj->getRenderTransform();
		objToWorld.mulP(mCurrentOrbitOffset, &cameraPosWorld);

		// use spherical to cartesian coord transforms to calculate offset
		//mOffsetX = mZoomDistance * sin(mDeclination) * cos(playerAzimuth);
		//mOffsetY = mZoomDistance * sin(mDeclination) * sin(playerAzimuth);
		//mOffsetZ = mZoomDistance * cos(mDeclination);
		//mConvertedOrbitOffset.set(mOffsetX, mOffsetY, mOffsetZ);
		//cameraPosWorld += mConvertedOrbitOffset;
		
		Point3F	DistanceBehindHead(0, mCurrentOrbitOffset.y, 0);
		Point3F	DistanceAboveGround(0, 0, mCurrentOrbitOffset.z);
	
		// Get direction player is facing 
		MatrixF	PlayerAzimuthMatrix(EulerF(0,0,playerAzimuth));
		objToWorld.mul(PlayerAzimuthMatrix);
		objToWorld.mulP(DistanceBehindHead,	&cameraPosWorld);
		cameraPosWorld += DistanceAboveGround;
		setPosition(cameraPosWorld);
	}
}