Mesh概念

Mesh是Unity中的一个组件,称为网格组件。通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而多边形实际上是由多个三角形拼接而成的。所以一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh。

Mesh的组成

  1. 顶点坐标数组vertexes 
  2. 顶点在uv坐标系中的位置信息数组uvs
  3. 三角形顶点顺时针或者逆时针索引数组triangles
  4. MeshFiler组件,用于增加mesh属性
  5. MeshRender组件,增加材质并渲染出来。
  6. (每个顶点的法线的数组normals)

创建面片

  Mesh(网格):顶点、三角形、段数。

  顶点(vertexes)    16=4*4
  段数(segment)    3*3
  三角形(triangles)    18

例:创建一个mesh

1 /*  Mesh属性
  2      *      长宽
  3      *      段数
  4      *      高度
  5      */
  6     Vector2 size; //长度和宽度
  7     float hight = 0;//高度
  8     Vector2 segment;//长度的段数和宽度的段数
  9     /*  顶点属性
 10      *      顶点
 11      *      uv
 12      *      三角形 
 13      */
 14     Vector3[] vertexes;//顶点数
 15     int[] triangles;//三角形索引
 16 
 17 
 18     void Start()
 19     {
 20         Debug.Log("Start");
 21         size = new Vector2(9, 9);
 22         hight = 1;
 23         segment = new Vector2(9, 9);
 24         computeVertexes();
 25         InitRenderMesh();
 26         DrawMesh();
 27     }
 28 
 29 
 30     /*计算顶点,存入顶点数组*/
 31     private void computeVertexes()
 32     {
 33         int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));//顶点总数
 34         float w = size.x / segment.x;//每一段的长度
 35         float h = size.y / segment.y;
 36 
 37         GetTriangles();//计算三角形索引顶点序列
 38 
 39         int index = 0;
 40         vertexes = new Vector3[sum];
 41         for (int i = 0; i < segment.y + 1; i++)
 42         {
 43             for (int j = 0; j < segment.x + 1; j++)
 44             {
 45                 float tempHeight = 0;
 46                 tempHeight = FloatNum(1-j * 1f / (segment.x + 1), LineType.NType, 0.3f)*10;
 47                 Debug.Log(tempHeight);
 48                 vertexes[index] = new Vector3(j * w, tempHeight, i * h);//计算完顶点
 49                 index++;
 50             }
 51         }
 52     }
 53 
 54 
 55     private int[] GetTriangles()
 56     {
 57         //三角形顶点总数:假设是1*1的网格,会有2个顶点复用,因此是6个顶点。假设是2*2的网格,则是4个1*1的网格,即4*6即2*2*6!
 58         int sum = Mathf.FloorToInt(segment.x * segment.y * 6);
 59         triangles = new int[sum];
 60         uint index = 0;
 61         for (int i = 0; i < segment.y; i++)
 62         {
 63             for (int j = 0; j < segment.x; j++)
 64             {
 65                 int role = Mathf.FloorToInt(segment.x) + 1;
 66                 int self = j + (i * role);
 67                 int next = j + ((i + 1) * role);
 68                 //顺时针
 69                 //第一个三角形
 70                 triangles[index] = self;
 71                 triangles[index + 1] = next + 1;
 72                 triangles[index + 2] = self + 1;
 73                 //第二个三角形
 74                 triangles[index + 3] = self;
 75                 triangles[index + 4] = next;
 76                 triangles[index + 5] = next + 1;
 77                 index += 6;
 78             }
 79         }
 80         return triangles;
 81     }
 82 
 83     //到此:顶点、三角形计算完成!接下来是渲染。
 84 
 85     /*
 86      * 渲染网格
 87      * 在Unity 3D中,一个GameObject只有一个transform组件。我们在程序中,声明一个GameObject变量,
 88      * 通过添加MeshFilter来增加Mesh属性,通过MeshRenderer渲染出来,在MeshRenderer中,我们使用默认材质球。
 89      * */
 90 
 91     GameObject mMesh;
 92     Material mMaterial;
 93 
 94     void InitRenderMesh()
 95     {
 96         mMesh = new GameObject();
 97         mMesh.name = "CreateMesh";
 98     }
 99     void DrawMesh()
100     {
101         Mesh mesh = mMesh.AddComponent<MeshFilter>().mesh;          //网格
102         mMesh.AddComponent<MeshRenderer>();                         //网格渲染器
103         mMaterial = Resources.Load<Material>("MeshMaterial");           //材质
104         mMesh.GetComponent<MeshRenderer>().material = mMaterial;
105 
106         //设置Mesh
107         mesh.Clear();
108         mesh.vertices = vertexes;
109         //mesh.uv
110         mesh.triangles = triangles;
111 
112         mesh.RecalculateNormals();
113         mesh.RecalculateBounds();
114     }
115 
116     /// <summary>
117     /// 
118     /// </summary>
119     /// <param name="x">变量</param>
120     /// <param name="T">线性类型</param>
121     /// <param name="agent">弯曲度(0,0.5)</param>
122     float FloatNum(float x,LineType T,float agent)
123     {
124         float y = 0;
125         if (T == LineType.UType)
126         {
127             y = agent * x * x;
128         }
129         else if (T == LineType.NType)
130         {
131             y = -agent * x * x+1;
132         }
133         return y;
134     }
135 
136 
137 
138 
139 
140 
141 
142     enum LineType 
143     {
144         UType=0,
145         NType=1,
146     }

 双面mesh

由于三角形序列的顺序决定了法线的朝向,从而确定了显示的面,先前只是顺时针序列,只能从“正面”看到,那么是不是可以认为加上逆时针序列就可以看到“反面了”。

由于顶点和三角形的个数并不是一个确定的关系,我们改变三角形序列,并不需要+-顶点数。

对比上面创建三角形序列的代码,我们可以这样写

int sum = Mathf.FloorToInt(segment.x * segment.y * 6);
        triangles = new int[sum*2];
        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;
            }
        }
        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 + 2] = next + 1;
                triangles[index + 1] = self + 1;
                //第二个三角形
                triangles[index + 3] = self;
                triangles[index + 5] = next;
                triangles[index + 4] = next + 1;
                index += 6;
            }
        }

三角形数列组数量翻倍,增加一个for循环,写上逆时针序列。效果完美实现。