简体   繁体   中英

Proper way of transforming 3D primitives in C#/XNA?

I have a Block class that basically contains an array of 36 vertices, a constructor that builds the block around the origin (0, 0, 0), and a method for updating.

I'm using a Physics library to manipulate the blocks. I assign a body and collision skin to the block and update the physics step every update. After every update I get a matrix back with the block's new position, orientation, etc.

Now, what I can't wrap my head around is the best way to go about applying the matrix to the block and efficiently updating the vertex buffer every frame.

This is basically what I have at the moment, I'm almost positive there's a better method...

class Block
{
    const float FullBlockSize = 20f;
    const float HalfBlockSize = FullBlockSize / 2;

    public VertexPositionNormalTexture [] vertices = new VertexPositionNormalTexture[36];
    public VertexPositionNormalTexture [] currentVertices = new VertexPositionNormalTexture[36];
    public DynamicVertexBuffer vBuffer;

    Vector3 position;

    public Block(Vector3 blockPosition)
    {
        position = blockPosition * FullBlockSize;

        /*
         * Build the 6 faces of the block here.
         * The block is built around the origin,
         * (0, 0, 0) being the center of the block.
        */

        vBuffer = new DynamicVertexBuffer(Game.Device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
        vBuffer.SetData(vertices);
    }
    public Matrix WorldMatrix
    {
        get
        {
            return Matrix.CreateTranslation(position);
        }
    }
    public void Update()
    {
        currentVertices = (VertexPositionNormalTexture[])vertices.Clone();
        Matrix currentWorld = WorldMatrix;
        for(int i = 0; i < currentVertices.Length; ++i)
        {
            currentVertices[i].Position = Vector3.Transform(currentVertices[i].Position, currentWorld);
        }
        vBuffer.SetData(currentVertices);
    }
}

Let the shader do it...one of the parameters of a shader is usually a WorldMatrix...

to draw it:

effect.Parameters["WorldMatrix"].SetValue(World);
effect.Apply(0);

if you have problems drawing a block... try to create a world transform matrix by yourself and test it...

effect.Parameters["WorldMatrix"].SetValue(Matrix.CreateRotationZ(angle));
effect.Apply(0);

If you have several instances of block, you can use instancing to pass the trasnform matrix in a vertexBuffer to the shader...

Here you can find info about instancing: http://blogs.msdn.com/b/shawnhar/archive/2010/06/17/drawinstancedprimitives-in-xna-game-studio-4-0.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM