Jump to content
  • Advertisement
Sign in to follow this  
BlackJoker

How to get rid of camera z-axis rotation

This topic is 1394 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. 

I have an issue with my quternion based camera: when I move it only on X and Y axis fast it is also begin rotate around Z axis, but it shouldn`t.

I use sharpDX lib and my code is following:

public void RotateX(float _degree_angle)
        {
            if (cameraType == CamType.ThirdPerson)
            {
                _degree_angle = -_degree_angle;
            }

            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitX, MathUtil.DegreesToRadians(_degree_angle)), qRotation);
            
            UpdateViewMatrix();
        }

        public void RotateY(float _degree_angle)
        {
            if (cameraType == CamType.ThirdPerson)
            {
                _degree_angle = -_degree_angle;
            }

            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitY, MathUtil.DegreesToRadians(_degree_angle)), qRotation);
            
            UpdateViewMatrix();
        }

private void UpdateViewMatrix()
        {
            qRotation = Quaternion.Normalize(qRotation);

            if (CameraType == CamType.ThirdPerson)
            {
                ViewMatrix = Matrix.Translation(Vector3.Negate(position)) * Matrix.RotationQuaternion(qRotation);

                position -= new Vector3(ViewMatrix.M13, ViewMatrix.M23, ViewMatrix.M33) * radius;

                ViewMatrix = Matrix.LookAtLH(position, lookAt, new Vector3(ViewMatrix.M12, ViewMatrix.M22, ViewMatrix.M32));
            }
            else
            {
                ViewMatrix = Matrix.Translation(Vector3.Negate(position)) * Matrix.RotationQuaternion(qRotation);
            }
        }

I tried to change order of multiplying for x and y quaternion rotations like this:

qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitY, MathUtil.DegreesToRadians(_degree_angle)), qRotation);

qRotation = Quaternion.Multiply(qRotation, Quaternion.RotationAxis(Vector3.UnitX, MathUtil.DegreesToRadians(_degree_angle2))); 

This helps - after that camera no longer rotate on Z-axis during fast moving on x-y axis, but if I move it on diagonal, if begins to rotate around all 3 axis, describing virtual 8 digit.

 

Could someone please point me the right way working with quaternions to stop camera rotation around Z-axis when I don`t need this?

 

This issue is driving me crazy.

 

Share this post


Link to post
Share on other sites
Advertisement

I use front, side and up vector for my camera. after each update, I will set the y component of the side vector zero, so that no rotation around z axis is possible. After that, I will normalize the vector and recompute the front and up vector.

Share this post


Link to post
Share on other sites

Could you please give the code responcible for recomputing the front and up vectors?

Or (better) the whole view matrix update. 

Share this post


Link to post
Share on other sites

D3DXVECTOR3 eye; //camera position

D3DXVECTOR3 at; //where you look at

D3DXVECTOR3 up(0,1,0); //assume the up vector is always pointing up, could have problem when you look straight up

D3DXVECTOR3 front = Normalize(at - eye);

D3DXVECTOR3 side = cross(front,up); //if you look through front vector, side vector will be on your right

use D3DXMatrixLookAtLH(....) or XMMatrixLookAtLH(...) to update the view matrix

Share this post


Link to post
Share on other sites

Thanks, but side and front is not using in XMMatrixLookAtLH(...) or D3DXMatrixLookAtLH(...). Where and when I need to apply them?

Edited by BlackJoker

Share this post


Link to post
Share on other sites

D3DXVECTOR3 eye; //camera position

D3DXVECTOR3 at; //where you look at

D3DXVECTOR3 up(0,1,0); //assume the up vector is always pointing up, could have problem when you look straight up

D3DXVECTOR3 front = Normalize(at - eye);

D3DXVECTOR3 side = cross(front,up); //if you look through front vector, side vector will be on your right

use D3DXMatrixLookAtLH(....) or XMMatrixLookAtLH(...) to update the view matrix

Doesn't D3DXMatrixLookAtLH(....) or XMMatrixLookAtLH(...) take as income parameters the mentioned 'eye', 'at' and 'up' and construct 'front' and 'side' automatically?

Share this post


Link to post
Share on other sites
If you rotate around the X axis, then rotate around the Y axis, then undo the rotation around the X axis, and finally undo the rotation around the Y axis, the resulting transformation is a rotation around the Z axis. This is a feature of rotations in 3D space, and you will observe it regardless of whether you use quaternions or anything else to represent them.

Perhaps instead of rotating around the X and Y axes, you meant to control pitch and yaw. If that's the case, use those angles to build the rotation from scratch every time.

Share this post


Link to post
Share on other sites

 

D3DXVECTOR3 eye; //camera position

D3DXVECTOR3 at; //where you look at

D3DXVECTOR3 up(0,1,0); //assume the up vector is always pointing up, could have problem when you look straight up

D3DXVECTOR3 front = Normalize(at - eye);

D3DXVECTOR3 side = cross(front,up); //if you look through front vector, side vector will be on your right

use D3DXMatrixLookAtLH(....) or XMMatrixLookAtLH(...) to update the view matrix

Doesn't D3DXMatrixLookAtLH(....) or XMMatrixLookAtLH(...) take as income parameters the mentioned 'eye', 'at' and 'up' and construct 'front' and 'side' automatically?

 

After 'side = cross(front,up)', set 'side.y = 1', then normalize it, then recompute the up vector.

At this time, 'eye' and 'at' haven't changed, but 'up' has changed. 

If you have rotation angle, álvaro's method would be simpler.

Share this post


Link to post
Share on other sites

If you rotate around the X axis, then rotate around the Y axis, then undo the rotation around the X axis, and finally undo the rotation around the Y axis, the resulting transformation is a rotation around the Z axis. This is a feature of rotations in 3D space, and you will observe it regardless of whether you use quaternions or anything else to represent them.

Perhaps instead of rotating around the X and Y axes, you meant to control pitch and yaw. If that's the case, use those angles to build the rotation from scratch every time.

 

Could you please write working example for your suggestion?

We already tried to accum degrees, but as a result, camera moving not on orbit, but on trajectory 8  (rotating in all 3 axis at the same time).

Edited by BlackJoker

Share this post


Link to post
Share on other sites

If you're trying to do a 3rd person camera, I'll echo Álvaro and suggest you just keep track of camera yaw and position then construct the transform each frame.

 

Pseudo code:

class Camera
{
 float m_yaw; // Should be a value between 0 and 2 PI
 float m_pitch; // Value between -PI/2 and PI/2
 Vector3 m_position;
 Matrix  m_cameraMatrix;
 
 void Update()
 {
 	Vector2 deltaMousePos; // Assume this is a 2D vector that has the delta X/Y of our mouse cursor since the last frame.
 	
 	m_yaw += deltaMousePos.x;
 	m_pitch += deltaMousePos.y;
 	
 	// Construct our rotation based on our current yaw/pitch
 	Quaternion yRotation(Vector3::UnitY, m_yaw);
 	Quaternion xRotation(Vector3::UnitX, m_pitch);
 	
 	m_cameraMatrix = Matrix::Identity;
 	m_cameraMatrix *= (xRotation * yRotation);
 	m_cameraMatrix.translation = m_position; // Restore our position.
 }
 
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!