Unity网格编程学习(二)

1.创建平面


定义平面的长、高,以及mesh的顶点、uv、法线

public int x = 3, y = 3;
private Vector3[] vertices;
private Vector2[] uvs;
private Vector3[] normals;

private void Start()
{
    Mesh mesh = new Mesh();
    MeshFilter filter = this.GetComponent<MeshFilter>();
    filter.mesh = mesh;

    vertices = new Vector3[(x + 1) * (y + 1)];
    uvs = new Vector2[vertices.Length];
    normals = new Vector3[vertices.Length];

    mesh.vertices = GetVertices();
    mesh.triangles = GetTriangles();
    mesh.uv = uvs;
    mesh.normals = normals;
}

定义获取顶点数据的方法GetVertices

private Vector3[] GetVertices()
{
    for (int i = 0; i < x + 1; i++)
    {
        for (int j = 0; j < y + 1; j++)
        {
            vertices[i * (y + 1) + j] = new Vector3(i, j, 0);
            uvs[i * (y + 1) + j] = new Vector2((float)i / x, (float)j / y);
            normals[i * (y + 1) + j] = GetNormal(i);
        }
    }
    return vertices;
}

因为平面的长为x,高为y,所以在长上需要x+1个顶点,在高上需要y+1个顶点,通过循环创建z轴坐标为0的顶点坐标,可以得到如图所示的绘制顺序的顶点

接下来定义获取绘制顺序的方法GetTriangle

private int[] GetTriangles()
{
    int[] temp = new int[x * y * 6];

    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
        {
            int index = i * (y + 1) + j;
            int tempIndex = (i * y + j) * 6;

            temp[tempIndex++] = index;
            temp[tempIndex++] = index + 1;
            temp[tempIndex++] = index + y + 1;

            temp[tempIndex++] = index + 1;
            temp[tempIndex++] = index + y + 2;
            temp[tempIndex++] = index + y + 1;
        }
    }
    
    return temp;
}

因为我们的顶点是从下至上,从左至右创建的,所以要创建如图所示的三角形,我们需要从左下角的(0,0)顶点开始向上遍历顶点,在这里我将以如图所示的方向进行三角形的绘制,因此我们只需要遍历图中标蓝的顶点便可以创建整个平面

通过观察可以发现,一号三角形的创建需要依次通过顶点0,1,4,而2号三角形的创建则需要通过顶点1,5,4

我们从y轴开始,得到第一个顶点的编号index以及数组中元素的下标tempIndex,不难发现一号三角形的绘制顺序是index,index+1,index+y+1,二号三角形的绘制顺序是index+1,index+y+2,index+y+1
通过循环遍历了所有需要遍历的顶点后,我们也已经将所有三角形的绘制顺序依次存入了数组temp中,进行绘制即可得到如图所示的平面

由于我们在GetVertices方法中就已经使用了uvs[i * (y + 1) + j] = new Vector2((float)i / x, (float)j / y);来获取uv数据,所以直接为平面添加uv贴图即可得到如图所示的效果

通过这段代码,我们将顶点的坐标标准化到(0,1)中,以此来与UV贴图进行对应
接下来定义获取法线数据的方法GetNormals

private Vector3 GetNormal(int y)
{
    if (y % 2 == 0)
    {
        return Vector3.up;
    }
    else
    {
        return Vector3.down;
    }
}

我们在GetVertices方法中通过normals[i * (y + 1) + j] = GetNormal(i);语句向GetNormal方法传参,如果是奇数列则返回Vector3.up,如果是偶数列则返回Vector3.down,因此我们可以得到如下图所示的效果

在这个光源下up方向的顶点受到更多的光照,而down方向的顶点则接收到较少的光照

2.创建立方体


要创建一个基本的正方体,我们应该需要8个顶点,6个面,每个面有两个三角形,所以我们需要定义8个顶点信息并绘制12个三角形
我们先进行正方体底面的创建,我们以原点作为正方形的中心点,可以得到正方形底面的四个点的坐标为(-0.5, -0.5, -0.5),(0.5, -0.5, -0.5),(-0.5, -0.5, 0.5),(0.5, -0.5, 0.5)
绘制顶点后如图所示

接下来进行面的绘制

依次定义顶面的四个顶点的坐标后,顶点以及底面的绘制方向如图所示

对6个面依次进行绘制后即可得到一个基本的正方体

posted @   NfishAndSli  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示