예제 #1
0
        /// <summary>
        /// Gets the data from the mesh buffers.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method is useful for extracting mesh data so it can be inspected or altered
        /// and reloaded.
        /// </para>
        /// </remarks>
        /// <param name="includeBuffer">
        /// If true, includes the unused buffer space.  Otherwise only the used buffer data is
        /// returned.
        /// </param>
        /// <returns>The data from the mesh buffers.</returns>
        public PolyMeshData GetData(bool includeBuffer)
        {
            int mp = (includeBuffer ? root.maxPolys : root.polyCount);
            int mv = (includeBuffer ? mMaxVerts : root.vertCount);

            PolyMeshData buffer = new PolyMeshData(mv
                                                   , mp
                                                   , root.maxVertsPerPoly);

            FillData(buffer);

            return(buffer);
        }
예제 #2
0
        /// <summary>
        /// Loads the data from the mesh buffers into the data object.
        /// </summary>
        /// <remarks>
        /// <para>
        /// A new buffer will be returned if the buffer argument is null.
        /// </para>
        /// <para>
        /// The buffer will be automatically resized if it is too small to hold the result.
        /// </para>
        /// <para>
        /// Only the used portions of the mesh buffers are copied.
        /// </para>
        /// </remarks>
        /// <param name="buffer">A buffer to load the data into.</param>
        /// <returns>A reference to the mesh data.</returns>
        public PolyMeshData GetData(PolyMeshData buffer)
        {
            if (IsDisposed)
            {
                return(null);
            }
            if (buffer == null)
            {
                return(GetData(true));
            }

            if (!buffer.CanFit(root.vertCount
                               , root.polyCount
                               , root.maxVertsPerPoly))
            {
                buffer.Resize(mMaxVerts, root.maxPolys, root.maxVertsPerPoly);
            }

            FillData(buffer);

            return(buffer);
        }
예제 #3
0
        private void FillData(PolyMeshData buffer)
        {
            buffer.maxVertsPerPoly = root.maxVertsPerPoly;
            buffer.boundsMax       = BoundsMax;
            buffer.boundsMin       = BoundsMin;
            buffer.yCellSize       = root.yCellSize;
            buffer.xzCellSize      = root.xzCellSize;
            buffer.polyCount       = root.polyCount;
            buffer.vertCount       = root.vertCount;
            buffer.walkableStep    = mWalkableStep;
            buffer.walkableHeight  = mWalkableHeight;
            buffer.walkableRadius  = mWalkableRadius;
            buffer.borderSize      = root.borderSize;

            UtilEx.Copy(root.polys
                        , buffer.polys
                        , root.polyCount * 2 * root.maxVertsPerPoly);
            Marshal.Copy(root.areas, buffer.areas, 0, root.polyCount);
            UtilEx.Copy(root.flags, buffer.flags, root.polyCount);
            UtilEx.Copy(root.regions, buffer.regions, root.polyCount);

            UtilEx.Copy(root.verts, buffer.verts, root.vertCount * 3);
        }
예제 #4
0
        /// <summary>
        /// Draws a debug view of a <see cref="PolyMeshData"/> object.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Meant to be called during the MonoBehavior.OnRenderObject() method.
        /// </para>
        /// </remarks>
        /// <param name="polyData">The polygon mesh to draw.</param>
        public static void Draw(PolyMeshData polyData)
        {
            DebugDraw.SimpleMaterial.SetPass(0);

            Color walkableColor = new Color(0, 0.75f, 1.0f, 0.25f);
            Color nullRegionColor = new Color(0, 0, 0, 0.25f);

            int[] pTargetVert = new int[3];

            GL.Begin(GL.TRIANGLES);
            for (int iPoly = 0; iPoly < polyData.polyCount; iPoly++)
            {
                int pPoly = iPoly * polyData.maxVertsPerPoly * 2;

                if (polyData.areas[iPoly] == NMGen.MaxArea)
                    GL.Color(walkableColor);
                else if (polyData.areas[iPoly] == NMGen.NullRegion)
                    GL.Color(nullRegionColor);
                else
                    GL.Color(ColorUtil.IntToColor(polyData.areas[iPoly], 1.0f));

                pTargetVert[0] = polyData.polys[pPoly + 0] * 3;
                for (int iPolyVert = 2
                    ; iPolyVert < polyData.maxVertsPerPoly
                    ; iPolyVert++)
                {

                    if (polyData.polys[pPoly + iPolyVert]
                            == PolyMesh.NullIndex)
                        break;

                    pTargetVert[1] =
                        polyData.polys[pPoly + iPolyVert] * 3;
                    pTargetVert[2] =
                        polyData.polys[pPoly + iPolyVert - 1] * 3;

                    for (int i = 0; i < 3; i++)
                    {
                        int p = pTargetVert[i];
                        int x = polyData.verts[p + 0];
                        // Offset y a little to ensure it clears the
                        // source geometry.
                        int y = polyData.verts[p + 1] + 1;
                        int z = polyData.verts[p + 2];
                        GL.Vertex3(polyData.boundsMin[0] + x * polyData.xzCellSize
                            , polyData.boundsMin[1] + y * polyData.yCellSize
                            , polyData.boundsMin[2] + z * polyData.xzCellSize);
                    }
                }
            }
            GL.End();

            Color internalEdgeColor = new Color(0, 0.2f, 0.25f, 0.25f);
            Color boundaryEdgeColor = new Color(0.65f, 0.2f, 0, 0.9f);

            GL.Begin(GL.LINES);
            for (int iPoly = 0; iPoly < polyData.polyCount; iPoly++)
            {
                int pPoly = iPoly * polyData.maxVertsPerPoly * 2;

                for (int iPolyVert = 0; iPolyVert < polyData.maxVertsPerPoly; iPolyVert++)
                {
                    int iv = polyData.polys[pPoly + iPolyVert];

                    if (iv == PolyMesh.NullIndex)
                        break;

                    if (polyData.polys[pPoly + polyData.maxVertsPerPoly + iPolyVert]
                                == PolyMesh.NullIndex)
                    {
                        GL.Color(boundaryEdgeColor);
                    }
                    else
                        GL.Color(internalEdgeColor);

                    // Note: Using only first two indexes.
                    pTargetVert[0] = iv * 3;

                    if (iPolyVert + 1 >= polyData.maxVertsPerPoly)
                    {
                        // Reached hard end of polygon.  Loop back.
                        iv = polyData.polys[pPoly + 0];
                    }
                    else
                    {
                        iv = polyData.polys[pPoly + iPolyVert + 1];

                        if (iv == PolyMesh.NullIndex)
                            // Reached soft end of polygon.  Loop back.
                            iv = polyData.polys[pPoly + 0];
                    }

                    pTargetVert[1] = iv * 3;

                    for (int i = 0; i < 2; i++)
                    {
                        int p = pTargetVert[i];
                        int x = polyData.verts[p + 0];
                        // Offset y a little to ensure it clears the
                        // source geometry.
                        int y = polyData.verts[p + 1] + 1;
                        int z = polyData.verts[p + 2];

                        GL.Vertex3(polyData.boundsMin[0] + x * polyData.xzCellSize
                            , polyData.boundsMin[1] + y * polyData.yCellSize
                            , polyData.boundsMin[2] + z * polyData.xzCellSize);
                    }
                }
            }
            GL.End();
        }
        /// <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;
        }
예제 #6
0
        /// <summary>
        /// Loads the data into the mesh buffers, overwriting existing content.
        /// </summary>
        /// <param name="data">The data to load.</param>
        /// <returns>True if the load was successful.</returns>
        public bool Load(PolyMeshData data)
        {
            int vcount = (data.verts == null || data.vertCount < 3 ?
                          0 : data.vertCount);
            int pcount = (data.polys == null || data.polyCount < 1 ?
                          0 : data.polyCount);

            if (pcount == 0 || pcount > root.maxPolys ||
                vcount == 0 || vcount > mMaxVerts ||
                data.xzCellSize < NMGen.MinCellSize ||
                data.yCellSize < NMGen.MinCellSize ||
                data.walkableHeight
                < NMGen.MinWalkableHeight * NMGen.MinCellSize ||
                data.walkableStep < 0 ||
                data.walkableRadius < 0 ||
                data.borderSize < 0 ||
                data.polys.Length
                < (pcount * 2 * root.maxVertsPerPoly) ||
                data.verts.Length < (vcount * 3) ||
                (data.areas != null && data.areas.Length < pcount) ||
                (data.regions != null &&
                 data.regions.Length < pcount) ||
                (data.flags != null && data.flags.Length < pcount))
            {
                return(false);
            }

            root.polyCount  = pcount;
            root.vertCount  = vcount;
            root.xzCellSize = data.xzCellSize;
            root.yCellSize  = data.yCellSize;
            mWalkableHeight = data.walkableHeight;
            mWalkableRadius = data.walkableRadius;
            mWalkableStep   = data.walkableStep;
            root.borderSize = data.borderSize;

            root.boundsMin = data.boundsMin;
            root.boundsMax = data.boundsMax;

            UtilEx.Copy(data.verts, 0, root.verts, root.vertCount * 3);

            UtilEx.Copy(data.polys
                        , 0
                        , root.polys
                        , root.polyCount * 2 * root.maxVertsPerPoly);

            if (data.regions == null)
            {
                UtilEx.ZeroMemory(root.regions, sizeof(ushort) * root.polyCount);
            }
            else
            {
                UtilEx.Copy(data.regions, 0, root.regions, root.polyCount);
            }

            if (data.flags == null)
            {
                UtilEx.ZeroMemory(root.flags, sizeof(ushort) * root.polyCount);
            }
            else
            {
                UtilEx.Copy(data.flags, 0, root.flags, root.polyCount);
            }

            if (data.areas == null)
            {
                UtilEx.ZeroMemory(root.areas, sizeof(byte) * root.polyCount);
            }
            else
            {
                Marshal.Copy(data.areas, 0, root.areas, root.polyCount);
            }

            return(true);
        }
예제 #7
0
        private void FillData(PolyMeshData buffer)
        {
            buffer.maxVertsPerPoly = root.maxVertsPerPoly;
            buffer.boundsMax = BoundsMax;
            buffer.boundsMin = BoundsMin;
            buffer.yCellSize = root.yCellSize;
            buffer.xzCellSize = root.xzCellSize;
            buffer.polyCount = root.polyCount;
            buffer.vertCount = root.vertCount;
            buffer.walkableStep = mWalkableStep;
            buffer.walkableHeight = mWalkableHeight;
            buffer.walkableRadius = mWalkableRadius;
            buffer.borderSize = root.borderSize;

            UtilEx.Copy(root.polys
                , buffer.polys
                , root.polyCount * 2 * root.maxVertsPerPoly);
            Marshal.Copy(root.areas, buffer.areas, 0, root.polyCount);
            UtilEx.Copy(root.flags, buffer.flags, root.polyCount);
            UtilEx.Copy(root.regions, buffer.regions, root.polyCount);

            UtilEx.Copy(root.verts, buffer.verts, root.vertCount * 3);
        }
예제 #8
0
        /// <summary>
        /// Loads the data from the mesh buffers into the data object.
        /// </summary>
        /// <remarks>
        /// <para>
        /// A new buffer will be returned if the buffer argument is null.
        /// </para>
        /// <para>
        /// The buffer will be automatically resized if it is too small to hold the result.
        /// </para>
        /// <para>
        /// Only the used portions of the mesh buffers are copied.
        /// </para>
        /// </remarks>
        /// <param name="buffer">A buffer to load the data into.</param>
        /// <returns>A reference to the mesh data.</returns>
        public PolyMeshData GetData(PolyMeshData buffer)
        {
            if (IsDisposed)
                return null;
            if (buffer == null)
                return GetData(true);

            if (!buffer.CanFit(root.vertCount
                , root.polyCount
                , root.maxVertsPerPoly))
            {
                buffer.Resize(mMaxVerts, root.maxPolys, root.maxVertsPerPoly);
            }

            FillData(buffer);

            return buffer;
        }
예제 #9
0
        /// <summary>
        /// Gets the data from the mesh buffers.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method is useful for extracting mesh data so it can be inspected or altered 
        /// and reloaded.
        /// </para>
        /// </remarks>
        /// <param name="includeBuffer">
        /// If true, includes the unused buffer space.  Otherwise only the used buffer data is 
        /// returned.
        /// </param>
        /// <returns>The data from the mesh buffers.</returns>
        public PolyMeshData GetData(bool includeBuffer)
        {
            int mp = (includeBuffer ? root.maxPolys : root.polyCount);
            int mv = (includeBuffer ? mMaxVerts : root.vertCount);

            PolyMeshData buffer = new PolyMeshData(mv
                , mp
                , root.maxVertsPerPoly);

            FillData(buffer);

            return buffer;
        }
예제 #10
0
        /// <summary>
        /// Loads the data into the mesh buffers, overwriting existing content.
        /// </summary>
        /// <param name="data">The data to load.</param>
        /// <returns>True if the load was successful.</returns>
        public bool Load(PolyMeshData data)
        {
            int vcount = (data.verts == null || data.vertCount < 3 ?
                0 : data.vertCount);
            int pcount = (data.polys == null || data.polyCount < 1 ?
                 0 : data.polyCount);

            if (pcount == 0 || pcount > root.maxPolys
                || vcount == 0 || vcount > mMaxVerts
                || data.xzCellSize < NMGen.MinCellSize
                || data.yCellSize < NMGen.MinCellSize
                || data.walkableHeight 
                    < NMGen.MinWalkableHeight * NMGen.MinCellSize
                || data.walkableStep < 0
                || data.walkableRadius < 0
                || data.borderSize < 0
                || data.polys.Length 
                    < (pcount * 2 * root.maxVertsPerPoly)
                || data.verts.Length < (vcount * 3)
                || (data.areas != null && data.areas.Length < pcount)
                || (data.regions != null 
                    && data.regions.Length < pcount)
                || (data.flags != null && data.flags.Length < pcount))
            {
                return false;
            }

            root.polyCount = pcount;
            root.vertCount = vcount;
            root.xzCellSize = data.xzCellSize;
            root.yCellSize = data.yCellSize;
            mWalkableHeight = data.walkableHeight;
            mWalkableRadius = data.walkableRadius;
            mWalkableStep = data.walkableStep;
            root.borderSize = data.borderSize;

            root.boundsMin = data.boundsMin;
            root.boundsMax = data.boundsMax;

            UtilEx.Copy(data.verts, 0, root.verts, root.vertCount * 3);

            UtilEx.Copy(data.polys
                , 0
                , root.polys
                , root.polyCount * 2 * root.maxVertsPerPoly);

            if (data.regions == null)
                UtilEx.ZeroMemory(root.regions, sizeof(ushort) * root.polyCount);
            else
                UtilEx.Copy(data.regions, 0, root.regions, root.polyCount);

            if (data.flags == null)
                UtilEx.ZeroMemory(root.flags, sizeof(ushort) * root.polyCount);
            else
                UtilEx.Copy(data.flags, 0, root.flags, root.polyCount);

            if (data.areas == null)
                UtilEx.ZeroMemory(root.areas, sizeof(byte) * root.polyCount);
            else
                Marshal.Copy(data.areas, 0, root.areas, root.polyCount);

            return true;
        }