用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;//为了使绘制后的物体仍在原地,将移动后的物体归位 }} |
