如何将额外的顶点添加到程序生成的平面?

时间:2016-09-15 17:08:17

标签: c# unity3d procedural-generation

我找到了一段时间没有更新的旧教程,并按照它创建了一些1D平面地形。它使用贝塞尔曲线生成表面,然后表面作为陆地。

但是,这只会创建两组顶点 - 一组位于底部,另一组位于顶部。我想填充它,以便它生成更多的立方体形状,但我不知道在哪里添加额外的顶点。另一个目标是在顶部和底部之间添加更多顶点,以创建更坚固的形状。我应该在哪里添加额外的顶点循环以创建类似立方体的形状,从而为网格提供更高的分辨率和深度?

using UnityEngine;
using System.Collections.Generic;

public class TerrainGenerator : MonoBehaviour
{
    public Vector3[] meshPoints = null;

    private Mesh _mesh = null;
    public List<Vector3> vertices = new List<Vector3>();
    private List<int> triangles = new List<int>();

    private MeshCollider _collider;
    private MeshFilter _filter;

    private float terrainSize = 0.4f;

    public LandTypes type;

    public float lastHeight = 3;

    void Awake()
    {
        _collider = GetComponent<MeshCollider>();
        _filter = GetComponent<MeshFilter>();
    }

    public void GenerateMesh(float lh, LandTypes Type)
    {
        type = Type;
        _mesh = _filter.mesh;
        _mesh.Clear();

        meshPoints = new Vector3[4];

        switch(Type)
        {
            case LandTypes.Flat:
                meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                meshPoints[1] = new Vector3(terrainSize * (float)1, lh, 0f);
                meshPoints[2] = new Vector3(terrainSize * (float)2, lh, 0f);
                meshPoints[3] = new Vector3(terrainSize * (float)3, lh, 0f);
                break;
            case LandTypes.Up:
                int typeOfUpChance = Random.Range(1, 20);

                if (typeOfUpChance > 10)
                {
                    meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                    meshPoints[1] = new Vector3(terrainSize * (float)1, lh + 1, 0f);
                    meshPoints[2] = new Vector3(terrainSize * (float)2, lh + 2, 0f);
                    meshPoints[3] = new Vector3(terrainSize * (float)3, lh + 3, 0f);
                } else
                {
                    meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                    meshPoints[1] = new Vector3(terrainSize * (float)1, lh + Random.Range(2, 3), 0f);
                    meshPoints[2] = new Vector3(terrainSize * (float)2, lh + Random.Range(2, 4), 0f);
                    meshPoints[3] = new Vector3(terrainSize * (float)3, lh + 5, 0f);
                }


                break;
            case LandTypes.Down:
                if (lh > 6f)
                {
                    meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                    meshPoints[1] = new Vector3(terrainSize * (float)1, lh - 2, 0f);
                    meshPoints[2] = new Vector3(terrainSize * (float)2, lh - 3, 0f);
                    meshPoints[3] = new Vector3(terrainSize * (float)3, lh - 4, 0f);
                }
                else
                {
                    meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                    meshPoints[1] = new Vector3(terrainSize * (float)1, lh, 0f);
                    meshPoints[2] = new Vector3(terrainSize * (float)2, lh, 0f);
                    meshPoints[3] = new Vector3(terrainSize * (float)3, lh, 0f);
                }
            break;
            case LandTypes.Hill:
                meshPoints[0] = new Vector3(terrainSize * (float)0, lh, 0f);
                meshPoints[1] = new Vector3(terrainSize * (float)1, lh + 1.5f, 0f);
                meshPoints[2] = new Vector3(terrainSize * (float)2, lh + 1.5f, 0f);
                meshPoints[3] = new Vector3(terrainSize * (float)3, lh, 0f);
            break;
        }

        LandController.Instance.HeightCounts.Add(meshPoints[3].y);
        LandController.Instance.lastHeight = meshPoints[3].y;

        int resolution = 8;
        for (int i = 0; i < resolution; i++)
        {
            float t = (float)i / (float)(resolution - 1);
            Vector3 p = CalculateBezierPoint(t, meshPoints[0], meshPoints[1], meshPoints[2], meshPoints[3]);

            AddTerrainPoint(p);
        }

        _mesh.vertices = vertices.ToArray();
        _mesh.triangles = triangles.ToArray();
        _mesh.RecalculateBounds();
        _mesh.RecalculateNormals();
        _collider.sharedMesh = _mesh;
    }

    void AddTerrainPoint(Vector3 point)
    {

        vertices.Add(new Vector3(point.x, 0f, 0f));
        vertices.Add(point);


        if (vertices.Count >= 4)
        {
            int start = vertices.Count - 4;
            triangles.Add(start + 0);
            triangles.Add(start + 1);
            triangles.Add(start + 2);
            triangles.Add(start + 1);
            triangles.Add(start + 3);
            triangles.Add(start + 2);
        }
    }



    private Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {

        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;
        float uuu = uu * u;
        float ttt = tt * t;

        Vector3 p = uuu * p0;
        p += 3 * uu * t * p1;
        p += 3 * u * tt * p2;
        p += ttt * p3;

        return p;
    }
}

1 个答案:

答案 0 :(得分:1)

我很确定我已经遵循了该教程,该代码看起来很熟悉。

你是对的,它已经过时了。你应该注意this resource on the Unity Wiki,它更新,包含更多的原始而不仅仅是平面,包括立方体,圆锥,圆环,球体和icosphere。我在这里复制了立方体代码,因为这就是你所问的。

MeshFilter filter = gameObject.AddComponent< MeshFilter >();
Mesh mesh = filter.mesh;
mesh.Clear();

float length = 1f;
float width = 1f;
float height = 1f;

#region Vertices
Vector3 p0 = new Vector3( -length * .5f,    -width * .5f, height * .5f );
Vector3 p1 = new Vector3( length * .5f,     -width * .5f, height * .5f );
Vector3 p2 = new Vector3( length * .5f,     -width * .5f, -height * .5f );
Vector3 p3 = new Vector3( -length * .5f,    -width * .5f, -height * .5f );  

Vector3 p4 = new Vector3( -length * .5f,    width * .5f,  height * .5f );
Vector3 p5 = new Vector3( length * .5f,     width * .5f,  height * .5f );
Vector3 p6 = new Vector3( length * .5f,     width * .5f,  -height * .5f );
Vector3 p7 = new Vector3( -length * .5f,    width * .5f,  -height * .5f );

Vector3[] vertices = new Vector3[]
{
    // Bottom
    p0, p1, p2, p3,

    // Left
    p7, p4, p0, p3,

    // Front
    p4, p5, p1, p0,

    // Back
    p6, p7, p3, p2,

    // Right
    p5, p6, p2, p1,

    // Top
    p7, p6, p5, p4
};
#endregion

#region Normales
Vector3 up  = Vector3.up;
Vector3 down    = Vector3.down;
Vector3 front   = Vector3.forward;
Vector3 back    = Vector3.back;
Vector3 left    = Vector3.left;
Vector3 right   = Vector3.right;

Vector3[] normales = new Vector3[]
{
    // Bottom
    down, down, down, down,

    // Left
    left, left, left, left,

    // Front
    front, front, front, front,

    // Back
    back, back, back, back,

    // Right
    right, right, right, right,

    // Top
    up, up, up, up
};
#endregion  

#region UVs
Vector2 _00 = new Vector2( 0f, 0f );
Vector2 _10 = new Vector2( 1f, 0f );
Vector2 _01 = new Vector2( 0f, 1f );
Vector2 _11 = new Vector2( 1f, 1f );

Vector2[] uvs = new Vector2[]
{
    // Bottom
    _11, _01, _00, _10,

    // Left
    _11, _01, _00, _10,

    // Front
    _11, _01, _00, _10,

    // Back
    _11, _01, _00, _10,

    // Right
    _11, _01, _00, _10,

    // Top
    _11, _01, _00, _10,
};
#endregion

#region Triangles
int[] triangles = new int[]
{
    // Bottom
    3, 1, 0,
    3, 2, 1,            

    // Left
    3 + 4 * 1, 1 + 4 * 1, 0 + 4 * 1,
    3 + 4 * 1, 2 + 4 * 1, 1 + 4 * 1,

    // Front
    3 + 4 * 2, 1 + 4 * 2, 0 + 4 * 2,
    3 + 4 * 2, 2 + 4 * 2, 1 + 4 * 2,

    // Back
    3 + 4 * 3, 1 + 4 * 3, 0 + 4 * 3,
    3 + 4 * 3, 2 + 4 * 3, 1 + 4 * 3,

    // Right
    3 + 4 * 4, 1 + 4 * 4, 0 + 4 * 4,
    3 + 4 * 4, 2 + 4 * 4, 1 + 4 * 4,

    // Top
    3 + 4 * 5, 1 + 4 * 5, 0 + 4 * 5,
    3 + 4 * 5, 2 + 4 * 5, 1 + 4 * 5,

};
#endregion

mesh.vertices = vertices;
mesh.normals = normales;
mesh.uv = uvs;
mesh.triangles = triangles;

mesh.RecalculateBounds();
mesh.Optimize();