void CCamera::SetViewByMouse()
{
POINT mousePos; // This is a window structure that holds an X and Y
int middleX = g_Width >> 1; // This is a binary shift to get half the width
int middleY = g_Height >> 1; // This is a binary shift to get half the height
float angleY = 0.0f; // This is the direction for looking up or down
float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
static float currentRotX = 0.0f;
GetCursorPos(&mousePos);
if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;
SetCursorPos(middleX, middleY);
angleY = (float)( (middleX - mousePos.x) ) / 500.0f;
angleZ = (float)( (middleY - mousePos.y) ) / 500.0f;
currentRotX -= angleZ;
if(currentRotX > 2)
currentRotX = 2;
else if(currentRotX < -1.0f)
currentRotX = -1.0f;
else{
CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector);
vAxis.Normalize();
RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
RotateView(angleY, 0, 1, 0);
}
}
spaceship camera (like Descent..)
i'm trying to write a small game like Xwing vs Tie Fighter and i've got some problems with the camera: basically when i try to rotate up or down i need to CONTINUE the rotation (not to stop like when i look up/down in a fps)... this way i could complete a circle if i wish.
in my old fps engine i used this function to rotate the camera with the mouse:
what should i modify? Does someone know a tutorial or a link?
There is a very simple way to do this. I had it on my old Tie Fighter game, lol. All u need to do is comment this line:
SetCursorPos(middleX, middleY);
This will stop the mouse being set to middle. And the distance will keep being added the further away u are from middle. Good Luck
SetCursorPos(middleX, middleY);
This will stop the mouse being set to middle. And the distance will keep being added the further away u are from middle. Good Luck
------------ "Here lies a toppled God,His fall was not a small one,We but built his pedastle,A narrow, and a tall one" Frank Herbert (Dune:Messiah)
What happens instead then.
------------ "Here lies a toppled God,His fall was not a small one,We but built his pedastle,A narrow, and a tall one" Frank Herbert (Dune:Messiah)
Basically, I can see 2 problems in your approach :
- you calculate the angles using the mouse movement only. You should "add" the mouse movement to previous values of the angles ;
- you might want to use a quaternion to store the orientation. You will avoid gimbal lock problems.
Tell me if you want me to post some code. I have a class that handles the position and orientation of objects/cameras that is pretty easy to use.
- you calculate the angles using the mouse movement only. You should "add" the mouse movement to previous values of the angles ;
- you might want to use a quaternion to store the orientation. You will avoid gimbal lock problems.
Tell me if you want me to post some code. I have a class that handles the position and orientation of objects/cameras that is pretty easy to use.
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
What I do in those cases is store the orientation of the ship as a 4x4 matrix (a quaternion works too).
From this matrix, I can extract the up/side/forward vectors through matrix multiplication so I can move the ship the right way.
To rotate, I simply generate a new rotation matrix (around the X Y or Z axis) and multiply the previous matrix by the new one: this changes the orientation as by a real rotation.
The "view" matrix is the inverse of the orientation matrix multiplied by the translation matrix (which you get from the position of the ship).
From this matrix, I can extract the up/side/forward vectors through matrix multiplication so I can move the ship the right way.
To rotate, I simply generate a new rotation matrix (around the X Y or Z axis) and multiply the previous matrix by the new one: this changes the orientation as by a real rotation.
The "view" matrix is the inverse of the orientation matrix multiplied by the translation matrix (which you get from the position of the ship).
@rodzilla: it would be very nice if you post your camera class :)
anyway, i've changed my approach: i don't need anymore to rotate the camera with the mouse, i have to use only the keyboard. So now for example, if i keep pressed the UP key, the camera view changes doing a complete circle if necessary.
I hope i've been clear...
anyway, i've changed my approach: i don't need anymore to rotate the camera with the mouse, i have to use only the keyboard. So now for example, if i keep pressed the UP key, the camera view changes doing a complete circle if necessary.
I hope i've been clear...
Here's the class I use to handle camera/objects movement.
First the math-related stuff ; you probably have your own classes so I won't put mine in here. All you need is a Vector3 and a Quaternion classes. You should define glTranslate and inv_glTranslate for the Vector3 and glRotate and inv_glRotate for the Quaternion.
glTranslate is straightforward, glRotate is:
Here's the PO (position-orientation) class:
Here's how to use the PO:
Sure this class could be made easier-to-use (add rotate_x, rotate_y and rotate_z functions for example).
Any feedback welcome !
First the math-related stuff ; you probably have your own classes so I won't put mine in here. All you need is a Vector3 and a Quaternion classes. You should define glTranslate and inv_glTranslate for the Vector3 and glRotate and inv_glRotate for the Quaternion.
glTranslate is straightforward, glRotate is:
voidQuaternion::glRotate() const { float scale_2 = x*x+y*y+z*z; if (scale_2 != 0.0) { float angle = acos(w); float inv_scale = inv_sqrt(scale_2); glRotatef(114.59155902616464175358*angle, x*inv_scale, y*inv_scale, z*inv_scale); }}
Here's the PO (position-orientation) class:
class PO {protected: //! Position. Vector3 m_position; //! Orientation. Quaternion m_orientation; //! A vector facing forward. Vector3 m_forward; //! A vector facing up. Vector3 m_up; //! A vector facing right. Vector3 m_right; void update_vectors();public: //! Default constructor. PO(); //! Get the position. /*! \return the position. */ const Vector3& get_position() const { return m_position; } //! Set the position. /*! \param p the new position. */ void set_position(const Vector3& p); //! Get the orientation. /*! \return the orientation. */ const Quaternion& get_orientation() const { return m_orientation; } //! Set the orientation. /*! \param p the new orientation. */ void set_orientation(const Quaternion& q); //! Move the PO. /*! \param v the translation vector in world coordinates. */ void translate(const Vector3& v); //! Rotate the PO. /*! \param q the rotation quaternion in world coordinates. */ void rotate(const Quaternion& q); //! Return the PO's forward vector. /*! \return the PO's forward vector in world coordinates. */ const Vector3& forward() const { return m_forward; } //! Return the PO's up vector. /*! \return the PO's up vector in world coordinates. */ const Vector3& up() const { return m_up; } //! Return the PO's right vector. /*! \return the PO's right vector in world coordinates. */ const Vector3& right() const { return m_right; }};voidPO::update_vectors() { m_right.x = 1.0f - 2.0f * ( m_orientation.y * m_orientation.y + m_orientation.z * m_orientation.z ); m_up.x = 2.0f * ( m_orientation.x * m_orientation.y - m_orientation.w * m_orientation.z ); m_forward.x = -2.0f * ( m_orientation.x * m_orientation.z + m_orientation.w * m_orientation.y ); m_right.y = 2.0f * ( m_orientation.x * m_orientation.y + m_orientation.w * m_orientation.z ); m_up.y = 1.0f - 2.0f * ( m_orientation.x * m_orientation.x + m_orientation.z * m_orientation.z ); m_forward.y = -2.0f * ( m_orientation.y * m_orientation.z - m_orientation.w * m_orientation.x ); m_right.z = 2.0f * ( m_orientation.x * m_orientation.z - m_orientation.w * m_orientation.y ); m_up.z = 2.0f * ( m_orientation.y * m_orientation.z + m_orientation.w * m_orientation.x ); m_forward.z = 2.0f * ( m_orientation.x * m_orientation.x + m_orientation.y * m_orientation.y ) - 1.0f; }// The default construtor initializes the forward, up and right vectors.PO::PO() : m_forward(0, 0, -1), m_up(0, 1, 0), m_right(1, 0, 0) {}// Moving the camera means adding a given vector to its position.voidPO::translate(const Vector3& v) { m_position += v;}// Rotate the camera :voidPO::rotate(const Quaternion& q) { // apply the rotation to the orientation. m_orientation *= q; update_vectors();}// Set the camera's position.voidPO::set_position(const Vector3& p) { m_position = p;}// Set the camera's orientation.voidPO::set_orientation(const Quaternion& q) { m_orientation = q; update_vectors();}
Here's how to use the PO:
// If the PO is used for a camera you can do the following// before drawing your scene :glMatrixMode(GL_MODELVIEW);glLoadIdentity(); // Set it to identity.po.get_orientation().inv_glRotate(); // Apply the inverted rotation po.get_position().inv_glTranslate(); // Apply the inverted translation// If the PO is used for an object you can do the// following before drawing it :po.get_orientation().glRotate(); // Apply the rotation po.get_position().glTranslate(); // Apply the translation// If you want to translate the camera/object, just use// the translate() method and forward, right, up vectors.// Here's how I handle keyboard-controlled time-based movement:float forward_move = (key_state(SDLK_e)-key_state(SDLK_x));float right_move = (key_state(SDLK_d)-key_state(SDLK_s));float up_move = (key_state(SDLK_r)-key_state(SDLK_c));Vector3 tmp = forward_move*m_camera.po.forward() + right_move*m_camera.po.right() + up_move*m_camera.po.up();m_camera.po.translate(dt*50.0*tmp);// Rotating is nearly as easy :boolTutorial::handle_mouse_motion(const int x, const int y) { if (mouse_button_state(SDL_BUTTON_RIGHT)) { // If right mouse button is pressed the mouse if (x != 0) { // rotates the camera around its forward vector. Vector3 v(0, 0, -1); // This is the forward vector (in camera coordinates). Quaternion q(v, x*0.001); // Create a quaternion that holds a rotation // around this vector. m_camera[m_current_camera].po.rotate(q);// Rotate the camera. } } else { // If right mouse button is not pressed the mouse if (x != 0) { // rotates the camera around its up and right vectors. Vector3 v(0, 1, 0); Quaternion q(v, -x*0.001); m_camera[m_current_camera].po.rotate(q); } if (y != 0) { Vector3 v(1, 0, 0); Quaternion q(v, -y*0.001); m_camera[m_current_camera].po.rotate(q); } } return true;}
Sure this class could be made easier-to-use (add rotate_x, rotate_y and rotate_z functions for example).
Any feedback welcome !
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement