Ejemplo n.º 1
0
        public virtual List <ChunkyTriMeshNode> getChunksOverlappingRect(float[] bmin, float[] bmax)
        {
            // Traverse tree
            List <ChunkyTriMeshNode> ids = new List <ChunkyTriMeshNode>();
            int i = 0;

            while (i < nodes.Count)
            {
                ChunkyTriMeshNode node = nodes[i];
                bool overlap           = checkOverlapRect(bmin, bmax, node.bmin, node.bmax);
                bool isLeafNode        = node.i >= 0;

                if (isLeafNode && overlap)
                {
                    ids.Add(node);
                }

                if (overlap || isLeafNode)
                {
                    i++;
                }
                else
                {
                    i = -node.i;
                }
            }
            return(ids);
        }
Ejemplo n.º 2
0
        private void subdivide(BoundsItem[] items, int imin, int imax, int trisPerChunk, List <ChunkyTriMeshNode> nodes, int[] inTris)
        {
            int inum = imax - imin;

            ChunkyTriMeshNode node = new ChunkyTriMeshNode();

            nodes.Add(node);

            if (inum <= trisPerChunk)
            {
                // Leaf
                calcExtends(items, imin, imax, node.bmin, node.bmax);

                // Copy triangles.
                node.i    = nodes.Count;
                node.tris = new int[inum * 3];

                int dst = 0;
                for (int i = imin; i < imax; ++i)
                {
                    int src = items[i].i * 3;
                    node.tris[dst++] = inTris[src];
                    node.tris[dst++] = inTris[src + 1];
                    node.tris[dst++] = inTris[src + 2];
                }
            }
            else
            {
                // Split
                calcExtends(items, imin, imax, node.bmin, node.bmax);

                int axis = longestAxis(node.bmax[0] - node.bmin[0], node.bmax[1] - node.bmin[1]);

                if (axis == 0)
                {
                    Array.Sort(items, imin, imax - imin, new CompareItemX());
                    // Sort along x-axis
                }
                else if (axis == 1)
                {
                    Array.Sort(items, imin, imax - imin, new CompareItemY());
                    // Sort along y-axis
                }

                int isplit = imin + inum / 2;

                // Left
                subdivide(items, imin, isplit, trisPerChunk, nodes, inTris);
                // Right
                subdivide(items, isplit, imax, trisPerChunk, nodes, inTris);

                // Negative index means escape.
                node.i = -nodes.Count;
            }
        }
Ejemplo n.º 3
0
    private LunaNav.NavMeshBuilder BuildTileMesh(int tx, int ty, RecastVertex min, RecastVertex max)
    {
        Config.Width        = Config.TileSize + Config.BorderSize * 2;
        Config.Height       = Config.TileSize + Config.BorderSize * 2;
        Config.MinBounds    = min;
        Config.MaxBounds    = max;
        Config.MinBounds.X -= Config.BorderSize * Config.CellSize;
        Config.MinBounds.Z -= Config.BorderSize * Config.CellSize;

        Config.MaxBounds.X += Config.BorderSize * Config.CellSize;
        Config.MaxBounds.Z += Config.BorderSize * Config.CellSize;

        HeightField heightfield = new HeightField(Config.Width, Config.Height, Config.MinBounds.ToArray(), Config.MaxBounds.ToArray(), Config.CellSize, Config.CellHeight);


        short[] triAreas = new short[Geometry.ChunkyTriMesh.MaxTrisPerChunk];

        float[] tbmin = new float[2], tbmax = new float[2];
        tbmin[0] = Config.MinBounds.X;
        tbmin[1] = Config.MinBounds.Z;

        tbmax[0] = Config.MaxBounds.X;
        tbmax[1] = Config.MaxBounds.Z;

        int[] cid = new int[512];

        int ncid = Geometry.ChunkyTriMesh.GetChunksOverlappingRect(tbmin, tbmax, ref cid, 512);

        if (ncid == 0)
        {
            return(null);
        }

        for (int i = 0; i < ncid; i++)
        {
            ChunkyTriMeshNode node = Geometry.ChunkyTriMesh.Nodes[cid[i]];
            int[]             tris = new int[node.n * 3];
            Array.Copy(Geometry.ChunkyTriMesh.Tris, node.i * 3, tris, 0, node.n * 3);
            List <int> ctris  = new List <int>(tris);
            int        nctris = node.n;

            Array.Clear(triAreas, 0, triAreas.Length);
            Geometry.MarkWalkableTriangles(Config.WalkableSlopeAngle, ctris, nctris, ref triAreas);

            heightfield.RasterizeTriangles(Geometry, ctris, nctris, triAreas, Config.WalkableClimb);
        }

        heightfield.FilterLowHangingWalkableObstacles(Config.WalkableClimb);
        heightfield.FilterLedgeSpans(Config.WalkableHeight, Config.WalkableClimb);
        heightfield.FilterWalkableLowHeightSpans(Config.WalkableHeight);


        CompactHeightfield compactHeightfield = new CompactHeightfield(Config.WalkableHeight, Config.WalkableClimb, heightfield);

        compactHeightfield.ErodeWalkableArea(Config.WalkableRadius);

        // optional convex volumes

        compactHeightfield.BuildDistanceField();
        compactHeightfield.BuildRegions(Config.BorderSize, Config.MinRegionArea, Config.MergeRegionArea);


        ContourSet contourSet = new ContourSet(compactHeightfield, Config.MaxSimplificationError, Config.MaxEdgeLength);

        if (contourSet.NConts == 0)
        {
            return(null);
        }

        PolyMesh polyMesh = new PolyMesh(contourSet, Config.MaxVertexesPerPoly);

        DetailPolyMesh detailPolyMesh = new DetailPolyMesh(polyMesh, compactHeightfield, Config.DetailSampleDistance,
                                                           Config.DetailSampleMaxError);

        // Convert the Areas and Flags for path weighting
        for (int i = 0; i < polyMesh.NPolys; i++)
        {
            if (polyMesh.Areas[i] == Geometry.WalkableArea)
            {
                polyMesh.Areas[i] = 0; // Sample_polyarea_ground
                polyMesh.Flags[i] = 1; // Samply_polyflags_walk
            }
        }
        NavMeshCreateParams param = new NavMeshCreateParams
        {
            Verts            = polyMesh.Verts,
            VertCount        = polyMesh.NVerts,
            Polys            = polyMesh.Polys,
            PolyAreas        = polyMesh.Areas,
            PolyFlags        = polyMesh.Flags,
            PolyCount        = polyMesh.NPolys,
            Nvp              = polyMesh.Nvp,
            DetailMeshes     = detailPolyMesh.Meshes,
            DetailVerts      = detailPolyMesh.Verts,
            DetailVertsCount = detailPolyMesh.NVerts,
            DetailTris       = detailPolyMesh.Tris,
            DetailTriCount   = detailPolyMesh.NTris,

            // Off Mesh data
            OffMeshConVerts  = Geometry.OffMeshConnectionVerts.ToArray(),
            OffMeshConRad    = Geometry.OffMeshConnectionRadii.ToArray(),
            OffMeshConDir    = Geometry.OffMeshConnectionDirections.ToArray(),
            OffMeshConAreas  = Geometry.OffMeshConnectionAreas.ToArray(),
            OffMeshConFlags  = Geometry.OffMeshConnectionFlags.ToArray(),
            OffMeshConUserId = Geometry.OffMeshConnectionIds.ToArray(),
            OffMeshConCount  = (int)Geometry.OffMeshConnectionCount,
            // end off mesh data

            WalkableHeight = Config.WalkableHeight,
            WalkableRadius = Config.WalkableRadius,
            WalkableClimb  = Config.WalkableClimb,
            BMin           = new float[] { polyMesh.BMin[0], polyMesh.BMin[1], polyMesh.BMin[2] },
            BMax           = new float[] { polyMesh.BMax[0], polyMesh.BMax[1], polyMesh.BMax[2] },
            Cs             = polyMesh.Cs,
            Ch             = polyMesh.Ch,
            BuildBvTree    = true,
            TileX          = tx,
            TileY          = ty,
            TileLayer      = 0
        };

        return(new LunaNav.NavMeshBuilder(param));
    }