Direction.x = -sinf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees)); Direction.y = sinf(DEG2RAD(-PitchDegrees)); Direction.z = cosf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees));where direction is the vector ponting down the z axis. Also, I have the vectors Right and Up transform along with this one (actually just one, because i could use a cross product to get the other) Thanks a lot! Grizwald
🔒 Locked
Camera Vector Transformations
Advertisement
Original Post
I''ve been using the following code for years to do camera rotation, but i now find that i need to understand how it works, and how to add a RollDegrees expression (don''t give me anything about quaternions, i already use those too; i just want to learn how to use this way (Eular i believe)
as i cant paint anything here: if you dont understand what this means and what it does you should really take a piece of paper, draw a circle and then draw a sin and cos function. if that doesnt help look up basic trigonometry and you will realize its pretty much the same just with a different vector and angle.
btw. if you can be sure its just small rotations each frame and dont even think about storing only angles and applying them all at once you should get away with euler quite fine. they wont bite you unless you apply more than one rotation (for example when pulling the stick back and to the left... this will be harmless with small rotations and else screw up *g*)
btw. if you can be sure its just small rotations each frame and dont even think about storing only angles and applying them all at once you should get away with euler quite fine. they wont bite you unless you apply more than one rotation (for example when pulling the stick back and to the left... this will be harmless with small rotations and else screw up *g*)
Here's some camera code I wrote a while back. It's a work in progress. Of particular interest should be that the camera has its own set of axis, and it is cleaned periodically.
The header file...
And the main code...
[Edit by Yann: just added source tags]
[edited by - Yann L on January 4, 2003 9:09:53 AM]
The header file...
/* camera.h */
#ifndef _CAMERA_H_
#define _CAMERA_H_
#include <vec/vec.h>
typedef struct _camera {
POINT3 pos;
VECTOR3 view;
VECTOR3 up;
VECTOR3 left;
float fov;
} CAMERA;
int camViewChanged ();
void camSetForwardKey (unsigned char keyCode);
void camSetBackKey (unsigned char keyCode);
void camSetLeftKey (unsigned char keyCode);
void camSetRightKey (unsigned char keyCode);
void camSetUpKey (unsigned char keyCode);
void camSetDownKey (unsigned char keyCode);
void camSetRollLeftKey (unsigned char keyCode);
void camSetRollRightKey (unsigned char keyCode);
void camSetPitchUpKey (unsigned char keyCode);
void camSetPitchDownKey (unsigned char keyCode);
void camSetYawLeftKey (unsigned char keyCode);
void camSetYawRightKey (unsigned char keyCode);
void camSetZShift (float v);
void camSetXShift (float v);
void camSetYShift (float v);
void camSetRollAngle (float angle);
void camSetPitchAngle (float angle);
void camSetYayAngle (float angle);
int camKeyProcess ();
void chooseCam (CAMERA *c);
CAMERA *getCam ();
void chooseDefCam ();
void initCam (float posX, float posY, float posZ,
float viewX, float viewY, float viewZ,
float upX, float upY, float upZ);
void cleanCam ();
void camForward (float step);
void camBack (float step);
void camLeft (float step);
void camRight (float step);
void camUp (float step);
void camDown (float step);
void camRoll (float angle);
void camPitch (float angle);
void camYaw (float angle);
void camZoom (float rate);
void camUnZoom (float rate);
#endif /* _CAMERA_H_ */
And the main code...
/* camera.c */
#ifndef _CAMERA_C_
#define _CAMERA_C_
#include <camera/camera.h>
#include <windows.h>
#define CAM_SERVICE_SCHEDULE 16
static CAMERA defCamera = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
45.0f
};
static CAMERA *camera = &defCamera
static unsigned long camMoves = 0;
static unsigned char camForwardKey = VK_UP;
static unsigned char camBackKey = VK_DOWN;
static unsigned char camLeftKey = VK_LEFT;
static unsigned char camRightKey = VK_RIGHT;
static unsigned char camUpKey = VK_PRIOR;
static unsigned char camDownKey = VK_NEXT;
static unsigned char camRollLeftKey = 'Z';
static unsigned char camRollRightKey = 'X';
static unsigned char camPitchUpKey = 'I';
static unsigned char camPitchDownKey = 'K';
static unsigned char camYawLeftKey = 'C';
static unsigned char camYawRightKey = 'V';
static unsigned char camZoomKey = '1';
static unsigned char camUnZoomKey = '2';
static float camZShift = 0.01f;
static float camXShift = 0.01f;
static float camYShift = 0.01f;
static float camRollAngle = 0.1f;
static float camPitchAngle = 0.1f;
static float camYawAngle = 0.1f;
static float camZoomRate = 0.01f;
static float camUnZoomRate = 0.01f;
static int fovChanged = 0;
static int viewChanged = 1;
int camViewChanged()
{
return viewChanged;
}
/* key binding functions */
void camSetForwardKey (unsigned char keyCode)
{
camForwardKey = keyCode;
}
void camSetBackKey (unsigned char keyCode)
{
camBackKey = keyCode;
}
void camSetLeftKey (unsigned char keyCode)
{
camLeftKey = keyCode;
}
void camSetRightKey (unsigned char keyCode)
{
camRightKey = keyCode;
}
void camSetUpKey (unsigned char keyCode)
{
camUpKey = keyCode;
}
void camSetDownKey (unsigned char keyCode)
{
camDownKey = keyCode;
}
void camSetRollLeftKey (unsigned char keyCode)
{
camRollLeftKey = keyCode;
}
void camSetRollRightKey (unsigned char keyCode)
{
camRollRightKey = keyCode;
}
void camSetPitchUpKey (unsigned char keyCode)
{
camPitchUpKey = keyCode;
}
void camSetPitchDownKey (unsigned char keyCode)
{
camPitchDownKey = keyCode;
}
void camSetYawLeftKey (unsigned char keyCode)
{
camYawLeftKey = keyCode;
}
void camSetZoomKey (unsigned char keyCode)
{
camZoomKey = keyCode;
}
void camSetUnZoomKey (unsigned char keyCode)
{
camUnZoomKey = keyCode;
}
void camSetZShift (float v)
{
camZShift = v;
}
void camSetXShift (float v)
{
camXShift = v;
}
void camSetYShift (float v)
{
camYShift = v;
}
void camSetRollAngle (float angle)
{
camRollAngle = angle;
}
void camSetPitchAngle (float angle)
{
camPitchAngle = angle;
}
void camSetYayAngle (float angle)
{
camYawAngle = angle;
}
void camSetZoomRate (float rate)
{
camZoomRate = rate;
}
void camSetUnZoomRate (float rate)
{
camUnZoomRate = rate;
}
#define keyDown(k) ( GetAsyncKeyState (k) & (0x0001 << 15) )
int camKeyProcess (float frameRate)
{
float s;
fovChanged = 0;
viewChanged = 0;
if (frameRate < 0.0001f)
s = 1.0f;
else
s = 60.0f / frameRate;
if (keyDown (camForwardKey))
camForward (camZShift * s);
if (keyDown (camBackKey))
camBack (camZShift * s);
if (keyDown (camLeftKey))
camLeft (camXShift * s);
if (keyDown (camRightKey))
camRight (camXShift * s);
if (keyDown (camUpKey))
camUp (camYShift * s);
if (keyDown (camDownKey))
camDown (camYShift * s);
if (keyDown (camRollLeftKey))
camRoll (-camRollAngle * s);
if (keyDown (camRollRightKey))
camRoll (camRollAngle * s);
if (keyDown (camPitchUpKey))
camPitch (-camPitchAngle * s);
if (keyDown (camPitchDownKey))
camPitch (camPitchAngle * s);
if (keyDown (camYawLeftKey))
camYaw (camYawAngle * s);
if (keyDown (camYawRightKey))
camYaw (-camYawAngle * s);
if (keyDown (camZoomKey))
camZoom (camZoomRate * s);
if (keyDown (camUnZoomKey))
camUnZoom (camUnZoomRate * s);
if (fovChanged == 1)
return 1;
return 0;
}
void chooseCam (CAMERA *c)
{
camera = c;
cleanCam ();
viewChanged = 1;
}
CAMERA *getCam ()
{
return camera;
}
void chooseDefCam ()
{
camera = &defCamera
cleanCam ();
viewChanged = 1;
}
void initCam (float posX, float posY, float posZ,
float viewX, float viewY, float viewZ,
float upX, float upY, float upZ)
{
p3setf (posX, posY, posZ, camera->pos);
v3setf (viewX, viewY, viewZ, camera->view);
v3setf (upX, upY, upZ, camera->up);
v3crossv3ccwrhs (camera->up, camera->view, camera->left);
cleanCam ();
viewChanged = 1;
}
void cleanCam ()
{
/* renormalize view and up */
v3normm (camera->view);
v3normm (camera->up);
/* straighten left vector */
v3crossv3ccwrhs (camera->up, camera->view, camera->left);
v3normm (camera->left);
/* straighten up vector */
v3crossv3ccwrhs (camera->view, camera->left, camera->up);
v3normm (camera->up);
}
void camForward (float step)
{
POINT3 V;
v3mulf (camera->view, step, V);
v3addv3m (camera->pos, V);
}
void camBack (float step)
{
POINT3 V;
v3mulf (camera->view, step, V);
v3subv3m (camera->pos, V);
}
void camLeft (float step)
{
POINT3 V;
v3mulf (camera->left, step, V);
v3addv3m (camera->pos, V);
}
void camRight (float step)
{
POINT3 V;
v3mulf (camera->left, step, V);
v3subv3m (camera->pos, V);
}
void camUp (float step)
{
POINT3 V;
v3mulf (camera->up, step, V);
v3addv3m (camera->pos, V);
}
void camDown (float step)
{
POINT3 V;
v3mulf (camera->up, step, V);
v3subv3m (camera->pos, V);
}
/*
camShiftXY (float x, float y)
camShiftXZ (float x, float z)
camShiftYZ (float y, float z)
camShiftArb (float x, float y, float z)
*/
void camRoll (float angle)
{
MATRIX44 M;
VECTOR3 V;
M44rot (camera->view, degtorad (angle), M);
v3trans (camera->up, M, V);
v3copv3 (V, camera->up);
v3trans (camera->left, M, V);
v3copv3 (V, camera->left);
cleanCam ();
}
void camPitch (float angle)
{
MATRIX44 M;
VECTOR3 V;
M44rot (camera->left, degtorad (angle), M);
v3trans (camera->view, M, V);
v3copv3 (V, camera->view);
v3trans (camera->up, M, V);
v3copv3 (V, camera->up);
cleanCam ();
viewChanged = 1;
}
void camYaw (float angle)
{
MATRIX44 M;
VECTOR3 V;
M44rot (camera->up, degtorad (angle), M);
v3trans (camera->view, M, V);
v3copv3 (V, camera->view);
v3trans (camera->left, M, V);
v3copv3 (V, camera->left);
cleanCam ();
viewChanged = 1;
}
void camZoom (float rate)
{
if (camera->fov > 1.0f) {
camera->fov -= rate;
if (camera->fov < 1.0f)
camera->fov = 1.0f;
fovChanged = 1;
}
}
void camUnZoom (float rate)
{
if (camera->fov < 120.0f) {
camera->fov += rate;
if (camera->fov > 120.0f)
camera->fov = 120.0f;
fovChanged = 1;
}
}
/*
camPosRotArb (V3 axis, float angle)
camRotArb (V3 axis, float angle)
camLockTarget (P3 point)
camUnlockTarget ()
camPosLockPath (Path)
camPosUnlockPath ()
camLockTarget (Path)
camUnlockTarget ()
*/
#endif /* _CAMERA_C_ */
[Edit by Yann: just added source tags]
[edited by - Yann L on January 4, 2003 9:09:53 AM]
quote:
Original post by bishop_pass
C?...
Why do your camera object is responsible for user input?!
Maybe some GameInput object with AttachCamera method will look better...?
Why do you camera object contain FOV? Maybe it is better to leave that to the Renderer object, camera is only for orientation in space. So Fristum = Camera + RenderView(FOV,Znear,Zfar)...
This way camera is just lightweight ''frame'' object with some special methods like ''LookAt'' and such.
Only some suggestions.
quote:
Why do you camera object contain FOV? Maybe it is better to leave that to the Renderer object, camera is only for orientation in space.
No, the FOV should definitely be in the camera class. the FOV is an inherent property of the camera, just as position, orientation, projection mode, lens parameters, etc. A camera object is a lot more than simply position and orientation. For an exmaple, fire up 3DSMax, create a camera and check it's properties.
Oh, btw, bishop_pass: you don't mind if I put in source tags in your post ? Makes the thread a bit shorter and easier to read.
[edited by - Yann L on January 4, 2003 9:08:27 AM]
quote:
Original post by Zemedelec
Why do your camera object is responsible for user input?!
Because that's the way I felt like doing it. There's actually a very good reason for it. The point was to have some code that I could drop into any app and instantly have a controllable camera up and running, independent of any user interface that would later be designed.
quote:
Original post by Zemedelec
Maybe some GameInput object with AttachCamera method will look better...?
Maybe, but that's not really good either. That implies that the input class needs knowledge of calls to controllable objects, which sounds messy, but I don't think too much that way. My camera is a controllable entity. I'd rather have it's controllability exist within its own framework. That way, another class doesn't need to be built with knowledge of the controllable features of the camera. And the beauty is, the camera comes prebound to controls, making it instantly available as a controllable object. My particular default key bindings aren't the greatest, but those can be changed.
quote:
Original post by Zemedelec
Why do you camera object contain FOV?
No. I would even consider placing the format (width to height ratio) of the image within the camera class as well. Let's say I wanted to use a virtual Fujifilm G617 camera with a 90 mm lens on it. Such a camera defines a 6 x 17 (height x width) image, and the FOV is implicitly defined as well by the lens's focal length and the size of the film plane. I am seriously considering adding a set of real world lens and camera parameters to my camera functions.
quote:
Original post by Zemedelec
This way camera is just lightweight 'frame' object with some special methods like 'LookAt' and such.
It's not whether the code is lightweight or not. What is important is that it binds you to another code object as little as possible. The best code is code that doesn't depend on other code or classes, making it usable in more paradigms.
[edited by - bishop_pass on January 4, 2003 6:02:55 PM]
quote:
Original post by Yann L
Oh, btw, bishop_pass: you don''t mind if I put in source tags in your post ? Makes the thread a bit shorter and easier to read.
Yeah, that''s fine. My block indenting has apparently been mangled - no fault of yours though - it happened with the original post.
I was looking at my code, and there''s a constant called CAMERA_SERVICE_SCHEDULE and it''s value is 16. This used to be in effect, but at the moment it appears that the camera is cleaned every frame. As I get around to cleaning up the code some more, the service schedule will go back into effect.
The idea is that cameras need to be cleaned periodically, in the real world and in the virtual world. Virtual cameras only need to be cleaned after a a certain number of rotations though. Translations don''t make the camera dirty.
The idea is that cameras need to be cleaned periodically, in the real world and in the virtual world. Virtual cameras only need to be cleaned after a a certain number of rotations though. Translations don''t make the camera dirty.
It''s a little bit more complex than that. Your camera has view vector, an up vector and a left vector (or right, depending on the way you code it).
Rolling is rotating on the axis defined by your view vector. Thus, you need to intialize an arbitrary rotation axis matrix, and then apply that matrix to the up and left vectors.
My matrix initialization code to create a matrix for that is this:
Rolling is rotating on the axis defined by your view vector. Thus, you need to intialize an arbitrary rotation axis matrix, and then apply that matrix to the up and left vectors.
My matrix initialization code to create a matrix for that is this:
float *M44rot (VECTOR3 V, float angle, MATRIX44 M)
{
float c = (float) cos (angle);
float s = (float) sin (angle);
float t = 1.0f - c;
float xy = V[0] * V[1];
float xz = V[0] * V[2];
float yz = V[1] * V[2];
float txy = t * xy;
float txz = t * xz;
float tyz = t * yz;
float sx = s * V[0];
float sy = s * V[1];
float sz = s * V[2];
M[0][0] = t * V[0] * V[0] + c;
M[0][1] = txy + sz;
M[0][2] = txz - sy;
M[0][3] = 0.0f;
M[1][0] = txy - sz;
M[1][1] = t * V[1] * V[1] + c;
M[1][2] = tyz + sx;
M[1][3] = 0.0f;
M[2][0] = txz + sy;
M[2][1] = tyz - sx;
M[2][2] = t * V[2] * V[2] + c;
M[2][3] = 0.0f;
M[3][0] = 0.0f;
M[3][1] = 0.0f;
M[3][2] = 0.0f;
M[3][3] = 1.0f;
return &M[0][0];
}
I messed that last one up royally....woooweee...what i mean is how can I use that same format, only for a different vector (Up or Right) My last post in this thread really messed that one up, so sorry for wasting your time bishop, but thanks for trying. I think i may have figured it (just now i'll have you know)
Direction.x = -sinf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees));
Direction.y = sinf(DEG2RAD(-PitchDegrees));
Direction.z = cosf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees));
that will calculate the good old direction vector
would i use this for the Right vector? :
Right.x = -sinf(DEG2RAD(YawDegrees+90)) * cosf(DEG2RAD(-RollDegrees));
Right.y = sinf(DEG2RAD(-RollDegrees));
Right.z = cosf(DEG2RAD(YawDegrees+90)) * cosf(DEG2RAD(-RollDegrees));
and then just calculate my Up vector with:
Direction (Cross Product) Right?
sorry again for my stupidity, i haven't been thinking correctly lately....thanks again.
P.S This editbox needs to be larger....(wider)
[edited by - Grizwald on January 7, 2003 6:02:10 PM]
Direction.x = -sinf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees));
Direction.y = sinf(DEG2RAD(-PitchDegrees));
Direction.z = cosf(DEG2RAD(YawDegrees)) * cosf(DEG2RAD(-PitchDegrees));
that will calculate the good old direction vector
would i use this for the Right vector? :
Right.x = -sinf(DEG2RAD(YawDegrees+90)) * cosf(DEG2RAD(-RollDegrees));
Right.y = sinf(DEG2RAD(-RollDegrees));
Right.z = cosf(DEG2RAD(YawDegrees+90)) * cosf(DEG2RAD(-RollDegrees));
and then just calculate my Up vector with:
Direction (Cross Product) Right?
sorry again for my stupidity, i haven't been thinking correctly lately....thanks again.
P.S This editbox needs to be larger....(wider)
[edited by - Grizwald on January 7, 2003 6:02:10 PM]
You're not getting it.
Your view vector is the Z axis. Your up vector is the Y axis. Your other vector is the X axis. Store those, because as you change your camera's view, they will change.
To Roll, initialize my matrix with the view vector, and transform your other vectors with it.
To Pitch, initialize my matrix with the left vector, and transform the other vectors with it.
To Yaw, initialize my matrix with the Up vector, and transform the other vectors with it.
Save these newly transformed vectors, becaue that's your camera's orientation now.
About every 10 or 20 frames, clean those vectors with a function like my cleanCam () funtion.
[edited by - bishop_pass on January 7, 2003 6:30:18 PM]
Your view vector is the Z axis. Your up vector is the Y axis. Your other vector is the X axis. Store those, because as you change your camera's view, they will change.
To Roll, initialize my matrix with the view vector, and transform your other vectors with it.
To Pitch, initialize my matrix with the left vector, and transform the other vectors with it.
To Yaw, initialize my matrix with the Up vector, and transform the other vectors with it.
Save these newly transformed vectors, becaue that's your camera's orientation now.
About every 10 or 20 frames, clean those vectors with a function like my cleanCam () funtion.
[edited by - bishop_pass on January 7, 2003 6:30:18 PM]
me got a camera problem too...
this is how i create view matrix, based on eye and look vectors and roll angle:
and given
cam.mEye.XYZ (500,500,-3000);
cam.mLook.XYZ(0,0,0);
mRoll = 0;
i get following matrix:
[0][0]= -0.9864 [0][1]= -0.0267 [0][2]= -0.1622 [0][3]= 0.0000
[1][0]= 0.0000 [1][1]= 0.9868 [1][2]= -0.1622 [1][3]= 0.0000
[2][0]= -0.1644 [2][1]= 0.1600 [2][2]= 0.9733 [2][3]= 0.0000
[3][0]= -500.0000 [3][1]= -500.0000 [3][2]= 3000.0000 [3][3]= 1.0000
can smby check this out?
coz, when i move look vector left or right on x axis, the objects are just rotating, but not moving in the opposite direction (like seen in 3d studio
). any ideas what''s going on?
Abnormal behavior of abnormal brain makes me normal...
this is how i create view matrix, based on eye and look vectors and roll angle:
y.X(sin(mRoll));
y.Y(-cos(mRoll));
y.Z(0.0f);
z = mLook - mEye;
z.Normalize();
x = y.CrossProduct(&y,&z);
x.Normalize();
y = x.CrossProduct(&x,&z);
y.Normalize();
mat.View(x,y,z,mEye);
// while mat.view does this
mData[0][0] = x.X();
mData[1][0] = x.Y();
mData[2][0] = x.Z();
mData[0][1] = y.X();
mData[1][1] = y.Y();
mData[2][1] = y.Z();
mData[0][2] = z.X();
mData[1][2] = z.Y();
mData[2][2] = z.Z();
mData[3][0] = - eye.X();
mData[3][1] = - eye.Y();
mData[3][2] = - eye.Z();
mData[0][3] = 0.0f;
mData[1][3] = 0.0f;
mData[2][3] = 0.0f;
mData[3][3] = 1.0f;
and given
cam.mEye.XYZ (500,500,-3000);
cam.mLook.XYZ(0,0,0);
mRoll = 0;
i get following matrix:
[0][0]= -0.9864 [0][1]= -0.0267 [0][2]= -0.1622 [0][3]= 0.0000
[1][0]= 0.0000 [1][1]= 0.9868 [1][2]= -0.1622 [1][3]= 0.0000
[2][0]= -0.1644 [2][1]= 0.1600 [2][2]= 0.9733 [2][3]= 0.0000
[3][0]= -500.0000 [3][1]= -500.0000 [3][2]= 3000.0000 [3][3]= 1.0000
can smby check this out?
coz, when i move look vector left or right on x axis, the objects are just rotating, but not moving in the opposite direction (like seen in 3d studio
Abnormal behavior of abnormal brain makes me normal...
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement