Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (3 posts)

camera rotation in 3D space

Last post 1/6/2012 9:44 AM by Lost World Creations. 2 replies.
  • 1/4/2012 11:55 AM

    camera rotation in 3D space

    Hello, I know this question is a common one but my brain is now fried. I have tried looking into it and everyone seems to do the camera stuff differently and now I am confused as to what I need.

    My code is below. I am trying to create a view matrix to rotate, tilt and yaw my camera in 3D space. No matter how I change it around I cant seem to get all the rotations to play ball. I think it has something to do with my up vector in the CreateLookAt call. This version of the code seems to rotate ok but the tilt gets thrown off once you rotate the camera. Its not tilting from camera's rotated angle.

    // Get the camera matrix

     

     

    public Matrix GetCameraMatrix()

     

    {

     

     

    // Create a rotation matrix to calculate new vectors

     

    rotationMatrix =

     

    Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(this.Spin), MathHelper.ToRadians(this.Tilt), MathHelper.ToRadians(this.Roll));

     

     

     

     

    // Transform the look at point to take account of the rotation

     

     

     

    Vector3 transformedReference = Vector3.Transform(new Vector3(0, 0, -1), rotationMatrix);

     

     

     

    // Where will we be looking in the lookat call

     

     

     

    Vector3 target = this.Position + transformedReference;

     

     

     

    // Adjust the up axis to always point up according to the camera

     

     

     

    Vector3 up = Vector3.Transform(Vector3.Up, rotationMatrix);

     

    target.Normalize();

    up.Normalize();

     

     

    return Matrix.CreateLookAt(this.Position, target, up);

     

    }

    Hopefully it is something very simple I am missing :o(

    Paul

  • 1/4/2012 1:36 PM In reply to

    Re: camera rotation in 3D space

    If you are essentially only utilizing yaw & pitch then angles are fine and you need to just order them properly:
    In your createLookAt, use Vector3.Up for the 3rd param instead of your 'up'.
    Internally, the createLookAt does create a new 'up' kinda like what you are trying to do with making your 'up', but if it starts with Vector3.Up, it wont let it tilt when it makes the final 'up', but the cost here is that it precludes you from ever intentionally inducing roll.
    Here is a video I made to describe that problem: http://www.screencast.com/users/sh8zen/folders/Xna/media/929e0a9a-16d1-498a-b777-8b3d85fd8a00
    Basically, to avoid tilt, it is better to pitch first then yaw (your 'spin').
    If, on the other hand, you plan to intentionally roll your camera at times, then your problem would be that storing angles becomes unfriendly and CreateYawPitchRoll() won't work for you. It would be necessary then to extract the camera's local space axes and rotate about them individually. To do this, it is easiest to instead of storing overall angles that represent world space yaw, pitch, & roll, Store only the camera's position, target, & last frame's up direction. Then yaw, pitch, or roll the target about the position:

    Matrix camOrientation= Matrix.Invert(view);

    //to pitch (tilt) the target about the position around an axis that is sticking out the side of the camera regardless of camera orientation
    target = Vector3.Transform(target - position, Matrix.CreateFromAxisAngle(camOrientation.Right, amountToPitchThisFrame)) + position;


    // to Yaw (pan)
    target = Vector3.Transform(target - position, Matrix.CreateFromAxisAngle(camOrientation.Up, amountToYawThisFrame)) + position;

    //to roll
    Vector3 up = Vector3.Transform(camOrientation.Up, Matrix.CreateFromAxisAngle(camOrientation.Forward, amountToRollThisFrame));

    // to move forward (w)
    Position += camOrientation.Forward * speedPerSecond * elapsedTimeSinceLastUpdate;
    target += camOrientation.Forward * speedPerSecond * elapsedTimeSinceLastUpdate;

    //to strafe right (d)
    Position += camOrientation.Right * speedPerSecond * elapsedTimeSinceLastUpdate;
    target += camOrientation.Right * speedPerSecond * elapsedTimeSinceLastUpdate;

    //to move vertically, simply do the same as (w) or (a) but use either the camOr.Up or Vector3.Up.

    //build final camera view matrix
    view = Matrix.CreateLookAt(position, target, up);

    This liberates you from needing to keep track of overall yaw, pitch, and roll angles.
  • 1/6/2012 9:44 AM In reply to

    Re: camera rotation in 3D space

    Hello, thanks for the response it was very helpfu :o)

    I have now converted over to using quarternion rotation and so far it all seems to be working perfectly :o)

    For anyone else who is looking here is a very basic camera using quarternions

     

     

    /// <summary>

     

     

     

    /// Basic Camera

     

     

     

    /// </summary>

     

     

     

    public class CameraBasic

     

    {

     

     

    private Quaternion rotation;

     

     

     

    private Vector3 position;

     

     

     

    public CameraBasic()

     

    {

     

     

    this.rotation = Quaternion.Identity;

     

     

     

    this.position = new Vector3(0, 0, 0);

     

    }

     

     

    public Quaternion RotQuarternion

     

    {

     

     

    get { return this.rotation; }

     

    }

     

     

    public Vector3 UpVector

     

    {

     

     

    get

     

    {

     

     

    return Vector3.Transform(Vector3.Up, Matrix.CreateFromQuaternion(this.rotation));

     

    }

    }

     

     

    public void AddRotation(Quaternion newquart)

     

    {

     

     

    this.rotation *= newquart;

     

    }

     

     

    public Matrix GetViewMatrix(Vector3 target)

     

    {

     

     

    Vector3 campos = new Vector3(0, 0, -1);

     

    campos =

     

    Vector3.Transform(campos, Matrix.CreateFromQuaternion(this.rotation));

     

    campos += target;

     

     

    return Matrix.CreateLookAt(target, campos, this.UpVector);

     

    }

    }

    To rotate the camera you just need to do the following. This is how much to add not the whole angle.

     

     

     

    Quaternion rotate= Quaternion.CreateFromAxisAngle(new Vector3(0, 0, -1), MathHelper.ToRadians(Roll)) * Quaternion.CreateFromAxisAngle(new Vector3(1,0,0), MathHelper.ToRadians(Tilt)) * Quaternion.CreateFromAxisAngle(new Vector3(0,1,0), MathHelper.ToRadians(Yaw));

     

     

     

     

     

     

     

     

    camera.AddRotation(rotate);


    To move forward in the direction of the camera its also very easy

     

    Vector3

     

     

    movevec = new Vector3(0 ,0 ,-1 ); // a vector of our movement (Move forward along Z)

     

    movevec =

     

    Vector3.Transform(movevec, camera.RotQuarternion);

     

     

     

    OriginalPosition += movevec;

    Hope that helps anyone else having trouble :o)

    Paul

     

Page 1 of 1 (3 posts) Previous Discussion Next Discussion