Unity 绘制Mesh线条












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]);
}
}
 
}
posted @ 2019-12-06 01:27  alps_01  阅读(2958)  评论(0编辑  收藏  举报