Relative camera transform problems
by Valador, Inc. · in Torque Game Engine · 06/21/2007 (6:24 am) · 2 replies
I've modified the camera class to support relative transformation (without use of mount points), but I've ran into some problems:
The overall idea: I can pick any shapebase-derived object to be the "origin of the universe" for any particular Camera instance. All camera movement (translation and rotation) is then relative to this ShapeBase derived object.
So far, so good, except for one big thing:
Whenever the final 4x4 matrix specifies a rotation around the lookat vector of the camera (a roll), it has no noticeable effect on the view: the camera's z vector (up vector) seems to be parallel to the global z vector at all times.
Pitch and yaw don't seem to give me any problems. The roll doesn't roll my viewpoint camera at all; it just seems to rotate the plane along which my flymode camera travels.
How can I rotate the camera (without using mount points) so that the up vector of the camera (z vector) is not parallel with the global z vector (global up vector)? In other words, HOW CAN I GET THE CAMERA TO VIEW THE WORLD ON ITS SIDE??
Any suggestings, explanations, hints, etc., are deeply appreciated.
Thanks,
Frank
The overall idea: I can pick any shapebase-derived object to be the "origin of the universe" for any particular Camera instance. All camera movement (translation and rotation) is then relative to this ShapeBase derived object.
So far, so good, except for one big thing:
Whenever the final 4x4 matrix specifies a rotation around the lookat vector of the camera (a roll), it has no noticeable effect on the view: the camera's z vector (up vector) seems to be parallel to the global z vector at all times.
Pitch and yaw don't seem to give me any problems. The roll doesn't roll my viewpoint camera at all; it just seems to rotate the plane along which my flymode camera travels.
How can I rotate the camera (without using mount points) so that the up vector of the camera (z vector) is not parallel with the global z vector (global up vector)? In other words, HOW CAN I GET THE CAMERA TO VIEW THE WORLD ON ITS SIDE??
Any suggestings, explanations, hints, etc., are deeply appreciated.
Thanks,
Frank
#2
Thanks for the reply. It verified my thinking was accurate. However, this was not directly the source of the problem I was having. It's a big explanation, but basically, interpolateTick(), and setPosition() ran from within readpacketData() was the source of my problem. I had two implementations of setPosition(): my new one, and the old engine version. readpacketData() kept executing the older version.
Thanks for your help,
Frank
06/22/2007 (5:51 am)
Drew,Thanks for the reply. It verified my thinking was accurate. However, this was not directly the source of the problem I was having. It's a big explanation, but basically, interpolateTick(), and setPosition() ran from within readpacketData() was the source of my problem. I had two implementations of setPosition(): my new one, and the old engine version. readpacketData() kept executing the older version.
Thanks for your help,
Frank
Torque 3D Owner Drew Parker
The problem could be that the standard TGE objects don't account for roll. I know the player doesn't, and with a quick look at the camera class it appears it doesn't either. I'm not sure exactly how you've modified the camera class, but here are some ideas:
In process tick, note how the TGE camera transform is set, especially the rotation. Even though the camera transformation is eventually stored in a matrix, internally it is manipulated from mRot which consists of Euler angles, and the roll value (mRot.y) is ignored:
camera.cc
void Camera::processTick(const Move* move) ... 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);Note at the very end, setPosition() is called.
Looking at setPosition(), this is where the transformation matrix is constructed from the passed in position and the Euler angle values of mRot:
void Camera::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; }Notice these lines:
Again, rot is in Euler angles, and it is skipping y - for the roll. So if you're still using mRot to handle the camera rotation, you're going to need to handle that y value for the roll. You'll have to include it in setPosition(), and do something about it in processTick().
Maybe you've already done that already though. :) Let me know if this helps at all and if not, if you want please give some more info and we can try to dig into it some more.
- Drew