Mesh概念
Mesh是Unity中的一个组件,称为网格组件。通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而多边形实际上是由多个三角形拼接而成的。所以一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh。
Mesh的组成
- 顶点坐标数组vertexes
- 顶点在uv坐标系中的位置信息数组uvs
- 三角形顶点顺时针或者逆时针索引数组triangles
- MeshFiler组件,用于增加mesh属性
- MeshRender组件,增加材质并渲染出来。
- (每个顶点的法线的数组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循环,写上逆时针序列。效果完美实现。