/// <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(PolyMeshDetailData data) { if (IsDisposed || data == null || data.meshes == null || data.tris == null || data.verts == null || data.meshCount < 0 || data.meshCount > mMaxMeshes || data.triCount < 0 || data.triCount > mMaxTris || data.vertCount < 0 || data.vertCount > mMaxVerts || data.meshes.Length < data.meshCount * 4 || data.tris.Length < data.triCount * 4 || data.verts.Length < data.vertCount) { return(false); } mMeshCount = data.meshCount; mTriCount = data.triCount; mVertCount = data.vertCount; UtilEx.Copy(data.meshes, 0, mMeshes, mMeshCount * 4); Marshal.Copy(data.tris, 0, mTris, mTriCount * 4); float[] fverts = Vector3Util.Flatten(data.verts, mVertCount); Marshal.Copy(fverts, 0, mVerts, mVertCount * 3); return(true); }
private void FillData(PolyMeshDetailData buffer) { buffer.vertCount = mVertCount; buffer.triCount = mTriCount; buffer.meshCount = mMeshCount; float[] fverts = new float[mVertCount * 3]; Marshal.Copy(mVerts, fverts, 0, mVertCount * 3); buffer.verts = Vector3Util.GetVectors(fverts, 0, buffer.verts, 0, mVertCount); Marshal.Copy(mTris, buffer.tris, 0, mTriCount * 4); UtilEx.Copy(mMeshes, buffer.meshes, mMeshCount * 4); }
/// <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 PolyMeshDetailData GetData(bool includeBuffer) { if (IsDisposed) { return(null); } PolyMeshDetailData result = new PolyMeshDetailData( (includeBuffer ? mMaxVerts : mVertCount) , (includeBuffer ? mMaxTris : mTriCount) , (includeBuffer ? mMaxMeshes : mMeshCount)); FillData(result); return(result); }
/// <summary> /// Loads the data from the mesh buffers into the data object. /// </summary> /// <remarks> /// <para> /// If the buffer argument is null, a new buffer will be returned. If the buffer is too /// small it will be resized. /// </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 PolyMeshDetailData GetData(PolyMeshDetailData buffer) { if (IsDisposed) { return(null); } if (buffer == null) { return(GetData(true)); } if (!buffer.CanFit(mVertCount, mTriCount, mMeshCount)) { buffer.Reset(mMaxVerts, mMaxTris, mMaxMeshes); } FillData(buffer); return(buffer); }
private void FillData(PolyMeshDetailData buffer) { buffer.vertCount = mVertCount; buffer.triCount = mTriCount; buffer.meshCount = mMeshCount; float[] fverts = new float[mVertCount * 3]; Marshal.Copy(mVerts, fverts, 0, mVertCount * 3); buffer.verts = Vector3Util.GetVectors(fverts, 0, buffer.verts, 0, mVertCount); Marshal.Copy(mTris, buffer.tris, 0, mTriCount * 4); UtilEx.Copy(mMeshes, buffer.meshes, mMeshCount * 4); }
/// <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(PolyMeshDetailData data) { if (IsDisposed || data == null || data.meshes == null || data.tris == null || data.verts == null || data.meshCount < 0 || data.meshCount > mMaxMeshes || data.triCount < 0 || data.triCount > mMaxTris || data.vertCount < 0 || data.vertCount > mMaxVerts || data.meshes.Length < data.meshCount * 4 || data.tris.Length < data.triCount * 4 || data.verts.Length < data.vertCount) { return false; } mMeshCount = data.meshCount; mTriCount = data.triCount; mVertCount = data.vertCount; UtilEx.Copy(data.meshes, 0, mMeshes, mMeshCount * 4); Marshal.Copy(data.tris, 0, mTris, mTriCount * 4); float[] fverts = Vector3Util.Flatten(data.verts, mVertCount); Marshal.Copy(fverts, 0, mVerts, mVertCount * 3); return true; }
/// <summary> /// Loads the data from the mesh buffers into the data object. /// </summary> /// <remarks> /// <para> /// If the buffer argument is null, a new buffer will be returned. If the buffer is too /// small it will be resized. /// </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 PolyMeshDetailData GetData(PolyMeshDetailData buffer) { if (IsDisposed) return null; if (buffer == null) return GetData(true); if (!buffer.CanFit(mVertCount, mTriCount, mMeshCount)) buffer.Reset(mMaxVerts, mMaxTris, mMaxMeshes); FillData(buffer); return buffer; }
/// <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 PolyMeshDetailData GetData(bool includeBuffer) { if (IsDisposed) return null; PolyMeshDetailData result = new PolyMeshDetailData( (includeBuffer ? mMaxVerts : mVertCount) , (includeBuffer ? mMaxTris : mTriCount) , (includeBuffer ? mMaxMeshes : mMeshCount)); FillData(result); return result; }
/// <summary> /// Draws a debug view of a <see cref="PolyMeshDetailData"/> object. /// </summary> /// <remarks> /// <para> /// Meant to be called during the MonoBehavior.OnRenderObject() method. /// </para> /// </remarks> /// <param name="detailData">The detail mesh to draw.</param> public static void Draw(PolyMeshDetailData detailData) { DebugDraw.SimpleMaterial.SetPass(0); GL.Begin(GL.TRIANGLES); for (int iMesh = 0; iMesh < detailData.meshCount; iMesh++) { GL.Color(ColorUtil.IntToColor(iMesh, 0.75f)); int pMesh = iMesh * 4; int pVertBase = (int)detailData.meshes[pMesh + 0]; int pTriBase = (int)detailData.meshes[pMesh + 2] * 4; int tCount = (int)detailData.meshes[pMesh + 3]; for (int iTri = 0; iTri < tCount; iTri++) { for (int iVert = 0; iVert < 3; iVert++) { int pVert = pVertBase + (detailData.tris[pTriBase + (iTri * 4 + iVert)]); GL.Vertex(detailData.verts[pVert]); } } } GL.End(); // Draw the triangle lines. GL.Begin(GL.LINES); Color portalColor = new Color(0, 0, 0, 0.25f); for (int iMesh = 0; iMesh < detailData.meshCount; iMesh++) { Color meshColor = ColorUtil.IntToColor(iMesh, 1.0f); int pMesh = iMesh * 4; int pVertBase = (int)detailData.meshes[pMesh + 0]; int pTriBase = (int)detailData.meshes[pMesh + 2] * 4; int tCount = (int)detailData.meshes[pMesh + 3]; for (int iTri = 0; iTri < tCount; iTri++) { byte flags = detailData.tris[pTriBase + (iTri * 4 + 3)]; for (int iVert = 0, iPrevVert = 2 ; iVert < 3 ; iPrevVert = iVert++) { if (((flags >> (iPrevVert * 2)) & 0x3) == 0) GL.Color(meshColor); else GL.Color(portalColor); int pVert = pVertBase + (detailData.tris[pTriBase + (iTri * 4 + iVert)]); int pPrevVert = pVertBase + (detailData.tris[pTriBase + (iTri * 4 + iPrevVert)]); GL.Vertex(detailData.verts[pVert]); GL.Vertex(detailData.verts[pPrevVert]); } } } 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; }