I'm writing a Windows tool that uses XNA and allows the user to place textures on the screen.
I'm using a 'camera' for the SpriteBatch used to draw the textures, e.g:
Matrix matrixForSpriteBatch = Matrix.CreateTranslation( -_cameraPosition.X, -_cameraPosition.Y, 0.0f) *Matrix.CreateRotationZ(_rotation) *Matrix.CreateScale(_scale) *Matrix.CreateTranslation( GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, 0.0f);
This is working fine - the user can drop a texture onto the canvas and move, rotate and size it. They can also move the camera around to see more things.
What I now want to do is let the users click around to define points of a polygon. These points are then sent to my DrawPolygonFilled
method:
public void DrawPolygonFilled( SpriteBatch spriteBatch, Vector2[ ] worldPoints, Color color ){ Matrix matrixForVertices = Matrix.CreateTranslation( _cameraPosition.X, -_cameraPosition.Y, 0.0f ) * Matrix.CreateRotationZ( -rotation ) * Matrix.CreateScale( camera.Scale ) ; Vector2[] transformedPoints = worldPoints.Transform( matrixForVertices ) ; var vertices = new VertexPositionColor[ transformedPoints.Length ] ; for (int i = 0; i < transformedPoints.Length; i++) { vertices[ i ] = new VertexPositionColor( new Vector3( transformedPoints[ i ], 0 ), color ) ; } Vector2[ ] outputVertices ; short[ ] outputIndicies ; Vertices.Triangulate( transformedPoints, Vertices.WindingOrder.Clockwise, out outputVertices, out outputIndicies ) ; if (outputIndicies.Length > 0) { foreach( EffectPass pass in _basicEffect.CurrentTechnique.Passes ) { pass.Apply( ) ; spriteBatch.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>( Microsoft.Xna.Framework.Graphics.PrimitiveType.TriangleList, vertices, 0, vertices.Length, outputIndicies, 0, outputIndicies.Length /3 ) ; } }}
This isn't displaying anything as the client space for BasicEffect
is 0,0 at top-left, and 1-1 at bottom-right.So I added this to BasicEffect
:
_basicEffect = new BasicEffect( GraphicsDevice ) { VertexColorEnabled = true } ;_viewMatrix = Matrix.CreateLookAt( new Vector3( 0, 0, GraphicsDevice.Viewport.Width ), Vector3.Zero, Vector3.Up ) ;_projectionMatrix = Matrix.CreateOrthographic( GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, .1f, GraphicsDevice.Viewport.Width ) ;_basicEffect.Projection = _projectionMatrix ;_basicEffect.View = _viewMatrix ;
With this, the polygon is displayed but it's upside-down. Also, when the position of the polygon changes (the user can drag the polygon around with the mouse), the polygon goes up when the user moves the mouse down!
I'm a bit thick (but trying to become less thick) when it comes to matrices and geometry. Am I missing something? I tried changing Down
to Up
in CreateLookAt
but it still didn't draw correctly and now when the user mouses left, then polygon goes right!
Here's a screen-shot when drawing a polygon at 0,0:
The points on the white path are where the user clicked (and are drawn with SpriteBatch) and the yellow polygon is what's drawn by my method above.
Here's another screen-shot that show what happens when I move the polygon to 20,20:
The white path is drawn starting from 20,20, but the filled polygon is starting from 20,-20 and is drawn upside-down
I think this is a matrix issue between the matrix used by the SpriteBatch
(to draw the white paths) and the matrix used by the BasicEffect
(to draw the filled polygon).