Làm cách nào để căn chỉnh ma trận được sử dụng trong SpriteBatch và ma trận được sử dụng trong BasicEffect?


7

Tôi đang viết một công cụ Windows sử dụng XNA và cho phép người dùng đặt họa tiết trên màn hình.

Tôi đang sử dụng 'máy ảnh' cho SpriteBatch được sử dụng để vẽ họa tiết, ví dụ:

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

Điều này đang hoạt động tốt - người dùng có thể thả một kết cấu vào khung vẽ và di chuyển, xoay và kích thước nó. Họ cũng có thể di chuyển camera xung quanh để xem nhiều thứ hơn.

Những gì tôi muốn làm bây giờ là cho phép người dùng nhấp xung quanh để xác định các điểm của đa giác. Những điểm này sau đó được gửi đến DrawPolygonFilledphương thức của tôi :

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

Điều này không hiển thị bất cứ điều gì vì không gian máy khách cho BasicEffect0,0 ở phía trên bên trái và 1-1 ở dưới cùng bên phải. Vì vậy, tôi đã thêm điều này vào 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 ;

Với điều này, đa giác được hiển thị nhưng nó lộn ngược. Ngoài ra, khi vị trí của đa giác thay đổi (người dùng có thể kéo đa giác xung quanh bằng chuột), đa giác sẽ tăng lên khi người dùng di chuyển chuột xuống!

Tôi hơi dày (nhưng cố gắng để trở nên ít dày hơn) khi nói đến ma trận và hình học. Tui bỏ lỡ điều gì vậy? Tôi đã thử thay đổi Downthành Uptrong CreateLookAtnhưng nó vẫn không vẽ chính xác và bây giờ khi người dùng chuyển sang trái, thì đa giác sẽ chuyển sang phải!

Đây là ảnh chụp màn hình khi vẽ đa giác ở 0,0: nhập mô tả hình ảnh ở đây

Các điểm trên đường dẫn màu trắng là nơi người dùng nhấp vào (và được vẽ bằng SpriteBatch) và đa giác màu vàng là những gì được vẽ theo phương pháp của tôi ở trên.

Đây là một ảnh chụp màn hình khác cho thấy những gì xảy ra khi tôi di chuyển đa giác đến 20,20: nhập mô tả hình ảnh ở đây

Đường dẫn màu trắng được vẽ bắt đầu từ 20,20, nhưng đa giác được lấp đầy bắt đầu từ 20, -20 và được vẽ lộn ngược

Tôi nghĩ rằng đây là một vấn đề ma trận giữa ma trận được sử dụng bởi SpriteBatch(để vẽ các đường dẫn màu trắng) và ma trận được sử dụng bởi BasicEffect(để vẽ đa giác đầy).

Câu trả lời:


5

Câu trả lời của r2d2rigo gần như đúng. Dưới đây là mã ma trận chính xác để thiết lập mã BasicEffecttrùng khớp SpriteBatch( từ blog của Shawn Hargreaves ):

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;

Lưu ý bù nửa pixel ( giải thích , MSDN ).


Phép nhân "phép chiếu HalfPixel Offerset *" này tạo ra kết quả sai nếu mục tiêu là có nguồn gốc của thế giới trong tọa độ màn hình trên cùng bên trái.
Tiểu vương quốc Lima

1
@EmirLima Có, nhưng thường thì đó không phải là mục tiêu. Mục tiêu trong hầu hết các trường hợp - bao gồm cả trường hợp của OP - là xếp hàng với các pixel màn hình theo cùng một cách SpriteBatch. Xem các liên kết trong câu trả lời của tôi để biết thêm chi tiết (và lưu ý, tất nhiên, điều này áp dụng cho XNA và DirectX 9, nhưng không áp dụng cho DirectX 10 và OpenGL).
Andrew Russell

3

Ma trận được sử dụng trong SpriteBatch được tạo bằng Matrix.CreateOrthographic OfferCenter:

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

Bằng cách này, bạn sẽ giữ được nguồn gốc thế giới của mình ở góc trên cùng bên trái.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.