/// <summary> /// 寻路数据转换为字符串 /// </summary> /// <param name="mesh"></param> /// <returns></returns> private string PathMeshToString(UnityEngine.AI.NavMeshTriangulation mesh) { if (mesh.indices.Length < 1) { return(""); } StringBuilder sb = new StringBuilder(); sb.Append("\"pathTriangles\":["); for (int i = 0; i < mesh.indices.Length; i++) { sb.Append(mesh.indices[i]).Append(","); } sb.Length--; sb.Append("],"); sb.Append("\"pathVertices\":["); for (int i = 0; i < mesh.vertices.Length; i++) { Vector3 v = mesh.vertices[i]; sb.Append("{\"x\":").Append(v.x).Append(",\"y\":").Append(v.y).Append(",\"z\":").Append(v.z).Append("},"); } sb.Length--; sb.Append("]"); return(sb.ToString()); }
static public int constructor(IntPtr l) { try { #if DEBUG var method = System.Reflection.MethodBase.GetCurrentMethod(); string methodName = GetMethodName(method); #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(methodName); #else Profiler.BeginSample(methodName); #endif #endif UnityEngine.AI.NavMeshTriangulation o; o = new UnityEngine.AI.NavMeshTriangulation(); pushValue(l, true); pushValue(l, o); return(2); } catch (Exception e) { return(error(l, e)); } #if DEBUG finally { #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else Profiler.EndSample(); #endif } #endif }
public static void Triangulate(out Vector3[] vertices, out int[] indices) { NavMeshTriangulation results = CalculateTriangulation(); vertices = results.vertices; indices = results.indices; }
static void Build() { GameObject g = new GameObject("navMesh"); MeshFilter mf = g.AddComponent <MeshFilter>(); #if UNITY_5_5_OR_NEWER UnityEngine.AI.NavMeshTriangulation triangles = UnityEngine.AI.NavMesh.CalculateTriangulation(); #else UnityEngine.NavMeshTriangulation triangles = UnityEngine.NavMesh.CalculateTriangulation(); #endif Mesh mesh = new Mesh(); mesh.vertices = triangles.vertices; mesh.triangles = triangles.indices; Vector2[] uvs = new Vector2[mesh.vertices.Length]; for (int i = 0; i < uvs.Length; i++) { uvs[i] = new Vector2(0f, 0f); } mesh.uv = uvs; mesh.RecalculateNormals(); mf.mesh = mesh; // MeshRenderer mr= g.AddComponent<MeshRenderer>(); }
public static void Triangulate(out Vector3[] vertices, out int[] indices) { NavMeshTriangulation navMeshTriangulation = NavMesh.CalculateTriangulation(); vertices = navMeshTriangulation.vertices; indices = navMeshTriangulation.indices; }
/// <summary> /// /// </summary> /// <param name="mesh"></param> /// <param name="type">0 阻挡 ;1行走;2安全</param> /// <returns></returns> static string MeshToString(UnityEngine.AI.NavMeshTriangulation mesh, int type) { if (mesh.indices.Length < 1) { return(""); } StringBuilder sb = new StringBuilder(); sb.Append(type == 0 ? "\"blockTriangles\":[" : (type == 1 ? "\"pathTriangles\":[" : "\"safeTriangles\":[")); for (int i = 0; i < mesh.indices.Length; i++) { sb.Append(mesh.indices[i]).Append(","); } sb.Length--; sb.Append("],"); sb.Append(type == 0 ? "\"blockVertices\":[" : (type == 1 ? "\"pathVertices\":[" : "\"safeVertices\":[")); for (int i = 0; i < mesh.vertices.Length; i++) { Vector3 v = mesh.vertices[i]; if (type > 0 && v.y < 1) { Debug.LogWarning("寻路mesh坐标小于1" + v.y); } sb.Append("{\"x\":").Append(v.x).Append(",\"y\":").Append(type == 0 ? 0 : v.y).Append(",\"z\":").Append(v.z) .Append("},"); } sb.Length--; sb.Append("]"); return(sb.ToString()); }
static string GenNavMeshOriginJson() { UnityEngine.AI.NavMeshTriangulation navtri = UnityEngine.AI.NavMesh.CalculateTriangulation(); string outnav = ""; outnav = "{\"v\":[\n"; for (int i = 0; i < navtri.vertices.Length; i++) { if (i > 0) { outnav += ",\n"; } outnav += "[" + navtri.vertices[i].x + "," + navtri.vertices[i].y + "," + navtri.vertices[i].z + "]"; } outnav += "\n],\"p\":[\n"; for (int i = 0; i < navtri.indices.Length; i++) { if (i > 0) { outnav += ",\n"; } int index = navtri.indices[i]; outnav += index.ToString(); var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.name = "s" + index; sphere.transform.position = navtri.vertices[index]; } outnav += "\n]}"; return(outnav); }
/// \brief Converts a NavMesh (or a NavMesh area) into a standard Unity mesh. This is later used /// to render the mesh on-screen using Unity's standard rendering tools. /// /// \param navMesh Precalculated Nav Mesh Triangulation /// \param vert_size size of vertex array /// \param tri_size size of triangle array private static Mesh ConvertNavmeshToMesh(UnityEngine.AI.NavMeshTriangulation navMesh, int vert_size, int tri_size) { Mesh ret = new Mesh(); if (vert_size >= 65535) { Debug.LogError("Playable NavMesh too big (vertex count >= 65535)! Limit the size of the playable area using" + "Area Masks. For now no preview mesh will render."); return(ret); } Vector3[] vertices = new Vector3[vert_size]; for (int x = 0; x < vertices.Length; x++) { // Note: Unity navmesh is offset 0.05m from the ground. This pushes it down to 0 vertices[x] = navMesh.vertices[x]; } int[] triangles = new int[tri_size * 3]; for (int x = 0; x < triangles.Length; x++) { triangles[x] = navMesh.indices[x]; } ret.name = "Navmesh"; ret.vertices = vertices; ret.triangles = triangles; RemoveMeshDuplicates(ret); ret.RecalculateNormals(); ret.RecalculateBounds(); return(ret); }
static void Export() { Debug.Log("NavMesh Export Start"); UnityEngine.AI.NavMeshTriangulation navMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); //文件路径 路径文件夹不存在会报错 string path = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".obj"; //新建文件 StreamWriter streamWriter = new StreamWriter(path); //顶点 for (int i = 0; i < navMeshTriangulation.vertices.Length; i++) { streamWriter.WriteLine("v " + navMeshTriangulation.vertices[i].x + " " + navMeshTriangulation.vertices[i].y + " " + navMeshTriangulation.vertices[i].z); } streamWriter.WriteLine("g pPlane1"); //索引 for (int i = 0; i < navMeshTriangulation.indices.Length;) { streamWriter.WriteLine("f " + (navMeshTriangulation.indices[i] + 1) + " " + (navMeshTriangulation.indices[i + 1] + 1) + " " + (navMeshTriangulation.indices[i + 2] + 1)); i = i + 3; } streamWriter.Flush(); streamWriter.Close(); AssetDatabase.Refresh(); Debug.Log("NavMesh Export Success"); }
/// <summary> /// 获取导航随机点 /// </summary> /// <returns></returns> public Vector3 GetRandomLocation() { UnityEngine.AI.NavMeshTriangulation navMeshData = UnityEngine.AI.NavMesh.CalculateTriangulation(); int t = Random.Range(0, navMeshData.indices.Length - 3); Vector3 point = Vector3.Lerp(navMeshData.vertices[navMeshData.indices[t]], navMeshData.vertices[navMeshData.indices[t + 1]], Random.value); point = Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t + 2]], Random.value); return(point); }
/// <summary> /// Triangulate and return a mesh based on every NavMesh currently loaded. /// Unity's triangulation system is very broken, so triangulation works correctly only for flat NavMeshes (no slopes). /// </summary> public Mesh GetMesh() { NavMeshTriangulation navTriangulation = NavMesh.CalculateTriangulation(); Mesh output = new Mesh(); output.name = "NavMeshTriangulated"; output.vertices = navTriangulation.vertices; output.triangles = navTriangulation.indices; return(output); }
/// <summary> /// 计算行走层三角网格 /// </summary> /// <returns></returns> private UnityEngine.AI.NavMeshTriangulation Path() { ClearTemp(); pathMesh.GetComponent <Renderer>().enabled = true; UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes(); UnityEditor.AI.NavMeshBuilder.BuildNavMesh(); UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); return(triangulatedNavMesh); }
static public int constructor(IntPtr l) { try { UnityEngine.AI.NavMeshTriangulation o; o = new UnityEngine.AI.NavMeshTriangulation(); pushValue(l, true); pushValue(l, o); return(2); } catch (Exception e) { return(error(l, e)); } }
static void Export() { UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); Mesh mesh = new Mesh(); mesh.name = "ExportedNavMesh"; mesh.vertices = triangulatedNavMesh.vertices; int[] areas = triangulatedNavMesh.areas; mesh.triangles = triangulatedNavMesh.indices; string filename = Application.dataPath + "/" + Path.GetFileNameWithoutExtension(EditorApplication.currentScene) + ".obj"; MeshToFile(mesh, areas, filename); print("NavMesh exported as '" + filename + "'"); AssetDatabase.Refresh(); }
static void Export() { Debug.Log("ExportNavMesh"); UnityEngine.AI.NavMeshTriangulation tmpNavMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); list = new List <Cell>(); //索引 for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;) { var cell = new Cell(); cell.v[0] = tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i]]; cell.v[1] = tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 1]]; cell.v[2] = tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 2]]; cell.v[0].y = 0; cell.v[1].y = 0; cell.v[2].y = 0; cell.MidPos = (cell.v[0] + cell.v[1] + cell.v[2]) / 3; cell.MaxX = GetMaxX(cell.v[0], cell.v[1], cell.v[2]); cell.MaxY = GetMaxZ(cell.v[0], cell.v[1], cell.v[2]); cell.MinX = GetMinX(cell.v[0], cell.v[1], cell.v[2]); cell.MinY = GetMinZ(cell.v[0], cell.v[1], cell.v[2]); //cell.AreaSize = GetAreaSize(cell.v[0], cell.v[1], cell.v[2]); cell.index = list.Count; list.Add(cell); i = i + 3; } for (int i = 0; i < list.Count; i++) { var a = list[i]; for (int j = 0; j < list.Count; j++) { var b = list[j]; if (a != b) { List <int> l = new List <int>(); if (IsNearCell(a, b, l)) { InsertNears(a, b, j, l); } } } } Debug.Log("ExportNavMesh Success"); }
static void Export() { UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); Debug.Log(triangulatedNavMesh.vertices.ToString()); Debug.Log(triangulatedNavMesh.indices.ToString()); Mesh mesh = new Mesh(); mesh.name = "ExportedNavMesh"; mesh.vertices = triangulatedNavMesh.vertices; mesh.triangles = triangulatedNavMesh.indices; string filename = Application.dataPath + "/../../Server/data/" + Path.GetFileNameWithoutExtension(SceneManager.GetActiveScene().name) + ".NavMesh.obj"; MeshToFile(mesh, filename); print("NavMesh exported as '" + filename + "'"); AssetDatabase.Refresh(); }
private static void Export() { UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); Mesh mesh = new Mesh(); mesh.name = "_NavMesh"; mesh.vertices = triangulatedNavMesh.vertices; mesh.triangles = triangulatedNavMesh.indices; string baseName = "navmesh_" + SceneManager.GetActiveScene().name; string fileName = Application.dataPath + "/navmesh/" + baseName + ".obj"; ExportNavmesh(mesh, fileName); string assetName = fileName.Replace(Application.dataPath, "Assets"); GameObject navMesh = Instantiate(AssetDatabase.LoadAssetAtPath <GameObject>(assetName)); navMesh.name = baseName; ExportNavData(navMesh); Debug.Log("导出完成:" + baseName); AssetDatabase.Refresh(); }
/// <summary> /// 创建网格数据 /// </summary> private void CreatePolyNavMesh() { UnityEngine.AI.NavMeshTriangulation triangulatedWalkNavMesh = Path(); string path = System.Environment.CurrentDirectory.Replace("\\", "/") + "/../Config/Nav_build/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } StringBuilder sb = new StringBuilder("{"); sb.Append("\"mapID\":").Append(mapID); sb.Append(",\"startX\":").Append(startX).Append(",\"startZ\":").Append(startZ); sb.Append(",\"endX\":").Append(endX).Append(",\"endZ\":").Append(endZ); string filename = path + mapID + ".navmesh"; string data = ""; data = PathMeshToString(triangulatedWalkNavMesh); sb.Append(",").Append(data); sb.Append("}"); MeshToFile(filename, sb.ToString()); }
public static void ExportNavMesh() { Debug.Log("Export NavMesh"); //Unity2017 API UnityEngine.AI.NavMeshTriangulation navMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); string sceneName = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; //新建文件 string savePath = Application.dataPath + "/" + sceneName + "_NavMesh.obj"; StreamWriter sw = new StreamWriter(savePath); //顶点 for (int i = 0; i < navMeshTriangulation.vertices.Length; i++) { sw.WriteLine("v " + navMeshTriangulation.vertices[i].x + " " + navMeshTriangulation.vertices[i].y + " " + navMeshTriangulation.vertices[i].z); } sw.WriteLine("g navmesh");//组名称 //索引 for (int i = 0; i < navMeshTriangulation.indices.Length;) { //obj文件中顶点索引是从1开始 sw.WriteLine("f " + (navMeshTriangulation.indices[i] + 1) + " " + (navMeshTriangulation.indices[i + 1] + 1) + " " + (navMeshTriangulation.indices[i + 2] + 1)); i = i + 3; } sw.Flush(); sw.Close(); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); Debug.Log(string.Format("Verts:{0} Tris:{1}", navMeshTriangulation.vertices.Length, navMeshTriangulation.indices.Length / 3)); Debug.Log(savePath); Debug.Log("ExportNavMesh Success"); }
void Awake() { draw = false; UnityEngine.AI.NavMeshTriangulation nav = UnityEngine.AI.NavMesh.CalculateTriangulation(); navMesh = new Mesh(); navMesh.vertices = nav.vertices; navMesh.triangles = nav.indices; GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f); wpMesh = sphere.GetComponent <MeshFilter>().mesh; Shader s = Shader.Find("Unlit/Color"); Material lineMaterial = new Material(s); lineMaterial.hideFlags = HideFlags.HideAndDontSave; lineMaterial.color = Color.blue; pathMaterial = new Material(s); pathMaterial.hideFlags = HideFlags.HideAndDontSave; pathMaterial.color = Color.red; lineRenderers = new List <GameObject> (navMesh.triangles.Length / 3); /*for (int i = 0; i < navMesh.triangles.Length; i += 3) { * GameObject obj = new GameObject ("renderer"); * LineRenderer renderer = obj.AddComponent<LineRenderer>(); * renderer.useWorldSpace = true; * renderer.SetWidth (0.01f, 0.01f); * renderer.material = lineMaterial; * renderer.SetVertexCount (3); * for (int j = 0; j < 3; j++) * renderer.SetPosition (j, navMesh.vertices [navMesh.triangles [i + j]] + 0.15f * Vector3.up); * lineRenderers.Add (obj); * }*/ }
public override void OnInspectorGUI() { GUIStyle bold_wrap = EditorStyles.boldLabel; bold_wrap.wordWrap = true; GUILayout.Label("Navmesh Preprocessor for HTC Vive Locomotion", bold_wrap); GUILayout.Label("Adrian Biagioli 2016", EditorStyles.miniLabel); GUILayout.Label("Before Using", bold_wrap); GUIStyle wrap = EditorStyles.label; wrap.wordWrap = true; GUILayout.Label( "Make sure you bake a Navigation Mesh (NavMesh) in Unity before continuing (Window > Navigation). When you " + "are done, click \"Update Navmesh Data\" below. This will update the graphic of the playable area " + "that the player will see in-game.\n", wrap); ViveNavMesh mesh = (ViveNavMesh)target; serializedObject.Update(); // Area Mask // string[] areas = GameObjectUtility.GetNavMeshAreaNames(); int[] area_index = new int[areas.Length]; int temp_mask = 0; for (int x = 0; x < areas.Length; x++) { area_index[x] = GameObjectUtility.GetNavMeshAreaFromName(areas[x]); temp_mask |= ((p_area.intValue >> area_index[x]) & 1) << x; } EditorGUI.BeginChangeCheck(); temp_mask = EditorGUILayout.MaskField("Area Mask", temp_mask, areas); if (EditorGUI.EndChangeCheck()) { p_area.intValue = 0; for (int x = 0; x < areas.Length; x++) { p_area.intValue |= (((temp_mask >> x) & 1) == 1 ? 0 : 1) << area_index[x]; } p_area.intValue = ~p_area.intValue; } serializedObject.ApplyModifiedProperties(); // Sanity check for Null properties // bool HasMesh = (mesh.SelectableMesh != null && mesh.SelectableMesh.vertexCount != 0) || (mesh.SelectableMeshBorder != null && mesh.SelectableMeshBorder.Length != 0); // Fixes below error message popping up with prefabs. Kind of hacky but gets the job done bool isPrefab = EditorUtility.IsPersistent(target); if (isPrefab && mesh.SelectableMesh == null) { mesh.SelectableMesh = new Mesh(); } bool MeshNull = mesh.SelectableMesh == null; bool BorderNull = mesh.SelectableMeshBorder == null; if (MeshNull || BorderNull) { string str = "Internal Error: "; if (MeshNull) { str += "Selectable Mesh == null. "; } if (BorderNull) { str += "Border point array == null. "; } str += "This may lead to strange behavior or serialization. Try updating the mesh or delete and recreate the Navmesh object. "; str += "If you are able to consistently get a Vive Nav Mesh object into this state, please submit a bug report."; EditorGUILayout.HelpBox(str, MessageType.Error); } // Update / Clear Navmesh Data // if (GUILayout.Button("Update Navmesh Data")) { Undo.RecordObject(mesh, "Update Navmesh Data"); UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation(); int vert_size, tri_size; CullNavmeshTriangulation(ref tri, p_area.intValue, out vert_size, out tri_size); Mesh m = ConvertNavmeshToMesh(tri, vert_size, tri_size); // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object mesh.SelectableMeshBorder = FindBorderEdges(m); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure that setter is called } GUI.enabled = HasMesh; if (GUILayout.Button("Clear Navmesh Data")) { Undo.RecordObject(mesh, "Clear Navmesh Data"); // Note: Unity does not serialize "null" correctly so we set everything to empty objects Mesh m = new Mesh(); serializedObject.Update(); p_mesh.objectReferenceValue = m; serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.SelectableMesh = mesh.SelectableMesh; // Make sure setter is called mesh.SelectableMeshBorder = new BorderPointSet[0]; } GUI.enabled = true; GUILayout.Label(HasMesh ? "Status: NavMesh Loaded" : "Status: No NavMesh Loaded"); // Render Settings // EditorGUILayout.LabelField("Render Settings", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(p_material); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(mesh, "Change Ground Material"); serializedObject.ApplyModifiedPropertiesWithoutUndo(); mesh.GroundMaterial = mesh.GroundMaterial; // Reload material } EditorGUILayout.PropertyField(p_alpha); serializedObject.ApplyModifiedProperties(); }
/// \brief Modifies the given NavMesh so that only the Navigation areas are present in the mesh. This is done only /// by swapping, so that no new memory is allocated. /// /// The data stored outside of the returned array sizes should be considered invalid and will contain garbage data. /// \param navMesh NavMesh data to modify /// \param area Area mask to include in returned mesh. Areas outside of this mask are culled. /// \param vert_size New size of navMesh.vertices /// \param tri_size New size of navMesh.areas and one third of the size of navMesh.indices private static void CullNavmeshTriangulation(ref UnityEngine.AI.NavMeshTriangulation navMesh, int area, out int vert_size, out int tri_size) { // Step 1: re-order triangles so that valid areas are in front. Then determine tri_size. tri_size = navMesh.indices.Length / 3; for (int i = 0; i < tri_size; i++) { Vector3 p1 = navMesh.vertices[navMesh.indices[i * 3]]; Vector3 p2 = navMesh.vertices[navMesh.indices[i * 3 + 1]]; Vector3 p3 = navMesh.vertices[navMesh.indices[i * 3 + 2]]; Plane p = new Plane(p1, p2, p3); bool vertical = Mathf.Abs(Vector3.Dot(p.normal, Vector3.up)) > 0.99f; // If the current triangle isn't flat (normal is up) or if it doesn't match // with the provided mask, we should cull it. if (((1 << navMesh.areas[i]) & area) == 0 || !vertical) // If true this triangle should be culled. { // Swap area indices and triangle indices with the end of the array int t_ind = tri_size - 1; int t_area = navMesh.areas[t_ind]; navMesh.areas[t_ind] = navMesh.areas[i]; navMesh.areas[i] = t_area; for (int j = 0; j < 3; j++) { int t_v = navMesh.indices[t_ind * 3 + j]; navMesh.indices[t_ind * 3 + j] = navMesh.indices[i * 3 + j]; navMesh.indices[i * 3 + j] = t_v; } // Then reduce the size of the array, effectively cutting off the previous triangle tri_size--; // Stay on the same index so that we can check the triangle we just swapped. i--; } } // Step 2: Cull the vertices that aren't used. vert_size = 0; for (int i = 0; i < tri_size * 3; i++) { int prv = navMesh.indices[i]; if (prv >= vert_size) { int nxt = vert_size; // Bring the current vertex to the end of the "active" array by swapping it with what's currently there Vector3 t_v = navMesh.vertices[prv]; navMesh.vertices[prv] = navMesh.vertices[nxt]; navMesh.vertices[nxt] = t_v; // Now change around the values in the triangle indices to reflect the swap for (int j = i; j < tri_size * 3; j++) { if (navMesh.indices[j] == prv) { navMesh.indices[j] = nxt; } else if (navMesh.indices[j] == nxt) { navMesh.indices[j] = prv; } } // Increase the size of the vertex array to reflect the changes. vert_size++; } } }
//TODO: 导出area字段 static string GenNavMesh(string style) { float progress = 0; float detailPro = 0; EditorUtility.DisplayProgressBar(ProgressBarName, "获取NavMesh三角形数据", progress); // return GenNavMeshOriginJson(); UnityEngine.AI.NavMeshTriangulation navtri = UnityEngine.AI.NavMesh.CalculateTriangulation(); //{ // var obj = GameObject.CreatePrimitive(PrimitiveType.Cube); // var mf = obj.GetComponent<MeshFilter>(); // Mesh m = new Mesh(); // m.vertices = navtri.vertices; // m.triangles = navtri.indices; // mf.mesh = m; //} Dictionary <int, int> indexmap = new Dictionary <int, int>(); List <Vector3> repos = new List <Vector3>(); progress += 0.1f; float mergeSameVertexSumPro = 0.1f; for (int i = 0; i < navtri.vertices.Length; i++) { detailPro = (progress + mergeSameVertexSumPro * (i + 1) / navtri.vertices.Length); EditorUtility.DisplayProgressBar(ProgressBarName, "合并相同顶点(" + (i + 1) + "/" + navtri.vertices.Length + ")", detailPro); int ito = -1; for (int j = 0; j < repos.Count; j++) { if (Vector3.Distance(navtri.vertices[i], repos[j]) < 0.01) { ito = j; break; } } if (ito < 0) { indexmap[i] = repos.Count; repos.Add(navtri.vertices[i]); } else { indexmap[i] = ito; } } progress = detailPro; detailPro = 0.0f; // for(int i=0; i<navtri.areas.Length; i++) // Debug.Log("area : "+navtri.areas[i].ToString()); //关系是 index 公用的三角形表示他们共同组成多边形 //多边形之间的连接用顶点位置识别 List <int> polylast = new List <int>(); // List<int[]> polys = new List<int[]>(); List <List <int> > polys = new List <List <int> >(); MaxVertexPerPoly = 6; float makePolySumPro = 0.1f; for (int i = 0; i < navtri.indices.Length / 3; i++) { detailPro = progress + makePolySumPro * i / navtri.indices.Length / 3; EditorUtility.DisplayProgressBar(ProgressBarName, "合并邻近三角形(" + i + "/" + (navtri.indices.Length / 3) + ")", detailPro); int i0 = navtri.indices[i * 3 + 0]; int i1 = navtri.indices[i * 3 + 1]; int i2 = navtri.indices[i * 3 + 2]; // i0 = indexmap[i0]; // i1 = indexmap[i1]; // i2 = indexmap[i2]; if (polylast.Contains(i0) || polylast.Contains(i1) || polylast.Contains(i2)) { if (polylast.Contains(i0) == false) { polylast.Add(i0); } if (polylast.Contains(i1) == false) { polylast.Add(i1); } if (polylast.Contains(i2) == false) { polylast.Add(i2); } } else { if (polylast.Count > 0) { AddPolyByVertex(polylast, ref polys, style == "json"); } polylast.Clear(); polylast.Add(i0); polylast.Add(i1); polylast.Add(i2); } } if (polylast.Count > 0) { AddPolyByVertex(polylast, ref polys, style == "json"); } progress = detailPro; detailPro = 0.0f; string outnav = ""; if (style == "json") { for (int i = 0; i < polys.Count; i++) { for (int j = 0; j < polys[i].Count; j++) { if (polys[i][j] != NullIndex) { polys[i][j] = indexmap[polys[i][j]]; } } for (int ii = polys[i].Count; ii < MaxVertexPerPoly; ii++) { polys[i].Add(NullIndex); } } List <List <int> > neighbor = new List <List <int> >(); GenNeighbor(polys, ref neighbor, progress); progress += 0.1f; MergePolyAndNeighbor(ref polys, neighbor); float[] boundsMin = new float[3]; float[] boundsMax = new float[3]; EditorUtility.DisplayProgressBar(ProgressBarName, "反转所有顶点X轴", progress += 0.1f); RevertX(ref repos); EditorUtility.DisplayProgressBar(ProgressBarName, "计算包围盒", progress += 0.1f); GetBounds(repos, ref boundsMin, ref boundsMax); // Debug.Log("max bounds :" + boundsMax[1].ToString()+" boundsMin:"+boundsMin[1].ToString()); for (int i = 0; i < repos.Count; i++) { ushort x = (ushort)Math.Round((repos[i].x - boundsMin[0]) / xzCellSize); ushort y = (ushort)Math.Round((repos[i].y - boundsMin[1]) / yCellSize); ushort z = (ushort)Math.Round((repos[i].z - boundsMin[2]) / xzCellSize); repos[i] = new Vector3(x, y, z); } outnav = "{"; outnav += "\"nvp\":" + MaxVertexPerPoly + ",\n"; outnav += "\"cs\":" + xzCellSize + ",\n"; outnav += "\"ch\":" + yCellSize + ",\n"; NavMeshBuildSettings settings = NavMesh.GetSettingsByIndex(0); outnav += "\"agentHeight\":" + settings.agentHeight + ",\n"; outnav += "\"agentRadius\":" + settings.agentRadius + ",\n"; outnav += "\"agentMaxClimb\":" + settings.agentClimb + ",\n"; outnav += "\"bmin\":[" + boundsMin[0] + ", " + boundsMin[1] + ", " + boundsMin[2] + "],\n"; outnav += "\"bmax\":[" + boundsMax[0] + ", " + boundsMax[1] + ", " + boundsMax[2] + "],\n"; outnav += "\"v\":[\n"; // List<List<uint>> vertexes = new List<List<uint>>(); detailPro = 0.0f; for (int i = 0; i < repos.Count; i++) { detailPro = progress + 0.1f * (i + 1) / repos.Count; EditorUtility.DisplayProgressBar(ProgressBarName, "生成json顶点数据(" + (i + 1) + "/" + repos.Count + ")", detailPro); // List<uint> vertex = new List<uint>(); // vertex.Add((uint)repos[i].x); // vertex.Add((uint)repos[i].y); // vertex.Add((uint)repos[i].z); // vertexes.Add(vertex); if (i > 0) { outnav += ",\n"; } outnav += "[" + (repos[i].x) + "," + repos[i].y + "," + repos[i].z + "]"; } outnav += "\n],\n\"p\":[\n"; progress = detailPro; detailPro = 0.0f; for (int i = 0; i < polys.Count; i++) { detailPro = progress + 0.1f * (i + 1) / polys.Count; EditorUtility.DisplayProgressBar(ProgressBarName, "生成json多边形数据(" + (i + 1) + "/" + polys.Count + ")", detailPro); // string outs = indexmap[polys[i][0]].ToString(); string outs = polys[i][0].ToString(); for (int j = 1; j < MaxVertexPerPoly; j++) { var verIndex = polys[i][j]; // if (verIndex!=NullIndex) // verIndex = indexmap[verIndex]; outs += "," + verIndex; } for (int j = MaxVertexPerPoly; j < MaxVertexPerPoly * 2; j++) { outs += "," + polys[i][j]; } if (i > 0) { outnav += ",\n"; } outnav += "[" + outs + "]"; } outnav += "\n]}"; // Debug.Log("outnav : "+outnav); } else if (style == "obj") { detailPro = 0.0f; outnav = ""; for (int i = 0; i < repos.Count; i++) {//unity 对obj 做了 x轴 -1 detailPro = progress + 0.4f * (i + 1) / polys.Count; EditorUtility.DisplayProgressBar(ProgressBarName, "生成json顶点数据(" + (i + 1) + "/" + repos.Count + ")", detailPro); outnav += "v " + (repos[i].x * -1) + " " + repos[i].y + " " + repos[i].z + "\r\n"; // outnav += "v " + (repos[i].x) + " " + repos[i].y + " " + repos[i].z + "\r\n"; } outnav += "\r\n"; progress = detailPro; detailPro = 0.0f; for (int i = 0; i < polys.Count; i++) { detailPro = progress + 0.5f * (i + 1) / polys.Count; EditorUtility.DisplayProgressBar(ProgressBarName, "生成json多边形数据(" + (i + 1) + "/" + polys.Count + ")", detailPro); outnav += "f"; //逆向 for (int j = polys[i].Count - 1; j >= 0; j--) // for (int j = 0; j < polys[i].Count; j++) { outnav += " " + (indexmap[polys[i][j]] + 1); } outnav += "\r\n"; } } return(outnav); }
/// <summary> /// 创建navmesh数据 /// </summary> void CreateNavMeshData() { lock (this) { map.SetActive(false); xingzouceng.GetComponent <Renderer>().enabled = false; UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); GameObject WalkAble = createOb("NavMesh_WalkAble", 1); Vector3[] pathVertices = triangulatedNavMesh.vertices; int[] triangles = triangulatedNavMesh.indices; Mesh WalkMesh = WalkAble.GetComponent <MeshFilter>().sharedMesh; Vector3[] vertexes = new Vector3[pathVertices.Length]; for (int i = 0; i < pathVertices.Length; i++) { float x = pathVertices[i].x; float z = pathVertices[i].z; vertexes[i] = new Vector3(x, 0, z); } WalkMesh.vertices = vertexes; WalkMesh.triangles = triangles; GameObject UnWalkAble = createOb("NavMesh_UnWalkAble", 0); Mesh UnWalkMesh = UnWalkAble.GetComponent <MeshFilter>().sharedMesh; UnWalkMesh.vertices = new Vector3[] { new Vector3(property.startX, 0, property.startZ), new Vector3(property.startX, 0, property.endZ), new Vector3(property.endX, 0, property.endZ), new Vector3(property.endX, 0, property.startZ) }; UnWalkMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 }; SetAgentRadius(0.3f); UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes(); UnityEditor.AI.NavMeshBuilder.BuildNavMesh(); Object.DestroyImmediate(WalkAble); Object.DestroyImmediate(UnWalkAble); string path = System.Environment.CurrentDirectory.Replace("\\", "/") + "/Nav_build/"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } StringBuilder sb = new StringBuilder("{"); sb.Append("\"mapID\":").Append(mapID); sb.Append(",\"startX\":").Append(property.startX).Append(",\"startZ\":").Append(property.startZ); sb.Append(",\"endX\":").Append(property.endX).Append(",\"endZ\":").Append(property.endZ); string filename = path + mapID + ".navmesh"; triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); string data = MeshToString(triangulatedNavMesh, 0); if (data.Length < 128) { alert("阻挡未打入!"); return; } sb.Append(",").Append(data); if (data.Length > 0) { sb.Append(",").Append(data); } BuildFloorNavMesh(property.agentRadius); triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); data = MeshToString(triangulatedNavMesh, 1); if (data.Length < 128) { alert("寻路未打入!"); return; } sb.Append(",").Append(data).Append("}"); MeshToFile(filename, sb.ToString()); BuildAllNavMesh(property.agentRadius); map.SetActive(true); alert("成功!"); EditorSceneManager.SaveOpenScenes(); } //Close(); }
/// <summary> /// /// </summary> /// <param name="style">0 json 1 obj</param> /// <returns></returns> string GenNavMesh(int style) { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; UnityEngine.AI.NavMeshTriangulation navtri = UnityEngine.AI.NavMesh.CalculateTriangulation(); //{ // var obj = GameObject.CreatePrimitive(PrimitiveType.Cube); // var mf = obj.GetComponent<MeshFilter>(); // Mesh m = new Mesh(); // m.vertices = navtri.vertices; // m.triangles = navtri.indices; // mf.mesh = m; //} Dictionary <int, int> indexmap = new Dictionary <int, int>(); List <Vector3> repos = new List <Vector3>(); for (int i = 0; i < navtri.vertices.Length; i++) { int ito = -1; for (int j = 0; j < repos.Count; j++) { if (Vector3.Distance(navtri.vertices[i], repos[j]) < 0.01) { ito = j; break; } } if (ito < 0) { indexmap[i] = repos.Count; repos.Add(navtri.vertices[i]); } else { indexmap[i] = ito; } } //关系是 index 公用的三角形表示他们共同组成多边形 //多边形之间的连接用顶点位置识别 List <int> polylast = new List <int>(); List <int[]> polys = new List <int[]>(); List <int> areas = new List <int>(); int lastArea = int.MaxValue; for (int i = 0; i < navtri.indices.Length / 3; i++) { int i0 = navtri.indices[i * 3 + 0]; int i1 = navtri.indices[i * 3 + 1]; int i2 = navtri.indices[i * 3 + 2]; if ((polylast.Contains(i0) || polylast.Contains(i1) || polylast.Contains(i2)) && lastArea == navtri.areas[i]) { if (polylast.Contains(i0) == false) { polylast.Add(i0); } if (polylast.Contains(i1) == false) { polylast.Add(i1); } if (polylast.Contains(i2) == false) { polylast.Add(i2); } } else { if (polylast.Count > 0) { polys.Add(polylast.ToArray()); areas.Add(lastArea); } polylast.Clear(); polylast.Add(i0); polylast.Add(i1); polylast.Add(i2); lastArea = navtri.areas[i]; } } if (polylast.Count > 0) { polys.Add(polylast.ToArray()); } System.Text.StringBuilder outnav = new System.Text.StringBuilder(); if (style == 0) { outnav.Append("{\"v\":[\n"); for (int i = 0; i < repos.Count; i++) { if (i > 0) { outnav.Append(",\n"); } outnav.Append("[").Append(repos[i].x).Append(",").Append(repos[i].y).Append(",").Append(repos[i].z).Append("]"); } outnav.Append("\n],\"p\":[\n"); for (int i = 0; i < polys.Count; i++) { string outs = indexmap[polys[i][0]].ToString(); for (int j = 1; j < polys[i].Length; j++) { outs += "," + indexmap[polys[i][j]]; } if (i > 0) { outnav.Append(",\n"); } outnav.Append("[").Append(outs).Append("]"); } outnav.Append("\n]}"); } else if (style == 1) { for (int i = 0; i < repos.Count; i++) {//unity 对obj 做了 x轴 -1 outnav.Append("v ").Append(repos[i].x * -1).Append(" ").Append(repos[i].y).Append(" ").Append(repos[i].z).Append("\r\n"); } outnav.Append("\r\n"); for (int i = 0; i < polys.Count; i++) { outnav.Append("f"); //逆向 for (int j = polys[i].Length - 1; j >= 0; j--) { outnav.Append(" ").Append(indexmap[polys[i][j]] + 1); } outnav.Append("\r\n"); } } else if (style == 2) { outnav.Append("v\n"); for (int i = 0; i < repos.Count; i++) { outnav.Append(repos[i].x).Append(" ").Append(repos[i].y).Append(" ").Append(repos[i].z).Append("\n"); } int maxVertPerPoly = 0; outnav.Append("p\n"); for (int i = 0; i < polys.Count; i++) { outnav.Append(indexmap[polys[i][0]]); for (int j = 1; j < polys[i].Length; j++) { outnav.Append(" ").Append(indexmap[polys[i][j]]); } outnav.Append("\n"); maxVertPerPoly = System.Math.Max(maxVertPerPoly, polys[i].Length); } //outnav.Append("a\n"); //for (int i = 0; i < areas.Count; ++i) //{ // outnav.Append(areas[i]).Append("\n"); //} outnav.Append("nvp\n").Append(maxVertPerPoly).Append("\n"); } return(outnav.ToString()); }
static void Export() { Debug.Log("ExportNavMesh"); UnityEngine.AI.NavMeshTriangulation tmpNavMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); GtMsg.NavData navData = new GtMsg.NavData(); list = new List <Cell>(); posList = new List <PosData>(); //初始化每个cell的点 for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;) { var cell = new Cell(); var v0 = tmpNavMeshTriangulation.indices[i]; var v1 = tmpNavMeshTriangulation.indices[i + 1]; var v2 = tmpNavMeshTriangulation.indices[i + 2]; cell.v[0] = CommonFunc.Round(tmpNavMeshTriangulation.vertices[v0]); cell.v[1] = CommonFunc.Round(tmpNavMeshTriangulation.vertices[v1]); cell.v[2] = CommonFunc.Round(tmpNavMeshTriangulation.vertices[v2]); cell.v[0].y = 0; cell.v[1].y = 0; cell.v[2].y = 0; //cell.vNormal[0] = new Vector3[2]; //cell.vNormal[0][0] = Vector3.Normalize(cell.v[0] - cell.v[1]); //cell.vNormal[0][1] = Vector3.Normalize(cell.v[0] - cell.v[2]); //cell.vNormal[1][0] = Vector3.Normalize(cell.v[1] - cell.v[0]); //cell.vNormal[1][1] = Vector3.Normalize(cell.v[1] - cell.v[2]); //cell.vNormal[2][0] = Vector3.Normalize(cell.v[2] - cell.v[1]); //cell.vNormal[2][1] = Vector3.Normalize(cell.v[2] - cell.v[0]); //cell.MaxX = GetMaxX(cell.v[0], cell.v[1], cell.v[2]); //cell.MaxY = GetMaxZ(cell.v[0], cell.v[1], cell.v[2]); //cell.MinX = GetMinX(cell.v[0], cell.v[1], cell.v[2]); //cell.MinY = GetMinZ(cell.v[0], cell.v[1], cell.v[2]); //cell.AreaSize = GetAreaSize(cell.v[0], cell.v[1], cell.v[2]); //cell.index = list.Count; list.Add(cell); i = i + 3; } //处理不合格的cell int Count = 0; for (int i = 0; i < list.Count; i++) { var a = list[i]; if (a.tobeRemove) { continue; } for (int j = 0; j < list.Count; j++) { var b = list[j]; if (b.tobeRemove) { continue; } if (a != b) { var a0 = a.v[0]; var a1 = a.v[1]; var a2 = a.v[2]; var b0 = b.v[0]; var b1 = b.v[1]; var b2 = b.v[2]; int index = -1; int vx1 = -1; int vx2 = -1; if (CommonFunc.PointInVector2(a0, a1, b0)) { index = 0; vx1 = 0; vx2 = 1; } else if (CommonFunc.PointInVector2(a1, a2, b0)) { index = 0; vx1 = 1; vx2 = 2; } else if (CommonFunc.PointInVector2(a2, a0, b0)) { index = 0; vx1 = 2; vx2 = 0; } else if (CommonFunc.PointInVector2(a0, a1, b1)) { index = 1; vx1 = 0; vx2 = 1; } else if (CommonFunc.PointInVector2(a1, a2, b1)) { index = 1; vx1 = 1; vx2 = 2; } else if (CommonFunc.PointInVector2(a2, a0, b1)) { index = 1; vx1 = 2; vx2 = 0; } else if (CommonFunc.PointInVector2(a0, a1, b2)) { index = 2; vx1 = 0; vx2 = 1; } else if (CommonFunc.PointInVector2(a1, a2, b2)) { index = 2; vx1 = 1; vx2 = 2; } else if (CommonFunc.PointInVector2(a2, a0, b2)) { index = 2; vx1 = 2; vx2 = 0; } if (index != -1) { testList = GetCellByPoint(b.v[index]); var length1 = Vector3.SqrMagnitude(b.v[index] - a.v[vx1]); var length2 = Vector3.SqrMagnitude(b.v[index] - a.v[vx2]); Vector3 pp; if (length1 > length2) { pp = a.v[vx2]; } else { pp = a.v[vx1]; } foreach (var tt in testList) { bool bb = IsCellPoint(tt, pp); // if (bb) { //删除小三角形 //list.Remove(tt); tt.tobeRemove = true; Count++; } else { //扩张大三角形 for (int k = 0; k < 3; k++) { if (tt.v[k].Equals(b.v[index])) { tt.v[k] = pp; break; } } } } } } } } //设置cell的属性 Debug.Log(Count); List <Cell> listtemp = new List <Cell>(); for (int k = 0; k < list.Count; k++) { var cell = list[k]; if (!cell.tobeRemove) { for (int i = 0; i < 3; i++) { int posIndex = -1; for (int j = 0; j < posList.Count; j++) { var v = posList[j]; if (v.Pos.Equals(cell.v[i])) { posIndex = j; break; } } if (posIndex == -1) { posList.Add(new PosData { Pos = cell.v[i] }); navData.PosList.Add(new GtMsg.PosData { Pos = CommonFunc.GetVec3(cell.v[i]) }); posIndex = posList.Count - 1; } cell.vIndex[i] = posIndex; posList[posIndex].CellIndexs.Add(k); navData.PosList[posIndex].CellIndexs.Add(k); } cell.LineMidPos[0] = CommonFunc.Round((cell.v[0] + cell.v[1]) / 2); cell.LineMidPos[1] = CommonFunc.Round((cell.v[1] + cell.v[2]) / 2); cell.LineMidPos[2] = CommonFunc.Round((cell.v[2] + cell.v[0]) / 2); cell.Normalize[0] = Vector3.Normalize(cell.v[1] - cell.v[0]); cell.Normalize[1] = Vector3.Normalize(cell.v[2] - cell.v[1]); cell.Normalize[2] = Vector3.Normalize(cell.v[0] - cell.v[2]); cell.LineMidSqrDistance[0] = CommonFunc.Round(GetLineMidDstance(cell.v[0], cell.v[1], cell.v[2])); cell.LineMidSqrDistance[1] = CommonFunc.Round(GetLineMidDstance(cell.v[1], cell.v[0], cell.v[2])); cell.LineMidSqrDistance[2] = CommonFunc.Round(GetLineMidDstance(cell.v[2], cell.v[0], cell.v[1])); cell.MidPos = (cell.v[0] + cell.v[1] + cell.v[2]) / 3; listtemp.Add(cell); GtMsg.Cell msg_cell = new GtMsg.Cell(); msg_cell.V.Add(CommonFunc.GetVec3(cell.v[0])); msg_cell.V.Add(CommonFunc.GetVec3(cell.v[1])); msg_cell.V.Add(CommonFunc.GetVec3(cell.v[2])); msg_cell.VIndex.Add(cell.vIndex[0]); msg_cell.VIndex.Add(cell.vIndex[1]); msg_cell.VIndex.Add(cell.vIndex[2]); msg_cell.MidPos = CommonFunc.GetVec3(cell.MidPos); msg_cell.Index = navData.Celllist.Count; msg_cell.LineMidSqrDistance.Add(cell.LineMidSqrDistance[0]); msg_cell.LineMidSqrDistance.Add(cell.LineMidSqrDistance[1]); msg_cell.LineMidSqrDistance.Add(cell.LineMidSqrDistance[2]); msg_cell.LineMidPos.Add(CommonFunc.GetVec3(cell.LineMidPos[0])); msg_cell.LineMidPos.Add(CommonFunc.GetVec3(cell.LineMidPos[1])); msg_cell.LineMidPos.Add(CommonFunc.GetVec3(cell.LineMidPos[2])); msg_cell.Normalize.Add(CommonFunc.GetVec3(cell.Normalize[0])); msg_cell.Normalize.Add(CommonFunc.GetVec3(cell.Normalize[1])); msg_cell.Normalize.Add(CommonFunc.GetVec3(cell.Normalize[2])); for (int i = 0; i < 3; i++) { GtMsg.Nears n = new GtMsg.Nears(); n.Enable = false; msg_cell.Nears.Add(n); } cell.index = msg_cell.Index; navData.Celllist.Add(msg_cell); } } list = listtemp; //设置相邻cell for (int i = 0; i < list.Count; i++) { var a = list[i]; for (int j = 0; j < list.Count; j++) { var b = list[j]; if (a != b) { int aLineIndex = -1; int bLineIndex = -1; if (IsNearCell(a, b, ref aLineIndex, ref bLineIndex)) { var a2 = navData.Celllist[i]; InsertNears(a, b, a2, aLineIndex, bLineIndex); } } } } string resourcePath = Application.dataPath + "/Resources/File/"; if (!Directory.Exists(resourcePath)) { Directory.CreateDirectory(resourcePath); } using (FileStream output = File.Create(resourcePath + "NavMesh.bytes")) { navData.WriteTo(output); } AssetDatabase.Refresh(); EditorUtility.DisplayDialog("加载地图网格", "加载成功", "关闭"); Debug.Log("ExportNavMesh Success"); }
void GenNavMesh(string outfile) { UnityEngine.AI.NavMeshTriangulation navtri = UnityEngine.AI.NavMesh.CalculateTriangulation(); Dictionary <int, int> indexmap = new Dictionary <int, int>(); List <Vector3> repos = new List <Vector3>(); for (int i = 0; i < navtri.vertices.Length; i++) { int ito = -1; for (int j = 0; j < repos.Count; j++) { if (Vector3.Distance(navtri.vertices[i], repos[j]) < 0.01) { ito = j; break; } } if (ito < 0) { indexmap[i] = repos.Count; repos.Add(navtri.vertices[i]); } else { indexmap[i] = ito; } } //关系是 index 公用的三角形表示他们共同组成多边形 //多边形之间的连接用顶点位置识别 List <int> polylast = new List <int>(); List <int[]> polys = new List <int[]>(); for (int i = 0; i < navtri.indices.Length / 3; i++) { int i0 = navtri.indices[i * 3 + 0]; int i1 = navtri.indices[i * 3 + 1]; int i2 = navtri.indices[i * 3 + 2]; if (polylast.Contains(i0) || polylast.Contains(i1) || polylast.Contains(i2)) { if (polylast.Contains(i0) == false) { polylast.Add(i0); } if (polylast.Contains(i1) == false) { polylast.Add(i1); } if (polylast.Contains(i2) == false) { polylast.Add(i2); } } else { if (polylast.Count > 0) { polys.Add(polylast.ToArray()); } polylast.Clear(); polylast.Add(i0); polylast.Add(i1); polylast.Add(i2); } } if (polylast.Count > 0) { polys.Add(polylast.ToArray()); } string outnav = ""; outnav = "{\"v\":[\n"; for (int i = 0; i < repos.Count; i++) { if (i > 0) { outnav += ",\n"; } outnav += "[" + (int)(repos[i].x * 10000) + "," + (int)(repos[i].z * 10000) + "]"; } outnav += "\n],\"p\":[\n"; for (int i = 0; i < polys.Count; i++) { string outs = indexmap[polys[i][0]].ToString(); for (int j = 1; j < polys[i].Length; j++) { outs += "," + indexmap[polys[i][j]]; } if (i > 0) { outnav += ",\n"; } outnav += "[" + outs + "]"; } outnav += "\n]}"; System.IO.File.WriteAllText(outfile, outnav); }
private static extern void CalculateTriangulation_Injected(out NavMeshTriangulation ret);
void PlaceProbes() { GameObject probe = probeObject; if (probe != null) { LightProbeGroup p = probe.GetComponent <LightProbeGroup>(); if (p != null) { working = true; progress = 0.0f; current = "Triangulating navmesh..."; EditorUtility.DisplayProgressBar("Generating probes", current, progress); probe.transform.position = Vector3.zero; UnityEngine.AI.NavMeshTriangulation navMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); current = "Generating necessary lists..."; EditorUtility.DisplayProgressBar("Generating probes", current, progress); Vector3[] newProbes = navMesh.vertices; List <Vector3> probeList = new List <Vector3>(newProbes); List <ProbeGenPoint> probeGen = new List <ProbeGenPoint>(); foreach (Vector3 pg in probeList) { probeGen.Add(new ProbeGenPoint(pg, false)); } EditorUtility.DisplayProgressBar("Generating probes", current, progress); List <Vector3> mergedProbes = new List <Vector3>(); int probeListLength = newProbes.Length; int done = 0; foreach (ProbeGenPoint pro in probeGen) { if (pro.used == false) { current = "Checking point at " + pro.point.ToString(); progress = (float)done / (float)probeListLength; EditorUtility.DisplayProgressBar("Generating probes", current, progress); List <Vector3> nearbyProbes = new List <Vector3>(); nearbyProbes.Add(pro.point); pro.used = true; foreach (ProbeGenPoint pp in probeGen) { if (pp.used == false) { current = "Checking point at " + pro.point.ToString(); //EditorUtility.DisplayProgressBar ("Generating probes", current, progress); if (Vector3.Distance(pp.point, pro.point) <= mergeDistance) { pp.used = true; nearbyProbes.Add(pp.point); } } } Vector3 newProbe = new Vector3(); foreach (Vector3 prooo in nearbyProbes) { newProbe += prooo; } newProbe /= nearbyProbes.ToArray().Length; newProbe += Vector3.up; mergedProbes.Add(newProbe); done += 1; //Debug.Log ("Added probe at point " + newProbe.ToString ()); } } /*for(int i=0; i<newProbes.Length; i++) { * newProbes[i] = newProbes[i] + Vector3.up; * }*/ current = "Final steps..."; EditorUtility.DisplayProgressBar("Generating probes", current, progress); p.probePositions = mergedProbes.ToArray(); EditorUtility.DisplayProgressBar("Generating probes", current, progress); working = false; } else { EditorUtility.DisplayDialog("Error", "Probe object does not have a Light Probe Group attached to it", "OK"); } } else { EditorUtility.DisplayDialog("Error", "Probe object not set", "OK"); } }
static void Export() { Debug.Log("ExportNavMesh"); UnityEngine.AI.NavMeshTriangulation tmpNavMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation(); //新建文件 string tmpPath = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".lua"; Debug.Log("=====================" + tmpPath + tmpNavMeshTriangulation.vertices.Length); StreamWriter tmpStreamWriter = new StreamWriter(tmpPath); tmpStreamWriter.WriteLine("-------本文件是地图导航网格文本"); tmpStreamWriter.WriteLine("local nav_triangle = {"); Hashtable pointTable = new Hashtable(); //顶点 for (int i = 0; i < tmpNavMeshTriangulation.vertices.Length; i++) { //tmpStreamWriter.WriteLine("v " + tmpNavMeshTriangulation.vertices[i].x + " " + tmpNavMeshTriangulation.vertices[i].y + " " + tmpNavMeshTriangulation.vertices[i].z); if (!pointTable.ContainsKey(tmpNavMeshTriangulation.vertices[i])) { pointTable.Add(tmpNavMeshTriangulation.vertices[i], new ArrayList()); } (pointTable[tmpNavMeshTriangulation.vertices[i]] as ArrayList).Add(i); } //tmpStreamWriter.WriteLine("g pPlane1"); Hashtable lineTable = new Hashtable(); List <NavTriangle> triangles = new List <NavTriangle>(); int triangleIndex = 1; for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;) { //tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 1] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 2] + 1)); NavTriangle item = new NavTriangle(); item.tLineKeyArr = new string[3]; item.tIndex = triangleIndex; SetTriangleInfo(0, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 2]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 1]] , pointTable, item, lineTable); SetTriangleInfo(1, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 1]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i]] , pointTable, item, lineTable); SetTriangleInfo(2, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i + 2]] , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[i]] , pointTable, item, lineTable); triangles.Add(item); triangleIndex += 1; i = i + 3; } for (int i = 0; i < triangles.Count; i++) { tmpStreamWriter.WriteLine(string.Format("\t[{0}] = {{", triangles[i].tIndex)); tmpStreamWriter.WriteLine(string.Format("\t\tv = {{{{{0}, {1}, {2}}}, {{{3}, {4}, {5}}},{{{6}, {7}, {8}}}}}," , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 2]].y , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3 + 1]].y , tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].x, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].z, tmpNavMeshTriangulation.vertices[tmpNavMeshTriangulation.indices[(triangles[i].tIndex - 1) * 3]].y)); tmpStreamWriter.WriteLine(string.Format("\t\tnedge = {{{0}, {1}, {2}}}," , GetSameLine(triangles[i].tLineKeyArr[0], triangles[i].tIndex, lineTable) , GetSameLine(triangles[i].tLineKeyArr[1], triangles[i].tIndex, lineTable) , GetSameLine(triangles[i].tLineKeyArr[2], triangles[i].tIndex, lineTable))); tmpStreamWriter.WriteLine("\t},\n"); } tmpStreamWriter.WriteLine("}"); tmpStreamWriter.Flush(); tmpStreamWriter.Close(); Debug.Log("ExportNavMesh Success"); }