using UnityEngine; using System.Collections; using System.Collections.Generic; public struct SegmentPoint { public Vector3 normal; public Vector3 pos; }; public class DrawMesh_Plane : MonoBehaviour { MeshFilter meshFilter; /// <summary> /// 面片中的最后一个点 /// </summary> SegmentPoint lastPoint; SegmentPoint penultPoint; bool startDraw = false; bool twoPoint = false; /// <summary> /// 线条半径 /// </summary> float r; /// <summary> /// 包含meshfilter、meshrenderer、材质球组件的预设体 /// </summary> public GameObject linePrefab; public Transform lineParent; /// <summary> /// 平滑点数 /// </summary> public int smooth = 3; [HideInInspector] public Color lineColor; public VRTracketObjManager vrtom; public bool usePressure; public DrawMeshManager drawMeshManager; void Start() { lineColor = drawMeshManager.color; } void Update() { DrawMeshByCollider(); } void DrawMeshVR() { var device = SteamVR_Controller.Input((int)vrtom.trackedObj_Left.index); if (device.GetPress(SteamVR_Controller.ButtonMask.Trigger)) { if (usePressure) { r = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_Axis1).x * drawMeshManager.brushRadius; } else { r = drawMeshManager.brushRadius; } if (!startDraw && !twoPoint) { GameObject line = Instantiate(linePrefab); line.transform.SetParent(lineParent); meshFilter = line.GetComponent<MeshFilter>(); line.GetComponent<MeshRenderer>().material.SetColor("_Color", lineColor); if (drawMeshManager.addStep != null) { drawMeshManager.addStep(line); } } float dis = Vector3.Distance(vrtom.leftPenPoint.position, lastPoint.pos); if (!startDraw) { lastPoint.pos = vrtom.leftPenPoint.position; lastPoint.normal = -vrtom.leftPenPoint.up; startDraw = true; } else if (!twoPoint && dis > drawMeshManager.spaceDis) { SegmentPoint hitP; hitP.pos = vrtom.leftPenPoint.position; hitP.normal = -vrtom.leftPenPoint.up; meshFilter.mesh = CreateStartMesh(lastPoint, hitP); penultPoint = lastPoint; lastPoint = hitP; twoPoint = true; } else if (dis > drawMeshManager.spaceDis) { SegmentPoint hitP; hitP.pos = vrtom.leftPenPoint.position; hitP.normal = -vrtom.leftPenPoint.up; SegmentPoint[] newSP = SmoothPoints(lastPoint, penultPoint, hitP); List<Vector3> nv = new List<Vector3>(); for (int i = 0; i <= newSP.Length - 2; i++) { nv.AddRange(ComputeVertex(newSP[i], newSP[i + 1])); } penultPoint = newSP[newSP.Length - 2]; lastPoint = hitP; SetMesh(nv.ToArray()); } } if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger)) { startDraw = false; twoPoint = false; meshFilter = null; } } /// <summary> /// 贴合模型画线 /// </summary> void DrawMeshByCollider() { r = drawMeshManager.brushRadius; if (Input.GetMouseButton(0)) { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit) && hit.collider.tag == TagManager.Line) { if (!startDraw && !twoPoint) { GameObject line = Instantiate(linePrefab); line.transform.SetParent(lineParent); meshFilter = line.GetComponent<MeshFilter>(); line.GetComponent<MeshRenderer>().material.SetColor("_Color", lineColor); if (drawMeshManager.addStep != null) { drawMeshManager.addStep(line); } } float dis = Vector3.Distance(hit.point, lastPoint.pos); if (!startDraw) //开始创建第一个点 { lastPoint.pos = hit.point; lastPoint.normal = hit.normal; startDraw = true; } else if (!twoPoint && dis > drawMeshManager.spaceDis) //开始创建第一个面片 { SegmentPoint hitP; hitP.pos = hit.point; hitP.normal = hit.normal; meshFilter.mesh = CreateStartMesh(lastPoint, hitP); penultPoint = lastPoint; lastPoint = hitP; twoPoint = true; } else if (dis > drawMeshManager.spaceDis) { SegmentPoint hitP; hitP.pos = hit.point; hitP.normal = hit.normal; SegmentPoint[] newSP = SmoothPoints(lastPoint, penultPoint, hitP); List<Vector3> nv = new List<Vector3>(); for (int i = 0; i <= newSP.Length - 2; i++) { nv.AddRange(ComputeVertex(newSP[i], newSP[i + 1])); } penultPoint = newSP[newSP.Length - 2]; lastPoint = hitP; SetMesh(nv.ToArray()); } } else { startDraw = false; twoPoint = false; meshFilter = null; } } if (Input.GetMouseButtonUp(0)) { startDraw = false; twoPoint = false; meshFilter = null; } } /// <summary> /// 创建第一个面片 /// </summary> /// <param name="startP"></param> /// <param name="endP"></param> /// <returns></returns> Mesh CreateStartMesh(SegmentPoint startP,SegmentPoint endP) { Vector3 v1 = endP.pos - startP.pos; Vector3 d1 = Vector3.Cross(v1.normalized, startP.normal); Vector3 d2 = Vector3.Cross(v1.normalized, endP.normal); d1 = d1.normalized; Vector3 p0, p1, p2, p3; p0 = startP.pos - d1 * r * 0.5f + startP.normal * drawMeshManager.expand; p1 = startP.pos + d1 * r * 0.5f + startP.normal * drawMeshManager.expand; p2 = endP.pos - d2 * r * 0.5f + endP.normal * drawMeshManager.expand; p3 = endP.pos + d2 * r * 0.5f + endP.normal * drawMeshManager.expand; Vector3[] newVertices = {p0, p1, p2, p3 }; Vector2[] newUV = { new Vector2(p0.x, p0.y), new Vector2(p1.x, p1.y), new Vector2(p2.x, p2.y), new Vector2(p3.x, p3.y) }; int[] newTriangles = { 0, 1, 2, 1, 3, 2 }; Mesh mesh = new Mesh(); mesh.vertices = newVertices; mesh.uv = newUV; mesh.triangles = newTriangles; return mesh; } /// <summary> /// 获取原先面片 /// </summary> /// <param name="vert"></param> /// <param name="uvs"></param> /// <param name="tri"></param> void GetMesh(out List<Vector3> vert,out List<Vector2> uvs,out List<int> tri) { vert = new List<Vector3>(); uvs = new List<Vector2>(); tri = new List<int>(); vert.AddRange(meshFilter.mesh.vertices); uvs.AddRange(meshFilter.mesh.uv); tri.AddRange(meshFilter.mesh.triangles); } public void GenerateMesh(LineData ld) { GameObject l = Instantiate(linePrefab); l.AddComponent<MeshFilter>(); l.AddComponent<MeshRenderer>(); l.transform.position = ld.position; l.transform.eulerAngles = ld.rotation; Vector3[] newVertices = ld.vertex; Vector2[] newUV = ld.uv; int[] newTriangles = ld.triangle; Mesh mesh = new Mesh(); mesh.vertices = newVertices; mesh.uv = newUV; mesh.triangles = newTriangles; l.GetComponent<MeshFilter>().mesh = mesh; l.GetComponent<MeshRenderer>().material.color = ld.color; } /// <summary> /// 使用贝塞尔平滑线段 /// </summary> /// <param name="last"></param> /// <param name="penult"></param> /// <param name="current"></param> /// <returns></returns> SegmentPoint[] SmoothPoints(SegmentPoint last, SegmentPoint penult, SegmentPoint current) { float d = 1f / (float)smooth; SegmentPoint[] ps = new SegmentPoint[smooth - 1]; for (int i = 0; i < ps.Length; i++) { float t = d * (i + 1); ps[i].pos = (1 - t) * (1 - t) * penult.pos + 2 * t * (1 - t) * last.pos + t * t * current.pos; ps[i].normal = Vector3.LerpUnclamped(penult.normal, current.normal, t); } List<SegmentPoint> segs = new List<SegmentPoint>(); segs.Add(penult); segs.AddRange(ps); segs.Add(current); return segs.ToArray(); } Vector3[] ComputeVertex(SegmentPoint p1,SegmentPoint p2) { Vector3 dir = p2.pos - p1.pos; Vector3 d = Vector3.Cross(dir, p2.normal).normalized; Vector3[] ps = new Vector3[2]; ps[0] = p2.pos - d * 0.5f * r + p2.normal * drawMeshManager.expand; ps[1] = p2.pos + d * 0.5f * r + p2.normal * drawMeshManager.expand; return ps; } /// <summary> /// 添加mesh /// </summary> /// <param name="vetexes"></param> void SetMesh(Vector3[] vertexes) { List<Vector3> vert; List<Vector2> uvs; List<int> tri; GetMesh(out vert, out uvs, out tri); Vector3[] newVert = vertexes; Vector2[] newUv = new Vector2[vertexes.Length]; for (int i = 0; i < newVert.Length; i++) { newUv[i] = newVert[i]; } vert.RemoveAt(vert.Count - 1); vert.RemoveAt(vert.Count - 1); vert.AddRange(newVert); uvs.RemoveAt(uvs.Count - 1); uvs.RemoveAt(uvs.Count - 1); uvs.AddRange(newUv); int[] newTri = new int[vert.Count * 3 - 6]; for (int i = 0; i < newTri.Length / 6; i++) { if (i == 0) { newTri[i] = 0; newTri[i + 1] = 1; newTri[i + 2] = 2; newTri[i + 3] = 1; newTri[i + 4] = 3; newTri[i + 5] = 2; } else { newTri[i * 6] = newTri[i * 6 - 6] + 2; newTri[i * 6 + 1] = newTri[i * 6 - 5] + 2; newTri[i * 6 + 2] = newTri[i * 6 - 4] + 2; newTri[i * 6 + 3] = newTri[i * 6 - 3] + 2; newTri[i * 6 + 4] = newTri[i * 6 - 2] + 2; newTri[i * 6 + 5] = newTri[i * 6 - 1] + 2; } } Mesh m = new Mesh(); m.SetVertices(vert); m.uv = uvs.ToArray(); m.triangles = newTri; meshFilter.mesh.Clear(); meshFilter.mesh = m; } } =====================================================================
using UnityEngine; using System.Collections; using System.Collections.Generic; using LitJson; using System.Text; using System.IO; using UnityEditor; public class DrawMeshManager : MonoBehaviour { /// <summary> /// 线条半径 /// </summary> public float brushRadius = 0.01f; /// <summary> /// 点之间最小间隔 /// </summary> public float spaceDis = 0.04f; /// <summary> /// 面片向外扩展距离 /// </summary> public float expand = 0.01f; public Color color; public float alpha; public delegate void AddStep(GameObject gameObj); public AddStep addStep; /// <summary> /// 最大保存步数 /// </summary> public int maxCount = 10; public GameObject line; public GameObject tips; List<GameObject> allLine = new List<GameObject>(); LineData[] allLineData ; StringBuilder stringB; string filepath; // Use this for initialization void Start () { filepath = Application.dataPath + @"/StreamingAssets/json_line.txt"; addStep = new AddStep(AddDrawStep); } // Update is called once per frame void Update () { } void AddDrawStep(GameObject mesh) { if (allLine.Count == maxCount) { allLine.RemoveAt(maxCount - allLine.Count); } allLine.Add(mesh); } void Undo() { if (Input.GetKeyDown(KeyCode.Z)) { if (allLine.Count > 0) { Destroy(allLine[allLine.Count - 1]); allLine.RemoveAt(allLine.Count - 1); } } } public void SaveI() { SaveAsyn(); } void SaveAsyn() { allLineData = new LineData[line.transform.childCount]; print(allLineData.Length); for (int i = 0; i < allLineData.Length; i++) { allLineData[i] = new LineData(); allLineData[i].name = line.transform.GetChild(i).name; allLineData[i].position = line.transform.GetChild(i).position; allLineData[i].rotation = line.transform.GetChild(i).eulerAngles; allLineData[i].vertex = line.transform.GetChild(i).GetComponent<MeshFilter>().mesh.vertices; allLineData[i].uv = line.transform.GetChild(i).GetComponent<MeshFilter>().mesh.uv; allLineData[i].triangle = line.transform.GetChild(i).GetComponent<MeshFilter>().mesh.triangles; allLineData[i].color = line.transform.GetChild(i).GetComponent<MeshRenderer>().material.color; } StringBuilder sb = LineData2Jason(allLineData); stringB = sb; //Loom.RunAsync(()=> { WriteToText(sb,filepath); }); WriteToText(sb, filepath); //AssetDatabase.Refresh(); } void WriteToText(StringBuilder sb,string filepath) { FileInfo t = new FileInfo(filepath); if (!File.Exists(filepath)) { File.Delete(filepath); } StreamWriter sw = t.CreateText(); sw.WriteLine(sb.ToString()); sw.Close(); sw.Dispose(); } /// <summary> /// 所有line转换为json /// </summary> /// <param name="ld"></param> /// <returns></returns> StringBuilder LineData2Jason(LineData[] ld) { StringBuilder sb = new StringBuilder(); JsonWriter writer = new JsonWriter(sb); writer.WriteObjectStart(); writer.WritePropertyName("allLine"); writer.WriteArrayStart(); foreach (LineData data in ld) { writer.WriteObjectStart(); writer.WritePropertyName("name"); writer.Write(data.name); writer.WritePropertyName("position"); writer.WriteArrayStart(); writer.WriteObjectStart(); writer.WritePropertyName("x"); writer.Write(data.position.x.ToString("F5")); writer.WritePropertyName("y"); writer.Write(data.position.x.ToString("F5")); writer.WritePropertyName("z"); writer.Write(data.position.x.ToString("F5")); writer.WriteObjectEnd(); writer.WriteArrayEnd(); writer.WritePropertyName("rotation"); writer.WriteArrayStart(); writer.WriteObjectStart(); writer.WritePropertyName("x"); writer.Write(data.rotation.x.ToString("F5")); writer.WritePropertyName("y"); writer.Write(data.rotation.y.ToString("F5")); writer.WritePropertyName("z"); writer.Write(data.rotation.z.ToString("F5")); writer.WriteObjectEnd(); writer.WriteArrayEnd(); writer.WritePropertyName("vertex"); writer.WriteArrayStart(); for (int i = 0; i < data.vertex.Length; i++) { writer.WriteObjectStart(); writer.WritePropertyName("index"); writer.Write(i.ToString()); writer.WritePropertyName("x"); writer.Write(data.vertex[i].x.ToString("F5")); writer.WritePropertyName("y"); writer.Write(data.vertex[i].y.ToString("F5")); writer.WritePropertyName("z"); writer.Write(data.vertex[i].z.ToString("F5")); writer.WriteObjectEnd(); } writer.WriteArrayEnd(); writer.WritePropertyName("uv"); writer.WriteArrayStart(); for (int i = 0; i < data.uv.Length; i++) { writer.WriteObjectStart(); writer.WritePropertyName("index"); writer.Write(i.ToString()); writer.WritePropertyName("x"); writer.Write(data.uv[i].x.ToString("F5")); writer.WritePropertyName("y"); writer.Write(data.uv[i].y.ToString("F5")); writer.WriteObjectEnd(); } writer.WriteArrayEnd(); writer.WritePropertyName("triangle"); writer.WriteArrayStart(); for (int i = 0; i < data.triangle.Length; i++) { writer.WriteObjectStart(); writer.WritePropertyName("index"); writer.Write(i.ToString()); writer.WritePropertyName("value"); writer.Write(data.triangle[i].ToString()); writer.WriteObjectEnd(); } writer.WriteArrayEnd(); writer.WritePropertyName("color"); writer.WriteArrayStart(); writer.WriteObjectStart(); writer.WritePropertyName("r"); writer.Write(data.color.r.ToString("F5")); writer.WritePropertyName("g"); writer.Write(data.color.g.ToString("F5")); writer.WritePropertyName("b"); writer.Write(data.color.b.ToString("F5")); writer.WritePropertyName("a"); writer.Write(data.color.a.ToString("F5")); writer.WriteObjectEnd(); writer.WriteArrayEnd(); writer.WriteObjectEnd(); } writer.WriteArrayEnd(); writer.WriteObjectEnd(); return sb; } public void Read() { LineData[] ld; StreamReader sr = File.OpenText(filepath); string strLine = sr.ReadToEnd(); JsonData jd = JsonMapper.ToObject(strLine); JsonData lineArray = jd["allLine"]; ld = new LineData[lineArray.Count]; for (int i = 0; i < lineArray.Count; i++) { ld[i] = new LineData(); JsonData name, px, py, pz, rx, ry, rz, cr, cg, cb, ca; name = lineArray[i]["name"]; JsonData position = lineArray[i]["position"]; px = position[0]["x"]; py = position[0]["y"]; pz = position[0]["z"]; JsonData rotation = lineArray[i]["rotation"]; rx = rotation[0]["x"]; ry = rotation[0]["y"]; rz = rotation[0]["z"]; JsonData color = lineArray[i]["color"]; cr = color[0]["r"]; cg = color[0]["g"]; cb = color[0]["b"]; ca = color[0]["a"]; ld[i].name = (string)name; ld[i].position.x = float.Parse((string)px); ld[i].position.y = float.Parse((string)py); ld[i].position.z = float.Parse((string)pz); ld[i].rotation.x = float.Parse((string)rx); ld[i].rotation.y = float.Parse((string)ry); ld[i].rotation.z = float.Parse((string)rz); ld[i].color.r = float.Parse((string)cr); ld[i].color.g = float.Parse((string)cg); ld[i].color.b = float.Parse((string)cb); ld[i].color.a = float.Parse((string)ca); JsonData vertex = lineArray[i]["vertex"]; ld[i].vertex = new Vector3[vertex.Count]; ld[i].uv = new Vector2[vertex.Count]; for (int j = 0; j < vertex.Count; j++) { ld[i].vertex[j] = new Vector3(); JsonData vx, vy, vz; vx = vertex[j]["x"]; vy = vertex[j]["y"]; vz = vertex[j]["z"]; ld[i].uv[j] = new Vector2(); ld[i].vertex[j].x = float.Parse((string)vx); ld[i].vertex[j].y = float.Parse((string)vy); ld[i].vertex[j].z = float.Parse((string)vz); ld[i].uv[j] = ld[i].vertex[j]; } JsonData triangle = lineArray[i]["triangle"]; ld[i].triangle = new int[triangle.Count]; for (int j = 0; j < triangle.Count; j++) { ld[i].triangle[j] = int.Parse((string)triangle[j]["value"]); } } CreateMesh(ld); } void CreateMesh(LineData[] ld) { for (int i = 0; i < ld.Length; i++) { //drawMesh.GenerateMesh(ld[i]); } } }
原文地址:https://www.cnblogs.com/alps/p/11992997.html
时间: 2024-11-12 19:30:19