【问题标题】:Rendering a cube defined by planes (Valve map file format)渲染由平面定义的立方体(阀门贴图文件格式)
【发布时间】:2024-01-17 23:16:01
【问题描述】:

目前我正在尝试在单人游戏应用程序中渲染立方体。 我正在使用 Valve 地图文件格式。地图格式在以下 wiki 页面中描述:

https://developer.valvesoftware.com/wiki/MAP_file_format.

导入格式很简单,完全没有问题。 重要的部分是对飞机的描述。格式如下:

{
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
    ( x1 y1 z1) ( x2 y2 z2) ( x3 y3 z3) texture_name  ...
}

每一行定义一个平面。要定义一个实际平面,必须给出三个点(用 x1、y1、z1、x2、y2、z2 和 x3、y3、z3 表示)。

plane ((vertex) (vertex) (vertex))

这定义了将用于设置平面在三维世界中的方向和位置的三个点。第一个标记脸的左下角,第二个标记左上角,第三个标记右上角。下面是通过 CSG 从六个平面构建的简单画笔的动画。第一、二、三平面点分别用红、绿、蓝点表示。

所以我正在加载这些平面并将它们渲染为三角形。 我的 monogame 应用程序中的重新渲染结果是这样的:

所以很明显,立方体中缺少一些部分。

我正在使用 Worldcraft 锤子编辑器创建地图文件。所以结果应该是这样的:

顶点创建方法:

将画笔和面转换为 xna VertexPositionColor 类型。

    private VertexPositionColor[] CreateVertexPositions(Brush brush)
    {
        VertexPositionColor[] vertices = new VertexPositionColor[brush.Faces.Count * 3];

        int j = 0;
        for (int i = 0; i < brush.Faces.Count; i++)
        {
            Face brushFace = brush.Faces[i];
            Color color = ColorUtils.GenerateRandomColor(Color.Wheat);

            vertices[i + j + 0] = new VertexPositionColor( // bottom left of the face
                new Vector3(brushFace.V1.X, brushFace.V1.Y, brushFace.V1.Z), color
            );
            vertices[i + j + 1] = new VertexPositionColor( // top left of the face
                new Vector3(brushFace.V2.X, brushFace.V2.Y, brushFace.V2.Z), color
            );
            vertices[i + j + 2] = new VertexPositionColor( // top right of the face
                new Vector3(brushFace.V3.X, brushFace.V3.Y, brushFace.V3.Z), color
            );

            j = j + 2;
        }

        return vertices;
    }

刷脸模型

public sealed class Face
{
    public Vertex3 V1 { get; set; }
    public Vertex3 V2 { get; set; }
    public Vertex3 V3 { get; set; }
    public string TextureName { get; set; }
    public Plane P1 { get; set; }
    public Plane P2 { get; set; }
    public int Rotation { get; set; }
    public float XScale { get; set; }
    public float YScale { get; set; }
}

渲染方法

    public override void Render(ICamera camera)
    {
        _effect.Projection = camera.Projection;
        _effect.View = camera.View;
        _effect.World = camera.World;

        RasterizerState rasterizerState = new RasterizerState();
        rasterizerState.CullMode = CullMode.None;
        rasterizerState.FillMode = FillMode.Solid;
        GraphicsDevice.RasterizerState = rasterizerState;

        foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, _vertices.ToArray(), 0, (_vertices.Count / 3), VertexPositionColor.VertexDeclaration);
        }
    }

我缺少一个基本的部分。如何从给定的平面创建一个立方体?

我要求的不是完整的代码或完成的解决方案,而是有人将我推向正确的方向。

提前谢谢你。

更新

我为此做了一个非常简单的项目并将其上传到我的 OneDrive 帐户:

OneDrive Link

【问题讨论】:

    标签: c# 3d xna rendering monogame


    【解决方案1】:

    一个立方体由 6 个四边形(6 个矩形)组成。四边形是两个三角形,而不是一个。由于四边形是 2 个三角形,因此它有 6 个顶点。所以要渲染一个立方体,你必须处理 36 个顶点。

    构成 36 个顶点的所有信息都在构成平面的 18 个顶点中。

    对于所有 36 个顶点,只有 6 个唯一的组件值。对于构成立方体的 36 个顶点中的任何一个,只能有 2 个可能的 X 值、2 个可能的 Y 值和 2 个可能的 Z 值。所有 36 个顶点都是由这 6 个唯一值的各种组合组成的。

    您的任务是遍历 6 个平面(18 个顶点)并提取 6 个唯一的组件值,然后从这 6 个组件值中组成您的 36 个顶点。然后用 36 个顶点填充您的 VertexBuffer。

    【讨论】: