SpriteBatchで使用されているマトリックスとBasicEffectで使用されているマトリックスを整列させる方法を教えてください。


7

XNAを使用して、ユーザーが画面にテクスチャを配置できるWindowsツールを作成しています。

テクスチャの描画に使用されるSpriteBatchに「カメラ」を使用しています。例:

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

これは正常に機能しています。ユーザーはキャンバスにテクスチャをドロップし、移動、回転、サイズ変更できます。また、カメラを動かしてより多くのものを見ることができます。

次に、ユーザーがクリックしてポリゴンのポイントを定義できるようにします。次に、これらのポイントが私のDrawPolygonFilledメソッドに送信されます。

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 ) ;
        }
    }
}

クライアントスペースBasicEffectは左上が0,0、右下が1-1であるため、これは何も表示していません。だから私はこれをに追加しました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 ;

これにより、ポリゴンは表示されますが、上下が逆になります。また、ポリゴンの位置が変わると(ユーザーはマウスでポリゴンをドラッグできます)、ユーザーがマウスを下に動かすとポリゴンが上がります!

マトリックスとジオメトリに関しては、少し厚みがあります(ただし、厚みを薄くしようとしています)。何か不足していますか?に変更DownしてみUpましたCreateLookAtが、まだ正しく描画されず、ユーザーがマウスを左に動かすと、ポリゴンが右に移動します。

以下は、0,0にポリゴンを描画するときのスクリーンショットです。 ここに画像の説明を入力してください

白いパス上のポイントは、ユーザーがクリックした場所(およびSpriteBatchで描画された場所)であり、黄色のポリゴンは上記の私の方法で描画されたものです。

次に、ポリゴンを20,20に移動したときに何が起こるかを示す別のスクリーンショットを示します。 ここに画像の説明を入力してください

白いパスは20、20から始まりますが、塗りつぶされたポリゴンは20、20から始まり、逆さまに描かれます。

これはSpriteBatch(白いパスを描くために)が使用する行列とBasicEffect(塗りつぶされた多角形を描くために)が使用する行列の間の行列の問題だと思います。

回答:


5

r2d2rigoの答えはほぼ正しいです。一致するを設定するための正しいマトリックスコードは次のとおりです(Shawn Hargreavesのブログから):BasicEffectSpriteBatch

Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);

basicEffect.World = Matrix.Identity;
basicEffect.View = Matrix.Identity;
basicEffect.Projection = halfPixelOffset * projection;

ハーフピクセルオフセットに注意してください(説明MSDN)。


この乗算「halfPixelOffset *プロジェクション」は、目的が画面の左上座標に原点を持つことである場合、誤った結果を生成します。
エミールリマ2014年

1
@EmirLimaはい、しかし通常それは目的ではありません。OPの場合を含め、ほとんどの場合の目的は、同じ方法で画面のピクセルに合わせることSpriteBatchです。詳細については、私の回答のリンクを参照してください(もちろん、これはXNAおよびDirectX 9に適用されますが、DirectX 10およびOpenGLには適用されません)。
Andrew Russell 14年

3

SpriteBatchで使用されるマトリックスは、Matrix.CreateOrthographicOffCenterで作成されます。

Matrix ortho = Matrix.CreateOrthographicOffCenter(0.0f, yourWidth, yourHeight, 0.0f, 0.0f, 1.0f);

このようにして、左上隅にワールドの原点を保持します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.