一个模型与另一个模型重叠,应该是另一种方式

时间:2011-09-11 18:55:27

标签: c# xna models

我目前正在尝试开发3D乒乓球比赛。我的问题是,当绘制桌子和球拍时,桌子当前与球拍重叠,这应该是相反的。有人可以帮忙吗?

代表部分代码:

   Model table;
   Model racket;

   Vector3 modelPosition = new Vector3(0,100,150);
   Vector3 modelPosition_table = new Vector3(0,40,0);

   // Set the position of the camera in world space, for our view matrix.
   Vector3 cameraPosition_racket = new Vector3(0.0f, 1000.0f, 10.0f);
   Vector3 cameraPosition_table = new Vector3(0.0f, 150.0f, 250.0f);

   void Draw_Racket()
    {
        // Copy any parent transforms.
        Matrix[] transforms_racket = new Matrix[racket.Bones.Count];
        racket.CopyAbsoluteBoneTransformsTo(transforms_racket);

        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in racket.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection.
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms_racket[mesh.ParentBone.Index] *     Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition);
                effect.View = Matrix.CreateLookAt(cameraPosition_racket, Vector3.Up, Vector3.Up);
                effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }
    }

    void Draw_Table()
    {

        // Copy any parent transforms.
        Matrix[] transforms_table = new Matrix[table.Bones.Count];
        table.CopyAbsoluteBoneTransformsTo(transforms_table);

        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in table.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection.
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms_table[mesh.ParentBone.Index] *                                                              Matrix.CreateTranslation(modelPosition_table);
                effect.View = Matrix.CreateLookAt(cameraPosition_table, Vector3.Down, Vector3.Up);
                effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 1000.0f);
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }

    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        Draw_Table();
        Draw_Racket();

        base.Draw(gameTime);
    }

如果您需要更多代码,请告诉我。在此先感谢:)

编辑...

@Pablo Ariel ..我现在明白了,并且意识到我没有尝试更换相机,而是可以在x轴上旋转球拍,并设法得到我想要的东西,但现在一个问题是球拍有点大......新的代码......

    // Set the 3D model to draw.
    Model table;
    Model racket;

    // The aspect ratio determines how to scale 3d to 2d projection.
    float aspectRatio;

    // Set the position of the model in world space, and set the rotation.
    Vector3 modelPosition = new Vector3(0,250,-25);
    Vector3 modelPosition_table = new Vector3(0,40,500);

    float modelRotation = (MathHelper.Pi*3)/2;

    Vector3 cameraPosition;
    Vector3 cameraTarget;
    Matrix mWorld;
    Matrix mWorld1;
    Matrix mView;
    Matrix mView1;
    Matrix mProjection;

    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        graphics.PreferredBackBufferWidth = 1000;
        graphics.PreferredBackBufferHeight = 500;
        graphics.IsFullScreen = false;
        graphics.ApplyChanges();
        Window.Title = "Table Tennis 3D";

        mProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), 1.0f, 1.0f, 10000.0f);
        cameraPosition = modelPosition;
        cameraTarget = modelPosition_table;
        modelPosition_table.Z += 40;
        mView = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);

        cameraPosition.Z -= 300;
        modelPosition.Y -= 100;
        mView1 = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);



        base.Initialize();
    }

    protected override void Draw(GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

        mWorld = Matrix.CreateRotationY(modelRotation) * Matrix.CreateRotationX(modelRotation) * Matrix.CreateTranslation(modelPosition);
        mWorld1 = Matrix.CreateTranslation(modelPosition_table);

        Draw_Table();
        Draw_Racket();

        base.Draw(gameTime);
    }

    void Draw_Table()
    {

        // Copy any parent transforms.
        Matrix[] transforms_table = new Matrix[table.Bones.Count];
        table.CopyAbsoluteBoneTransformsTo(transforms_table);

        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in table.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection.
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms_table[mesh.ParentBone.Index] * mWorld1;
                effect.View = mView;
                effect.Projection = mProjection;
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }

    }

    void Draw_Racket()
    {
        Matrix[] transforms_racket = new Matrix[racket.Bones.Count];
        racket.CopyAbsoluteBoneTransformsTo(transforms_racket);

        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in racket.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection.
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms_racket[mesh.ParentBone.Index] * mWorld;
                effect.View = mView1;
                effect.Projection = mProjection;
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }
    }

我应该为球拍做一个新的投影,以便我将其大小改为一半?我已经尝试改变它的z位置,但没有运气:/ ..再次感谢:) ps..heres a screenshot ..http://i1099.photobucket.com/albums/g395/krt_ricci/3.png

...编辑 我将球拍的世界矩阵与Matrix.CreateScale(0.5f,0.5f,0.5f)相乘,以便将球拍缩小一半:)

1 个答案:

答案 0 :(得分:0)

我认为这是错误的:

Matrix.CreateLookAt(cameraPosition_racket, Vector3.Up, Vector3.Up);

它应该是:

Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);

我想提出的一个建议是你不应该使用像1000.0f这样大的数字作为位置,除非你的游戏架构需要这个,但是由于浮动不精确,使用较小的比例会更好。

如果您将相机放在球拍所在的位置,那么您的相机可能会在球拍内部并且您将无法看到它(因为背面剔除,您无法从球拍内部看到面部)

除此之外,我无法从这段代码中弄清楚什么是错误的,但是错误的视图矩阵可能会以一种混淆深度缓冲区的方式反转你的z值。

这很复杂,因为我不明白相机矢量应该是什么,你应该使用3个矢量用于相机:cameraPosition,cameraTarget和cameraUp,然后它会更清晰你想要相机指向的地方,如果你改变您不必修改矩阵创建的摄像机值,只需指定另一个矢量。

编辑:看看有些事情需要改变

首先,计算每个骨骼的视图和投影矩阵(对于场景中的每个网格都是相同的)是非常糟糕的,因为生成矩阵是非常慢的特别是在C#,所以你应该设法做到这一点:effect.View = mView;和投影矩阵相同。

这就是你错误的原因,因为生成矩阵这么多次,你构建了2个不同的投影矩阵:

你在DrawRacket()中做到这一点:

effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);

并在DrawTable()中:

effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 1000.0f);

你将表格网格映射到1到1000,并将球拍映射到1到10k然后当你需要为每个对象使用相同的投影矩阵时,由于单个零点,所有坐标都会搞乱,所以你应该存储它作为一个globabl变量,或者它在c#中处理(一个成员变量或类似的东西)

编辑2:

当然你必须为两个物体使用相同的相机!如果不这样做,那么每个对象都会被绘制,就好像相机在每个对象的不同位置一样!

这是您的固定代码:

Model table;
Model racket;

Vector3 modelPosition = new Vector3(0,100,150);
Vector3 modelPosition_table = new Vector3(0,40,0);

// Set the position of the camera in world space, for our view matrix.
Vector3 cameraPosition_racket = new Vector3(0.0f, 1000.0f, 10.0f);
Vector3 cameraPosition_table = new Vector3(0.0f, 150.0f, 250.0f);

Vector3 cameraPosition = cameraPosition_racket;
Vector3 cameraTarget  = new Vector3(0.0f, 0.0f, 0.0f);

Matrix mView = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
Matrix mProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);



void Draw_Racket()
{
    // Copy any parent transforms.
    Matrix[] transforms_racket = new Matrix[racket.Bones.Count];
    racket.CopyAbsoluteBoneTransformsTo(transforms_racket);

    // Draw the model. A model can have multiple meshes, so loop.
    foreach (ModelMesh mesh in racket.Meshes)
    {
        // This is where the mesh orientation is set, as well 
        // as our camera and projection.
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.EnableDefaultLighting();
            effect.World = transforms_racket[mesh.ParentBone.Index] *     Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition);
            effect.View = mView;
            effect.Projection = mProjection;
        }
        // Draw the mesh, using the effects set above.
        mesh.Draw();
    }
}

void Draw_Table()
{

    // Copy any parent transforms.
    Matrix[] transforms_table = new Matrix[table.Bones.Count];
    table.CopyAbsoluteBoneTransformsTo(transforms_table);

    // Draw the model. A model can have multiple meshes, so loop.
    foreach (ModelMesh mesh in table.Meshes)
    {
        // This is where the mesh orientation is set, as well 
        // as our camera and projection.
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.EnableDefaultLighting();
            effect.World = transforms_table[mesh.ParentBone.Index] * Matrix.CreateTranslation(modelPosition_table);
            effect.View = mView;
            effect.Projection = mProjection;
        }
        // Draw the mesh, using the effects set above.
        mesh.Draw();
    }

}

protected override void Draw(GameTime gameTime)
{
    graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

    Draw_Table();
    Draw_Racket();

    base.Draw(gameTime);
}

更新:试试这个:

 Vector3 modelPosition_racket = new Vector3(0,100,100); // former modelPosition
 Vector3 modelPosition_table  = new Vector3(0,40,500);

 // Set the position of the camera in world space, for our view matrix.
 Vector3 cameraPosition = modelPosition_racket;
 Vector3 cameraPosition.z -= 300;
 Vector3 cameraTarget   = modelPosition_table;

更新:您必须了解的是,正确显示图像您正在使用的模型正在将每个对象从其局部坐标空间转换为全局/世界坐标空间(每个模型都有自己的modelPosition)。所有对象共享相同的坐标空间和相同的投影变换。在全局/世界坐标空间中,您还可以指定摄像机位置,然后根据摄像机的世界变换值构建矩阵。 如果你想在世界空间中移动一个对象,你必须修改modelPosition ..这不是我只是“相信”的方式,这就是3d的工作原理。如果你修改其他值来改变对象的位置,比如投影或视图矩阵,那么这对你没有任何好处,因为它不会那样工作,你的所有数学都会搞砸了你赢了能够正常工作。