Beispiel #1
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="navMesh">Precalculated Nav Mesh Triangulation</param>
        /// <param name="vert_size">Size of vertex array</param>
        /// <param name="tri_size">Size of triangle array</param>
        /// <returns></returns>
        public 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);
        }
Beispiel #2
0
        static string GenerateNavToObj()
        {
            Vector3[] vs;
            int[]     ids;
            string    txt = "";

#if false
            NavMesh.Triangulate(out vs, out ids);
#else
            UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation();
            vs  = tri.vertices;
            ids = tri.indices;
#endif

            foreach (Vector3 v in vs)
            {
                // EosHack :
                //txt += "v " + (v.x) + " " + (v.y) + " " + (v.z) + "\n";
                txt += "v " + (v.x) + " " + (v.y + BaseOffset) + " " + (v.z) + "\n";
            }
            for (int i = 0; i < ids.Length; i += 3)
            {
                txt += "f " + (ids[i] + 1) + " " + (ids[i + 1] + 1) + " " + (ids[i + 2] + 1) + "\n";
            }
            return(txt);
        }
 /// <summary>
 /// Write the specified value using the writer.
 /// </summary>
 /// <param name="value">Value.</param>
 /// <param name="writer">Writer.</param>
 public override void Write(object value, ISaveGameWriter writer)
 {
     UnityEngine.AI.NavMeshTriangulation navMeshTriangulation = (UnityEngine.AI.NavMeshTriangulation)value;
     writer.WriteProperty("vertices", navMeshTriangulation.vertices);
     writer.WriteProperty("indices", navMeshTriangulation.indices);
     writer.WriteProperty("areas", navMeshTriangulation.areas);
 }
Beispiel #4
0
        public void Build()
        {
            if (fromUnityNavigation)
            {
                UnityEngine.AI.NavMeshTriangulation triangulatedNavMesh = UnityEngine.AI.NavMesh.CalculateTriangulation();

                Mesh mesh = new Mesh();
                mesh.name      = "ExportedNavMesh";
                mesh.vertices  = triangulatedNavMesh.vertices;
                mesh.triangles = triangulatedNavMesh.indices;
                Mesh sourceMesh = mesh;
                if (sourceMesh == null)
                {
                    return;
                }
                ScanInternal(sourceMesh.triangles, sourceMesh.vertices);
            }
            else
            {
                AstarPathEditor.MenuScan();

                Pathfinding.RecastGraph target = AstarPath.active.graphs[0] as Pathfinding.RecastGraph;
                int[]     triangles;
                Vector3[] vertices;
                GetRecastData(target, out triangles, out vertices);

                ScanInternal(triangles, vertices);
            }
        }
Beispiel #5
0
        static void Export()
        {
            Debug.Log("NavMesh Export Start");

            UnityEngine.AI.NavMeshTriangulation navMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation();

            //文件路径
            string path = Application.dataPath + "/" /*+ "/AStar/obj/"*/ + 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: " + path);
        }
Beispiel #6
0
        public static void UpdateNavMesh(NavMeshRenderer mesh, SerializedObject serializedObject, ArcTeleportData teleportSettings)
        {
            UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation();
            int vert_size, tri_size;

            CullNavmeshTriangulation(ref tri, teleportSettings.NavAreaMask, 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);

            teleportSettings.SelectableMesh = m;
            mesh.SelectableMesh             = mesh.SelectableMesh; // Make sure that setter is called
        }
Beispiel #7
0
        static int _m_CalculateTriangulation_xlua_st_(RealStatePtr L)
        {
            ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L);



            try {
                {
                    UnityEngine.AI.NavMeshTriangulation __cl_gen_ret = UnityEngine.AI.NavMesh.CalculateTriangulation(  );
                    translator.Push(L, __cl_gen_ret);



                    return(1);
                }
            } catch (System.Exception __gen_e) {
                return(LuaAPI.luaL_error(L, "c# exception:" + __gen_e));
            }
        }
        /// <summary>
        /// Read the data using the reader.
        /// </summary>
        /// <param name="reader">Reader.</param>
        public override object Read(ISaveGameReader reader)
        {
            UnityEngine.AI.NavMeshTriangulation navMeshTriangulation = new UnityEngine.AI.NavMeshTriangulation();
            foreach (string property in reader.Properties)
            {
                switch (property)
                {
                case "vertices":
                    navMeshTriangulation.vertices = reader.ReadProperty <UnityEngine.Vector3[]> ();
                    break;

                case "indices":
                    navMeshTriangulation.indices = reader.ReadProperty <System.Int32[]> ();
                    break;

                case "areas":
                    navMeshTriangulation.areas = reader.ReadProperty <System.Int32[]> ();
                    break;
                }
            }
            return(navMeshTriangulation);
        }
Beispiel #9
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="navMesh">NavMesh data to modify</param>
        /// <param name="area">Area mask to include in returned mesh.  Areas outside of this mask are culled.</param>
        /// <param name="vert_size">New size of navMesh.vertices</param>
        /// <param name="tri_size">New size of navMesh.areas and one third of the size of navMesh.indices</param>
        public 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++;
                }
            }
        }
Beispiel #10
0
        public void PlaceProbes()
        {
            if (probeObject != null)
            {
                probeObject.transform.position = Vector3.zero;

                UnityEngine.AI.NavMeshTriangulation navMesh = UnityEngine.AI.NavMesh.CalculateTriangulation();

                Vector3[] _pos = navMesh.vertices;

                // construct kd tree
                KdTree         _kd     = new KdTree();
                KdTree.Entry[] _kdents = new KdTree.Entry[_pos.Length];
                for (int i = 0; i < _kdents.Length; ++i)
                {
                    _kdents[i] = new KdTree.Entry(_pos[i], i);
                }
                _kd.build(_kdents);

                List <ProbeGenPoint> probeGen = new List <ProbeGenPoint>();
                foreach (Vector3 _pt in _pos)
                {
                    probeGen.Add(new ProbeGenPoint(_pt, false));
                }

                List <Vector3> mergedProbes = new List <Vector3>();

                var _watch = new System.Diagnostics.Stopwatch();
                _watch.Start();

                var _queue = new KdTree.RQueue();

                for (int i = 0; i < probeGen.Count; ++i)
                {
                    ProbeGenPoint _pro = probeGen[i];

                    if (_pro.used)
                    {
                        continue;
                    }

                    float   _mergedCnt = 1.0f;
                    Vector3 _mergedPos = _pro.pos;

                    var _neighbor = _kd.rquery(_queue, _pro.pos, mergeDistance);

                    for (int n = 0; n < _neighbor.Length; ++n)
                    {
                        if (_neighbor[n] == i)
                        {
                            continue;
                        }

                        ProbeGenPoint _subject = probeGen[_neighbor[n]];
                        _subject.used = true;
                    }

                    if (_mergedCnt > 1.0f)
                    {
                        _mergedPos *= 1.0f / _mergedCnt;
                    }

                    for (int l = 0; l < layers; ++l)
                    {
                        mergedProbes.Add(_mergedPos + Vector3.up * (layerHeight * l));
                    }

                    _pro.used = true;
                }

                _watch.Stop();
                Log.I("merging completed in {0} ms", _watch.ElapsedMilliseconds);

                probeObject.probePositions = mergedProbes.ToArray();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Execute when Update Navmesh button is clicked.
        /// </summary>
        private void OnNavmeshUpdateClick()
        {
            GameObject featureObject = FindFeatureOfType(typeof(ArcTeleportManager));

            if (featureObject == null)
            {
                Debug.LogError("Add Arc Teleport before clicking Update Navmesh.");
            }
            else
            {
                ArcTeleportManager arcTeleportManager = featureObject.GetComponent <ArcTeleportManager>();


                NavMeshRenderer mesh = featureObject.transform.Find("Navmesh").GetComponent <NavMeshRenderer>();

                // 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    |= ((TeleportSettings.NavAreaMask >> area_index[x]) & 1) << x;
                }
                EditorGUI.BeginChangeCheck();
                temp_mask = EditorGUILayout.MaskField("Area Mask", temp_mask, areas);
                if (EditorGUI.EndChangeCheck())
                {
                    TeleportSettings.NavAreaMask = 0;
                    for (int x = 0; x < areas.Length; x++)
                    {
                        TeleportSettings.NavAreaMask |= (((temp_mask >> x) & 1) == 1 ? 0 : 1) << area_index[x];
                    }
                    TeleportSettings.NavAreaMask = ~TeleportSettings.NavAreaMask;
                }

                // Sanity check for Null properties //
                bool HasMesh = (mesh.SelectableMesh != null && mesh.SelectableMesh.vertexCount != 0) || (mesh.SelectableMeshBorder != null && mesh.SelectableMeshBorder.Length != 0);

                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);
                }

                UnityEngine.AI.NavMeshTriangulation tri = UnityEngine.AI.NavMesh.CalculateTriangulation();
                int vert_size, tri_size;

                NavMeshHelper.CullNavmeshTriangulation(ref tri, TeleportSettings.NavAreaMask, out vert_size, out tri_size);

                Mesh m = NavMeshHelper.ConvertNavmeshToMesh(tri, vert_size, tri_size);
                // Can't use SerializedProperties here because BorderPointSet doesn't derive from UnityEngine.Object
                mesh.SelectableMeshBorder = NavMeshHelper.FindBorderEdges(m);

                TeleportSettings.SelectableMesh = m;
                mesh.SelectableMesh             = mesh.SelectableMesh;
                TeleportSettings.Save();
            }
        }