Unity 3D 创建Mesh(一)

时间:2021-12-25 04:12:04

Unity 3D 创建Mesh(一)


一、Unity 3D 创建面片(Mesh)

Mesh是一种网格,可以产生像地形那样震撼的效果,那么怎样创建Mesh呢?那就要知道Mesh包含什么!
Mesh(网格):顶点、三角形、段数。
Unity 3D 创建Mesh(一)
如图所示:该网格该如何表示呢?
顶点(vertexes) 16=4*4
段数(segment) 3*3
三角形(triangles) 18
但是,三角形数目不是自己数,而是计算出来的。

二、创建Mesh属性

我们来创建一个长宽为100m*100m,高度为0m,段数为3*3的网格,如上图所示
/*  Mesh属性
     *      长宽
     *      段数
     *      高度
     */
    private Vector2 size;//长度和宽度
    private float height= 0;//高度
    private Vector2 segment;//长度的段数和宽度的段数
/*  顶点属性
     *      顶点
     *      uv
     *      三角形 
     */
    private Vector3[] vertexes;//顶点数
    private int[] triangles;//三角形索引


 
  
    /*计算顶点,存入顶点数组*/
    private void computeVertexes()
    {
        int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));//顶点总数
        float w = size.x / segment.x;//每一段的长度
        float h = size.y / segment.y;
 
        GetTriangles();//计算三角形索引顶点序列

        int index = 0;
        vertexes = new Vector3[sum];
        for (int i = 0; i < segment.y + 1;i++ )
        {
            for (int j = 0; j < segment.x + 1; j++)
            {
                float tempHeight = 0;
                vertexes[index] = new Vector3(j*w, 0, i*h);//计算完顶点
                index++;
            }
        }
    }
/*计算三角形的顶点索引*/
private int[] GetTriangles()
    {
        int sum = Mathf.FloorToInt(segment.x * segment.y * 6);//三角形顶点总数:假设是1*1的网格,会有2个顶点复用,因此是6个顶点。假设是2*2的网格,则是4个1*1的网格,即4*6即2*2*6!
        triangles = new int[sum];
        uint index = 0;
        for (int i = 0; i < segment.y; i++)
        {
            for (int j = 0; j < segment.x; j++)
            {
                int role = Mathf.FloorToInt(segment.x) + 1;
                int self = j + (i * role);
                int next = j + ((i + 1) * role);
                //顺时针
//第一个三角形
                triangles[index] = self;
                triangles[index + 1] = next + 1;
                triangles[index + 2] = self + 1;
//第二个三角形
                triangles[index + 3] = self;
                triangles[index + 4] = next;
                triangles[index + 5] = next + 1;
                index += 6;
            }
        }
        return triangles;
    }
 
  
 
 
到此:顶点、三角形计算完成!接下来是渲染。

三、渲染网格

在Unity 3D中,一个GameObject只有一个transform组件。我们在程序中,声明一个GameObject变量,通过添加MeshFilter来增加Mesh属性,通过MeshRenderer渲染出来,在MeshRenderer中,我们使用默认材质球。
    private GameObject mMesh;
    private Material mMaterial;
mMesh = new GameObject();
        mMesh.name = "CreateMesh";
</pre><pre code_snippet_id="655703" snippet_file_name="blog_20150429_12_2096575" name="code" class="cpp">    private void DrawMesh()
    {
        Mesh mesh = mMesh.AddComponent<MeshFilter>().mesh;//网格
        mMesh.AddComponent<MeshRenderer>();//网格渲染器

        mMaterial = new Material(Shader.Find("Diffuse"));//材质

        mMesh.GetComponent<Renderer>().material = mMaterial;

        /*设置mesh*/
        mesh.Clear();//更新
        mesh.vertices = vertexes;
        //mesh.uv 
        mesh.triangles = triangles;

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

    }

 
 
 
 

四、完整代码(有点不一样,扩充了点,拖在摄像机下面即可)

using UnityEngine;
using System.Collections;

/*仅仅创建Mesh
 *
 *
 */
public class CreatMesh : MonoBehaviour {

    private GameObject mMesh;
    private Material mMaterial;

    /*  Mesh属性
     *      长宽
     *      段数
     *      高度
     *      高度差
     */
    private Vector2 size;//长度和宽度
    private float minHeight = -10;//最小高度
    private float maxHeight = 10;//最大高度
    private Vector2 segment;//长度的段数和宽度的段数
    private float unitH;//最小高度和最大高度只差,值为正

    /*  顶点属性
     *      顶点
     *      uv
     *      三角形 
     */
    private Vector3[] vertexes;//顶点数
    private Vector2 uvs;//uvs坐标
    private int[] triangles;//三角形索引

	void Start () {
        creatMesh(100, 100, 3, 3, -10, 10);
	}
	
    private void creatMesh(float width, float height, uint segmentX, uint segmentY,int min, int max)
    {
        size = new Vector2(width, height);
        maxHeight = max;
        minHeight = min;
        unitH = maxHeight - minHeight;
        segment = new Vector2(segmentX, segmentY);

        if (mMesh != null)
        {
            Destroy(mMesh);
        }
        mMesh = new GameObject();
        mMesh.name = "CreateMesh";

        computeVertexes();
        DrawMesh();
    }

    private void computeVertexes()
    {
        int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));//顶点总数
        float w = size.x / segment.x;//每一段的长度
        float h = size.y / segment.y;
 
        GetTriangles();

        int index = 0;
        vertexes = new Vector3[sum];
        for (int i = 0; i < segment.y + 1;i++ )
        {
            for (int j = 0; j < segment.x + 1; j++)
            {
                float tempHeight = 0;
                vertexes[index] = new Vector3(j*w, 0, i*h);
                index++;
            }
        }
    }

    private void DrawMesh()
    {
        Mesh mesh = mMesh.AddComponent<MeshFilter>().mesh;//网格
        mMesh.AddComponent<MeshRenderer>();//网格渲染器

        mMaterial = new Material(Shader.Find("Diffuse"));//材质

        mMesh.GetComponent<Renderer>().material = mMaterial;

        /*设置mesh*/
        mesh.Clear();//更新
        mesh.vertices = vertexes;
        //mesh.uv 
        mesh.triangles = triangles;

        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

    }

    private int[] GetTriangles()
    {
        int sum = Mathf.FloorToInt(segment.x * segment.y * 6);//三角形顶点总数
        triangles = new int[sum];
        uint index = 0;
        for (int i = 0; i < segment.y; i++)
        {
            for (int j = 0; j < segment.x; j++)
            {
                int role = Mathf.FloorToInt(segment.x) + 1;
                int self = j + (i * role);
                int next = j + ((i + 1) * role);
                //顺时针
                triangles[index] = self;
                triangles[index + 1] = next + 1;
                triangles[index + 2] = self + 1;
                triangles[index + 3] = self;
                triangles[index + 4] = next;
                triangles[index + 5] = next + 1;
                index += 6;
            }
        }
        return triangles;
    }
}