Player's Camera
by Scott Doerrfeld · in Torque Game Engine · 05/14/2007 (8:13 am) · 7 replies
Where in the engine is the camera that follows the client's control object (i.e. 1st-person, 3rd-person camera). I would like to modify the engine so that I can set Client A's camera to follow Client B's control object, but without relinquishing control to Client A. Having trouble finding the appropriate code. Can anyone give me a starting point here?
About the author
#2
MatrixF ret;
shape->getRenderEyeTransform( &ret );
setTransform(ret);
This works well...EXCEPT for when the orbit object isn't moving for some reason the camera's z-rotation snaps to zero.
Why...WHY?!??!?
05/14/2007 (12:44 pm)
OK I am REALLLY close here. Much simpler solution:MatrixF ret;
shape->getRenderEyeTransform( &ret );
setTransform(ret);
This works well...EXCEPT for when the orbit object isn't moving for some reason the camera's z-rotation snaps to zero.
Why...WHY?!??!?
#3
05/14/2007 (2:13 pm)
Can someone please help me out? I have a camera orbiting a player object. Using the above method it will follow both the orientation and the position of the player object. But if the player's position does not change then the orbiting camera's z-rotation goes back to the center. Soon as the player starts moving again, the camera goes back to matching the player. There is obviously some sort of update issue going on here. I just can't find it.
#4
TGE's 1st/3rd person camera is not actually a separate game object, it is simply rendered by pulling the viewpoint of the player's eyeoffset backwards. That logic is in ShapeBase::getCameraTransform()
If you want to do anything more complicated (which sounds like you do) you need a seperate camera object as you are. Below I just cut and pasted the important parts from camera::processTick() which should set the rotation and position of a free flying camera (I have not tested this)
You said you were using setTransform(), you need to use setPosition() like in the below example
mRot is the angle of rotation in radians from 0-6.3 (0-2PI, or 0-360 degrees) in the x,y,z axis. mObjToWorld.getColumn(3,&pos) is getting the 4th column of the transformation matrix, which is the position. mObjToWorld.getColumn(0,&vec) is getting a column of the transformation matrix, which turns out to be one of the objects facing vectors, like forward vector, right vector, or up vector.
move->x, move->y, move->z are part of the move packet from the Move Manager, (gameconnectionmoves.cpp), and they represent the input values the player gave. For keyboard input, they are typically just 1 or -1. So if you hit "moveForward" on your keyboard ('w'), that translates into move->y being 1. If you use a gamepad it might be 0.2 or something. Thus, combining an object vector with the move packet gets the object to move the way you want, like this:
That takes the object's forward vector, multiples it by the player input "move forward" button, and get it to move.
Since you don't want a free flying camera but some kind of orbit or following camera, you need to set the pos value in setPosition(pos,mRot) differently.
You may have known most of that stuff already, I figured while I was on the topic I might as well write it out since I've done a lot of work with cameras and the move manager.
Hope that helps some...
05/16/2007 (6:42 am)
You are on the right track in terms of needing to use a separate camera object.TGE's 1st/3rd person camera is not actually a separate game object, it is simply rendered by pulling the viewpoint of the player's eyeoffset backwards. That logic is in ShapeBase::getCameraTransform()
If you want to do anything more complicated (which sounds like you do) you need a seperate camera object as you are. Below I just cut and pasted the important parts from camera::processTick() which should set the rotation and position of a free flying camera (I have not tested this)
You said you were using setTransform(), you need to use setPosition() like in the below example
// Update orientation
delta.rotVec = mRot;
mObjToWorld.getColumn(3,&delta.posVec);
mRot.x += move->pitch;
if(mRot.x > MaxPitch)
mRot.x = MaxPitch;
else if(mRot.x < -MaxPitch)
mRot.x = -MaxPitch;
mRot.z += move->yaw;
// Update pos
bool faster = move->trigger[0] || move->trigger[1];
F32 scale = mMovementSpeed * (faster + 1);
mObjToWorld.getColumn(3,&pos);
mObjToWorld.getColumn(0,&vec);
pos += vec * move->x * TickSec * scale;
mObjToWorld.getColumn(1,&vec);
pos += vec * move->y * TickSec * scale;
mObjToWorld.getColumn(2,&vec);
pos += vec * move->z * TickSec * scale;
setPosition(pos,mRot);mRot is the angle of rotation in radians from 0-6.3 (0-2PI, or 0-360 degrees) in the x,y,z axis. mObjToWorld.getColumn(3,&pos) is getting the 4th column of the transformation matrix, which is the position. mObjToWorld.getColumn(0,&vec) is getting a column of the transformation matrix, which turns out to be one of the objects facing vectors, like forward vector, right vector, or up vector.
move->x, move->y, move->z are part of the move packet from the Move Manager, (gameconnectionmoves.cpp), and they represent the input values the player gave. For keyboard input, they are typically just 1 or -1. So if you hit "moveForward" on your keyboard ('w'), that translates into move->y being 1. If you use a gamepad it might be 0.2 or something. Thus, combining an object vector with the move packet gets the object to move the way you want, like this:
mObjToWorld.getColumn(1,&vec);
pos += vec * move->y * TickSec * scale;That takes the object's forward vector, multiples it by the player input "move forward" button, and get it to move.
Since you don't want a free flying camera but some kind of orbit or following camera, you need to set the pos value in setPosition(pos,mRot) differently.
You may have known most of that stuff already, I figured while I was on the topic I might as well write it out since I've done a lot of work with cameras and the move manager.
Hope that helps some...
#5
In game/camera.cc...
Perhaps the issue has to do with the x-rotation being tied to the player's HEAD rotation, as opposed to the z-rotation which is probably tied to the BODY rotation. Or perhaps I need to add an extra step to calculating the deltas?
07/16/2007 (3:32 pm)
Can someone check this out and offer any pointers? The following code makes my camera mimic another client's player object for BOTH position and rotation, but the x-rotation (up-down) is choppy for some reason.In game/camera.cc...
void Camera::processTick(const Move* move)
{
.
.
.
if(mode == OrbitObjectMode || mode == OrbitPointMode)
{
if(mode == OrbitObjectMode && bool(mOrbitObject))
{
GameBase *castObj = mOrbitObject;
Player* shape = dynamic_cast<Player*>(castObj);
if( shape != NULL )
{
MatrixF ret;
shape->getRenderEyeTransform( &ret );
mRot = ret.toEuler();
mPosition = ret.getPosition();
}
}
setPosition(mPosition, mRot);
pos = mPosition;
}
.
.
.
}
void Camera::interpolateTick(F32 dt)
{
.
.
.
if(mode == OrbitObjectMode || mode == OrbitPointMode)
{
if(mode == OrbitObjectMode && bool(mOrbitObject))
{
GameBase *castObj = mOrbitObject;
Player* shape = dynamic_cast<Player*>(castObj);
if( shape != NULL )
{
MatrixF ret;
shape->getRenderEyeTransform( &ret );
rot = ret.toEuler();
mPosition = ret.getPosition();
}
}
setRenderPosition(mPosition, rot);
}
.
.
.
}Perhaps the issue has to do with the x-rotation being tied to the player's HEAD rotation, as opposed to the z-rotation which is probably tied to the BODY rotation. Or perhaps I need to add an extra step to calculating the deltas?
#6
07/17/2007 (7:58 am)
Can anyone offer any advice on this? I can't figure out why it would be smooth updating a rotation in one direction, but choppy rotating in another direction.
#7
07/18/2007 (9:05 am)
Any links to other posts/resources that might help?
Torque Owner Scott Doerrfeld
MatrixF ret;
shape->getRenderEyeTransform( &ret );
ret.getRow(1, &mRot); // <<< line I added to get shape's orientation
mPosition = ret.getPosition();
This isn't quite right. It is jittery AND it is not getting the correct orientation. Any suggestions?