Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I asked this question on stackoverflow but assumed this might be a better area to ask it as well for a more informed answer.

My problem is that I am trying to create a camera class and have it so that my camera follows the proper RHS, however the Y axis seems to be inverted since on the screen the 0 starts at the top.

Here is my Camera2D Class:

    class Camera2D
    {
        private Vector2 _position;
        private float _zoom;
        private float _rotation;
        private float _cameraSpeed;
        private Viewport _viewport;
        private Matrix _viewMatrix;
        private Matrix _viewMatrixIverse;

        public static float MinZoom = float.Epsilon;
        public static float MaxZoom = float.MaxValue;

        public Camera2D(Viewport viewport)
        {
            _viewMatrix = Matrix.Identity;
            _viewport = viewport;
            _cameraSpeed = 4.0f;
            _zoom = 1.0f;
            _rotation = 0.0f;
            _position = Vector2.Zero;
        }

        public void Move(Vector2 amount)
        {
            _position += amount;
        }

        public void Zoom(float amount)
        {
            _zoom += amount;
            _zoom = MathHelper.Clamp(_zoom, MaxZoom, MinZoom);
            UpdateViewTransform();
        }

        public Vector2 Position
        {
            get { return _position; }
            set { _position = value; UpdateViewTransform(); }
        }

        public Matrix ViewMatrix
        {
            get { return _viewMatrix; }
        }


        private void UpdateViewTransform()
        {
             Matrix proj = Matrix.CreateTranslation(new Vector3(_viewport.Width * 0.5f, _viewport.Height * 0.5f, 0)) * 
                           Matrix.CreateScale(new Vector3(1f, 1f, 1f));

             _viewMatrix = Matrix.CreateRotationZ(_rotation) *
                          Matrix.CreateScale(new Vector3(_zoom, _zoom, 1.0f)) *
                          Matrix.CreateTranslation(_position.X, _position.Y, 0.0f);

             _viewMatrix = proj * _viewMatrix;

        }



    }

I test it using SpriteBatch in the following way:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    Vector2 position = new Vector2(0, 0);
    // TODO: Add your drawing code here
    spriteBatch.Begin(SpriteSortMode.Immediate,
        BlendState.AlphaBlend,
        null,
        null,
        null,
        null,
        camera.ViewMatrix);

    Texture2D circle = CreateCircle(100);
    spriteBatch.Draw(circle, position, Color.Red);
    spriteBatch.End();

    base.Draw(gameTime);
}
share|improve this question
    
I've answered my own question on StackOverflow –  Setheron Aug 19 '11 at 20:40
add comment

3 Answers

This is the mistake: Matrix.CreateTranslation(_position.X, _position.Y, 0.0f)

Make it like this: Matrix.CreateTranslation(-_position.X, -_position.Y, 0.0f)

Explanation: The matrix specifies how the world should be transformed, not how the camera is transformed. Thats why you need to insert the negative values.

share|improve this answer
    
Wouldn't that just be the inverse of the ViewMatrix? –  Setheron Aug 19 '11 at 13:46
    
I want to build the ViewMatrix and Projection Matrix such that I should just be using the inverse to from World to View. –  Setheron Aug 19 '11 at 13:46
1  
Also, using Matrix.CreateTranslation(-_position.X,_position.Y, 0.0f) [The Y Position is not negated] seems to be correct. When the Y is negated the Y value still remains inverted. –  Setheron Aug 19 '11 at 13:49
add comment

All of my Camera classes start with this as a base:


public class Camera {

    private Vector2 position = Vector2.Zero;

    public float Left {
        get { return position.X; }
        set { position.X = value; }
    }

    public float Top {
        get { return position.Y; }
        set { position.Y = value; }
    }

    public Matrix TransformMatrix {
        get {
            return Matrix.CreateTranslation( new Vector3( -position, 0f ) );
        }
    }

    public Camera( ) { }

} // Camera

I use the same method that Felheart has highlighted by inserting the negative values (-position) into the Matrix.CreateTranslation function call and have never had a problem with the camera moving in the wrong direction. My camera is used just like yours:


spriteBatch.Begin( 
    SpriteSortMode.Deferred, 
    BlendState.Additive, 
    SamplerState.AnisotropicClamp, 
    null, 
    null, 
    null, 
    camera.TransformMatrix );

spriteBatch.Draw( 
    someTexture, 
    x, 
    y, 
    width, 
    height, 
    color );

spriteBatch.End();
share|improve this answer
add comment
up vote 0 down vote accepted

So after just thinking logically, I was able to deduce the proper transformation. I'll outline the steps here incase anyone wants the real breakdown:

It is important to understand what is a Camera Transformation or View Transformation. A View Transformation is normally what is needed to go from Coordinates relative to your Camera to World-Space coordinates. The inverse of the View Transformation would then make a world coordinate relative to your Camera!

Creating a View Matrix

  1. Apply the camera's rotation. We are doing it in the Z axis only because this is for a 2D camera.
  2. Apply the transformation of the Camera. This make sense since we want the World coordinate which is the sum of the camera coordinate and the object relative to the camera.
    1. You might notice that I multiplied the Y Component by -1. This is so that increasing the Camera's Y Position correlates to moving up since the screen's Y value points downward.
  3. Apply the camera's zoom

Now the inverse of the matrix will do World Coordinate -> View Cordinates.

I also chose to center my camera in the center of the screen, so I included a pre-appended translation.

Matrix proj = Matrix.CreateTranslation(new Vector3(_viewport.Width * 0.5f, _viewport.Height * 0.5f, 0));

        _viewMatrix = Matrix.CreateRotationZ(moveComponent.Rotation) *
                    Matrix.CreateTranslation(moveComponent.Position.X, -1 * moveComponent.Position.Y, 0.0f) *
                     Matrix.CreateScale(new Vector3(zoomComponent.Zoom, zoomComponent.Zoom, 1.0f));

        _viewMatrix = proj * Matrix.Invert(_viewMatrix);
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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