3
\$\begingroup\$

Consider my following (abstracted) C# w/ SharpDX code:

class Game
{
    Camera _camera = new Camera();

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        // Roll
        if (e.KeyCode == Keys.Home)
        {
            _camera.TurnRoll(-0.05f);
        }
        else if (e.KeyCode == Keys.End)
        {
            _camera.TurnRoll(0.05f);
        }
        // Other rotation / movement works...
    }
}

class Camera
{
    private Vector3 _position;
    private Vector3 _rotation;
    private Vector3 _right;
    private Vector3 _up;
    private Vector3 _forward;
    private Matrix  _view;

    public Camera()
    {
        _right = Vector3.Right;
        _up = Vector3.Up;
        _forward = Vector3.ForwardLH;
        UpdateViewMatrix();
    }

    public void TurnRoll(float roll)
    {
        // Relative rotation
        _rotation.Z += roll;
        UpdateViewMatrix();
    }

    private void UpdateViewMatrix()
    {
        Matrix cameraRotationMatrix = Matrix.RotationYawPitchRoll(_rotation.Y, _rotation.X, _rotation.Z);
        Vector3 cameraTarget = Vector3.TransformCoordinate(Vector3.ForwardLH, cameraRotationMatrix);
        cameraTarget = cameraTarget.Normalize();
        cameraTarget += _position;

        // I bet the problem lies in and/or after this line
        Matrix rotateYTempMatrix = Matrix.RotationY(_rotation.Y);

        _right   = Vector3.TransformCoordinate(Vector3.Right,     rotateYTempMatrix);
        _up      = Vector3.TransformCoordinate(Vector3.Up,        rotateYTempMatrix);
        _forward = Vector3.TransformCoordinate(Vector3.ForwardLH, rotateYTempMatrix);

        _view = Matrix.LookAtLH(_position, cameraTarget, _up);
    }
}

My problem: Even when pressing the Home and End keys, the camera roll visibly stays untouched. I have trouble correcting my UpdateViewMatrix function, and I bet that the error is in there. I'm a bit lost with the maths here and my tries to use another rotation matrix to update the _up vector all failed or created other problems.

Can anybody clear my math mind up and help me correct this method?

EDIT: Solved with the help of winged's answer below. I edited the code to be

private void UpdateViewMatrix()
{
    Matrix rotation = Matrix.RotationYawPitchRoll(_rotation.Y, _rotation.X, _rotation.Z);

    _forward = Vector3.TransformCoordinate(Vector3.ForwardLH, rotation);
    _forward += _position;

    _up = Vector3.TransformCoordinate(Vector3.Up, rotation);

    _view = Matrix.LookAtLH(_position, _forward, _up);
}

However, this is still not completely correct. The camera rolls now, which solves this question. But if it is rolled and I try to yaw it, the yaw happens like as if the camera is non-rolled and moves along the default Y-axis :/. Especially when looking downwards 90 degrees this causes something like gimble-lock to happen (or IS it gimble lock?) because rolling and yawing the camera has the same effect then.

EDIT2: I completely replaced my rotation with quaternions. I don't know why people think these are "harder" or at least "different" to understand. This solution works perfectly.

public void Turn(Vector3 turning)
{
    // Relative rotation
    Quaternion delta = Quaternion.RotationYawPitchRoll(-turning.Y, -turning.X, -turning.Z);
    _rotation = delta * _rotation;
    _rotation.Normalize();
    UpdateViewMatrix();
}

public void TurnRoll(float roll)
{
    Turn(new Vector3(0, 0, roll));
}

private void UpdateViewMatrix()
{
    Matrix view = Matrix.RotationQuaternion(_rotation);
    Matrix translation = Matrix.Translation(-_position.X, -_position.Y, -_position.Z);
    _view = translation * view;
}
\$\endgroup\$
  • \$\begingroup\$ Are the values of the _up vector what you expect, and are you sure you're rotating around the correct axis? For roll you should rotate around the Z axis, or even better around the cameraTarget axis (depending on the style of camera you want). \$\endgroup\$ – Roy T. Apr 20 '14 at 11:34
  • \$\begingroup\$ You should move this to Stackoverflow \$\endgroup\$ – bluewhile Apr 20 '14 at 12:37
  • \$\begingroup\$ @bluewhile: Sorry, I'm often confused with SO vs. GD if it comes to game development questions ;S \$\endgroup\$ – Ray Koopa Apr 20 '14 at 12:43
  • \$\begingroup\$ This is a very basic code, so I'd put it on SO. Think you'll get there a faster answer as well when it comes to specific code stuff. \$\endgroup\$ – bluewhile Apr 20 '14 at 18:18
2
\$\begingroup\$

I guess that the problem lies in here:

_up = Vector3.TransformCoordinate(Vector3.Up, rotateYTempMatrix);

You're calculating the up vector (and also the rest of them) from a matrix unrelated to the cameraRotationMatrix matrix, in which you have stored the new rotation. Usually, what I do is multiply an old rotation matrix by the new rotation matrix, and then calculate the up vector from the outcome matrix.

Hope this helps.

\$\endgroup\$
  • \$\begingroup\$ You're right, I fixed the code, s. my edit in my answer for the final result. Howver, another problem arises, if I yaw my camera now when it's rolled, it yaw's around a non-rolled axis... I ask that on Stackoverflow as recommended. \$\endgroup\$ – Ray Koopa Apr 20 '14 at 19:21
  • \$\begingroup\$ I'm not familiar with SharpDX, but I believe that you didn't update the right and the forward camera vectors along with your up vector, so at the moment you are still rotating the camera along the old right vector (which is equal to world's right vector). \$\endgroup\$ – Winged Apr 20 '14 at 20:29
  • \$\begingroup\$ I thought the exact same thing :) however, as you can see from my code above - I don't even include the _right vector in my calculation... am I missing something? \$\endgroup\$ – Ray Koopa Apr 21 '14 at 10:08
  • \$\begingroup\$ My spider sense tells me that something is wrong with your function that moves the camera around ^^. Are you sure that you are moving your camera along newly calculated vectors? You could post the code of this function if you are unsure. \$\endgroup\$ – Winged Apr 21 '14 at 10:39
  • \$\begingroup\$ Well thanks for the help... after messing this up with vectors I got it working with a quaternion rotation. For some reason people say quaternions are harder to understand... but for me they're the only thing making sense :D should I post my new quaternion code? \$\endgroup\$ – Ray Koopa Apr 21 '14 at 11:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.