Esempio n. 1
0
        public byte[] Build()
        {
            var wdt = new WDT("World\\maps\\" + Dungeon + "\\" + Dungeon + ".wdt");

            if (!wdt.IsGlobalModel || !wdt.IsValid)
                return null;



            Geometry = new Geometry.Geometry {};
            var model = new WMORoot(wdt.ModelFile);
            Geometry.AddDungeon(model, wdt.ModelDefinition);



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

            Geometry.SaveWavefrontObject($"{Dungeon}.obj");
            Context = new RecastContext();

            // get raw geometry - lots of slowness here
            float[] vertices;
            int[] triangles;
            byte[] areas;
            Geometry.GetRawData(out vertices, out triangles, out areas);
            Geometry.Indices.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");

   

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

          

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

           

            // 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");

         

            hf.Delete();

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

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

            // 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");
          

            // Create contours.
            ContourSet cset;
            if (!Context.BuildContours(chf, Config.MaxSimplificationError, Config.MaxEdgeLength, out cset))
                throw new OutOfMemoryException("BuildContours ran out of memory");
         

            // Build polygon navmesh from the contours.
            PolyMesh pmesh;
            if (!Context.BuildPolyMesh(cset, Config.MaxVertsPerPoly, out pmesh))
                throw new OutOfMemoryException("BuildPolyMesh ran out of memory");
            

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

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

            // 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.TileWidth, null))
            {
                pmesh.Delete();
                dmesh.Delete();
                return null;
            }        
            pmesh.Delete();
            dmesh.Delete();
           

            if (Directory.Exists(Dungeon))
                Directory.Delete(Dungeon, true);
            Directory.CreateDirectory(Dungeon);
            
            if (meshData != null)
                File.WriteAllBytes(Dungeon + "\\" + Dungeon + ".dmesh", meshData);

            return meshData;
        }