24

我正在 Unity 中实现 Marching Cubes。我的代码基于 Paul Bourke 的代码,实际上进行了很多修改,但无论如何,我正在检查某个位置的块是否为空,如果它是,则将在其上放置调试纹理。

这是问题的图像

这是我的 MC 脚本

    public class MarchingCubes
{
private World world;
private Chunk chunk;
private List<Vector3> vertices = new List<Vector3> ();
private List<Vector3> normals = new List<Vector3> ();
private Vector3[] ns;
private List<int> triangles = new List<int> ();
private List<Vector2> uvs = new List<Vector2> ();
private Vector3[] positions = new Vector3[8];
private float[] corners = new float[8];
private Vector3i size = new Vector3i (16, 128, 16);

Vector3[] vertlist = new Vector3[12];

private float isolevel = 1f;

private float Corner (Vector3i pos)
{
    int x = pos.x;
    int y = pos.y;
    int z = pos.z;
    if (x < size.x && z < size.z) {
        return chunk.GetValue (x, y, z);
    } else {
        int ix = chunk.X, iz = chunk.Z;
        int rx = chunk.region.x, rz = chunk.region.z;
        if (x >= size.x) {
            ix++;
            x = 0;
        }

        if (z >= size.z) {
            iz++;
            z = 0;
        }
        return chunk.region.GetChunk (ix, iz).GetValue (x, y, z);
    }
}

Block block;

public Mesh MarchChunk (World world, Chunk chunk, Mesh mesh)
{
    this.world = world;
    this.chunk = chunk;

    vertices.Clear ();
    triangles.Clear ();
    uvs.Clear ();

    for (int x = 0; x < size.x; x++) {
        for (int y = 1; y < size.y - 2; y++) {
            for (int z = 0; z < size.z; z++) {

                block = chunk.GetBlock (x, y, z);
                int cubeIndex = 0;

                for (int i = 0; i < corners.Length; i++) {
                    corners [i] = Corner (new Vector3i (x, y, z) + offset [i]);
                    positions [i] = (new Vector3i (x, y, z) + offset [i]).ToVector3 ();

                    if (corners [i] < isolevel)
                        cubeIndex |= (1 << i);
                }

                if (eTable [cubeIndex] == 0)
                    continue;

                for (int i = 0; i < vertlist.Length; i++) {
                    if ((eTable [cubeIndex] & 1 << i) == 1 << i)
                        vertlist [i] = LinearInt (positions [eCons [i, 0]], positions [eCons [i, 1]], corners [eCons [i, 0]], corners [eCons [i, 1]]);
                }

                for (int i = 0; triTable [cubeIndex, i] != -1; i += 3) {
                    int index = vertices.Count;

                    vertices.Add (vertlist [triTable [cubeIndex, i]]);
                    vertices.Add (vertlist [triTable [cubeIndex, i + 1]]);
                    vertices.Add (vertlist [triTable [cubeIndex, i + 2]]);

                    float tec = (0.125f);
                    Vector2 uvBase = block != null ? block.UV : new Vector2 ();

                    uvs.Add (uvBase);
                    uvs.Add (uvBase + new Vector2 (0, tec));
                    uvs.Add (uvBase + new Vector2 (tec, tec));

                    triangles.Add (index + 0);
                    triangles.Add (index + 1);
                    triangles.Add (index + 2);
                }
            }
        }
    }       

    if (mesh == null)
        mesh = new Mesh ();
    mesh.Clear ();
    mesh.vertices = vertices.ToArray ();
    mesh.triangles = triangles.ToArray ();
    mesh.uv = uvs.ToArray ();
    mesh.RecalculateNormals ();
    return mesh;
}

bool IsBitSet (int b, int pos)
{
    return ((b & pos) == pos);
}

Vector3 LinearInt (Vector3 p1, Vector3 p2, float v1, float v2)
{
    Vector3 p;
    p.x = p1.x + (isolevel - v1) * (p2.x - p1.x) / (v2 - v1);
    p.y = p1.y + (isolevel - v1) * (p2.y - p1.y) / (v2 - v1);
    p.z = p1.z + (isolevel - v1) * (p2.z - p1.z) / (v2 - v1);
    return p;
}

private static int[,] eCons = new int[12, 2] {
    { 0, 1 },
    { 1, 2 },
    { 2, 3 },
    { 3, 0 },
    { 4, 5 },
    { 5, 6 },
    { 6, 7 },
    { 7, 4 },
    { 0, 4 },
    { 1, 5 },
    { 2, 6 },
    { 3, 7 }
};

private static Vector3i[] offset = new Vector3i[8] {
    new Vector3i (0, 0, 1),
    new Vector3i (1, 0, 1),
    new Vector3i (1, 0, 0),
    new Vector3i (0, 0, 0),
    new Vector3i (0, 1, 1),
    new Vector3i (1, 1, 1),
    new Vector3i (1, 1, 0),
    new Vector3i (0, 1, 0)
};
  }

我没有将表格放入示例中,因为它们与 Bourke 代码中的表格相同。

编辑:我发现蓝色三角形处的单元格值为 0,因此不必对它们进行三角剖分,但它们下方的单元格值为 1,因此创建了一个顶部三角形来完成网格。

4

0 回答 0