用unity实现tilt brush绘制面片功能(一)
发表于2017-04-24
相信很多人都被去年亮相的tilt brush绘图效果所惊艳,最近有些手痒,便打算自行实现一下tilt brush的绘制面片功能。由于代码量相对较大,预计会分三次实现完整的效果,并将实现思路记录在腾讯GAD中,供大家学习交流,如发现不合理的地方,请及时告知,谢谢。
由于手上没有htcvive,所以只能通过键盘输入来模拟移动,下面是移动的代码
1 2 3 4 5 6 7 8 | if (Input.GetKey( "q" )) { transform.Rotate( new Vector3(0, 0, -rotat)); } if (Input.GetKey( "e" )) { transform.Rotate( new Vector3(0, 0, rotat)); } |
1 2 3 4 5 6 7 8 9 10 | if (!isprint) { if (Vector3.Distance(transform.position, pos) > 0.2f) { //将2个小球位置保存 m_point1.Add(point1.transform.position); m_point2.Add(point2.transform.position); pos = transform.position; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | m_vertices = new Vector3[m_point1.Count * 2]; for ( int i=0;i< m_point1.Count; i++) { //逐个添加顶点 m_vertices[i * 2] = m_point1[i]; m_vertices[i * 2 + 1] = m_point2[i]; } m_uv = new Vector2[m_point1.Count * 2]; for ( int i = 0; i < m_point1.Count; i++) { //设置uv,从左下到右上,从0到1 m_uv[i * 2] = new Vector2(0, ( float )i / ( float )m_point1.Count); m_uv[i * 2 + 1] = new Vector2(0, ( float )i / ( float )m_point1.Count); } m_triangles = new int [m_point1.Count * 3]; for ( int i = 0; i < m_point1.Count; i++) { //设置三角面 m_triangles[i * 3] = i; if (i % 2 == 0) { m_triangles[i * 3 + 1] = i + 1; m_triangles[i * 3 + 2] = i + 2; } else { m_triangles[i * 3 + 1] = i + 2; m_triangles[i * 3 + 2] = i + 1; } } |
然后是存储uv,根据需求,我们在一个面片中只需要绘制一张图片,所以uv从左下到右上只能是从0到1,这样我们便可以通过i值除以数组长度来获得uv值的大小,别忘了数据类型转换喔!
最后是设置三角面,由于我们的网格是单面的,如果三角面设置顺序错误,便只能看见一半的图像,切记。
如图,该网格的三角面应该是(1,2,3),(2,4,3),(3,4,5),(4,6,5),(5,6,7),(6,8,8)找到规律了吗?
将数据保存后当然是更新我们的网格啦,直接上代码
1 2 3 4 5 6 7 8 | mesh.Clear(); //将原来的网格信息清除 mesh.vertices = m_vertices; mesh.uv = m_uv; mesh.colors = m_color; mesh.normals = m_normals; mesh.triangles = m_triangles; mesh.RecalculateNormals(); //重绘网格 transform.position = Vector3.zero; //为了使绘制后的物体仍在原地,将移动后的物体归位 |
下面是完整的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | using UnityEngine; using System.Collections; using System.Collections.Generic; public class demo : MonoBehaviour { public float speed = 0.1f; public float rotat = 1; public Vector3[] m_vertices; public Vector2[] m_uv; public Color[] m_color; public Vector3[] m_normals; public int [] m_triangles; private List m_point1 = new List(); private List m_point2 = new List(); private Mesh mesh; private bool isprint = false ; private Vector3 pos = Vector3.zero; private Transform point1; private Transform point2; void Start() { mesh = transform.GetComponent().mesh;//无法打出尖括号!注意,这里要先获取MeshFilter再.mesh point1 = transform.GetChild(0); point2 = transform.GetChild(1); } void FixedUpdate() { Move(); } void Update() { //按下p键开始绘制网格 if (Input.GetKeyDown( "p" )) { isprint = true ; DrawMesh(); } } void Move() { transform.Translate( new Vector3(Input.GetAxis( "Vertical" ), Input.GetAxis( "Horizontal" ), 0)*speed,Space.World); if (Input.GetKey( "q" )) { transform.Rotate( new Vector3(0, 0, -rotat)); } if (Input.GetKey( "e" )) { transform.Rotate( new Vector3(0, 0, rotat)); } if (!isprint) { if (Vector3.Distance(transform.position, pos) > 0.2f) { //将2个小球位置保存 m_point1.Add(point1.transform.position); m_point2.Add(point2.transform.position); pos = transform.position; } } } void DrawMesh() { m_vertices = new Vector3[m_point1.Count * 2]; for ( int i=0;i< m_point1.Count; i++) { //逐个添加顶点 m_vertices[i * 2] = m_point1[i]; m_vertices[i * 2 + 1] = m_point2[i]; } m_uv = new Vector2[m_point1.Count * 2]; for ( int i = 0; i < m_point1.Count; i++) { //设置uv,从左下到右上从0到1 m_uv[i * 2] = new Vector2(0, ( float )i / ( float )m_point1.Count); m_uv[i * 2 + 1] = new Vector2(0, ( float )i / ( float )m_point1.Count); } m_triangles = new int [m_point1.Count * 3]; for ( int i = 0; i < m_point1.Count; i++) { //设置三角面 m_triangles[i * 3] = i; if (i % 2 == 0) { m_triangles[i * 3 + 1] = i + 1; m_triangles[i * 3 + 2] = i + 2; } else { m_triangles[i * 3 + 1] = i + 2; m_triangles[i * 3 + 2] = i + 1; } } ChangeMesh(); } void ChangeMesh() { mesh.Clear(); //将原来的网格信息清除 mesh.vertices = m_vertices; mesh.uv = m_uv; mesh.colors = m_color; mesh.normals = m_normals; mesh.triangles = m_triangles; mesh.RecalculateNormals(); //重绘网格 transform.position = Vector3.zero; //为了使绘制后的物体仍在原地,将移动后的物体归位 } } |