Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new heightfield object.
        /// </summary>
        /// <param name="width">The width of the field. [Limit: >= 1] [Units: Cells]</param>
        /// <param name="depth">The depth of the field. [Limit: >= 1] [Units: Cells]</param>
        /// <param name="boundsMin">The minimum bounds of the field's AABB. [Units: World]</param>
        /// <param name="boundsMax">The maximum bounds of the field's AABB. [Units: World]</param>
        /// <param name="xzCellSize">
        /// The xz-plane cell size. [Limit:>= <see cref="NMGen.MinCellSize"/>] [Units: World]
        /// </param>
        /// <param name="yCellSize">
        /// The y-axis span increments. [Limit:>= <see cref="NMGen.MinCellSize"/>] [Units: World]
        /// </param>
        /// <returns>The heightfield, or null on error.</returns>
        public static Heightfield Create(int width, int depth
                                         , Vector3 boundsMin, Vector3 boundsMax
                                         , float xzCellSize, float yCellSize)
        {
            if (width < 1 || depth < 1 ||
                !TriangleMesh.IsBoundsValid(boundsMin, boundsMax) ||
                xzCellSize < NMGen.MinCellSize ||
                yCellSize < NMGen.MinCellSize)
            {
                return(null);
            }

            IntPtr root = HeightfieldEx.nmhfAllocField(width, depth
                                                       , ref boundsMin, ref boundsMax, xzCellSize, yCellSize);

            if (root == IntPtr.Zero)
            {
                return(null);
            }

            return(new Heightfield(root
                                   , width, depth
                                   , boundsMin, boundsMax
                                   , xzCellSize, yCellSize));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Voxelizes the triangles from the provided <see cref="ChunkyTriMesh"/> into the
        /// heightfield.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The chunks that are voxelized is controled by the bounds parameters.
        /// </para>
        /// </remarks>
        /// <param name="context">The build context.</param>
        /// <param name="mesh">The mesh.</param>
        /// <param name="boundsMin">The minimum bounds for the mesh query.</param>
        /// <param name="boundsMax">The maximum bounds for the mesh query.</param>
        /// <param name="flagMergeThreshold">
        /// The distance where the walkable flag is favored over the non-walkable flag.
        /// [Limit: >= 0] [Normal: 1]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool AddTriangles(BuildContext context, ChunkyTriMesh mesh
                                 , Vector3 boundsMin, Vector3 boundsMax
                                 , int flagMergeThreshold)
        {
            if (IsDisposed || mesh == null || mesh.IsDisposed)
            {
                return(false);
            }

            List <ChunkyTriMeshNode> nodeList = new List <ChunkyTriMeshNode>();

            int triCount = mesh.GetChunks(boundsMin.x, boundsMin.z
                                          , boundsMax.x, boundsMax.z
                                          , nodeList);

            if (triCount == 0)
            {
                return(true);
            }

            return(HeightfieldEx.nmhfRasterizeNodes(context.root
                                                    , mesh.verts
                                                    , mesh.tris
                                                    , mesh.areas
                                                    , nodeList.ToArray()
                                                    , nodeList.Count
                                                    , root
                                                    , flagMergeThreshold));
        }
Ejemplo n.º 3
0
 /// <summary>
 /// The number of spans in the field.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This is a non-trivial method call.  Cache the result when possible.
 /// </para>
 /// </remarks>
 /// <returns>The number of spans in the field.</returns>
 public int GetSpanCount()
 {
     if (IsDisposed)
     {
         return(0);
     }
     return(HeightfieldEx.nmhfGetHeightFieldSpanCount(root));
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Marks walkable spans as not walkable if the clearence above the span is less than the
        /// specified height.
        /// </summary>
        /// <remarks>
        /// <para>
        /// For this method, the clearance above the span is the distance from the span's maximum
        /// to the next higher span's minimum. (Same column.)
        /// </para>
        /// </remarks>
        /// <param name="context">The context to use for the operation</param>
        /// <param name="walkableHeight">
        /// The maximum allowed floor to ceiling height that is considered still walkable.
        /// [Limit: > <see cref="NMGen.MinWalkableHeight"/>]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool MarkLowHeightSpansNotWalkable(BuildContext context, int walkableHeight)
        {
            if (IsDisposed)
            {
                return(false);
            }

            return(HeightfieldEx.nmhfFilterWalkableLowHeightSpans(context.root
                                                                  , walkableHeight
                                                                  , root));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Marks non-walkable spans as walkable if their maximum is within walkableStep of a
        /// walkable neighbor.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Example of test: <c>Math.Abs(currentSpan.Max - neighborSpan.Max) &lt; walkableStep</c>
        /// </para>
        /// <para
        /// >Allows the formation of walkable regions that will flow over low lying objects such
        /// as curbs, and up structures such as stairways.
        /// </para>
        /// </remarks>
        /// <param name="context">The context to use for the operation</param>
        /// <param name="walkableStep">
        /// The maximum allowed difference between span maximum's for the step to be considered
        /// waklable. [Limit: > 0]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool MarkLowObstaclesWalkable(BuildContext context, int walkableStep)
        {
            if (IsDisposed)
            {
                return(false);
            }

            return(HeightfieldEx.nmhfFilterLowHangingWalkableObstacles(context.root
                                                                       , walkableStep
                                                                       , root));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets an buffer that is sized to fit the maximum number of spans within a column of
        /// the field.
        /// </summary>
        /// <returns>A buffer that is sized to fit the maximum spans within a column.</returns>
        public HeightfieldSpan[] GetSpanBuffer()
        {
            if (IsDisposed)
            {
                return(null);
            }

            int size = HeightfieldEx.nmhfGetMaxSpansInColumn(root);

            return(new HeightfieldSpan[size]);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Voxelizes the provided triangles into the heightfield.
        /// </summary>
        /// <param name="context">The context to use for the operation</param>
        /// <param name="verts">The triangles. [(vertA, vertB, vertC) * triCount]</param>
        /// <param name="areas">
        /// The ids of the areas the triangles belong to.
        /// [Limit: &lt;= <see cref="NMGen.MaxArea"/>] [Size: >= triCount]
        /// </param>
        /// <param name="triCount">The number of triangles in the vertex array.</param>
        /// <param name="flagMergeThreshold">
        /// The distance where the walkable flag is favored over the non-walkable flag.
        /// [Limit: >= 0] [Normal: 1]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool AddTriangles(BuildContext context
                                 , Vector3[] verts, byte[] areas, int triCount
                                 , int flagMergeThreshold)
        {
            if (IsDisposed)
            {
                return(false);
            }

            return(HeightfieldEx.nmhfRasterizeTriangles(context.root
                                                        , verts, areas, triCount
                                                        , root
                                                        , flagMergeThreshold));
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Frees all resources and marks object as disposed.
 /// </summary>
 public void RequestDisposal()
 {
     if (!IsDisposed)
     {
         HeightfieldEx.nmhfFreeField(root);
         root        = IntPtr.Zero;
         mWidth      = 0;
         mDepth      = 0;
         mXZCellSize = 0;
         mYCellSize  = 0;
         mBoundsMin  = Vector3Util.Zero;
         mBoundsMax  = Vector3Util.Zero;
     }
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the spans within the specified column.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The spans will be ordered from lowest height to highest.
        /// </para>
        /// <para>
        /// The <see cref="GetSpanBuffer"/> method can be used to get a properly sized buffer.
        /// </para>
        /// </remarks>
        /// <param name="widthIndex">
        /// The width index. [Limits: 0 &lt;= value &lt; <see cref="Width"/>]
        /// </param>
        /// <param name="depthIndex">
        /// The depth index. [Limits: 0 &lt;= value &lt; <see cref="Depth"/>]
        /// </param>
        /// <param name="buffer">
        /// The buffer to load the result into. [Size: Maximum spans in a column]
        /// </param>
        /// <returns>The number of spans returned.</returns>
        public int GetSpans(int widthIndex
                            , int depthIndex
                            , HeightfieldSpan[] buffer)
        {
            if (IsDisposed)
            {
                return(-1);
            }

            return(HeightfieldEx.nmhfGetSpans(root
                                              , widthIndex
                                              , depthIndex
                                              , buffer
                                              , buffer.Length));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Voxelizes the triangles in the provided mesh into the heightfield.
        /// </summary>
        /// <param name="context">The context to use for the operation</param>
        /// <param name="mesh">The triangle mesh.</param>
        /// <param name="areas">
        /// The ids of the areas the triangles belong to.
        /// [Limit: &lt;= <see cref="NMGen.MaxArea"/>] [Size: >= mesh.triCount]
        /// </param>
        /// <param name="flagMergeThreshold">
        /// The distance where the walkable flag is favored over the non-walkable flag.
        /// [Limit: >= 0] [Normal: 1]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool AddTriangles(BuildContext context, TriangleMesh mesh, byte[] areas
                                 , int flagMergeThreshold)
        {
            if (IsDisposed)
            {
                return(false);
            }

            return(HeightfieldEx.nmhfRasterizeTriMesh(context.root
                                                      , mesh.verts
                                                      , mesh.vertCount
                                                      , mesh.tris
                                                      , areas
                                                      , mesh.triCount
                                                      , root
                                                      , flagMergeThreshold));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Voxelizes the provided triangles into the heightfield.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Unlike many other methods in the library, the arrays must be sized exactly to the
        /// content.  If you need to pass buffers, use the method that takes a
        /// <see cref="TriangleMesh"/> object.
        /// </para>
        /// </remarks>
        /// <param name="context">The context to use for the operation</param>
        /// <param name="verts">The vertices. [Length: >= vertCount] (No buffering allowed.)</param>
        /// <param name="tris">
        /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount]
        /// </param>
        /// <param name="areas">
        /// The ids of the areas the triangles belong to.
        /// [Limit: &lt;= <see cref="NMGen.MaxArea"/>] [Size: >= triCount]
        /// </param>
        /// <param name="flagMergeThreshold">
        /// The distance where the walkable flag is favored over the non-walkable flag.
        /// [Limit: >= 0] [Normal: 1]
        /// </param>
        /// <returns>True if the operation was successful.</returns>
        public bool AddTriangles(BuildContext context
                                 , Vector3[] verts, ushort[] tris, byte[] areas
                                 , int flagMergeThreshold)
        {
            if (IsDisposed)
            {
                return(false);
            }

            return(HeightfieldEx.nmhfRasterizeTriMeshShort(context.root
                                                           , verts
                                                           , verts.Length / 3
                                                           , tris
                                                           , areas
                                                           , tris.Length / 3
                                                           , root
                                                           , flagMergeThreshold));
        }