Controlling a mounted camera object
by Adam Beer · in Torque 3D Professional · 09/09/2010 (4:00 pm) · 10 replies
I am trying to allow a player to control a mounted camera object on a vehicle. It seems that while the camera is mounted, it doesnt take any inputs for pitch and yaw into account for doing the transform.
Inside the camera.cpp at the beginning of processTick there's an if(isMounted()) statement that just grabs the mounts transform info. Would anyone be able to tell me how I can add the pitch and yaw inputs into this transform?
Thanks,
Adam
Inside the camera.cpp at the beginning of processTick there's an if(isMounted()) statement that just grabs the mounts transform info. Would anyone be able to tell me how I can add the pitch and yaw inputs into this transform?
Thanks,
Adam
About the author
Adam is the owner of Ignition Games, an indie game and software development company.
#2
My problem is I know what has to be done, just not how. I already have variables setup to get the data from move->pitch/yaw, but I just dont know how to include them in the transform. Heres the code I have:
I see the mMount.xfm, but I just dont understand matrices enough to figure out how to add my mRot variable to it. Any help would be appreciated.
09/10/2010 (3:39 pm)
Thanks for the reply Thomas. My scenario is an actual camera object mounted to an aircraft to act as the camera from a targeting pod. I have it setup so the client can switch between the 2 control objects (aircraft, and camera object mounted to the aircraft).My problem is I know what has to be done, just not how. I already have variables setup to get the data from move->pitch/yaw, but I just dont know how to include them in the transform. Heres the code I have:
void Camera::processTick(const Move* move)
{
Parent::processTick(move);
if ( isMounted() )
{
MatrixF mat;
VectorF rotVec(0, 0, 0);
if(move)
{
rotVec.x = move->pitch;
rotVec.z = move->yaw;
}
mRot.x += rotVec.x;
mRot.z += rotVec.z;
mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
setTransform( mat );
updateContainer();
return;
}
...I see the mMount.xfm, but I just dont understand matrices enough to figure out how to add my mRot variable to it. Any help would be appreciated.
#3
09/10/2010 (4:36 pm)
I believe you should do something like this:... MatrixF xRot, zRot , fmat; xRot.set(EulerF(rotVec.x, 0, 0)); zRot.set(EulerF(0, 0, rotVec.z)); // let's combine the euler rotation fmat.mul(zRot, xRot); // pull the node transform and translate it to world space, // we need only the world position,we discard rotation values MatrixF mat; mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat ); Point3F position; mat.getColumn(3,&position); fmat.setColumn(3,position); Parent::setTransform( fmat ); ...This is totally untested code,but eventually will work.
#4
mRot.x: -0.179476
mRot.z: 0.179476
Any ideas?
09/10/2010 (4:58 pm)
Thanks Ivan! I tried this out and it points the camera straight ahead, but it doesnt move as far as I can see. I echoed mRot.z/x and they are both spitting out values so it doesnt really make sense why there is no movement. Unless values like this wouldnt move the camera much?:mRot.x: -0.179476
mRot.z: 0.179476
Any ideas?
#5
Hmmm now I see that you should use Parent::setTransform(),because the current setTransform() deals with a new rotation,which is incorrect in your case and wrong results may appear.
09/10/2010 (5:03 pm)
You should check what happens in interpolateTick() and put in comment the cycle with isMounted() , because it resets the new transform for each frame.Hmmm now I see that you should use Parent::setTransform(),because the current setTransform() deals with a new rotation,which is incorrect in your case and wrong results may appear.
#6
1) mRot.x/z echoed in processTick and interpolateTick dont equal:
processTick - mRot.x: 0.130388
processTick - mRot.z: 0.000000
interpolateTick - mRot.x: 0.065194
interpolateTick - mRot.z: 0.000000
2) I can only pitch/yaw a little bit and then it stops rotating.
09/10/2010 (5:40 pm)
Gah, didnt even see that. I updated the code and it works but there are 2 issues.1) mRot.x/z echoed in processTick and interpolateTick dont equal:
processTick - mRot.x: 0.130388
processTick - mRot.z: 0.000000
interpolateTick - mRot.x: 0.065194
interpolateTick - mRot.z: 0.000000
2) I can only pitch/yaw a little bit and then it stops rotating.
void Camera::processTick(const Move* move)
{
Parent::processTick(move);
if ( isMounted() )
{
MatrixF mat;
VectorF rotVec(0, 0, 0);
if(move)
{
rotVec.x = move->pitch;
rotVec.z = move->yaw;
mRot.x += rotVec.x;
mRot.z += rotVec.z;
}
Con::printf("processTick - mRot.x: %f", mRot.x);
Con::printf("processTick - mRot.z: %f", mRot.z);
MatrixF xRot, zRot , fmat;
xRot.set(EulerF(rotVec.x, 0, 0));
zRot.set(EulerF(0, 0, rotVec.z));
// let's combine the euler rotation
fmat.mul(zRot, xRot);
// this will pull the transform and translate to world space
// we need only the world position,we discard rotation values
mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
Point3F position;
mat.getColumn(3,&position);
fmat.setColumn(3,position);
setTransform( fmat );
updateContainer(); // Consider removing this
//mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
//setTransform( mat );
//updateContainer();
return;
}
...
void Camera::interpolateTick(F32 dt)
{
Parent::interpolateTick(dt);
if ( isMounted() )
{
MatrixF mat;
Con::printf("interpolateTick - mRot.x: %f", mRot.x);
Con::printf("interpolateTick - mRot.z: %f", mRot.z);
MatrixF xRot, zRot , fmat;
xRot.set(EulerF(mRot.x, 0, 0));
zRot.set(EulerF(0, 0, mRot.z));
// let's combine the euler rotation
fmat.mul(zRot, xRot);
// this will pull the transform and translate to world space
// we need only the world position,we discard rotation values
mMount.object->getRenderMountTransform( dt, mMount.node, mMount.xfm, &mat );
Point3F position;
mat.getColumn(3,&position);
fmat.setColumn(3,position);
setRenderTransform( fmat );
return;
}
...
#7
Also use Parent::setRenderTransform() there to skip the camera's inner logic.
And don't forget to replace setTransform() with Parent::setTransform() in processtick()
09/10/2010 (6:06 pm)
In interpolateTick() you should not use mRot,but:Point3F rot = delta.rot + delta.rotVec * dt;..because you benefit from interpolation
Also use Parent::setRenderTransform() there to skip the camera's inner logic.
And don't forget to replace setTransform() with Parent::setTransform() in processtick()
#8
I use:
Correct?
09/10/2010 (6:24 pm)
So in interpolateTick instead of:MatrixF xRot, zRot , fmat; xRot.set(EulerF(mRot.x, 0, 0)); zRot.set(EulerF(0, 0, mRot.z)); // let's combine the euler rotation fmat.mul(zRot, xRot);
I use:
MatrixF fmat; Point3F rot = delta.rot + delta.rotVec * dt; fmat.set(rot);
Correct?
#9
09/10/2010 (6:45 pm)
No,just replace mRot with rot this way:... Point3F rot = delta.rot + delta.rotVec * dt; MatrixF xRot, zRot , fmat; xRot.set(EulerF(rot.x, 0, 0)); zRot.set(EulerF(0, 0, rot.z)); // let's combine the euler rotation fmat.mul(zRot, xRot); ...
#10
09/15/2010 (3:23 am)
Thank you very much Ivan, works like a charm.
Torque 3D Owner Thomas
mercatronics
I would assume, that the mounted camera is disconnected from the client, so it doesn't accept any inputs.
It should be another thing, if you have a camera attached to a player and you mount the player to the vehicle. There is a far though in my mind of remembering, that the player still accepts input mounted on an object.
To disconnect movement you should create another actionmap, which only accepts mouse movement for example.
Hope this helps!