Help with Camera math

Started by
4 comments, last by MARS_999 11 years, 11 months ago
Here is my camera code, and I do not know for sure what I need to do to make the camera move forward after the rotations... What happens is if I rotate and use say "s" to move forward after I rotate "s" will move backwards and "w" will move forward... I am not sure what to do to fix this? I can't imagine this is a simple fix e.g. - vs. + value in the calculation.


template<class T>
class Camera
{
private:
cml::matrix44f_c matrix, matrixAvatarTranslation, projection;
T xPos, yPos, zPos, xRot, yRot, prevX, prevY;
T radius;//our radius distance from our object
bool mouseMove;

public:
explicit Camera(T r = 10)
{
xPos = yPos = zPos = xRot = yRot = prevX = prevY = 0;
radius = r;
mouseMove = false;
matrix.identity();
matrixAvatarTranslation.identity();
projection.identity();
}
~Camera(){}
inline void UpdatePerspective(unsigned int width, unsigned int height,
T nearPlane = 3,
T farPlane = 100,
T fov = 60)
{
glMatrixMode(GL_PROJECTION);
cml::matrix_perspective_yfov_RH(projection, cml::rad(fov),
static_cast<T>(width) / static_cast<T>(height),
nearPlane, farPlane,
cml::z_clip_neg_one);
glLoadMatrixf(projection.data());
glMatrixMode(GL_MODELVIEW);
}
inline void UpdateViewport(unsigned int width, unsigned int height)
{
glViewport(0, 0, width, height);
}
inline void Update(void)
{
cml::matrix44f_c rot, trans;
trans.identity();
rot.identity();
cml::matrix_translation(trans, T(0), T(0), -radius);
cml::matrix_rotation_world_axis(rot, 0, cml::rad(xRot));
matrixAvatarTranslation = trans * rot;

cml::matrix_translation(trans, -xPos, T(0), -zPos);
cml::matrix_rotation_world_axis(rot, 1, cml::rad(yRot));
matrix = matrixAvatarTranslation * rot * trans;
//glMatrixMode(GL_MODELVIEW);
//glLoadMatrixf(matrix.data());
}
inline void MouseMovement(int x, int y)
{
if(mouseMove)
{
T diffX = static_cast<T>(x - prevX); //check the difference between the current x and the last x position
T diffY = static_cast<T>(y - prevY); //check the difference between the current y and the last y position
prevX = static_cast<T>(x); //set prevX to the current x position
prevY = static_cast<T>(y); //set prevY to the current y position
xRot += diffY; //set the xrot to xrot with the addition of the difference in the y position
yRot += diffX; //set the xrot to yrot with the addition of the difference in the x position
}
}
inline bool IsMouseMove(void)
{
return mouseMove;
}
inline void SetMouseMove(bool b)
{
mouseMove = b;
}
inline const cml::matrix44f_c& GetTransform(void) const
{
return matrix;
}
inline void SetTransform(const cml::matrix44f_c& m)
{
matrix = m;
}
inline const cml::matrix44f_c& GetTransformAvatar(void) const
{
return matrixAvatarTranslation;
}
inline void SetTransformAvatar(const cml::matrix44f_c& m)
{
matrixAvatarTranslation = m;
}
inline T GetRadius(void)
{
return radius;
}
inline T GetRotateX(void)
{
return xRot;
}
inline T GetRotateY(void)
{
return yRot;
}
inline T GetPositionX(void)
{
return xPos;
}
inline T GetPositionY(void)
{
return yPos;
}
inline T GetPositionZ(void)
{
return zPos;
}
inline void Move(T t)
{
T yRotRad = static_cast<T>(yRot / cml::constants<T>::deg_per_rad());
T xRotRad = static_cast<T>(xRot / cml::constants<T>::deg_per_rad());
xPos -= static_cast<T>(sin(yRotRad) * t);
zPos += static_cast<T>(cos(yRotRad) * t);
yPos += static_cast<T>(sin(xRotRad) * t);
}
inline void Strafe(T t)
{
T yRotRad = static_cast<T>(yRot / cml::constants<T>::deg_per_rad());
xPos += static_cast<T>(cos(yRotRad) * t);
zPos += static_cast<T>(sin(yRotRad) * t);
}
inline void Rotate(T t)
{
xRot += t;
if(xRot > 360)
{
xRot -= 360;
return;
}
if(xRot < -360)
{
xRot += 360;
return;
}
}
};

Advertisement
I am not an expert, but I have wrestled with this in the distant past. With matrix math it's usually the order that you do things. Maybe apply the move before the rotation?

cml::matrix44f_c rot, trans;
trans.identity();
rot.identity();
cml::matrix_translation(trans, T(0), T(0), -radius);
cml::matrix_rotation_world_axis(rot, 0, cml::rad(xRot));
matrixAvatarTranslation = trans * rot;

With this code you seem to rotate your camera around the avatar ..

cml::matrix_translation(trans, -xPos, T(0), -zPos);
cml::matrix_rotation_world_axis(rot, 1, cml::rad(yRot));
matrix = matrixAvatarTranslation * rot * trans;

Here you want to move the camera to the avatars world position and rotate the camera relative to the avatar orientation ?

Here's my approach:

Tc = camera translation (radius), iTc = inverse(Tc) =-radius
Rc = camera rotation around avatar
Ta = avatar translation/position in world, iTa = inverse(Ta)
Ra = avatar orientation/look at

From a logical approach (hope I make no misstake now, I have not slept much):
Starting at the origin. First you need to rotate the camera around its origin at distance radius (move away from origin)
final = Rc * iTc
then you need to rotate the avatar
final = Ra * Rc * iTc
eventually move the camera to the avatar world position
final = Ta * Ra * Rc * iTc
It seems, that you are applying the transformations from the right, therefore:
final = iTc * Rc * Ra * Ta

As you can see, the first part is correct (iTc*Rc) , but the second part should look like Ra * Ta:

cml::matrix_translation(trans,xPos, T(0), zPos); // <= no wrong direction
Ashaman73 Not sure I am following your code example, I think you are assuming I have a clue where final is... I assume it's a matrix4x4 and

Tc = camera translation (radius), iTc = inverse(Tc) =-radius

how can I assign a radius to a matrix4x4? I never seen this syntax before...

Thanks!

how can I assign a radius to a matrix4x4? I never seen this syntax before..

You already did :-)
cml::matrix_translation(trans, T(0), T(0), -radius);
I think, that this call creates a 4x4 translation matrix from the vector (0,0,-radius), in the same way that this call
cml::matrix_rotation_world_axis(rot, 1, cml::rad(yRot))
creates a rotation matrix.

Sorry if I confuse you smile.png
Yeah that does, I was confused by your example

inverse(Tc) =-radius

This topic is closed to new replies.

Advertisement