【Unity3D】Mesh

Unity3D如果要用代码绘制不规则形状的立体图形,必须借助Mesh。其实除了Unity3D提供的Cube、Sphere、Capsule、Cylinder、Plane,可以用GameObject.CreatePrimitive(PrimitiveType.XX);来生成以外,其余的3D图形,如果你不是直接导入模型的话,都要用Mesh去构造。Mesh本质上是一堆由三角形组成的物体。下面用Mesh来画一个矩形平面和圆形面来说明Mesh的使用。

如下图:


一块很简单的白色1x1矩形平面,用Mesh生成的代码如下,可以将如下代码MeshCreate.cs挂载到主摄像机或者空物体则可以直接看到效果了。当然平时这块东西直接用Plane来生成更合适。

using UnityEngine;
using System.Collections;

public class MeshCreate : MonoBehaviour
{
    Mesh CreateMesh()
    {
        Mesh mesh = new Mesh();
        mesh.name = "rectangle";
        mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
        mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) };
        mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
        return mesh;
    }
    void Start()
    {
        GameObject rectangle = new GameObject("rectangle");
        rectangle.AddComponent("MeshFilter");
        rectangle.GetComponent<MeshFilter>().mesh = CreateMesh();//创建Mesh
        //赋予Mesh一个UI/Default材质,颜色为白色,此材质不受灯光影响
        MeshRenderer meshRenderer = rectangle.AddComponent<MeshRenderer>();
        meshRenderer.material.shader = Shader.Find("UI/Default");
        meshRenderer.material.color = Color.white;
    }
}
基本上Mesh会赋予到一个空物体GameObject。需要同时赋予MeshFilter与MeshRenderer两部分,一个用来指定Mesh的形状,另一个用来指定这个Mesh所用的材质。这里Mesh使用了纯色材质,没什么好说的。关键是MeshFilter中指定的Mesh。

Mesh由顶点数组vertices、贴图坐标数组uv和三角形数组triangles。这三个概念是Mesh的难点。如下图:


如上文所言,Mesh是由三角形组成的。你用Mesh画出来的平面必须又三角形拼成。这里的矩形平面可以分解为2个三角形拼成,不为什么,显然可以。那么自然而然,矩形的四个顶点的坐标则拼成Mesh顶点数组vertices的内容。而贴图坐标数组uv,是指1x1的材质正方形里面,顶点数组vertices中的顶点所处的位置,以用来截取的这个1x1的正方形,坐标数组uv中只能由坐标取值在[0,1]的二维坐标组成,由于这里只是贴个纯色材质,整个材质正方形上的所有点都是一个意思,所以这里的坐标怎么写都一样,但贴图坐标数组uv中的长度必须和顶点数组vertices的坐标数量相同,Unity3D要求各个顶点都有一个材质落脚点。

至于三角形数组,则是Mesh的形成方式,如下图:


要求Mesh由顶点0->1->2遍历从而形成一个三角形,然后要求由顶点0->2->3由形成一个三角形,从而形成一个最终的Mesh。Unity3D对三角形数组triangles的数组也是三个一读,三个一读。读取方式必须统一方向,统一顺时针或者统一逆时针。所以这里我的三角形数组写了mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };。

下面举一个更复杂的例子说明Mesh,如下图的圆平面:


对应的CircleCreate.cs如下:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;//用到容器

public class CircleCreate : MonoBehaviour
{
    Mesh CreateMesh()
    {
        Mesh mesh = new Mesh();
        mesh.name = "circle";
        float circle_radius = 5;//圆的半径
        int segment = 360;//分段数
        float circle_Z = 0;//圆所处的Z平面
        //圆心(0,0)
        float circle_center_point_x = 0;
        float circle_center_point_y = 0;
        List<Vector3> circle_mesh_vertices = new List<Vector3>();
        List<Vector2> circle_mesh_uv = new List<Vector2>();
        List<int> circle_triangles = new List<int>();
        circle_mesh_vertices.Add(new Vector3(circle_center_point_x, circle_center_point_y, circle_Z));
        circle_mesh_uv.Add(new Vector2(0, 0));
        for (int i = 1; i < segment + 1; i++)
        {
            float angle_in_circular_segment = (i - 1) * (360 / segment);//圆周角
            circle_mesh_vertices.Add(new Vector3(
                circle_radius * Mathf.Cos(angle_in_circular_segment) * Mathf.Sin(angle_in_circular_segment),
                circle_radius * Mathf.Pow(Mathf.Cos(angle_in_circular_segment), 2),
                circle_Z
            ));
            circle_mesh_uv.Add(new Vector2(0, 0));
            circle_triangles.Add(0);
            circle_triangles.Add(i);
            //平时都是0,i,i+1的,但最后一个0,360,1需要特殊处理
            if (i + 1 < segment + 1)
            {
                circle_triangles.Add(i + 1);
            }
            else
            {
                circle_triangles.Add(1);
            }
        }
        mesh.vertices = circle_mesh_vertices.ToArray();
        mesh.uv = circle_mesh_uv.ToArray();
        mesh.triangles = circle_triangles.ToArray();
        return mesh;
    }
    void Start()
    {
        GameObject circle = new GameObject("circle");
        circle.AddComponent("MeshFilter");
        circle.GetComponent<MeshFilter>().mesh = CreateMesh();
        MeshRenderer meshRenderer = circle.AddComponent<MeshRenderer>();
        meshRenderer.material.shader = Shader.Find("UI/Default");
        meshRenderer.material.color = Color.white;
    }
}

这里的圆弧实质是不平整的,它实质是由360个三角形组成的圆而已。具体绘制思想如下:



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值