Estou escrevendo uma ferramenta do Windows que usa XNA e permite que o usuário coloque texturas na tela.
Estou usando uma 'câmera' para o SpriteBatch usado para desenhar as texturas, por exemplo:
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);
Isso está funcionando bem - o usuário pode soltar uma textura na tela e movê-la, girá-la e dimensioná-la. Eles também podem mover a câmera para ver mais coisas.
O que agora quero fazer é permitir que os usuários cliquem ao redor para definir os pontos de um polígono. Esses pontos são então enviados para o meu DrawPolygonFilled
método:
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 ) ;
}
}
}
Isso não está exibindo nada, pois o espaço do cliente BasicEffect
é 0,0 na parte superior esquerda e 1-1 na parte inferior direita. Então eu adicionei isso a 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 ;
Com isso, o polígono é exibido, mas de cabeça para baixo. Além disso, quando a posição do polígono muda (o usuário pode arrastar o polígono com o mouse), o polígono aumenta quando o usuário move o mouse para baixo!
Sou um pouco grossa (mas estou tentando ficar menos grossa) quando se trata de matrizes e geometria. Estou esquecendo de algo? Eu tentei mudar Down
para Up
dentro, CreateLookAt
mas ele ainda não desenhou corretamente e agora, quando o usuário passa o mouse para a esquerda, o polígono vai para a direita!
Aqui está uma captura de tela ao desenhar um polígono em 0,0:
Os pontos no caminho branco são onde o usuário clicou (e é desenhado com SpriteBatch) e o polígono amarelo é o que é desenhado pelo meu método acima.
Aqui está outra captura de tela que mostra o que acontece quando movo o polígono para 20,20:
O caminho em branco é desenhado a partir de 20,20, mas o polígono preenchido está começando em 20, -20 e é desenhado de cabeça para baixo
Eu acho que esse é um problema de matriz entre a matriz usada pelo SpriteBatch
(para desenhar os caminhos brancos) e a matriz usada pelo BasicEffect
(para desenhar o polígono preenchido).
SpriteBatch
faz. Veja os links na minha resposta para obter mais detalhes (e observe, é claro, isso se aplica ao XNA e DirectX 9, mas não ao DirectX 10 e OpenGL).A matriz usada no SpriteBatch é criada com Matrix.CreateOrthographicOffCenter:
Dessa forma, você manterá sua origem mundial no canto superior esquerdo.
fonte