Exemplo n.º 1
0
        /// <summary>
        /// Gets the result of the completed task.
        /// </summary>
        /// <param name="result">The result of the completed task.</param>
        /// <returns>True if the result is available, false if the task should abort with no
        /// result. (I.e. An internal abort.)</returns>
        protected override bool GetResult(out TileBuildAssets result)
        {
            BuildContext logger = new BuildContext();

            result = new TileBuildAssets();

            NavmeshTileBuildData tbd =
                NMBuild.GetBuildData(logger, mTileX, mTileZ
                                     , mPolyData, (mDetailData == null ? null : mDetailData), mConnections
                                     , mBVTreeEnabled);

            AddMessages(logger.GetMessages());

            if (tbd == null)
            {
                return(false);
            }

            NavmeshTileData td = NavmeshTileData.Create(tbd);

            if (td.Size == 0)
            {
                AddMessage(string.Format(
                               "Could not create {2} object. Cause unknown."
                               + " Tile: ({0},{1})"
                               , mTileX, mTileZ, td.GetType().Name));

                return(false);
            }

            result = new TileBuildAssets(mTileX, mTileZ, td, tbd.PolyCount);

            return(true);
        }
Exemplo n.º 2
0
    /// <summary>
    /// Loads a single-tile navigation mesh from the provided data.
    /// </summary>
    /// <param name="buildData">The tile build data.</param>
    /// <param name="buildConfig">The build information. (Optional)</param>
    /// <returns>The <see cref="NavStatus"/> flags for the operation.</returns>
    public NavStatus Load(NavmeshTileBuildData buildData, NavmeshBuildInfo buildConfig)
    {
        if (buildData == null || buildData.IsDisposed)
        {
            return(NavStatus.Failure | NavStatus.InvalidParam);
        }

        Navmesh   navmesh;
        NavStatus status = Navmesh.Create(buildData, out navmesh);

        if ((status & NavStatus.Sucess) == 0)
        {
            return(status);
        }

        mDataPack = navmesh.GetSerializedMesh();

        if (mDataPack == null)
        {
            return(NavStatus.Failure);
        }

        mBuildInfo = buildConfig;

        mVersion++;

        return(NavStatus.Sucess);
    }
Exemplo n.º 3
0
        private bool BuildSingleTile()
        {
            TileBuildData tdata  = mBuild.BuildData;
            NMGenConfig   config = mBuild.Config;
            InputGeometry geom   = mBuild.InputGeom;

            mContext.ResetLog();

            /*
             * Design note:
             *
             * Not using the build task since it doesn't provide enough progress
             * feedback for a single tile.
             *
             */

            // Create the NMGen builder.

            IncrementalBuilder builder = IncrementalBuilder.Create(config.GetConfig()
                                                                   , config.ResultOptions
                                                                   , geom
                                                                   , mBuild.NMGenProcessors);

            if (builder == null)
            {
                mContext.PostError("Unexpected failure creating NMGen builder.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }
            else if (builder.IsFinished)
            {
                if (builder.State == NMGenState.NoResult)
                {
                    mContext.PostError("NMGen build did not produce a result. (Early exit.)"
                                       , builder.GetMessages(), mBuild);
                    tdata.SetAsFailed(0, 0);
                    return(false);
                }
                else
                {
                    mContext.PostError("Unexpected NMGen builder completion."
                                       , builder.GetMessages(), mBuild);
                    tdata.SetAsFailed(0, 0);
                    return(false);
                }
            }

            mBuild.BuildData.SetAsInProgress(0, 0);

            // Run the NMGen builder.

            while (!builder.IsFinished)
            {
                if (EditorUtility.DisplayCancelableProgressBar("Build Single Tile Mesh"
                                                               , IncrementalBuilder.ToLabel(builder.State)
                                                               , IncrementalBuilder.ToProgress(builder.State)))
                {
                    return(false);
                }

                builder.Build();
            }

            // Handle NMGen failures.

            mContext.Log(builder.GetMessages());   // Single tile build.  So go ahead an record.

            switch (builder.State)
            {
            case NMGenState.Aborted:

                mContext.PostError("NMGen build failed.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);

            case NMGenState.NoResult:

                mContext.PostError("NMGen build did not produce a result.", mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            mContext.Log(string.Format("Completed NMGen build: {0} polygons."
                                       , builder.Result.PolyMesh.PolyCount)
                         , mBuild);

            // Build the tile.

            NMGenAssets result = builder.Result;

            if (result.DetailMesh == null)
            {
                Debug.LogError("result.DetailMesh ==null!");
            }

            NavmeshTileBuildData tbd = org.critterai.nmbuild.NMBuild.GetBuildData(
                mContext, 0, 0
                , result.PolyMesh.GetData(false), result.DetailMesh.GetData(false)
                , mBuild.Connections
                , (config.BuildFlags & NMGenBuildFlag.BVTreeEnabled) != 0);

            if (tbd == null)
            {
                // No need to log the error.  The above method takes care of that.
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            NavmeshTileData td = NavmeshTileData.Create(tbd);

            if (td.Size == 0)
            {
                mContext.PostError(
                    "Could not create {0} object. Cause unknown." + typeof(NavmeshTileData)
                    , mBuild);
                tdata.SetAsFailed(0, 0);
                return(false);
            }

            // Finalize the tile.

            tdata.SetWorkingData(0, 0, result.PolyMesh, result.DetailMesh);
            tdata.SetWorkingData(0, 0, td, tbd.PolyCount);

            mContext.PostTrace("Completed single tile build.", mBuild);

            return(true);
        }
Exemplo n.º 4
0
    private static Navmesh GenerateNavmesh()
    {
        #region Generate Neighboring polygon data

        //Then generate neighboring polygon data, by parsing the face list
        MyVector3 <bool> sharedVertex;          //For the current face, what vertices are shared with the other face?
        int sharedVertices;                     //if goes to 2, edge is shared

        for (ushort q = 0; q < faces.Count; q++)
        {
            //Index of face and neighborPoly refer to the same polygon.
            neighborPolys.Add(new MyVector3 <ushort>());
            neighborPolys[q].x = Navmesh.NullIndex;
            neighborPolys[q].y = Navmesh.NullIndex;
            neighborPolys[q].z = Navmesh.NullIndex;

            //Compare this face with every other face
            for (ushort w = 0; w < faces.Count; w++)
            {
                if (w != q)
                {
                    sharedVertices = 0;
                    sharedVertex   = new MyVector3 <bool>();

                    //Go from left to right in the face MyVector3
                    for (int j = 0; j <= 2; j++)
                    {
                        //And compare each index with every other index
                        for (int k = 0; k <= 2; k++)
                        {
                            if (faces[q][j] == faces[w][k])
                            {
                                //If we find a matching index, update stuff (only for the current face, dont bother with other face, can optimise but will be confusing)
                                sharedVertices++;
                                sharedVertex[j] = true;                                 //could break out of the for loop now, as face will not list the same index twice
                            }
                        }
                    }
                    if (sharedVertices > 2)
                    {
                        ReportError("error: more than 2 vertices shared between polys " + q + " and " + w);
                    }

                    //Check if these faces are sharing an edge
                    if (sharedVertices == 2)
                    {
                        //get the Leftmost Right-To-Left Pair in the neighborPolys MyVector3
                        //options are: edge 0-1, 1-2, and 2-0, respectively indexing neighboringPolys. (i.e. if index 1 of neighboring polys is 45, that means that the current polygon and polygon 45 share the edge face[1] <-> face[2]
                        if (sharedVertex[0] == true)
                        {
                            if (sharedVertex[1] == true)
                            {
                                neighborPolys[q][0] = w;                                        //I.e. tell this face's MyVector3 of neighboring polygons that the edge made up by vertices at 0 and 1 is shared between polygon q and w
                            }
                            else
                            {
                                neighborPolys[q][2] = w;
                            }
                        }
                        else
                        {
                            neighborPolys[q][1] = w;
                        }
                    }
                } //End iterating through other faces
            }
        }         //End iterating through each face
        #endregion

        //Now, Load these into Critter AI and create a navmesh
        navData = new NavmeshTileBuildData(maxPolyVerts, maxPolys, maxVertsPerPoly, 0, 0, 0);

        #region LoadBase
        //Get the min and max bounds from the vertex positions
        float lowest;
        float highest;

        //Find the bounds of the mesh. iterate through the x, y and z axes
        for (int axis = 0; axis <= 2; axis++)
        {
            lowest  = UPPER_LIMIT;               //set to inital values that they do not reach
            highest = LOWER_LIMIT;

            //iterate through every vertex to find highest and lowest value of this axis
            for (int i = 0; i < vertices.Count; i++)
            {
                if (vertices[i][axis] < lowest)
                {
                    lowest = vertices[i][axis];
                }

                if (vertices[i][axis] > highest)
                {
                    highest = vertices[i][axis];
                }
            }

            if (axis == 0)            //x
            {
                boundsMin.x = lowest;
                boundsMax.x = highest;
            }
            else if (axis == 1)
            {
                boundsMin.y = lowest;
                boundsMax.y = highest;
            }
            else if (axis == 2)
            {
                boundsMin.z = lowest;
                boundsMax.z = highest;
            }
        }

        bool sucess;
        sucess = navData.LoadBase(tileX, tileZ, tileLayer, tileUserId, boundsMin, boundsMax, xzCellSize, yCellSize, walkableHeight, walkableRadius, walkableStep, bvTreeEnabled);
        if (!sucess)
        {
            ReportError("Error, LoadBase returned false");
        }

        #endregion

        #region LoadPolys
        vertCount = vertices.Count;
        polyCount = faces.Count;

        //Convert vertices from world space to grid space
        polyVerts = new ushort[vertCount * 3];

        for (int i = 0; i < vertCount; i++)
        {
            polyVerts[3 * i + 0] = (ushort)Math.Round((vertices[i].x - boundsMin.x) / xzCellSize);
            polyVerts[3 * i + 1] = (ushort)Math.Round((vertices[i].y - boundsMin.y) / yCellSize);
            polyVerts[3 * i + 2] = (ushort)Math.Round((vertices[i].z - boundsMin.z) / xzCellSize);
        }

        //build polys array (http://www.critterai.org/projects/cainav/doc/html/B8C2F0F4.htm)
        polys = new ushort[6 * polyCount];
        int ind    = 0;
        int faceNo = 0;

        while (faceNo < polyCount)
        {
            polys[ind + 0] = faces[faceNo].x;
            polys[ind + 1] = faces[faceNo].y;
            polys[ind + 2] = faces[faceNo].z;

            polys[ind + 3] = neighborPolys[faceNo].x;
            polys[ind + 4] = neighborPolys[faceNo].y;
            polys[ind + 5] = neighborPolys[faceNo].z;

            ind += 6;
            faceNo++;
        }

        //Fill polyflags array with default flags
        polyFlags = new ushort[polyCount];
        for (int i = 0; i < polyCount; i++)
        {
            polyFlags[i] = 1;                           //custom user flag
        }
        //Fill polyAreas array
        polyAreas = new byte[polyCount];
        for (int i = 0; i < polyCount; i++)
        {
            polyAreas[i] = 1;
        }

        sucess = navData.LoadPolys(polyVerts, vertCount, polys, polyFlags, polyAreas, polyCount);

        if (!sucess)
        {
            ReportError("Error, LoadPolys returned false");
        }

        #endregion

        //Build the Navmesh using the navData
        NavStatus status = Navmesh.Create(navData, out navmesh);

        if (status != NavStatus.Sucess)
        {
            ReportError("Navmesh build status was " + status.ToString());
        }

        return(navmesh);
    }
Exemplo n.º 5
0
 public static extern bool dtnmBuildTileData(NavmeshTileBuildData sourceData
     , [In, Out] NavmeshTileData resultTile);
Exemplo n.º 6
0
 public static extern bool dtnmBuildTileData(NavmeshTileBuildData sourceData
                                             , [In, Out] NavmeshTileData resultTile);
Exemplo n.º 7
0
        /// <summary>
        /// Creates a standard <see cref="NavmeshTileBuildData"/> object from the provided
        /// parameters.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Errors will be logged to the build context.
        /// </para>
        /// </remarks>
        /// <param name="tx">The x-index of the tile.</param>
        /// <param name="tz">The z-index of the tile.</param>
        /// <param name="polyMesh">The polygon mesh data.</param>
        /// <param name="detailMesh">The detail mesh data. (Optional)</param>
        /// <param name="connections">The off-mesh connections. (Null allowed.)</param>
        /// <param name="bvTreeEnabled">True if bounding volumes should be generated.</param>
        /// <param name="context">The build context.</param>
        /// <returns>The tile build data, or null on error.</returns>
        public static NavmeshTileBuildData GetBuildData(BuildContext context
                                                        , int tx, int tz
                                                        , PolyMeshData polyMesh, PolyMeshDetailData detailMesh
                                                        , ConnectionSet connections
                                                        , bool bvTreeEnabled)
        {
            if (context == null)
            {
                // Silent.
                return(null);
            }

            Vector3[] verts   = null;
            float[]   radii   = null;
            byte[]    dirs    = null;
            byte[]    areas   = null;
            ushort[]  flags   = null;
            uint[]    userIds = null;

            Vector3 bmin = polyMesh.boundsMin;
            Vector3 bmax = polyMesh.boundsMax;

            int connCount = (connections == null)
                ? 0
                : connections.GetConnections(bmin.x, bmin.z, bmax.x, bmax.z
                                             , out verts, out radii, out dirs, out areas, out flags, out userIds);

            NavmeshTileBuildData result = new NavmeshTileBuildData(
                polyMesh.vertCount
                , polyMesh.polyCount
                , polyMesh.maxVertsPerPoly
                , (detailMesh == null ? 0 : detailMesh.vertCount)
                , (detailMesh == null ? 0 : detailMesh.triCount)
                , connCount);

            if (!result.LoadBase(tx, tz, 0, 0
                                 , polyMesh.boundsMin
                                 , polyMesh.boundsMax
                                 , polyMesh.xzCellSize
                                 , polyMesh.yCellSize
                                 , polyMesh.walkableHeight
                                 , polyMesh.walkableRadius
                                 , polyMesh.walkableStep
                                 , bvTreeEnabled))
            {
                context.LogError("Base data load failed. Bad configuration data or internal error."
                                 , null);
                return(null);
            }

            if (!result.LoadPolys(polyMesh.verts
                                  , polyMesh.vertCount
                                  , polyMesh.polys
                                  , polyMesh.flags
                                  , polyMesh.areas
                                  , polyMesh.polyCount))
            {
                context.LogError("Polygon load failed. Bad mesh data or internal error.", null);
                return(null);
            }

            if (detailMesh != null)
            {
                if (!result.LoadDetail(detailMesh.verts
                                       , detailMesh.vertCount
                                       , detailMesh.tris
                                       , detailMesh.triCount
                                       , detailMesh.meshes
                                       , detailMesh.meshCount))
                {
                    context.LogError("Detail load failed. Bad mesh data or internal error.", null);
                    return(null);
                }
            }

            if (connCount > 0)
            {
                if (!result.LoadConns(verts, radii, dirs, areas, flags, userIds, connCount))
                {
                    context.LogError("Off-mesh connection load failed. Bad data or internal error."
                                     , null);
                    return(null);
                }
            }

            return(result);
        }
Exemplo n.º 8
0
 public static extern NavStatus dtnmBuildSingleTileMesh(
     NavmeshTileBuildData buildData
     , ref IntPtr resultMesh);
Exemplo n.º 9
0
 public static extern NavStatus dtnmBuildSingleTileMesh(
     NavmeshTileBuildData buildData
     , ref IntPtr resultMesh);