public void Process(ref NavMeshCreateParams param, NavMeshTileBuildContext bc)
        {
            // Update poly flags from areas.
            for (int i = 0; i < param.polyCount; ++i)
            {
                if ((int)bc.LMesh.Areas[i] == (int)TileCacheAreas.RC_WALKABLE_AREA)
                {
                    bc.LMesh.Areas[i] = SamplePolyAreas.SAMPLE_POLYAREA_GROUND;
                }

                if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_GROUND ||
                    bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_GRASS ||
                    bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_ROAD)
                {
                    bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_WALK;
                }
                else if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_WATER)
                {
                    bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_SWIM;
                }
                else if (bc.LMesh.Areas[i] == SamplePolyAreas.SAMPLE_POLYAREA_DOOR)
                {
                    bc.LMesh.Flags[i] = SamplePolyFlagTypes.SAMPLE_POLYFLAGS_WALK | SamplePolyFlagTypes.SAMPLE_POLYFLAGS_DOOR;
                }
            }

            // Pass in off-mesh connections.
            if (m_geom != null)
            {
                param.offMeshCon      = m_geom.GetConnections().ToArray();
                param.offMeshConCount = m_geom.GetConnectionCount();
            }
        }
Пример #2
0
        public bool BuildNavMeshTile(CompressedTile tile, NavMesh navmesh)
        {
            NavMeshTileBuildContext bc = new NavMeshTileBuildContext();
            int walkableClimbVx        = (int)(m_params.WalkableClimb / m_params.CellHeight);

            // Decompress tile layer data.
            if (!DetourTileCache.DecompressTileCacheLayer(tile.Header, tile.Data, 0, out var layer))
            {
                return(false);
            }
            bc.Layer = layer;

            // Rasterize obstacles.
            for (int i = 0; i < m_params.MaxObstacles; ++i)
            {
                var ob = m_obstacles[i];

                if (ob.State == ObstacleState.DT_OBSTACLE_EMPTY || ob.State == ObstacleState.DT_OBSTACLE_REMOVING)
                {
                    continue;
                }

                if (DetourTileCache.Contains(ob.Touched, ob.NTouched, tile))
                {
                    if (ob.Type == ObstacleType.DT_OBSTACLE_CYLINDER)
                    {
                        DetourTileCache.MarkCylinderArea(bc,
                                                         tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                         ob.Cylinder.Pos, ob.Cylinder.Radius, ob.Cylinder.Height, 0);
                    }
                    else if (ob.Type == ObstacleType.DT_OBSTACLE_BOX)
                    {
                        DetourTileCache.MarkBoxArea(bc,
                                                    tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                    ob.Box.BMin, ob.Box.BMax, 0);
                    }
                    else if (ob.Type == ObstacleType.DT_OBSTACLE_ORIENTED_BOX)
                    {
                        DetourTileCache.MarkBoxArea(bc,
                                                    tile.Header.BBox.Minimum, m_params.CellSize, m_params.CellHeight,
                                                    ob.OrientedBox.Center, ob.OrientedBox.HalfExtents, ob.OrientedBox.RotAux, 0);
                    }
                }
            }

            // Build navmesh
            if (!DetourTileCache.BuildTileCacheRegions(bc, walkableClimbVx))
            {
                return(false);
            }

            if (!DetourTileCache.BuildTileCacheContours(bc, walkableClimbVx, m_params.MaxSimplificationError))
            {
                return(false);
            }

            if (!DetourTileCache.BuildTileCachePolyMesh(bc))
            {
                return(false);
            }

            // Early out if the mesh tile is empty.
            if (bc.LMesh.NPolys == 0)
            {
                // Remove existing tile.
                navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0);
                return(true);
            }

            var param = new NavMeshCreateParams
            {
                Verts          = bc.LMesh.Verts,
                VertCount      = bc.LMesh.NVerts,
                Polys          = bc.LMesh.Polys,
                PolyAreas      = bc.LMesh.Areas,
                PolyFlags      = bc.LMesh.Flags,
                polyCount      = bc.LMesh.NPolys,
                nvp            = Detour.DT_VERTS_PER_POLYGON,
                walkableHeight = m_params.WalkableHeight,
                walkableRadius = m_params.WalkableRadius,
                walkableClimb  = m_params.WalkableClimb,
                tileX          = tile.Header.TX,
                tileY          = tile.Header.TY,
                tileLayer      = tile.Header.TLayer,
                cs             = m_params.CellSize,
                ch             = m_params.CellHeight,
                buildBvTree    = false,
                bmin           = tile.Header.BBox.Minimum,
                bmax           = tile.Header.BBox.Maximum,
            };

            if (m_tmproc != null)
            {
                m_tmproc.Process(ref param, bc);
            }

            if (!Detour.CreateNavMeshData(param, out MeshData navData))
            {
                return(false);
            }

            // Remove existing tile.
            navmesh.RemoveTile(navmesh.GetTileRefAt(tile.Header.TX, tile.Header.TY, tile.Header.TLayer), null, 0);

            // Add new tile, or leave the location empty.
            if (navData != null && !navmesh.AddTile(navData, TileFlagTypes.DT_TILE_FREE_DATA, 0, out int result))
            {
                // Let the navmesh own the data.
                navData = null;

                return(false);
            }

            return(true);
        }