关于绘制网格, 雨松前辈 已经解释的非常的到位,这里我只是搬运工,实在是感觉自己去描述的话不会有雨松大神描述的清楚,该文章循序渐进,一步步引导读者去理解unirty 绘图机制,真的是没有比这个再好得了,下面是文章原文:
首先创建Unity工程,接着创建一个空的游戏对象,然后给该游戏对象绑定Mesh Filter组件 与 Mesh Renderer组件。
Mesh Filter组件:表示网格面,这个网格面是由我们使用代码将所有三角形拼接起来生成的面。
Mesh Renderer组件:表示表示网格的渲染,可设置一个渲染的材质,它包括贴图与颜色。
如下图所示,我说说里面比较重要的属性。Mesh Renderer中,Materials下拉列表中可设置网格模型的材质,此时我们设置了一个红色的材质。 Mesh Filter:目前为None,也不用再编辑器中为它赋值,因为这个网格模型我们会在代码中生成并且赋值。在下面就是方刚我们设置红色的材质资源,Shader中设置了贴图的属性,目前是GUI/ TextShader。它表示这个材质的渲染级别在GUI上,就是优先级是最一层的。举个例子无论在这个网格模型的前面绘制多少模型,它永远都会在最前面显示。就这个例子而言它的存在并不是必需的,其实Shader的选项还有很多,可透明、不可透明、镜面、反射等等,后期我会向大家详细道来。
1 using UnityEngine;
2 using System.Collections.Generic;
3 using System;
4
5 public class Test : MonoBehaviour {
6
7 void Start ()
8 {
9 //得到MeshFilter对象,目前是空的。
10 MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
11 //得到对应的网格对象
12 Mesh mesh = meshFilter.mesh;
13
14 //三角形顶点的坐标数组
15 Vector3[] vertices = new Vector3[3];
16 //三角形顶点ID数组
17 int[] triangles = new int[3];
18
19 //三角形三个定点坐标,为了显示清楚忽略Z轴
20 vertices[0] = new Vector3(0,0,0);
21 vertices[1] = new Vector3(0,1,0);
22 vertices[2] = new Vector3(1,0,0);
23
24 //三角形绘制顶点的数组
25 triangles[0] =0;
26 triangles[1] =1;
27 triangles[2] =2;
28
29 //注释1
30 mesh.vertices = vertices;
31
32 mesh.triangles = triangles;
33
34 }
35
36 }
代码中有两个非常重要的概念,就是三角形顶点数组与坐标数组。先说说坐标数组,假设需要绘制一个四边形,此时三角形坐标数组的长度应当是4,它保存着四边形四个顶点的坐标。然后是顶点数组,四边形是由两个三角形组成,然而一个三角形是由3个顶点组成,两个三角形就应当是6个顶点组成,无论多少个三角形它们的结构都应当是以此类推。
注解1:这里是将模型的顶点数组与坐标数组赋值给网格模型,还记得刚刚在创建Mesh Filter时,当时没有在编辑器中给网格模型赋值,实际上代码走到这里就会重新为网格模型MeshFilter赋值,接着我们在代码中绘制的三角形就会显示在屏幕当中。
如图所示,三角形已经绘制在屏幕当中。 图中数组 0 1 2 表示该三角形的三个顶点的ID。这个ID对应代码中对应vertices数组索引顶点的坐标。
下面我们修改一下代码,让屏幕中一共绘制4个三角形。
根据上面的逻辑,我们修改一下算法。假设三角形的顶点坐标为任意数量,我们需要更根据顶点坐标数量来计算对应顶点ID的数组内容。在for循环中start =0 与end =3的含义是绘制从顶点坐标数组中索引为0的顶点开始绘制到数组索引为3的顶点,也就说是这里从0到3绘制了3个三角形。
1 using UnityEngine;
2 using System.Collections.Generic;
3 using System;
4
5 public class Test : MonoBehaviour {
6
7 //网格模型顶点数量
8 private int VERTICES_COUNT = 6;
9
10 void Start ()
11 {
12 //得到MeshFilter对象,目前是空的。
13 MeshFilter meshFilter = (MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
14 //得到对应的网格对象
15 Mesh mesh = meshFilter.mesh;
16
17 //三角形顶点的坐标数组
18 Vector3[] vertices = new Vector3[VERTICES_COUNT];
19
20 //得到三角形的数量
21 int triangles_count = VERTICES_COUNT - 2;
22
23 //三角形顶点ID数组
24 int[] triangles = new int[triangles_count *3];
25
26 //三角形三个定点坐标,为了显示清楚忽略Z轴
27 vertices[0] = new Vector3(0,0,0);
28 vertices[1] = new Vector3(0,1,0);
29 vertices[2] = new Vector3(1,0,0);
30 vertices[3] = new Vector3(1,1,0);
31 vertices[4] = new Vector3(2,0,0);
32 vertices[5] = new Vector3(2,1,0);
33
34 //绘制三角形
35 mesh.vertices = vertices;
36
37 //起始三角形顶点
38 int start = 0;
39
40 //结束三角形的顶点
41 int end = 3;
42
43 for(int i = start; i <end; i++)
44 {
45 for(int j = 0; j < 3; j++)
46 {
47 if( i%2 ==0)
48 {
49 triangles[3*i + j] = i +j;
50 }else
51 {
52 triangles[3*i + j] = i + 2-j;
53 }
54
55 }
56 }
57
58 mesh.triangles = triangles;
59 }
60 }
如下图所示,根据上面的逻辑算法,共绘制了3个三角形,并且顶点坐标ID是由 0 到3 。 说到这里请大家仔细想想本文的标题内容,其实两个动态轨迹的点就是在维护triangles顶点坐标数组。triangles[0]、triangles[2]、triangles[4]……表示一个轨迹点的值,triangles[1]、triangles[3]、triangles[5]……就表示另一个轨迹点的值,最终将它们通过上面的算法将三角形面连接起来那么就是动态的两个点轨迹绘制面了。
以上内容引用了雨松前辈的文章,其中开篇处去掉了一些引导性的内容,另外,为便于理解使用的图片有所不同。
比如要绘制4个三角形,那么会有4+2= 6个关键点,每个三角形有三个顶点。那么需要3*4=12个三角形顶点,但只有6个点,实际上是有些点需要被用2次,有的点被用了三次;
三点确定一个面。这三个点按顺时针连接在一起,如下图:
案例中列举了比较规则的只是为了便于理解,道理算是讲明白了。
看了前辈的博客,我感受到了算法是多么的牛逼,不得不服。只最后那个脚本的双层for 循环的内容就让我理解了很久,才弄明白,算法很是精妙。