Farseer coordinates and mouse coordinates

Topics: Developer Forum, Project Management Forum, User Forum
Jun 25, 2012 at 6:27 PM
Edited Jun 25, 2012 at 6:29 PM

Hello.

I ran into a little bit of a problem trying to create functionality to remove fixtures on mouse click. I'm sure this problem is a quite common one and perhaps even answered before, but I couldn't for the life of me find the answer.

I created a little video to demonstrate the problem:

http://www.youtube.com/watch?v=GD_P2z3ldKI&feature=youtu.be 

Basically the Farseer body is out of sync with the mouse cursor, except on the middle of the screen on the very top.

The position of the body is set this way:

Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

position = Camera2D.ConvertScreenToWorld(position);
// mouseBall is just a static body
mouseBall.Position = position;

 

 

Camera2D class is the one that comes with either the testbed or the samples of Farseer Physics. 

The Projection is set with:

 

Vector2 _lower = -new Vector2(25.0f * GraphicsDevice.Viewport.AspectRatio, 25.0f);
Vector2 _upper = new Vector2(25.0f * GraphicsDevice.Viewport.AspectRatio, 25.0f);

// L/R/B/T
Matrix Projection = Matrix.CreateOrthographicOffCenter(_lower.X, _upper.X, _lower.Y, _upper.Y, -1, 1);

 

I noticed that by fiddling around with the projection and it's parameters the problem would change.

Sometimes the 'cursor' (mouseBall) was too fast compared to the cursor etc. While this could be used to fix the problem, I won't accept such a hacky way, and I want to know what causes it and what am I doing wrong. 

Jun 25, 2012 at 8:22 PM

There is something unclear in your code. There is no Camera2D in the testbed so you must be using the class from the samples. But the projection you set seems lifted off the TestBed because the Camera2D sets it's properties in the constructor. I'm a bit confused.

If you're using the TestBed it should be enough to call GameInstance.ConvertScreenToWorld() like in Framework\Test.cs

If you're using the samples screen system then the projection seems wrong.

Jun 25, 2012 at 8:43 PM

I'm not using the testbed, and I do have an instance of the Camera2D in use for my own project. 

The projection indeed seems to be wrong, but I can't figure out what to do to it 

Jun 25, 2012 at 9:29 PM

If you're using the samples ScreenSystem why do you need to set a projection? It does it automatically. I think when you draw you use your own projection and not the Camera's and when you unproject you pass the projected values from your own projection but the Camera has different matrices.

Try this to unproject (lifted off the testbed). If I'm right it will solve the issue and you can discard the camera altogether although I don't think you'd want to do that:

        public Vector2 ConvertScreenToWorld(int x, int y)
        {
            Vector3 temp = GraphicsDevice.Viewport.Unproject(new Vector3(x, y, 0), Projection, View,
                                                             Matrix.Identity);

            return new Vector2(temp.X, temp.Y);
        }

Jun 25, 2012 at 10:14 PM

I am not using the ScreenSystem entirely, I am using only the Camera2D class and I can't really ditch the camera system due to the way my game works. I tried what you proposed and the problem is exactly the same what it was before.

Jun 26, 2012 at 11:26 AM

Are you sure you're not setting a projection somewhere else in the game ? Like the main game class ?

Jun 26, 2012 at 2:04 PM
Edited Jun 26, 2012 at 3:40 PM

No, that projection is set just before I call DebugView.RenderDebugData. Like so:

   protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            Vector2 _lower = -new Vector2(25.0f * GraphicsDevice.Viewport.AspectRatio, 25.0f);
            Vector2 _upper = new Vector2(25.0f * GraphicsDevice.Viewport.AspectRatio, 25.0f);

            // L/R/B/T
            Matrix Projection = Matrix.CreateOrthographicOffCenter(_lower.X, _upper.X, _lower.Y, _upper.Y, -1, 1);
         //   Matrix Projection = Matrix.CreateOrthographicOffCenter(-25 * GraphicsDevice.Viewport.AspectRatio, 25 * GraphicsDevice.Viewport.AspectRatio, -25, 25, -1, 1);

            
            Matrix View = cam.GetView();

         //   DebugView.Flags = FarseerPhysics.DebugViewFlags.AABB | FarseerPhysics.DebugViewFlags.PerformanceGraph | FarseerPhysics.DebugViewFlags.CenterOfMass | FarseerPhysics.DebugViewFlags.Joint | FarseerPhysics.DebugViewFlags.ContactNormals | FarseerPhysics.DebugViewFlags.Controllers | FarseerPhysics.DebugViewFlags.PolygonPoints;
            DebugView.RenderDebugData(ref Projection, ref View);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
 
Jun 26, 2012 at 6:20 PM

Oh boy.


I figured out what caused that. It was quite obvious when I sat down to think about it.

I had these rows in the code:

            graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width - 50;
            graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height - 100;


            graphics.ApplyChanges();

 

And these were run AFTER initializing the camera, debugview and all that. Oh god I am embarassed.

Jun 27, 2012 at 12:10 PM

I was actually about the suggest to check the Buffer size :D ,crap like that always happens !