Exemple #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <remarks>
        /// <para>
        /// A 'no result' object will be created if the <paramref name="polyMesh"/> parameter
        /// is null or has a polygon count of zero.
        /// </para>
        /// </remarks>
        /// <param name="tx">The x-index of the tile within the tile grid. (tx, tz)</param>
        /// <param name="tz">The z-index of the tile within the tile grid. (tx, tz)</param>
        /// <param name="polyMesh">The polymesh.</param>
        /// <param name="detailMesh">The detail mesh.</param>
        /// <param name="heightfield">The heightfield.</param>
        /// <param name="compactField">The compact field.</param>
        /// <param name="contours">The contour set.</param>
        public NMGenAssets(int tx, int tz
                           , PolyMesh polyMesh
                           , PolyMeshDetail detailMesh
                           , Heightfield heightfield
                           , CompactHeightfield compactField
                           , ContourSet contours)
        {
            mTileX = tx;
            mTileZ = tz;

            if (polyMesh == null || polyMesh.PolyCount == 0)
            {
                mPolyMesh     = null;
                mDetailMesh   = null;
                mHeightfield  = null;
                mCompactField = null;
                mContours     = null;
            }
            else
            {
                mPolyMesh     = polyMesh;
                mDetailMesh   = detailMesh; // OK to be null.
                mHeightfield  = heightfield;
                mCompactField = compactField;
                mContours     = contours;
            }
        }
Exemple #2
0
        /// <summary>
        /// Generates a <see cref="NavMesh"/> given a collection of triangles and some settings.
        /// </summary>
        /// <param name="triangles">The triangles that form the level.</param>
        /// <param name="settings">The settings to generate with.</param>
        /// <returns>A <see cref="NavMesh"/>.</returns>
        public static NavMesh Generate(IEnumerable <Triangle3> triangles, NavMeshGenerationSettings settings)
        {
            BBox3 bounds = triangles.GetBoundingBox(settings.CellSize);
            var   hf     = new Heightfield(bounds, settings);

            hf.RasterizeTriangles(triangles);
            hf.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            hf.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            hf.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

            var chf = new CompactHeightfield(hf, settings);

            chf.Erode(settings.VoxelAgentRadius);
            chf.BuildDistanceField();
            chf.BuildRegions(2, settings.MinRegionSize, settings.MergedRegionSize);

            var cont = chf.BuildContourSet(settings);

            var polyMesh = new PolyMesh(cont, settings);

            var polyMeshDetail = new PolyMeshDetail(polyMesh, chf, settings);

            var buildData = new NavMeshBuilder(polyMesh, polyMeshDetail, new Pathfinding.OffMeshConnection[0], settings);

            var navMesh = new NavMesh(buildData);

            return(navMesh);
        }
Exemple #3
0
        public NavMeshBuilder GenerateNavmesh(BBox3 bbox)
        {
            float[]  vertices;
            int[]    indices;
            AreaId[] areas;
            GetRawData(out vertices, out indices, out areas);
            var settings = WoWSettings;

            var hf = new Heightfield(bbox, settings);

            hf.RasterizeTrianglesWithAreas(vertices, areas);
            hf.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            hf.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            hf.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

            var chf = new CompactHeightfield(hf, settings);

            chf.Erode(settings.VoxelAgentWidth);
            chf.BuildDistanceField();
            chf.BuildRegions((int)(settings.AgentWidth / settings.CellSize) + 8, settings.MinRegionSize, settings.MergedRegionSize);

            var cset  = new ContourSet(chf, settings);
            var pmesh = new PolyMesh(cset, settings);
            var dmesh = new PolyMeshDetail(pmesh, chf, settings);

            var buildData = new NavMeshBuilder(pmesh, dmesh, new SharpNav.Pathfinding.OffMeshConnection[0], settings);

            return(buildData);
        }
Exemple #4
0
 public static extern bool rcpdFlattenMesh([In] PolyMeshDetail detailMesh
                                           , [In, Out] Vector3[] verts
                                           , ref int vertCount
                                           , int vertsSize
                                           , [In, Out] int[] tris
                                           , ref int triCount
                                           , int trisSize);
Exemple #5
0
 /// <summary>
 /// Sets the context as having produced no result.
 /// </summary>
 public void SetAsNoResult()
 {
     mHeightfield  = null;
     mCompactField = null;
     mContours     = null;
     mPolyMesh     = null;
     mDetailMesh   = null;
     mNoResult     = true;
 }
Exemple #6
0
        internal void SetWorkingData(int x, int z, PolyMesh polyMesh, PolyMeshDetail detailMesh)
        {
            int i = GetIndex(x, z);

            if (i == IndexError)
            {
                return;
            }

            unsafeItems[i].SetWorkingData(polyMesh, detailMesh);

            mIsDirty = true;
            unsafeVersion++;
        }
Exemple #7
0
 public NavMeshDataResult CreateNavMeshData(RcConfig config, PolyMeshDetail polyMeshDetail, PolyMesh polyMesh,
                                            InputGeom geom, int tx, int ty, float agentHeight, float agentRadius, float agentMaxClimb)
 {
     return(RecastLibrary.navmesh_data_create(
                _context.DangerousGetHandle(),
                ref config,
                polyMeshDetail.DangerousGetHandle(),
                polyMesh.DangerousGetHandle(),
                geom.DangerousGetHandle(),
                tx,
                ty,
                agentHeight,
                agentRadius,
                agentMaxClimb));
 }
Exemple #8
0
        //private void GenerateNavMesh()
        //{
        //    Console.WriteLine("Generating NavMesh");

        //    long prevMs = 0;
        //    try
        //    {
        //        var levelTris = level.GetTriangles();
        //        var triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
        //        BBox3 bounds = triEnumerable.GetBoundingBox();

        //        settings = NavMeshGenerationSettings.Default;
        //        heightfield = new Heightfield(bounds, settings);

        //        heightfield.RasterizeTriangles(levelTris, Area.Default);
        //        heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
        //        heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
        //        heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
        //        compactHeightfield = new CompactHeightfield(heightfield, settings);
        //        compactHeightfield.Erode(settings.VoxelAgentRadius);
        //        compactHeightfield.BuildDistanceField();
        //        compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

        //        contourSet = compactHeightfield.BuildContourSet(settings);

        //        polyMesh = new PolyMesh(contourSet, settings);

        //        polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);


        //        buildData = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
        //        tiledNavMesh = new TiledNavMesh(buildData);
        //        navMeshQuery = new NavMeshQuery(tiledNavMesh, 2048);
        //    }
        //    catch (Exception e)
        //    {
        //        //if (!interceptExceptions)
        //        //    throw;
        //        //else
        //        //    Console.WriteLine("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
        //    }
        //    finally
        //    {
        //        //sw.Stop();
        //    }
        //}


        private void GenerateNavMesh()
        {
            Console.WriteLine("Generating NavMesh");

            long prevMs = 0;
            //try
            //{
            var   levelTris     = level.GetTriangles();
            var   triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
            BBox3 bounds        = triEnumerable.GetBoundingBox();

            settings    = NavMeshGenerationSettings.Default;
            heightfield = new Heightfield(bounds, settings);

            heightfield.RasterizeTriangles(levelTris, Area.Default);
            heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
            compactHeightfield = new CompactHeightfield(heightfield, settings);
            compactHeightfield.Erode(settings.VoxelAgentRadius);
            compactHeightfield.BuildDistanceField();
            compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

            contourSet = compactHeightfield.BuildContourSet(settings);

            polyMesh = new PolyMesh(contourSet, settings);

            polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);


            buildData    = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
            tiledNavMesh = new TiledNavMesh(buildData);
            navMeshQuery = new NavMeshQuery(tiledNavMesh, 2048);
            OutMesh();
            //}
            //catch (Exception e)
            //{
            //    //if (!interceptExceptions)
            //    //    throw;
            //    //else
            //    //    Console.WriteLine("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
            //}
            //finally
            //{
            //    //sw.Stop();
            //}
        }
Exemple #9
0
        private void BuildDetailMesh()
        {
            if ((mResultOptions & NMGenAssetFlag.DetailMesh) == 0)
            {
                UnityEngine.Debug.Log("(mResultOptions & NMGenAssetFlag.DetailMesh) == 0");
                FinalizeComplete();
                return;
            }

            PolyMesh           polyMesh = mBuildContext.PolyMesh;
            CompactHeightfield chf      = mBuildContext.CompactField;

            PolyMeshDetail detailMesh = PolyMeshDetail.Build(mBuildContext
                                                             , polyMesh
                                                             , chf
                                                             , mConfig.detailSampleDistance
                                                             , mConfig.detailMaxDeviation);

            if (CanDispose(NMGenAssetFlag.CompactField))
            {
                chf.RequestDisposal();
                mBuildContext.CompactField = null;
            }

            if (detailMesh == null)
            {
                UnityEngine.Debug.Log("BuildDetailMesh==null");
                FinalizeAbort("Aborted at detail mesh build.");
                return;
            }

            mBuildContext.DetailMesh = detailMesh;

            if (detailMesh.MeshCount < 1)
            {
                // Will only happen on an error.
                FinalizeAbort("Aborted after detail mesh build. No detail meshes generated.");
                return;
            }

            if (PostProcess() & PostPolyMeshCheck() & PostDetailCheck())
            {
                mBuildContext.Log("Built detail mesh. TriangleCount: " + detailMesh.TriCount, this);
                FinalizeComplete();
            }
        }
Exemple #10
0
        internal PolyMeshDetail GetDetailMesh(int x, int z)
        {
            int i = GetIndex(x, z);

            if (i == IndexError)
            {
                return(null);
            }

            BuildDataItem item = unsafeItems[i];

            if (item.detailMesh.Length == 0)
            {
                return(null);
            }

            return(PolyMeshDetail.Create(item.detailMesh));
        }
        private bool PostDetailCheck()
        {
            PolyMeshDetail detailMesh = mBuildContext.DetailMesh;
            PolyMesh       polyMesh   = mBuildContext.PolyMesh;

            if (detailMesh == null || detailMesh.IsDisposed)
            {
                FinalizeAbort("Custom processors destroyed the detail mesh.  (" + mState + " Post)");
                return(false);
            }
            else if (polyMesh.PolyCount != detailMesh.MeshCount)
            {
                FinalizeAbort("Custom processors returned with poly/detail count mismatch. ("
                              + mState + " Post)");
                return(false);
            }

            return(true);
        }
Exemple #12
0
        internal void SetWorkingData(PolyMesh polyMesh, PolyMeshDetail detailMesh)
        {
            if (polyMesh == null ||
                polyMesh.PolyCount == 0)
            {
                SetAsEmpty();
                return;
            }

            this.polyMesh = polyMesh.GetSerializedData(false);

            if (detailMesh == null)
            {
                this.detailMesh = new byte[0];
            }
            else
            {
                this.detailMesh = detailMesh.GetSerializedData(false);
            }
        }
        public void HandleDetailMesh(NavmeshBuild build, int tx, int tz)
        {
            if (!build)
            {
                return;
            }

            if (mDebugObject == null)
            {
                PolyMeshDetail mesh = build.BuildData.GetDetailMesh(tx, tz);

                if (mesh != null)
                {
                    mDebugObject = mesh.GetData(false);
                }
            }

            if (mDebugObject != null)
            {
                NMGenDebug.Draw(( PolyMeshDetailData )mDebugObject);
            }
        }
Exemple #14
0
        public NavMeshBuilder Build()
        {
            // Generate tile data
            LoadTileData();

            // Extract raw data from geometry
            float[] vertices;
            int[]   indices;

            s_Geometry.GetRawData(out vertices, out indices /*, out areas*/);

            var hf = new Heightfield(Bounds, NavmeshSettings);

            hf.RasterizeTriangles(vertices, Area.Default);
            hf.FilterLedgeSpans(NavmeshSettings.VoxelAgentHeight, NavmeshSettings.VoxelMaxClimb);
            hf.FilterLowHangingWalkableObstacles(NavmeshSettings.VoxelMaxClimb);
            hf.FilterWalkableLowHeightSpans(NavmeshSettings.VoxelAgentHeight);

            var chf = new CompactHeightfield(hf, NavmeshSettings);

            chf.Erode(NavmeshSettings.VoxelAgentRadius);
            chf.BuildDistanceField();
            chf.BuildRegions((int)(NavmeshSettings.AgentRadius / NavmeshSettings.CellSize) + 8, NavmeshSettings.MinRegionSize, NavmeshSettings.MergedRegionSize);

            var cset  = chf.BuildContourSet(NavmeshSettings);
            var pmesh = new PolyMesh(cset, NavmeshSettings);
            var dmesh = new PolyMeshDetail(pmesh, chf, NavmeshSettings);

            var buildData = new NavMeshBuilder(pmesh, dmesh, new SharpNav.Pathfinding.OffMeshConnection[0], NavmeshSettings);

            Console.WriteLine("Rasterized " + vertices.Length / 9 + " triangles.");
            Console.WriteLine("Generated " + cset.Count + " regions.");
            Console.WriteLine("PolyMesh contains " + pmesh.VertCount + " vertices in " + pmesh.PolyCount + " polys.");
            Console.WriteLine("PolyMeshDetail contains " + dmesh.VertCount + " vertices and " + dmesh.TrisCount + " tris in " + dmesh.MeshCount + " meshes.");

            return(buildData);
        }
Exemple #15
0
        public bool QueueTask(BuildContext context
                              , int tx, int tz
                              , PolyMesh polyMesh, PolyMeshDetail detailMesh
                              , bool bvTreeEnabled
                              , int priority)
        {
            TileBuildTask task = TileBuildTask.Create(tx, tz
                                                      , polyMesh.GetData(false)
                                                      , (detailMesh == null ? null : detailMesh.GetData(true))
                                                      , Build.Connections
                                                      , bvTreeEnabled
                                                      , true
                                                      , priority);

            if (!mTaskProcessor.QueueTask(task))
            {
                context.LogError("Task processor rejected task.", this);
                return(false);
            }

            mTileTasks.Add(task);

            return(true);
        }
Exemple #16
0
        private void GenerateNavMesh()
        {
            //Debug.Log("Generating NavMesh");

            Stopwatch sw = new Stopwatch();

            sw.Start();
            long prevMs = 0;

            try
            {
                //level.SetBoundingBoxOffset(new SVector3(settings.CellSize * 0.5f, settings.CellHeight * 0.5f, settings.CellSize * 0.5f));
                var   levelTris     = level.GetTriangles();
                var   triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
                BBox3 bounds        = triEnumerable.GetBoundingBox();

                heightfield = new Heightfield(bounds, settings);

                //Debug.Log("Heightfield");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                /*Area[] areas = AreaGenerator.From(triEnumerable, Area.Default)
                 *  .MarkAboveHeight(areaSettings.MaxLevelHeight, Area.Null)
                 *  .MarkBelowHeight(areaSettings.MinLevelHeight, Area.Null)
                 *  .MarkBelowSlope(areaSettings.MaxTriSlope, Area.Null)
                 *  .ToArray();
                 * heightfield.RasterizeTrianglesWithAreas(levelTris, areas);*/
                heightfield.RasterizeTriangles(levelTris, Area.Default);

                //Debug.Log(" + Rasterization\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                //Debug.Log(" + Filtering");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);

                //Debug.Log("   + Ledge Spans\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);

                //Debug.Log("   + Low Hanging Obstacles\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);

                //Debug.Log("   + Low Height Spans\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield = new CompactHeightfield(heightfield, settings);

                //Debug.Log("CompactHeightfield");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.Erode(settings.VoxelAgentRadius);

                //Debug.Log(" + Erosion\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildDistanceField();

                //Debug.Log(" + Distance Field\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);

                //Debug.Log(" + Regions\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;


                contourSet = compactHeightfield.BuildContourSet(settings);

                //Debug.Log("ContourSet");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMesh = new PolyMesh(contourSet, settings);

                //Debug.Log("PolyMesh");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);

                //Debug.Log("PolyMeshDetail");
                //Debug.Log(" + Ctor\t\t\t\t" + (sw.ElapsedMilliseconds - prevMs).ToString("D3") + " ms");
                prevMs = sw.ElapsedMilliseconds;

                hasGenerated = true;
            }
            catch (Exception e)
            {
                if (!interceptExceptions)
                {
                    throw;
                }
                else
                {
                    //Debug.Log("Navmesh generation failed with exception:" + Environment.NewLine + e.ToString());
                }
            }
            finally
            {
                sw.Stop();
            }

            if (hasGenerated)
            {
                try
                {
                    GeneratePathfinding();

                    //Pathfinding with multiple units
                    //GenerateCrowd();
                }
                catch (Exception e)
                {
                    //Debug.Log("Pathfinding generation failed with exception" + Environment.NewLine + e.ToString());
                    hasGenerated = false;
                }

                //Label l = (Label)statusBar.FindChildByName("GenTime");
                //l.Text = "Generation Time: " + sw.ElapsedMilliseconds + "ms";

                //Debug.Log("Navmesh generated successfully in " + sw.ElapsedMilliseconds + "ms.");
                //Debug.Log("Rasterized " + level.GetTriangles().Length + " triangles.");
                //Debug.Log("Generated " + contourSet.Count + " regions.");
                //Debug.Log("PolyMesh contains " + polyMesh.VertCount + " vertices in " + polyMesh.PolyCount + " polys.");
                //Debug.Log("PolyMeshDetail contains " + polyMeshDetail.VertCount + " vertices and " + polyMeshDetail.TrisCount + " tris in " + polyMeshDetail.MeshCount + " meshes.");
            }
        }
Exemple #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NavMeshBuilder" /> class.
        /// Add all the PolyMesh and PolyMeshDetail attributes to the Navigation Mesh.
        /// Then, add Off-Mesh connection support.
        /// </summary>
        /// <param name="polyMesh">The PolyMesh</param>
        /// <param name="polyMeshDetail">The PolyMeshDetail</param>
        /// <param name="offMeshCons">Offmesh connection data</param>
        /// <param name="settings">The settings used to build.</param>
        public NavMeshBuilder(PolyMesh polyMesh, PolyMeshDetail polyMeshDetail, OffMeshConnection[] offMeshCons, NavMeshGenerationSettings settings)
        {
            if (settings.VertsPerPoly > PathfindingCommon.VERTS_PER_POLYGON)
            {
                throw new InvalidOperationException("The number of vertices per polygon is above SharpNav's limit");
            }
            if (polyMesh.VertCount == 0)
            {
                throw new InvalidOperationException("The provided PolyMesh has no vertices.");
            }
            if (polyMesh.PolyCount == 0)
            {
                throw new InvalidOperationException("The provided PolyMesh has not polys.");
            }

            int nvp = settings.VertsPerPoly;

            //classify off-mesh connection points
            BoundarySide[] offMeshSides          = new BoundarySide[offMeshCons.Length * 2];
            int            storedOffMeshConCount = 0;
            int            offMeshConLinkCount   = 0;

            if (offMeshCons.Length > 0)
            {
                //find height bounds
                float hmin = float.MaxValue;
                float hmax = -float.MaxValue;

                if (polyMeshDetail != null)
                {
                    for (int i = 0; i < polyMeshDetail.VertCount; i++)
                    {
                        float h = polyMeshDetail.Verts[i].Y;
                        hmin = Math.Min(hmin, h);
                        hmax = Math.Max(hmax, h);
                    }
                }
                else
                {
                    for (int i = 0; i < polyMesh.VertCount; i++)
                    {
                        PolyVertex iv = polyMesh.Verts[i];
                        float      h  = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
                        hmin = Math.Min(hmin, h);
                        hmax = Math.Max(hmax, h);
                    }
                }

                hmin -= settings.MaxClimb;
                hmax += settings.MaxClimb;
                BBox3 bounds = polyMesh.Bounds;
                bounds.Min.Y = hmin;
                bounds.Max.Y = hmax;

                for (int i = 0; i < offMeshCons.Length; i++)
                {
                    Vector3 p0 = offMeshCons[i].Pos0;
                    Vector3 p1 = offMeshCons[i].Pos1;

                    offMeshSides[i * 2 + 0] = BoundarySideExtensions.FromPoint(p0, bounds);
                    offMeshSides[i * 2 + 1] = BoundarySideExtensions.FromPoint(p1, bounds);

                    //off-mesh start position isn't touching mesh
                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        if (p0.Y < bounds.Min.Y || p0.Y > bounds.Max.Y)
                        {
                            offMeshSides[i * 2 + 0] = 0;
                        }
                    }

                    //count number of links to allocate
                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        offMeshConLinkCount++;
                    }
                    if (offMeshSides[i * 2 + 1] == BoundarySide.Internal)
                    {
                        offMeshConLinkCount++;
                    }

                    if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                    {
                        storedOffMeshConCount++;
                    }
                }
            }

            //off-mesh connections stored as polygons, adjust values
            int totPolyCount = polyMesh.PolyCount + storedOffMeshConCount;
            int totVertCount = polyMesh.VertCount + storedOffMeshConCount * 2;

            //find portal edges
            int edgeCount   = 0;
            int portalCount = 0;

            for (int i = 0; i < polyMesh.PolyCount; i++)
            {
                PolyMesh.Polygon p = polyMesh.Polys[i];
                for (int j = 0; j < nvp; j++)
                {
                    if (p.Vertices[j] == PolyMesh.NullId)
                    {
                        break;
                    }

                    edgeCount++;

                    if (PolyMesh.IsBoundaryEdge(p.NeighborEdges[j]))
                    {
                        int dir = p.NeighborEdges[j] % 16;
                        if (dir != 15)
                        {
                            portalCount++;
                        }
                    }
                }
            }

            int maxLinkCount = edgeCount + portalCount * 2 + offMeshConLinkCount * 2;

            //find unique detail vertices
            int uniqueDetailVertCount = 0;
            int detailTriCount        = 0;

            if (polyMeshDetail != null)
            {
                detailTriCount = polyMeshDetail.TrisCount;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
                    int numPolyVerts   = polyMesh.Polys[i].VertexCount;
                    uniqueDetailVertCount += numDetailVerts - numPolyVerts;
                }
            }
            else
            {
                uniqueDetailVertCount = 0;
                detailTriCount        = 0;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numPolyVerts = polyMesh.Polys[i].VertexCount;
                    uniqueDetailVertCount += numPolyVerts - 2;
                }
            }

            //allocate data
            header             = new PathfindingCommon.NavMeshInfo();
            navVerts           = new Vector3[totVertCount];
            navPolys           = new Poly[totPolyCount];
            navDMeshes         = new PolyMeshDetail.MeshData[polyMesh.PolyCount];
            navDVerts          = new Vector3[uniqueDetailVertCount];
            navDTris           = new PolyMeshDetail.TriangleData[detailTriCount];
            offMeshConnections = new OffMeshConnection[storedOffMeshConCount];

            //store header
            //HACK TiledNavMesh should figure out the X/Y/layer instead of the user maybe?
            header.X               = 0;
            header.Y               = 0;
            header.Layer           = 0;
            header.PolyCount       = totPolyCount;
            header.VertCount       = totVertCount;
            header.MaxLinkCount    = maxLinkCount;
            header.Bounds          = polyMesh.Bounds;
            header.DetailMeshCount = polyMesh.PolyCount;
            header.DetailVertCount = uniqueDetailVertCount;
            header.DetailTriCount  = detailTriCount;
            header.OffMeshBase     = polyMesh.PolyCount;
            header.WalkableHeight  = settings.AgentHeight;
            header.WalkableRadius  = settings.AgentRadius;
            header.WalkableClimb   = settings.MaxClimb;
            header.OffMeshConCount = storedOffMeshConCount;
            header.BvNodeCount     = settings.BuildBoundingVolumeTree ? polyMesh.PolyCount * 2 : 0;
            header.BvQuantFactor   = 1f / settings.CellSize;

            int offMeshVertsBase = polyMesh.VertCount;
            int offMeshPolyBase  = polyMesh.PolyCount;

            //store vertices
            for (int i = 0; i < polyMesh.VertCount; i++)
            {
                PolyVertex iv = polyMesh.Verts[i];
                navVerts[i].X = polyMesh.Bounds.Min.X + iv.X * settings.CellSize;
                navVerts[i].Y = polyMesh.Bounds.Min.Y + iv.Y * settings.CellHeight;
                navVerts[i].Z = polyMesh.Bounds.Min.Z + iv.Z * settings.CellSize;
            }

            //off-mesh link vertices
            int n = 0;

            for (int i = 0; i < offMeshCons.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    navVerts[offMeshVertsBase + (n * 2 + 0)] = offMeshCons[i].Pos0;
                    navVerts[offMeshVertsBase + (n * 2 + 1)] = offMeshCons[i].Pos1;
                    n++;
                }
            }

            //store polygons
            for (int i = 0; i < polyMesh.PolyCount; i++)
            {
                navPolys[i]           = new Poly();
                navPolys[i].VertCount = 0;
                navPolys[i].Tag       = polyMesh.Polys[i].Tag;
                navPolys[i].Area      = polyMesh.Polys[i].Area;
                navPolys[i].PolyType  = PolygonType.Ground;
                navPolys[i].Verts     = new int[nvp];
                navPolys[i].Neis      = new int[nvp];
                for (int j = 0; j < nvp; j++)
                {
                    if (polyMesh.Polys[i].Vertices[j] == PolyMesh.NullId)
                    {
                        break;
                    }

                    navPolys[i].Verts[j] = polyMesh.Polys[i].Vertices[j];
                    if (PolyMesh.IsBoundaryEdge(polyMesh.Polys[i].NeighborEdges[j]))
                    {
                        //border or portal edge
                        int dir = polyMesh.Polys[i].NeighborEdges[j] % 16;
                        if (dir == 0xf)                         //border
                        {
                            navPolys[i].Neis[j] = 0;
                        }
                        else if (dir == 0)                         //portal x-
                        {
                            navPolys[i].Neis[j] = Link.External | 4;
                        }
                        else if (dir == 1)                         //portal z+
                        {
                            navPolys[i].Neis[j] = Link.External | 2;
                        }
                        else if (dir == 2)                         //portal x+
                        {
                            navPolys[i].Neis[j] = Link.External | 0;
                        }
                        else if (dir == 3)                         //portal z-
                        {
                            navPolys[i].Neis[j] = Link.External | 6;
                        }
                    }
                    else
                    {
                        //normal connection
                        navPolys[i].Neis[j] = polyMesh.Polys[i].NeighborEdges[j] + 1;
                    }

                    navPolys[i].VertCount++;
                }
            }

            //off-mesh connection vertices
            n = 0;
            for (int i = 0; i < offMeshCons.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    navPolys[offMeshPolyBase + n].VertCount = 2;
                    navPolys[offMeshPolyBase + n].Verts     = new int[nvp];
                    navPolys[offMeshPolyBase + n].Verts[0]  = offMeshVertsBase + (n * 2 + 0);
                    navPolys[offMeshPolyBase + n].Verts[1]  = offMeshVertsBase + (n * 2 + 1);
                    navPolys[offMeshPolyBase + n].Tag       = offMeshCons[i].Flags;
                    navPolys[offMeshPolyBase + n].Area      = polyMesh.Polys[offMeshCons[i].Poly].Area;                //HACK is this correct?
                    navPolys[offMeshPolyBase + n].PolyType  = PolygonType.OffMeshConnection;
                    n++;
                }
            }

            //store detail meshes and vertices
            if (polyMeshDetail != null)
            {
                int            vbase             = 0;
                List <Vector3> storedDetailVerts = new List <Vector3>();
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int vb             = polyMeshDetail.Meshes[i].VertexIndex;
                    int numDetailVerts = polyMeshDetail.Meshes[i].VertexCount;
                    int numPolyVerts   = navPolys[i].VertCount;
                    navDMeshes[i].VertexIndex   = vbase;
                    navDMeshes[i].VertexCount   = numDetailVerts - numPolyVerts;
                    navDMeshes[i].TriangleIndex = polyMeshDetail.Meshes[i].TriangleIndex;
                    navDMeshes[i].TriangleCount = polyMeshDetail.Meshes[i].TriangleCount;

                    //Copy detail vertices
                    //first 'nv' verts are equal to nav poly verts
                    //the rest are detail verts
                    for (int j = 0; j < navDMeshes[i].VertexCount; j++)
                    {
                        storedDetailVerts.Add(polyMeshDetail.Verts[vb + numPolyVerts + j]);
                    }

                    vbase += numDetailVerts - numPolyVerts;
                }

                navDVerts = storedDetailVerts.ToArray();

                //store triangles
                for (int j = 0; j < polyMeshDetail.TrisCount; j++)
                {
                    navDTris[j] = polyMeshDetail.Tris[j];
                }
            }
            else
            {
                //create dummy detail mesh by triangulating polys
                int tbase = 0;
                for (int i = 0; i < polyMesh.PolyCount; i++)
                {
                    int numPolyVerts = navPolys[i].VertCount;
                    navDMeshes[i].VertexIndex   = 0;
                    navDMeshes[i].VertexCount   = 0;
                    navDMeshes[i].TriangleIndex = tbase;
                    navDMeshes[i].TriangleCount = numPolyVerts - 2;

                    //triangulate polygon
                    for (int j = 2; j < numPolyVerts; j++)
                    {
                        navDTris[tbase].VertexHash0 = 0;
                        navDTris[tbase].VertexHash1 = j - 1;
                        navDTris[tbase].VertexHash2 = j;

                        //bit for each edge that belongs to the poly boundary
                        navDTris[tbase].Flags = 1 << 2;
                        if (j == 2)
                        {
                            navDTris[tbase].Flags |= 1 << 0;
                        }
                        if (j == numPolyVerts - 1)
                        {
                            navDTris[tbase].Flags |= 1 << 4;
                        }

                        tbase++;
                    }
                }
            }

            //store and create BV tree
            if (settings.BuildBoundingVolumeTree)
            {
                //build tree
                navBvTree = new BVTree(polyMesh.Verts, polyMesh.Polys, nvp, settings.CellSize, settings.CellHeight);
            }

            //store off-mesh connections
            n = 0;
            for (int i = 0; i < offMeshConnections.Length; i++)
            {
                //only store connections which start from this tile
                if (offMeshSides[i * 2 + 0] == BoundarySide.Internal)
                {
                    offMeshConnections[n].Poly = offMeshPolyBase + n;

                    //copy connection end points
                    offMeshConnections[n].Pos0 = offMeshCons[i].Pos0;
                    offMeshConnections[n].Pos1 = offMeshCons[i].Pos1;

                    offMeshConnections[n].Radius = offMeshCons[i].Radius;
                    offMeshConnections[n].Flags  = offMeshCons[i].Flags;
                    offMeshConnections[n].Side   = offMeshSides[i * 2 + 1];
                    offMeshConnections[n].Tag    = offMeshCons[i].Tag;

                    n++;
                }
            }
        }
Exemple #18
0
        public void GenNavMesh()
        {
            // MeshCollider
            List <Triangle3> colliderTringles = new List <Triangle3>();

            Collider[]        colliders  = GameObject.FindObjectsOfType <Collider>();
            List <GameObject> destroyGos = new List <GameObject>();

            foreach (Collider collider in colliders)
            {
                Mesh      mesh = null;
                Matrix4x4 localToWorldMatrix = Matrix4x4.identity;

                if (collider is MeshCollider)
                {
                    MeshCollider mc = collider as MeshCollider;
                    mesh = mc.sharedMesh;
                    localToWorldMatrix = mc.transform.localToWorldMatrix;
                }
                if (collider is BoxCollider)
                {
                    BoxCollider bc = collider as BoxCollider;
                    GameObject  go = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    mesh = go.GetComponent <MeshFilter>().sharedMesh;
                    go.transform.parent        = collider.transform;
                    go.transform.localRotation = Quaternion.identity;
                    go.transform.localPosition = bc.center;
                    go.transform.localScale    = bc.size;
                    localToWorldMatrix         = go.transform.localToWorldMatrix;
                    destroyGos.Add(go);
                }
                if (null != mesh)
                {
                    UnityEngine.Vector3[] vertices = mesh.vertices;
                    for (int i = 0; i < mesh.subMeshCount; ++i)
                    {
                        var subMesh = mesh.GetIndices(i);
                        for (int j = 0; j < subMesh.Length; j += 3)
                        {
                            UnityEngine.Vector3 a = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j]]);
                            UnityEngine.Vector3 b = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j + 1]]);
                            UnityEngine.Vector3 c = localToWorldMatrix.MultiplyPoint(vertices[subMesh[j + 2]]);
                            colliderTringles.Add(new Triangle3(ConvertVector3(a), ConvertVector3(b), ConvertVector3(c)));
                        }
                    }
                }
            }
            foreach (var go in destroyGos)
            {
                GameObject.DestroyImmediate(go);
            }
            destroyGos.Clear();

            Triangle3[] levelTris     = colliderTringles.ToArray();
            var         triEnumerable = TriangleEnumerable.FromTriangle(levelTris, 0, levelTris.Length);
            BBox3       bounds        = triEnumerable.GetBoundingBox();

            heightfield = new Heightfield(bounds, settings);
            heightfield.RasterizeTriangles(levelTris, Area.Default);
            heightfield.FilterLedgeSpans(settings.VoxelAgentHeight, settings.VoxelMaxClimb);
            heightfield.FilterLowHangingWalkableObstacles(settings.VoxelMaxClimb);
            heightfield.FilterWalkableLowHeightSpans(settings.VoxelAgentHeight);
            compactHeightfield = new CompactHeightfield(heightfield, settings);
            compactHeightfield.Erode(settings.VoxelAgentRadius);
            compactHeightfield.BuildDistanceField();
            compactHeightfield.BuildRegions(0, settings.MinRegionSize, settings.MergedRegionSize);
            contourSet     = compactHeightfield.BuildContourSet(settings);
            polyMesh       = new PolyMesh(contourSet, settings);
            polyMeshDetail = new PolyMeshDetail(polyMesh, compactHeightfield, settings);
            buildData      = new NavMeshBuilder(polyMesh, polyMeshDetail, new SharpNav.Pathfinding.OffMeshConnection[0], settings);
            tiledNavMesh   = new TiledNavMesh(buildData);
            navMeshQuery   = new NavMeshQuery(tiledNavMesh, 2048);

            {
                System.Random r = new System.Random();
                regionColors    = new Color[compactHeightfield.MaxRegions];
                regionColors[0] = Color.black;
                for (int i = 1; i < regionColors.Length; i++)
                {
                    regionColors[i] = new Color((byte)r.Next(0, 255), (byte)r.Next(0, 255), (byte)r.Next(0, 255), 255);
                }
            }

            this.GenDrawMesh();

            Debug.Log("GenNavMesh Done!");
        }
Exemple #19
0
		public bool BuildNavMesh( out string error )
		{
			DestroyNavMesh();

			if( !EnabledInHierarchy )
			{
				error = "Is not enabled.";
				return false;
			}

			//get geometry data
			var collector = GetAllGeometriesForNavigationMesh();
			Vector3[] vertices = collector.resultVertices;
			int[] indices = collector.resultIndices;
			int vertexCount = collector.resultVertexCount;
			int indexCount = collector.resultIndexCount;

			if( vertexCount == 0 )
			{
				error = "No vertices were gathered from collision objects.";
				return false;
			}

			//get settings
			var settings = new NavMeshGenerationSettings();
			settings.CellSize = (float)CellSize;
			settings.CellHeight = (float)CellHeight;
			settings.MaxClimb = (float)AgentMaxClimb;
			settings.AgentHeight = (float)AgentHeight;
			settings.AgentRadius = (float)AgentRadius;
			settings.MinRegionSize = MinRegionSize;
			settings.MergedRegionSize = MergedRegionSize;
			settings.MaxEdgeLength = MaxEdgeLength;
			settings.MaxEdgeError = (float)MaxEdgeError;
			settings.VertsPerPoly = MaxVerticesPerPolygon;
			settings.SampleDistance = DetailSampleDistance;
			settings.MaxSampleError = DetailMaxSampleError;
			settings.BuildBoundingVolumeTree = true;

			TiledNavMesh newTiledNavMesh;

			try
			{
				//level.SetBoundingBoxOffset(new SVector3(settings.CellSize * 0.5f, settings.CellHeight * 0.5f, settings.CellSize * 0.5f));

				var bounds = Bounds.Cleared;
				bounds.Add( vertices );
				var heightfield = new Heightfield( ToSharpNav( bounds ), settings );

				var vertices2 = new SharpNav.Geometry.Vector3[ indexCount ];
				for( int index = 0; index < indexCount; index++ )
					vertices2[ index ] = ToSharpNav( vertices[ indices[ index ] ] );

				//Area[] areas = AreaGenerator.From( vertices2, Area.Default )
				//	.MarkBelowSlope( (float)AgentMaxSlope.Value.InRadians(), Area.Null )
				//	.ToArray();
				//Area[] areas = AreaGenerator.From(triEnumerable, Area.Default)
				//	.MarkAboveHeight(areaSettings.MaxLevelHeight, Area.Null)
				//	.MarkBelowHeight(areaSettings.MinLevelHeight, Area.Null)
				//	.MarkBelowSlope(areaSettings.MaxTriSlope, Area.Null)
				//	.ToArray();
				//heightfield.RasterizeTrianglesWithAreas( vertices2, areas );
				heightfield.RasterizeTriangles( vertices2, Area.Default );

				heightfield.FilterLedgeSpans( settings.VoxelAgentHeight, settings.VoxelMaxClimb );
				heightfield.FilterLowHangingWalkableObstacles( settings.VoxelMaxClimb );
				heightfield.FilterWalkableLowHeightSpans( settings.VoxelAgentHeight );

				var compactHeightfield = new CompactHeightfield( heightfield, settings );
				compactHeightfield.Erode( settings.VoxelAgentRadius );
				compactHeightfield.BuildDistanceField();
				compactHeightfield.BuildRegions( 0, settings.MinRegionSize, settings.MergedRegionSize );

				//!!!!
				System.Random r = new System.Random();
				var regionColors = new ColorByte[ compactHeightfield.MaxRegions ];
				regionColors[ 0 ] = new ColorByte( 0, 0, 0 );
				for( int i = 1; i < regionColors.Length; i++ )
					regionColors[ i ] = new ColorByte( (byte)r.Next( 0, 255 ), (byte)r.Next( 0, 255 ), (byte)r.Next( 0, 255 ), (byte)255 );

				var contourSet = compactHeightfield.BuildContourSet( settings );
				var polyMesh = new PolyMesh( contourSet, settings );
				var polyMeshDetail = new PolyMeshDetail( polyMesh, compactHeightfield, settings );

				var buildData = new NavMeshBuilder( polyMesh, polyMeshDetail, new OffMeshConnection[ 0 ], settings );
				newTiledNavMesh = new TiledNavMesh( buildData );

				//!!!!
				////Pathfinding with multiple units
				//GenerateCrowd();
			}
			catch( Exception e )
			{
				DestroyNavMesh();
				error = e.Message;
				return false;
			}

			int dataLength;
			byte[] data;

			using( var memoryStream = new MemoryStream() )
			{
				var serializer = new NavMeshBinarySerializer();
				serializer.Serialize( memoryStream, newTiledNavMesh );

				dataLength = (int)memoryStream.Length;
				data = memoryStream.GetBuffer();
			}

			//generate nav mesh data
			var writer = new ArrayDataWriter();
			writer.Write( navMeshDataVersion );
			writer.Write( dataLength );
			writer.Write( data, 0, dataLength );

			//set NavMeshData and init
			var newNavMeshData = new byte[ writer.BitLength / 8 ];
			Buffer.BlockCopy( writer.Data, 0, newNavMeshData, 0, newNavMeshData.Length );
			NavMeshData = newNavMeshData;

			error = "";
			return true;
		}
Exemple #20
0
        public byte[] Build(int i = 0, int j = 0)
        {
            float[] bbMin, bbMax;
            CalculateTileBounds(out bbMin, out bbMax, false, i, j);

#if (TIMETHIS)
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            stopWatch.Start();
            long cur = 0;
            #endif
            // add border
            bbMin[0] -= Config.BorderSize * Config.CellSize;
            bbMin[2] -= Config.BorderSize * Config.CellSize;
            bbMax[0] += Config.BorderSize * Config.CellSize;
            bbMax[2] += Config.BorderSize * Config.CellSize;

            // get raw geometry - lots of slowness here
            float[] vertices;
            int[]   triangles;
            byte[]  areas;

            Geometry.GetRawData(out vertices, out triangles, out areas);
#if (TIMETHIS)
            Console.WriteLine("GetRawData: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
#endif
            // Following code would check if we have Index out of range error while computing the sum. the result itself is useless.

            /*float sum = 0;
             * foreach (int i2 in triangles)
             *  sum += vertices[i2*3+0] + vertices[i2*3+1] + vertices[i2*3+2];
             * Console.WriteLine(sum);*/

            // now we can find the min/max height for THIS tile
            float MinHeight, MaxHeight;
            Geometry.CalculateMinMaxHeight(out MinHeight, out MaxHeight, bbMin, bbMax);
            //Geometry.Triangles.Clear(); // We should not clear triangles and stuff because we have severals files for one tile.
            //Geometry.Vertices.Clear(); // It will be reset at the next tile anyway, no memory issues.
            bbMin[1] = MinHeight;
            bbMax[1] = MaxHeight;

            Heightfield hf;
            int         width = Config.TileWidth + (Config.BorderSize * 2);
            if (!Context.CreateHeightfield(out hf, width, width, bbMin, bbMax, Config.CellSize, Config.CellHeight))
            {
                throw new OutOfMemoryException("CreateHeightfield ran out of memory");
            }

#if (TIMETHIS)
            Console.WriteLine("CreateHeightfield: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            if (triangles.Count() > 0)
            {
                /*Console.WriteLine("Context.ClearUnwalkableTriangles: verticles: " + vertices.Length + ", triangles: " + triangles.Length + ", areas: " + areas.Length);
                 * Console.WriteLine("Memory allocated GC: " + GC.GetTotalMemory(true));/*/
                Context.ClearUnwalkableTriangles(Config.WalkableSlopeAngle, ref vertices, ref triangles, areas);
#if (TIMETHIS)
                Console.WriteLine("ClearUnwalkableTriangles: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
                cur = stopWatch.ElapsedMilliseconds;
                #endif
                Context.RasterizeTriangles(ref vertices, ref triangles, ref areas, hf, Config.WalkableClimb);
#if (TIMETHIS)
                Console.WriteLine("RasterizeTriangles: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
                cur = stopWatch.ElapsedMilliseconds;
                #endif

                GC.KeepAlive(vertices); // force C# to keep vertices, triangles and areas alive while it's in unamanaged code.
                GC.KeepAlive(triangles);
                GC.KeepAlive(areas);
            }
            vertices  = null;
            triangles = null;
            areas     = null;
            GC.Collect();

            // Once all geometry is rasterized, we do initial pass of filtering to
            // remove unwanted overhangs caused by the conservative rasterization
            // as well as filter spans where the character cannot possibly stand.
            Context.FilterLowHangingWalkableObstacles(Config.WalkableClimb, hf);
#if (TIMETHIS)
            Console.WriteLine("FilterLowHangingWalkableObstacles: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif
            Context.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb, hf);
#if (TIMETHIS)
            Console.WriteLine("FilterLedgeSpans: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif
            Context.FilterWalkableLowHeightSpans(Config.WalkableHeight, hf);
#if (TIMETHIS)
            Console.WriteLine("FilterWalkableLowHeightSpans: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Rasterize once again after the cleanup we did
            //Context.RasterizeTriangles(ref vertices, ref triangles, ref areas, hf, Config.WalkableClimb);
            //#if (TIMETHIS)
            //    Console.WriteLine("RasterizeTriangles: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            //    cur = stopWatch.ElapsedMilliseconds;
            //#endif

            // Compact the heightfield so that it is faster to handle from now on.
            // This will result in more cache coherent data as well as the neighbours
            // between walkable cells will be calculated.
            CompactHeightfield chf;
            if (!Context.BuildCompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, hf, out chf))
            {
                throw new OutOfMemoryException("BuildCompactHeightfield ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("BuildCompactHeightfield: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif
            hf.Delete();

            // Erode the walkable area by agent radius.
            if (!Context.ErodeWalkableArea(Config.WalkableRadius, chf))
            {
                throw new OutOfMemoryException("ErodeWalkableArea ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("ErodeWalkableArea: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Prepare for region partitioning, by calculating distance field along the walkable surface.
            if (!Context.BuildDistanceField(chf))
            {
                throw new OutOfMemoryException("BuildDistanceField ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("BuildDistanceField: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Partition the walkable surface into simple regions without holes.
            if (!Context.BuildRegions(chf, Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea))
            {
                throw new OutOfMemoryException("BuildRegions ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("BuildRegions: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Create contours.
            ContourSet cset;
            if (!Context.BuildContours(chf, Config.MaxSimplificationError, Config.MaxEdgeLength, out cset))
            {
                throw new OutOfMemoryException("BuildContours ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("BuildContours: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Build polygon navmesh from the contours.
            PolyMesh pmesh;
            if (!Context.BuildPolyMesh(cset, Config.MaxVertsPerPoly, out pmesh))
            {
                throw new OutOfMemoryException("BuildPolyMesh ran out of memory");
            }
#if (TIMETHIS)
            Console.WriteLine("BuildPolyMesh: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            cur = stopWatch.ElapsedMilliseconds;
            #endif

            // Build detail mesh.
            PolyMeshDetail dmesh = null;
            //if (!Context.BuildPolyMeshDetail(pmesh, chf, Config.DetailSampleDistance, Config.DetailSampleMaxError,out dmesh))
            //    throw new OutOfMemoryException("BuildPolyMeshDetail ran out of memory");
            //#if (TIMETHIS)
            //    Console.WriteLine("BuildPolyMeshDetail: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            //   cur = stopWatch.ElapsedMilliseconds;
            //#endif

            chf.Delete();
            cset.Delete();

            // Set flags according to area types (e.g. Swim for Water)
            pmesh.MarkAll();

            // get original bounds
            float[] tilebMin, tilebMax;
            CalculateTileBounds(out tilebMin, out tilebMax, false, i, j);
            tilebMin[1] = bbMin[1];
            tilebMax[1] = bbMax[1];

            // build off mesh connections for flightmasters
            // bMax and bMin are switched here because of the coordinate system transformation

            var connections = new List <OffMeshConnection>();

            if (MapId == 1220)
            {
                SlimDX.Vector3    from = new SlimDX.Vector3(1685.681f, 4709.121f, 139.4296f);
                SlimDX.Vector3    to   = new SlimDX.Vector3(1682.194f, 4712.713f, 139.6532f);
                OffMeshConnection conn = new OffMeshConnection
                {
                    AreaId = PolyArea.Road,
                    Flags  = PolyFlag.Walk,
                    From   = from.ToRecast().ToFloatArray(),
                    To     = to.ToRecast().ToFloatArray(),
                    Radius = 5,
                    Type   = ConnectionType.BiDirectional,
                    UserID = 1,
                };
                connections.Add(conn);
                from = new SlimDX.Vector3(1661.302f, 4727.02f, 139.4618f);
                to   = new SlimDX.Vector3(1669.568f, 4733.722f, 138.7087f);
                conn = new OffMeshConnection
                {
                    AreaId = PolyArea.Road,
                    Flags  = PolyFlag.Walk,
                    From   = from.ToRecast().ToFloatArray(),
                    To     = to.ToRecast().ToFloatArray(),
                    Radius = 5f,
                    Type   = ConnectionType.BiDirectional,
                    UserID = 2,
                };
                connections.Add(conn);
            }

            /*if (MapId == 0 && X == 31 && Y == 58)
             * {
             *  //<X>-14250.71</X>
             *  //<Y>329.7578</Y>
             *  //<Z>24.17678</Z>
             *
             *  //<X>-14254.86</X>
             *  //<Y>336.1039</Y>
             *  //<Z>26.79213</Z>
             *
             *  SlimDX.Vector3 from = new SlimDX.Vector3(1.0f, 1.0f, 1.0f);
             *  SlimDX.Vector3 to   = new SlimDX.Vector3(1.0f, 1.0f, 1.0f);
             *  OffMeshConnection conn = new OffMeshConnection
             *          {
             *              From = from.ToRecast().ToFloatArray(),
             *              To = to.ToRecast().ToFloatArray(),
             *              Radius = 2.5f,
             *              Type = ConnectionType.BiDirectional,
             *              UserID = 88,
             *          };
             *  connections.Add(conn);
             * }*/

            /* // Disable mesh connexion RIVAL
             * var taxis = TaxiHelper.GetNodesInBBox(MapId, tilebMax.ToWoW(), tilebMin.ToWoW());
             * foreach (var taxi in taxis)
             * {
             *  Log.Log(LogCategory.Warning,
             *          "Flightmaster \"" + taxi.Name + "\", Id: " + taxi.Id + " Horde: " + taxi.IsHorde + " Alliance: " +
             *          taxi.IsAlliance);
             *
             *  var data = TaxiHelper.GetTaxiData(taxi);
             *  var from = taxi.Location.ToRecast().ToFloatArray();
             *  connections.AddRange(data.To.Select(to => new OffMeshConnection
             *                                                {
             *                                                    AreaId = PolyArea.Road,
             *                                                    Flags = PolyFlag.FlightMaster,
             *                                                    From = from,
             *                                                    To = to.Value.Location.ToRecast().ToFloatArray(),
             *                                                    Radius = Config.WorldWalkableRadius,
             *                                                    Type = ConnectionType.OneWay,
             *                                                    UserID = (uint) to.Key
             *                                                }));
             *
             *  foreach (var target in data.To)
             *      Log.Log(LogCategory.Warning,
             *              "\tPath to: \"" + target.Value.Name + "\" Id: " + target.Value.Id + " Path Id: " +
             *              target.Key);
             * }*/


            byte[] tileData;
            if (!Detour.CreateNavMeshData(out tileData, pmesh, dmesh,
                                          X * Constant.Division + i, Y * Constant.Division + j, tilebMin, tilebMax,
                                          Config.WorldWalkableHeight, Config.WorldWalkableRadius,
                                          Config.WorldWalkableClimb, Config.CellSize,
                                          Config.CellHeight, Config.BuildBvTree,
                                          connections.ToArray()))
            {
                pmesh.Delete();
                //dmesh.Delete();
                return(null);
            }
#if (TIMETHIS)
            Console.WriteLine("CreateNavMeshData: " + (stopWatch.ElapsedMilliseconds - cur) + ", total: " + stopWatch.ElapsedMilliseconds);
            #endif
            pmesh.Delete();
            //dmesh.Delete();
            GC.Collect();

            return(tileData);
        }
Exemple #21
0
 public static extern bool rcpdBuildPolyMeshDetail(IntPtr context
                                                   , ref PolyMeshEx polyMesh
                                                   , [In] CompactHeightfield chf
                                                   , float sampleDist
                                                   , float sampleMaxError
                                                   , [In, Out] PolyMeshDetail detailMesh);
Exemple #22
0
        public byte[] Build()
        {
            Log = new MemoryLog(); //ConsoleLog();
            if (!Directory.Exists(_meshDir + "Dungeons"))
            {
                Directory.CreateDirectory(_meshDir + "Dungeons");
            }

            if (File.Exists(GetDungeonLockAndPath()) || File.Exists(GetMeshPath()))
            {
                return(null);
            }

            try
            {
                string tlock = GetDungeonLockAndPath();
                var    sw    = File.CreateText(tlock);
                sw.Close();
            }
            catch (Exception)
            {
                // In case 2 builder are trying to create the same file
                return(null);
            }
            InitializeProgress(12);

            Geometry = new Geometry {
                Transform = true
            };

            if (Dungeon == "AllianceGunship")
            {
                // hardcode for AllianceGunship in Deephome.
                Geometry.AddAllianceGunShip();
            }
            else
            {
                var wdt = new WDT("World\\maps\\" + Dungeon + "\\" + Dungeon + ".wdt");
                if (!wdt.IsGlobalModel || !wdt.IsValid)
                {
                    return(null);
                }
                var model = new WorldModelRoot(wdt.ModelFile);
                Geometry.AddDungeon(model, wdt.ModelDefinition);
            }

            CompleteWorkUnit();

            if (Geometry.Vertices.Count == 0 && Geometry.Triangles.Count == 0)
            {
                throw new InvalidOperationException("Can't build mesh with empty geometry");
            }

            InsertAllGameobjectGeometry(MapId);

            Context = new RecastContext();
            Context.SetContextHandler(Log);

            // get raw geometry - lots of slowness here
            float[] vertices;
            int[]   triangles;
            byte[]  areas;
            Geometry.GetRawData(out vertices, out triangles, out areas);
            Geometry.Triangles.Clear();

            float[] bmin, bmax;
            Geometry.CalculateBoundingBox(out bmin, out bmax);
            Geometry.Vertices.Clear();

            // Allocate voxel heightfield where we rasterize our input data to.
            Heightfield hf;
            int         width, height;

            Recast.CalcGridSize(bmin, bmax, Config.CellSize, out width, out height);
            if (!Context.CreateHeightfield(out hf, width, height, bmin, bmax, Config.CellSize, Config.CellHeight))
            {
                throw new OutOfMemoryException("CreateHeightfield ran out of memory");
            }

            CompleteWorkUnit();

            // Find triangles which are walkable based on their slope and rasterize them.
            Context.ClearUnwalkableTriangles(Config.WalkableSlopeAngle, ref vertices, ref triangles, areas);
            Context.RasterizeTriangles(ref vertices, ref triangles, ref areas, hf, Config.WalkableClimb);

            vertices  = null;
            triangles = null;
            areas     = null;
            GC.Collect();

            CompleteWorkUnit();

            // Once all geometry is rasterized, we do initial pass of filtering to
            // remove unwanted overhangs caused by the conservative rasterization
            // as well as filter spans where the character cannot possibly stand.
            Context.FilterLowHangingWalkableObstacles(Config.WalkableClimb, hf);
            Context.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb, hf);
            Context.FilterWalkableLowHeightSpans(Config.WalkableHeight, hf);

            CompleteWorkUnit();

            // Compact the heightfield so that it is faster to handle from now on.
            // This will result in more cache coherent data as well as the neighbours
            // between walkable cells will be calculated.
            CompactHeightfield chf;

            if (!Context.BuildCompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, hf, out chf))
            {
                throw new OutOfMemoryException("BuildCompactHeightfield ran out of memory");
            }

            CompleteWorkUnit();

            hf.Delete();

            // Erode the walkable area by agent radius.
            if (!Context.ErodeWalkableArea(Config.WalkableRadius, chf))
            {
                throw new OutOfMemoryException("ErodeWalkableArea ran out of memory");
            }
            CompleteWorkUnit();

            // Prepare for region partitioning, by calculating distance field along the walkable surface.
            if (!Context.BuildDistanceField(chf))
            {
                throw new OutOfMemoryException("BuildDistanceField ran out of memory");
            }
            CompleteWorkUnit();

            // Partition the walkable surface into simple regions without holes.
            if (!Context.BuildRegions(chf, Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea))
            {
                throw new OutOfMemoryException("BuildRegions ran out of memory");
            }
            CompleteWorkUnit();

            // Create contours.
            ContourSet cset;

            if (!Context.BuildContours(chf, Config.MaxSimplificationError, Config.MaxEdgeLength, out cset))
            {
                throw new OutOfMemoryException("BuildContours ran out of memory");
            }
            CompleteWorkUnit();

            // Build polygon navmesh from the contours.
            PolyMesh pmesh;

            if (!Context.BuildPolyMesh(cset, Config.MaxVertsPerPoly, out pmesh))
            {
                throw new OutOfMemoryException("BuildPolyMesh ran out of memory");
            }
            CompleteWorkUnit();

            // Build detail mesh.
            PolyMeshDetail dmesh = null;

            //if (!Context.BuildPolyMeshDetail(pmesh, chf, Config.DetailSampleDistance, Config.DetailSampleMaxError, out dmesh))
            //    throw new OutOfMemoryException("BuildPolyMeshDetail ran out of memory");
            chf.Delete();
            cset.Delete();

            CompleteWorkUnit();

            // Set flags according to area types (e.g. Swim for Water)
            pmesh.MarkAll();

            byte[] meshData;
            if (
                !Detour.CreateNavMeshData(out meshData, pmesh, dmesh, 0, 0, bmin, bmax, Config.WorldWalkableHeight, Config.WorldWalkableRadius, Config.WorldWalkableClimb, Config.CellSize, Config.CellHeight,
                                          Config.BuildBvTree, null))
            {
                pmesh.Delete();
                //dmesh.Delete();
                return(null);
            }

            CompleteWorkUnit();
            pmesh.Delete();
            //dmesh.Delete();
            File.Delete(GetDungeonLockAndPath());
            return(meshData);
        }
Exemple #23
0
 public static extern bool rcpdBuildFromMeshData([In] byte[] meshData
                                                 , int dataSize
                                                 , [In, Out] PolyMeshDetail detailMesh);
Exemple #24
0
 public static extern bool rcpdGetSerializedData(
     [In] PolyMeshDetail detailMesh
     , bool includeBuffer
     , ref IntPtr resultData
     , ref int dataSize);
Exemple #25
0
 public static extern bool rcpdFreeMeshData([In, Out] PolyMeshDetail detailMesh);