Xna 围绕创建的顶点旋转

Xna 围绕创建的顶点旋转,xna,xna-4.0,Xna,Xna 4.0,我最近学习了xna,并尝试使用顶点创建房间。我尝试了Riemeres XNA教程,学到了很多东西,但我似乎无法让我的相机正常工作,每次我向左或向右移动时,我的一些图像或纹理似乎消失并重新出现。请帮忙 这是我的密码 public struct MyOwnVertexFormat { public Vector3 position; private Vector2 texCoord; public MyOwnVertexFormat(Vector3 position, Ve

我最近学习了xna,并尝试使用顶点创建房间。我尝试了Riemeres XNA教程,学到了很多东西,但我似乎无法让我的相机正常工作,每次我向左或向右移动时,我的一些图像或纹理似乎消失并重新出现。请帮忙

这是我的密码

public struct MyOwnVertexFormat
{
    public Vector3 position;
    private Vector2 texCoord;

    public MyOwnVertexFormat(Vector3 position, Vector2 texCoord)
    {
        this.position = position;
        this.texCoord = texCoord;
    }

    public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
         (
             new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
             new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
         );
}

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    GraphicsDevice device;

    Effect effect;
    Matrix viewMatrix;
    Matrix projectionMatrix;
    VertexBuffer vertexBuffer;
    Vector3 cameraPos;
    Texture2D streetTexture;
    private Vector3 Position = Vector3.One;
    private float Zoom = 2500;
    private float RotationY = 0.0f;
    private float RotationX = 0.0f;
    private Matrix gameWorldRotation;
    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        graphics.PreferredBackBufferWidth =1024;
        graphics.PreferredBackBufferHeight = 768;
        graphics.IsFullScreen = false;
        graphics.ApplyChanges();

        base.Initialize();
    }

    protected override void LoadContent()
    {
        device = GraphicsDevice;


        effect = Content.Load<Effect>("OurHLSLfile"); SetUpVertices();
        SetUpCamera();


        streetTexture = Content.Load<Texture2D>("streettexture");
    }
    private void UpdateKeyboard()
    {
        if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();
        if (Keyboard.GetState().IsKeyDown(Keys.Up))
            RotationX += 1.0f;
        if (Keyboard.GetState().IsKeyDown(Keys.Down))
            RotationX -= 1.0f;
        if (Keyboard.GetState().IsKeyDown(Keys.Left))
            RotationY += 1.0f;
        if (Keyboard.GetState().IsKeyDown(Keys.Right))
            RotationY -= 1.0f;
        gameWorldRotation =
            Matrix.CreateRotationX(MathHelper.ToRadians(RotationX)) *
            Matrix.CreateRotationY(MathHelper.ToRadians(RotationY));
    }
    private void SetUpVertices()
    {

        MyOwnVertexFormat[] vertices = new MyOwnVertexFormat[12];

        vertices[0] = new MyOwnVertexFormat(new Vector3(-20, 0, 10), new Vector2(-0.25f, 25.0f));
        vertices[1] = new MyOwnVertexFormat(new Vector3(-20, 0, -100), new Vector2(-0.25f, 0.0f));
        vertices[2] = new MyOwnVertexFormat(new Vector3(2, 0, 10), new Vector2(0.25f, 25.0f));
        vertices[3] = new MyOwnVertexFormat(new Vector3(2, 0, -100), new Vector2(0.25f, 0.0f));

        vertices[4] = new MyOwnVertexFormat(new Vector3(2, 1, 10), new Vector2(0.375f, 25.0f));
        vertices[5] = new MyOwnVertexFormat(new Vector3(2, 1, -100), new Vector2(0.375f, 0.0f));
        vertices[6] = new MyOwnVertexFormat(new Vector3(3, 1, 10), new Vector2(0.5f, 25.0f));
        vertices[7] = new MyOwnVertexFormat(new Vector3(3, 1, -100), new Vector2(0.5f, 0.0f));

        vertices[8] = new MyOwnVertexFormat(new Vector3(-13, 1, 10), new Vector2(0.75f, 25.0f));
        vertices[9] = new MyOwnVertexFormat(new Vector3(-13, 1, -100), new Vector2(0.75f, 0.0f));
        vertices[10] = new MyOwnVertexFormat(new Vector3(-13, 21, 10), new Vector2(1.25f, 25.0f));
        vertices[11] = new MyOwnVertexFormat(new Vector3(-13, 21, -100), new Vector2(1.25f, 0.0f));

        vertexBuffer = new VertexBuffer(device, MyOwnVertexFormat.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
        vertexBuffer.SetData(vertices);
    }

    private void SetUpCamera()
    {
        cameraPos = new Vector3(-25, 13, 75);
        viewMatrix = Matrix.CreateLookAt(cameraPos, new Vector3(0, 2, -12), new Vector3(0, 1, 0));
        projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 5000.0f);
    }

    protected override void UnloadContent()
    {
    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();
        UpdateKeyboard();
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);

        effect.CurrentTechnique = effect.Techniques["Simplest"];
        effect.Parameters["xViewProjection"].SetValue(viewMatrix * projectionMatrix * gameWorldRotation);
        effect.Parameters["xTexture"].SetValue(streetTexture);

        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();

            device.SetVertexBuffer(vertexBuffer);
            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 10);
        }

        base.Draw(gameTime);
    }
}
公共结构MyOwnVertexFormat { 公共向量3位置; 私人Vector2 texCoord; 公共MyOwnVertexFormat(矢量3位置,矢量2 texCoord) { 这个位置=位置; this.texCoord=texCoord; } 公共只读静态VertexDeclaration VertexDeclaration=新VertexDeclaration ( 新的VertexElement(0,VertexElementFormat.Vector3,VertexElementUsage.Position,0), 新的顶点元素(sizeof(float)*3,VertexElementFormat.Vector2,VertexElementUsage.TextureCoordination,0) ); } 公共类游戏1:Microsoft.Xna.Framework.Game { 图形管理器图形; 图形设备; 效应; 矩阵视图矩阵; 矩阵投影矩阵; 顶点缓冲区顶点缓冲区; 矢量摄像机3; 纹理2D streetTexture; 私有向量3位置=向量3.1; 私有浮动缩放=2500; 专用浮动旋转Y=0.0f; 专用浮动旋转X=0.0f; 私有矩阵; 公共游戏1() { graphics=新的GraphicsDeviceManager(此); Content.RootDirectory=“Content”; } 受保护的覆盖无效初始化() { graphics.PreferredBackBufferWidth=1024; graphics.PreferredBackBufferHeight=768; graphics.IsFullScreen=false; graphics.ApplyChanges(); base.Initialize(); } 受保护的覆盖void LoadContent() { 设备=图形设备; 效果=Content.Load(“OurHLSLfile”);设置顶点(); 设置摄像头(); streetTexture=内容物荷载(“streetTexture”); } 私有void UpdateKeyboard() { if(Keyboard.GetState().IsKeyDown(Keys.Escape)) 退出(); if(Keyboard.GetState().IsKeyDown(Keys.Up)) 旋转X+=1.0f; if(Keyboard.GetState().IsKeyDown(Keys.Down)) 旋转X-=1.0f; if(Keyboard.GetState().IsKeyDown(Keys.Left)) 旋转Y+=1.0f; if(Keyboard.GetState().IsKeyDown(Keys.Right)) 旋转Y-=1.0f; 游戏世界轮换= 矩阵.CreateRotationX(MathHelper.ToRadians(RotationX))* 矩阵.CreateRotationY(MathHelper.ToRadians(RotationY)); } 私有void SetUpVertices() { MyOwnVertexFormat[]顶点=新的MyOwnVertexFormat[12]; 顶点[0]=新的MyOwnVertexFormat(新向量3(-20,0,10),新向量2(-0.25f,25.0f)); 顶点[1]=新的MyOwnVertexFormat(新向量3(-20,0,-100),新向量2(-0.25f,0.0f)); 顶点[2]=新的MyOwnVertexFormat(新向量3(2,0,10),新向量2(0.25f,25.0f)); 顶点[3]=新的MyOwnVertexFormat(新向量3(2,0,-100),新向量2(0.25f,0.0f)); 顶点[4]=新的MyOwnVertexFormat(新向量3(2,1,10),新向量2(0.375f,25.0f)); 顶点[5]=新的MyOwnVertexFormat(新向量3(2,1,-100),新向量2(0.375f,0.0f)); 顶点[6]=新的MyOwnVertexFormat(新向量3(3,1,10),新向量2(0.5f,25.0f)); 顶点[7]=新的MyOwnVertexFormat(新向量3(3,1,-100),新向量2(0.5f,0.0f)); 顶点[8]=新的MyOwnVertexFormat(新向量3(-13,1,10),新向量2(0.75f,25.0f)); 顶点[9]=新的MyOwnVertexFormat(新向量3(-13,1,-100),新向量2(0.75f,0.0f)); 顶点[10]=新的MyOwnVertexFormat(新向量3(-13,21,10),新向量2(1.25f,25.0f)); 顶点[11]=新的MyOwnVertexFormat(新向量3(-13,21,-100),新向量2(1.25f,0.0f)); vertexBuffer=新的vertexBuffer(设备,MyOwnVertexFormat.VertexDeclaration,顶点.Length,BufferUsage.WriteOnly); SetData(顶点); } 专用照相机() { cameraPos=新矢量3(-25,13,75); viewMatrix=Matrix.CreateLookAt(cameraPos,新矢量3(0,2,-12),新矢量3(0,1,0)); projectionMatrix=Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,device.Viewport.AspectRatio,1.0f,5000.0f); } 受保护的覆盖无效UnloadContent() { } 受保护覆盖无效更新(游戏时间游戏时间) { if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed) 这是Exit(); UpdateKeyboard(); 更新(游戏时间); } 受保护覆盖无效绘制(游戏时间游戏时间) { 设备.清除(ClearOptions.Target | ClearOptions.DepthBuffer,Color.DarkSlateBlue,1.0f,0); effect.currentTechnical=effect.technologies[“最简单”]; 效果参数[“xViewProjection”].SetValue(viewMatrix*projectionMatrix*gameWorldRotation); 效应.参数[“xTexture”].设定值(streetTexture); foreach(EffectPass-in-effect.currentTechnology.passs) { pass.Apply(); 设备。SetVertexBuffer(vertexBuffer); device.DrawPrimitives(PrimitiveType.TriangleStrip,0,10); } 基础。抽签(游戏时间); } }
我认为这是一个投影问题。这行代码加强了我的假设:

viewMatrix * projectionMatrix * gameWorldRotation
tl;dr,正确的顺序是:

gameWorldRotation * viewMatrix * projectionMatrix

请记住,矩阵相乘时顺序很重要。用数学术语来说:

矩阵乘法不是可交换的

这三个矩阵将向量映射到三个不同的坐标系,即世界、视图和投影空间。通常在对象空间中定义顶点。将向量与世界(视图、投影)矩阵相乘,将向量带到世界(视图、投影)空间:

XNA使用行向量布局(与列向量相反)。这意味着向量是
object space => world space => view space => projection space
A := [3x3 Matrix]

(x, y, z) * A = (x', y', z')  // The result is another 3D vector
W .... world matrix
V .... view matrix
W .... projection matrix
x .... vector
x' ... transformed vector

x' = ((x * W) * V) * P
x' = ((x *  W) * V) * P  =  x * W * V * P  =  x * (W * V * P)