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).