2

有没有办法制作一个原语并一遍又一遍地使用它?例如:如果我制作一个立方体,我可以创建 100 个并制作一个 10x10 的网格吗?我尝试使用 for 循环并通过每个循环更新 x 和 z 坐标,但它只移动一开始创建的一个立方体。我的课程是使用书中的示例创建的。我知道如何通过更改 PositionCube 方法中的坐标来在该区域周围移动立方体。我可以在我的主游戏类中做什么来创建一个简单的 10x10 网格?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Cube_Chaser
{
    class Cube
    {
        private GraphicsDevice device;
        private Texture2D texture;

        public Vector3 location;

        private Vector3 position;

        private VertexBuffer cubeVertexBuffer;
        private List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();

        public Cube(GraphicsDevice graphicsDevice, Vector3 playerLocation, float minDistance, Texture2D texture)
        {
            device = graphicsDevice;
            this.texture = texture;

            PositionCube(playerLocation, minDistance);

            BuildFace(new Vector3(0, 0, 0), new Vector3(0, 1, 1));
            BuildFace(new Vector3(0, 0, 1), new Vector3(1, 1, 1));
            BuildFace(new Vector3(1, 0, 1), new Vector3(1, 1, 0));
            BuildFace(new Vector3(1, 0, 0), new Vector3(0, 1, 0));

            BuildFaceHorizontal(new Vector3(0, 1, 0), new Vector3(1, 1, 1));
            BuildFaceHorizontal(new Vector3(0, 0, 1), new Vector3(1, 0, 0));

            cubeVertexBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration, vertices.Count, BufferUsage.WriteOnly);

            cubeVertexBuffer.SetData<VertexPositionTexture>(vertices.ToArray());

            this.position = position;
        }

        private void BuildFace(Vector3 p1, Vector3 p2)
        {
            vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
            vertices.Add(BuildVertex(p1.X, p2.Y, p1.Z, 1, 1));
            vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
            vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
            vertices.Add(BuildVertex(p2.X, p1.Y, p2.Z, 0, 0));
            vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
        }

        private void BuildFaceHorizontal(Vector3 p1, Vector3 p2)
        {
            vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
            vertices.Add(BuildVertex(p2.X, p1.Y, p1.Z, 1, 1));
            vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
            vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
            vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
            vertices.Add(BuildVertex(p1.X, p1.Y, p2.Z, 0, 0));
        }

        private VertexPositionTexture BuildVertex(float x, float y, float z, float u, float v)
        {
            return new VertexPositionTexture(new Vector3(x, y, z), new Vector2(u, v));
        }

        public void PositionCube(Vector3 playerLocation, float minDistance)
        {
            location = new Vector3(.5f, .5f, .5f);
        }

        public void Draw(Camera camera, BasicEffect effect)
        {
            effect.VertexColorEnabled = false;
            effect.TextureEnabled = true;
            effect.Texture = texture;

            Matrix center = Matrix.CreateTranslation(new Vector3(-0.5f, -0.5f, -0.5f));
            Matrix scale = Matrix.CreateScale(0.05f);
            Matrix translate = Matrix.CreateTranslation(location);

            effect.World = center * scale * translate;
            effect.View = camera.View;
            effect.Projection = camera.Projection;

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                device.SetVertexBuffer(cubeVertexBuffer);
                device.DrawPrimitives(PrimitiveType.TriangleList, 0, cubeVertexBuffer.VertexCount / 3);
            }
        }
    }
}
4

2 回答 2

1

我接受了@nico-schetler 的回答并为您创建了课程。

立方体.cs

class Cube
{
    private GraphicsDevice device;
    private VertexBuffer cubeVertexBuffer;

    public Cube(GraphicsDevice graphicsDevice)
    {
        device = graphicsDevice;

        var vertices = new List<VertexPositionTexture>();

        BuildFace(vertices, new Vector3(0, 0, 0), new Vector3(0, 1, 1));
        BuildFace(vertices, new Vector3(0, 0, 1), new Vector3(1, 1, 1));
        BuildFace(vertices, new Vector3(1, 0, 1), new Vector3(1, 1, 0));
        BuildFace(vertices, new Vector3(1, 0, 0), new Vector3(0, 1, 0));

        BuildFaceHorizontal(vertices, new Vector3(0, 1, 0), new Vector3(1, 1, 1));
        BuildFaceHorizontal(vertices, new Vector3(0, 0, 1), new Vector3(1, 0, 0));

        cubeVertexBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration, vertices.Count, BufferUsage.WriteOnly);

        cubeVertexBuffer.SetData<VertexPositionTexture>(vertices.ToArray());
    }

    private void BuildFace(List<VertexPositionTexture> vertices, Vector3 p1, Vector3 p2)
    {
        vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
        vertices.Add(BuildVertex(p1.X, p2.Y, p1.Z, 1, 1));
        vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
        vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
        vertices.Add(BuildVertex(p2.X, p1.Y, p2.Z, 0, 0));
        vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
    }

    private void BuildFaceHorizontal(List<VertexPositionTexture> vertices, Vector3 p1, Vector3 p2)
    {
        vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
        vertices.Add(BuildVertex(p2.X, p1.Y, p1.Z, 1, 1));
        vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
        vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
        vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
        vertices.Add(BuildVertex(p1.X, p1.Y, p2.Z, 0, 0));
    }

    private VertexPositionTexture BuildVertex(float x, float y, float z, float u, float v)
    {
        return new VertexPositionTexture(new Vector3(x, y, z), new Vector2(u, v));
    }

    public void Draw( BasicEffect effect)
    {
        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            device.SetVertexBuffer(cubeVertexBuffer);
            device.DrawPrimitives(PrimitiveType.TriangleList, 0, cubeVertexBuffer.VertexCount / 3);
        }
    }
}

CubeDrawable.cs

public class DrawableList<T> : DrawableGameComponent
{
    private BasicEffect effect;
    private Camera camera;
    private class Entity
    {
        public Vector3 Position { get; set; }
        public Matrix Orientation { get; set; }
        public Texture2D Texture { get; set; }
    }

    private Cube cube;
    private List<Entity> entities = new List<Entity>();

    public DrawableList (Game game, Camera camera, BasicEffect effect) 
        : base( game ) 
    {
        this.effect = effect;
        cube = new Cube (game.GraphicsDevice);
        this.camera = camera;
    }

    public void Add( Vector3 position, Matrix orientation, Texture2D texture )
    {
        entities.Add (new Entity() { 
            Position = position,
            Orientation = orientation,
            Texture = texture
        });
    }

    public override void Draw (GameTime gameTime )
    {
        base.Draw (gameTime);

        foreach (var item in entities) {

            effect.VertexColorEnabled = false;
            effect.TextureEnabled = true;
            effect.Texture = item.Texture;

            Matrix center = Matrix.CreateTranslation(new Vector3(-0.5f, -0.5f, -0.5f));
            Matrix scale = Matrix.CreateScale(0.05f);
            Matrix translate = Matrix.CreateTranslation(item.Position);

            effect.World = center * scale * translate;
            effect.View = camera.View;
            effect.Projection = camera.Projection;

            cube.Draw (effect);
        }
    }
}

用法

        camera = new Camera (graphics.GraphicsDevice);
        effect = new BasicEffect (graphics.GraphicsDevice);
        cubes = new DrawableList<Cube> (this, camera, effect);

        Components.Add (cubes);

        for (int i=0 ; i < 50; i++)
        {
            cubes.Add (new Vector3( i*0.5f, 50.0f, 50.0f), Matrix.Identity, logoTexture);
        }
于 2013-05-14T17:11:05.943 回答
0

您应该将多维数据集的逻辑表示与物理表示分开。物理表示将是顶点缓冲区等。这对于每个立方体都是相同的。您可以通过例如世界变换来影响渲染(就像您已经做过的那样)。

逻辑表示是您的多维数据集类。您将需要 100 个实例(每个实例都有自己的位置、比例等)。逻辑表示可以参考物理表示。所以没有必要拥有一个以上的顶点缓冲区。

于 2013-05-14T08:54:26.003 回答