zoukankan      html  css  js  c++  java
  • 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]);
    }
    }
     
    }
  • 相关阅读:
    封装异常处理之坑
    30multipart/form-data和application/x-www-form-urlencoded的区别(二)urlencoded之自动deocde
    使用MAT时的Shallow Size和 Retained Size的区别
    当动态代理遇到ioc
    线程池的原理
    synchroned原理与对象头(yet)
    mysql压力测试与qps监控
    一种mysql jvm死锁
    Android Jni变量对照表
    结构体中使用函数指针
  • 原文地址:https://www.cnblogs.com/alps/p/11992997.html
Copyright © 2011-2022 走看看