Exemplo n.º 1
0
    /// <summary>
    /// Generates a human readable report of the mesh data.
    /// </summary>
    /// <returns>A human readable report of the mesh data.</returns>
    public string GetMeshReport()
    {
        if (!HasNavmesh)
        {
            return("No mesh.");
        }

        Navmesh nm = GetNavmesh();

        NavmeshParams nmconfig = nm.GetConfig();

        System.Text.StringBuilder sb = new System.Text.StringBuilder();

        sb.AppendLine("Navigation mesh report for " + name);

        if (mBuildInfo != null)
        {
            sb.AppendLine("Built from scene: " + mBuildInfo.inputScene);
        }

        sb.AppendLine(string.Format("Tiles: {0}, Tile Size: {1:F3}x{2:F3}, Max Polys Per Tile: {3}"
                                    , nmconfig.maxTiles, nmconfig.tileWidth, nmconfig.tileDepth, nmconfig.maxPolysPerTile));

        int polyCount = 0;
        int vertCount = 0;
        int connCount = 0;

        for (int i = 0; i < nmconfig.maxTiles; i++)
        {
            NavmeshTileHeader header = nm.GetTile(i).GetHeader();

            if (header.polyCount == 0)
            {
                continue;
            }

            sb.AppendLine(string.Format(
                              "Tile ({0},{1}): Polygons: {2}, Vertices: {3}, Off-mesh Connections: {4}"
                              , header.tileX, header.tileZ
                              , header.polyCount, header.vertCount
                              , header.connCount));

            polyCount += header.polyCount;
            vertCount += header.vertCount;
            connCount += header.connCount;
        }

        sb.AppendLine(string.Format(
                          "Totals: Polygons: {0}, Vertices: {1}, Off-mesh Connections: {2}"
                          , polyCount, vertCount, connCount));

        return(sb.ToString());
    }
Exemplo n.º 2
0
    private void SetConfigFromTargetIntern(Navmesh navmesh)
    {
        NavmeshBuildInfo targetConfig = BuildTarget.BuildInfo;
        NMGenParams      currConfig   = mConfig.GetConfig();

        // Note: Must ensure exact match with original configuration.
        // So this process is using the fields and trusting the
        // original configuration to have valid values.

        currConfig.tileSize       = targetConfig.tileSize;
        currConfig.walkableHeight = targetConfig.walkableHeight;
        currConfig.walkableRadius = targetConfig.walkableRadius;
        currConfig.walkableStep   = targetConfig.walkableStep;
        currConfig.xzCellSize     = targetConfig.xzCellSize;
        currConfig.yCellSize      = targetConfig.yCellSize;
        currConfig.borderSize     = targetConfig.borderSize;

        mBoundsMin = navmesh.GetConfig().origin;

        int maxTiles = navmesh.GetMaxTiles();

        // Make sure the maximum bounds fits the target mesh.
        // Note: Will not shrink the existing max bounds.
        for (int i = 0; i < maxTiles; i++)
        {
            NavmeshTile tile = navmesh.GetTile(i);

            if (tile == null)
            {
                continue;
            }

            NavmeshTileHeader tileHeader = tile.GetHeader();

            if (tileHeader.polyCount == 0)
            {
                continue;
            }

            mBoundsMax = Vector3.Max(mBoundsMax, tileHeader.boundsMax);
        }

        mConfig.SetConfig(currConfig);

        mIsDirty = true;
    }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the centroids for the polygons that are part of the tile.
        /// </summary>
        private static int GetCentroids(NavmeshTile tile
                                        , uint[] polyRefs
                                        , int polyCount
                                        , UnityEngine.Vector3[] centroids)
        {
            NavmeshTileHeader header = tile.GetHeader();

            if (header.polyCount < 1)
            {
                return(0);
            }

            uint polyBase = tile.GetBasePolyRef();

            NavmeshPoly[] polys = new NavmeshPoly[header.polyCount];
            tile.GetPolys(polys);

            Vector3[] verts = new Vector3[header.vertCount];
            tile.GetVerts(verts);
            UnityEngine.Vector3[] vverts = VectorHelper.ToUnityVector3Array(ref verts);


            int resultCount = 0;

            for (int i = 0; i < header.polyCount; i++)
            {
                uint polyRef = polyBase | ( uint )i;

                int iResult = IsInList(polyRef, polyRefs, polyCount);

                if (iResult == -1)
                {
                    continue;
                }

                resultCount++;

                NavmeshPoly poly = polys[i];

                centroids[iResult] = GetCentroid(vverts, poly.indices, poly.vertCount);
            }

            return(resultCount);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Draws the polygon boundary lines based on the height detail.
        /// </summary>
        private static void DrawPolyBoundaries(NavmeshTileHeader header
                                               , NavmeshPoly[] polys
                                               , Vector3[] verts
                                               , NavmeshDetailMesh[] meshes
                                               , byte[] detailTris
                                               , Vector3[] detailVerts
                                               , NavmeshLink[] links
                                               , Color color
                                               , bool inner)
        {
            const float thr = 0.01f * 0.01f;

            for (int i = 0; i < header.polyCount; i++)
            {
                NavmeshPoly poly = polys[i];

                if (poly.Type == NavmeshPolyType.OffMeshConnection)
                {
                    continue;
                }

                NavmeshDetailMesh mesh = meshes[i];
                Vector3[]         tv   = new Vector3[3];

                for (int j = 0, nj = (int)poly.vertCount; j < nj; j++)
                {
                    Color c = color;  // Color may change.
                    if (inner)
                    {
                        if (poly.neighborPolyRefs[j] == 0)
                        {
                            continue;
                        }
                        if ((poly.neighborPolyRefs[j]
                             & Navmesh.ExternalLink) != 0)
                        {
                            bool con = false;
                            for (uint k = poly.firstLink
                                 ; k != Navmesh.NullLink
                                 ; k = links[k].next)
                            {
                                if (links[k].edge == j)
                                {
                                    con = true;
                                    break;
                                }
                            }
                            if (con)
                            {
                                c = new Color(1, 1, 1, 0.2f);
                            }
                            else
                            {
                                c = new Color(0, 0, 0, 0.2f);
                            }
                        }
                        else
                        {
                            c = new Color(0, 0.2f, 0.25f, 0.13f);
                        }
                    }
                    else
                    {
                        if (poly.neighborPolyRefs[j] != 0)
                        {
                            continue;
                        }
                    }

                    GL.Color(c);

                    int pVertA = poly.indices[j];
                    int pVertB = poly.indices[(j + 1) % nj];

                    for (int k = 0; k < mesh.triCount; k++)
                    {
                        int pTri = (int)((mesh.triBase + k) * 4);
                        for (int m = 0; m < 3; m++)
                        {
                            int iVert = detailTris[pTri + m];
                            if (iVert < poly.vertCount)
                            {
                                int pv = poly.indices[iVert];
                                tv[m] = verts[pv];
                            }
                            else
                            {
                                int pv = (int)(mesh.vertBase
                                               + (iVert - poly.vertCount));
                                tv[m] = detailVerts[pv];
                            }
                        }
                        for (int m = 0, n = 2; m < 3; n = m++)
                        {
                            if (((detailTris[pTri + 3] >> (n * 2)) & 0x3) == 0)
                            {
                                // Skip inner detail edges.
                                continue;
                            }

                            float distN = Line2.GetPointLineDistanceSq(
                                new Vector2(tv[n].x, tv[n].z)
                                , new Vector2(verts[pVertA].x, verts[pVertA].z)
                                , new Vector2(verts[pVertB].x, verts[pVertB].z));
                            float distM = Line2.GetPointLineDistanceSq(
                                new Vector2(tv[m].x, tv[m].z)
                                , new Vector2(verts[pVertA].x, verts[pVertA].z)
                                , new Vector2(verts[pVertB].x, verts[pVertB].z));

                            if (distN < thr && distM < thr)
                            {
                                GL.Vertex(tv[n]);
                                GL.Vertex(tv[m]);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Draws a debug visualization of an individual navmesh tile.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The tile will be checked to see if it is in use before it is drawn.  So there is no
        /// need for caller to do so.
        /// </para>
        /// </remarks>
        private static void Draw(NavmeshTile tile
                                 , NavmeshQuery query, uint[] markPolys, int markPolyCount
                                 , int colorId)
        {
            NavmeshTileHeader header = tile.GetHeader();

            // Keep this check.  Less trouble for clients.
            if (header.polyCount < 1)
            {
                return;
            }

            DebugDraw.SimpleMaterial.SetPass(0);

            uint polyBase = tile.GetBasePolyRef();

            NavmeshPoly[] polys = new NavmeshPoly[header.polyCount];
            tile.GetPolys(polys);

            Vector3[] verts = new Vector3[header.vertCount];
            tile.GetVerts(verts);

            NavmeshDetailMesh[] meshes =
                new NavmeshDetailMesh[header.detailMeshCount];
            tile.GetDetailMeshes(meshes);

            byte[] detailTris = new byte[header.detailTriCount * 4];
            tile.GetDetailTris(detailTris);

            Vector3[] detailVerts = new Vector3[header.detailVertCount];
            tile.GetDetailVerts(detailVerts);

            GL.Begin(GL.TRIANGLES);
            for (int i = 0; i < header.polyCount; i++)
            {
                NavmeshPoly poly = polys[i];

                if (poly.Type == NavmeshPolyType.OffMeshConnection)
                {
                    continue;
                }

                NavmeshDetailMesh mesh = meshes[i];

                Color color = GetStandardColor(polyBase | (uint)i
                                               , poly.Area, colorId
                                               , query, markPolys, markPolyCount);

                GL.Color(color);

                for (int j = 0; j < mesh.triCount; j++)
                {
                    int pTri = (int)(mesh.triBase + j) * 4;

                    for (int k = 0; k < 3; k++)
                    {
                        // Note: iVert and pVert refer to different
                        // arrays.
                        int iVert = detailTris[pTri + k];
                        if (iVert < poly.vertCount)
                        {
                            // Get the vertex from the main vertices.
                            int pVert = poly.indices[iVert];
                            GL.Vertex(verts[pVert]);
                        }
                        else
                        {
                            // Get the vertex from the detail vertices.
                            int pVert = (int)
                                        (mesh.vertBase + iVert - poly.vertCount);
                            GL.Vertex(detailVerts[pVert]);
                        }
                    }
                }
            }
            GL.End();

            NavmeshLink[] links = new NavmeshLink[header.maxLinkCount];
            tile.GetLinks(links);

            GL.Begin(GL.LINES);

            DrawPolyBoundaries(header
                               , polys
                               , verts
                               , meshes
                               , detailTris
                               , detailVerts
                               , links
                               , new Color(0, 0.2f, 0.25f, 0.13f)
                               , true);

            DrawPolyBoundaries(header
                               , polys
                               , verts
                               , meshes
                               , detailTris
                               , detailVerts
                               , links
                               , new Color(0.65f, 0.2f, 0, 0.9f)
                               , false);

            if (header.connCount == 0)
            {
                GL.End();
                return;
            }

            NavmeshConnection[] conns = new NavmeshConnection[header.connCount];
            tile.GetConnections(conns);

            for (int i = 0; i < header.polyCount; i++)
            {
                NavmeshPoly poly = polys[i];

                if (poly.Type != NavmeshPolyType.OffMeshConnection)
                {
                    continue;
                }

                Color color = GetStandardColor(polyBase | (uint)i
                                               , poly.Area, colorId
                                               , query, markPolys, markPolyCount);

                // Note: Alpha of less than one doesn't look good because connections tend to
                // overlay a lot of geometry, resulting is off color transitions.
                color.a = 1;

                GL.Color(color);

                NavmeshConnection conn = conns[i - header.connBase];

                Vector3 va = verts[poly.indices[0]];
                Vector3 vb = verts[poly.indices[1]];

                // Check to see if start and end end-points have links.
                bool startSet = false;
                bool endSet   = false;
                for (uint k = poly.firstLink; k != Navmesh.NullLink; k = links[k].next)
                {
                    if (links[k].edge == 0)
                    {
                        startSet = true;
                    }
                    if (links[k].edge == 1)
                    {
                        endSet = true;
                    }
                }

                // For linked endpoints: Draw a line between on-mesh location and endpoint,
                // and draw circle at the endpoint.
                // For un-linked endpoints: Draw a small red x-marker.

                if (startSet)
                {
                    GL.Vertex(va);
                    GL.Vertex(conn.endpoints[0]);
                    DebugDraw.AppendCircle(conn.endpoints[0], conn.radius);
                }
                else
                {
                    GL.Color(Color.red);
                    DebugDraw.AppendXMarker(conn.endpoints[0], 0.1f);
                    GL.Color(color);
                }

                if (endSet)
                {
                    GL.Vertex(vb);
                    GL.Vertex(conn.endpoints[1]);
                    DebugDraw.AppendCircle(conn.endpoints[1], conn.radius);
                }
                else
                {
                    GL.Color(Color.red);
                    DebugDraw.AppendXMarker(conn.endpoints[1], 0.1f);
                    GL.Color(color);
                }

                DebugDraw.AppendArc(conn.endpoints[0], conn.endpoints[1]
                                    , 0.25f
                                    , conn.IsBiDirectional ? 0.6f : 0
                                    , 0.6f);
            }

            GL.End();
        }
Exemplo n.º 6
0
        /// <summary>
        /// Draws a debug visualization of a corridor.
        /// </summary>
        /// <param name="mesh">The navigation mesh associated with the corridor.</param>
        /// <param name="corridor">The corridor to draw.</param>
        public static void Draw(Navmesh mesh, PathCorridorData corridor)
        {
            if (corridor.pathCount == 0)
            {
                return;
            }

            DebugDraw.SimpleMaterial.SetPass(0);

            Vector3[] tileVerts = null;

            for (int iPoly = 0; iPoly < corridor.pathCount; iPoly++)
            {
                NavmeshTile tile;
                NavmeshPoly poly;
                mesh.GetTileAndPoly(corridor.path[iPoly], out tile, out poly);

                if (poly.Type == NavmeshPolyType.OffMeshConnection)
                {
                    continue;
                }

                NavmeshTileHeader header = tile.GetHeader();
                if (tileVerts == null ||
                    tileVerts.Length < 3 * header.vertCount)
                {
                    // Resize.
                    tileVerts = new Vector3[header.vertCount];
                }

                tile.GetVerts(tileVerts);

                GL.Begin(GL.TRIANGLES);
                GL.Color(polygonOverlayColor);

                int pA = poly.indices[0];
                for (int i = 2; i < poly.vertCount; i++)
                {
                    int pB = poly.indices[i - 1];
                    int pC = poly.indices[i];

                    GL.Vertex(tileVerts[pA]);
                    GL.Vertex(tileVerts[pB]);
                    GL.Vertex(tileVerts[pC]);
                }

                GL.End();

                // Not drawing boundaries since it would obscure other agent
                // debug data.
            }

            Vector3 v = corridor.position;

            DebugDraw.XMarker(v, positionScale, positionColor);
            DebugDraw.Circle(v, positionScale, positionColor);
            DebugDraw.Circle(v, positionScale * 0.5f, positionColor);
            DebugDraw.Circle(v, positionScale * 0.25f, positionColor);

            v = corridor.target;
            DebugDraw.XMarker(v, goalScale, goalColor);
            DebugDraw.Circle(v, goalScale, goalColor);
            DebugDraw.Circle(v, goalScale * 0.5f, goalColor);
            DebugDraw.Circle(v, goalScale * 0.25f, goalColor);
        }
Exemplo n.º 7
0
    internal bool CanLoadFromTarget(BuildContext context, bool fullCheck)
    {
        INavmeshData target = BuildTarget;

        if (target == null || !target.HasNavmesh)
        {
            if (context != null)
            {
                context.LogError("Build target does not have an existing navigation mesh.", this);
            }
            return(false);
        }

        NavmeshBuildInfo targetConfig = target.BuildInfo;

        // Note: The tile size is checked since the original builder
        // may have supported a tile size not supported by the the standard build.
        if (targetConfig == null ||
            targetConfig.tileSize >= 0 && targetConfig.tileSize < MinAllowedTileSize)
        {
            if (context != null)
            {
                context.LogError("Unavailable or unsupported build target configuration.", this);
            }
            return(false);
        }

        if (!fullCheck)
        {
            return(true);
        }

        Navmesh nm = target.GetNavmesh();

        if (nm == null)
        {
            if (context != null)
            {
                context.LogError(
                    "Build target does not have an existing navigation mesh. (It lied.)", this);
            }
            return(false);
        }

        NavmeshParams nmConfig = nm.GetConfig();

        if (nmConfig.maxTiles < 2)
        {
            if (context != null)
            {
                context.LogError("Target navigation mesh is not tiled.", this);
            }
            return(false);
        }

        int tileCount = 0;

        for (int i = 0; i < nmConfig.maxTiles; i++)
        {
            NavmeshTile tile = nm.GetTile(i);

            if (tile == null)
            {
                continue;
            }

            NavmeshTileHeader header = tile.GetHeader();

            if (header.polyCount == 0)
            {
                continue;
            }

            tileCount++;

            if (header.layer > 0)
            {
                if (context != null)
                {
                    context.LogError(
                        "Target navigation mesh contains layered tiles. (Not supported.)", this);
                }
                return(false);
            }
        }

        if (tileCount < 2)
        {
            if (context != null)
            {
                context.LogError(
                    "Target navigation mesh is either not tiled or has no tiles loaded.", this);
            }
            return(false);
        }

        return(true);
    }
Exemplo n.º 8
0
 public static extern NavStatus dtnmGetTileDataHeaderAlt(IntPtr rawData
     , int dataSize
     , ref NavmeshTileHeader resultHeader);
Exemplo n.º 9
0
 public static extern NavStatus dtnmGetTileDataHeader([In] byte[] rawData
     , int dataSize
     , ref NavmeshTileHeader resultHeader);
Exemplo n.º 10
0
 public static extern NavStatus dtnmGetTileDataHeaderAlt(IntPtr rawData
                                                         , int dataSize
                                                         , ref NavmeshTileHeader resultHeader);
Exemplo n.º 11
0
 public static extern NavStatus dtnmGetTileDataHeader([In] byte[] rawData
                                                      , int dataSize
                                                      , ref NavmeshTileHeader resultHeader);
Exemplo n.º 12
0
        /// <summary>
        /// Draws the polygon boundary lines based on the height detail.
        /// </summary>
        private static void DrawPolyBoundaries(NavmeshTileHeader header
            , NavmeshPoly[] polys
            , Vector3[] verts
            , NavmeshDetailMesh[] meshes
            , byte[] detailTris
            , Vector3[] detailVerts
            , NavmeshLink[] links
            , Color color
            , bool inner)
        {
            const float thr = 0.01f * 0.01f;

            for (int i = 0; i < header.polyCount; i++)
            {
                NavmeshPoly poly = polys[i];

                if (poly.Type == NavmeshPolyType.OffMeshConnection)
                    continue;

                NavmeshDetailMesh mesh = meshes[i];
                Vector3[] tv = new Vector3[3];

                for (int j = 0, nj = (int)poly.vertCount; j < nj; j++)
                {
                    Color c = color;  // Color may change.
                    if (inner)
                    {
                        if (poly.neighborPolyRefs[j] == 0)
                            continue;
                        if ((poly.neighborPolyRefs[j]
                            & Navmesh.ExternalLink) != 0)
                        {
                            bool con = false;
                            for (uint k = poly.firstLink
                                ; k != Navmesh.NullLink
                                ; k = links[k].next)
                            {
                                if (links[k].edge == j)
                                {
                                    con = true;
                                    break;
                                }
                            }
                            if (con)
                                c = new Color(1, 1, 1, 0.2f);
                            else
                                c = new Color(0, 0, 0, 0.2f);
                        }
                        else
                            c = new Color(0, 0.2f, 0.25f, 0.13f);
                    }
                    else
                    {
                        if (poly.neighborPolyRefs[j] != 0)
                            continue;
                    }

                    GL.Color(c);

                    int pVertA = poly.indices[j];
                    int pVertB = poly.indices[(j + 1) % nj];

                    for (int k = 0; k < mesh.triCount; k++)
                    {
                        int pTri = (int)((mesh.triBase + k) * 4);
                        for (int m = 0; m < 3; m++)
                        {
                            int iVert = detailTris[pTri + m];
                            if (iVert < poly.vertCount)
                            {
                                int pv = poly.indices[iVert];
                                tv[m] = verts[pv];
                            }
                            else
                            {
                                int pv = (int)(mesh.vertBase 
                                    + (iVert - poly.vertCount));
                                tv[m] = detailVerts[pv];
                            }
                        }
                        for (int m = 0, n = 2; m < 3; n = m++)
                        {
                            if (((detailTris[pTri + 3] >> (n * 2)) & 0x3) == 0)
                                // Skip inner detail edges.
                                continue;

                            float distN = Line2.GetPointLineDistanceSq(
                                new Vector2(tv[n].x, tv[n].z)
                                , new Vector2(verts[pVertA].x, verts[pVertA].z)
                                , new Vector2(verts[pVertB].x, verts[pVertB].z));
                            float distM = Line2.GetPointLineDistanceSq(
                                new Vector2(tv[m].x, tv[m].z)
                                , new Vector2(verts[pVertA].x, verts[pVertA].z)
                                , new Vector2(verts[pVertB].x, verts[pVertB].z));

                            if (distN < thr && distM < thr)
                            {
                                GL.Vertex(tv[n]);
                                GL.Vertex(tv[m]);
                            }
                        }
                    }
                }
            }
        }