/// <summary> /// Builds a detail mesh from the provided polygon mesh. /// </summary> /// <param name="context">The context to use for the operation.</param> /// <param name="polyMesh">The source polygon mesh.</param> /// <param name="field">The compact heightfield used to build the polygon mesh.</param> /// <param name="detailSampleDistance"> /// The sample distance to use when sampling the surface height of the polygon mesh. /// </param> /// <param name="detailMaxDeviation"> /// The maximum the surface of the detail mesh should deviate from the heightfield data. /// </param> /// <returns>A new detail mesh, or null on error.</returns> public static PolyMeshDetail Build(BuildContext context , PolyMesh polyMesh, CompactHeightfield field , float detailSampleDistance, float detailMaxDeviation) { if (context == null || polyMesh == null || polyMesh.IsDisposed || field == null || field.IsDisposed || detailSampleDistance < 0 || detailMaxDeviation < 0) { return(null); } PolyMeshDetail result = new PolyMeshDetail(AllocType.External); if (PolyMeshDetailEx.rcpdBuildPolyMeshDetail(context.root , ref polyMesh.root , field , detailSampleDistance , detailMaxDeviation , result)) { return(result); } return(null); }
/// <summary> /// Gets a serialized version of the mesh that can be used to recreate it later. /// </summary> /// <param name="includeBuffer"> /// True if serialized data should include the full buffer size. Otherwise the buffers will /// be stripped and the smallest possible serialized data returned. /// </param> /// <returns>A serialized version of the mesh.</returns> public byte[] GetSerializedData(bool includeBuffer) { if (IsDisposed) { return(null); } // Design note: This is implemented using interop calls // bacause it is so much easier and faster to serialize in C++ // than in C#. IntPtr ptr = IntPtr.Zero; int dataSize = 0; if (!PolyMeshDetailEx.rcpdGetSerializedData(this , includeBuffer , ref ptr , ref dataSize)) { return(null); } byte[] result = UtilEx.ExtractArrayByte(ptr, dataSize); NMGenEx.nmgFreeSerializationData(ref ptr); return(result); }
/// <summary> /// Frees all resources and marks the object as disposed. /// </summary> public void RequestDisposal() { if (!IsDisposed) { if (ResourceType == AllocType.Local) { Marshal.FreeHGlobal(mMeshes); Marshal.FreeHGlobal(mTris); Marshal.FreeHGlobal(mVerts); } else if (ResourceType == AllocType.External) { PolyMeshDetailEx.rcpdFreeMeshData(this); } mMeshes = IntPtr.Zero; mTris = IntPtr.Zero; mVerts = IntPtr.Zero; mMeshCount = 0; mVertCount = 0; mTriCount = 0; mMaxMeshes = 0; mMaxTris = 0; mMaxVerts = 0; } }
private PolyMeshDetail(SerializationInfo info, StreamingContext context) { // Note: Version compatability is handled by the interop call. if (info.MemberCount != 1) { return; } byte[] rawData = (byte[])info.GetValue(DataKey, typeof(byte[])); PolyMeshDetailEx.rcpdBuildFromMeshData(rawData, rawData.Length, this); }
/// <summary> /// Constructs a detail mesh from the data generated by the <see cref="GetSerializedData"/> /// method. /// </summary> /// <param name="serializedMesh">The source data.</param> /// <returns>The new detail mesh, or null on error.</returns> public static PolyMeshDetail Create(byte[] serializedMesh) { PolyMeshDetail result = new PolyMeshDetail(AllocType.External); if (PolyMeshDetailEx.rcpdBuildFromMeshData(serializedMesh , serializedMesh.Length , result)) { return(result); } return(null); }
/// <summary> /// Builds an aggregate triangle mesh from a detail mesh. /// </summary> /// <remarks> /// <para> /// All duplicate vertices are merged. /// </para> /// </remarks> /// <param name="source">The detail mesh to extract the triangle mesh from.</param> /// <param name="verts">The result vertices.</param> /// <param name="tris"> /// The result triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount] /// </param> /// <returns>True if the operation completed successfully.</returns> public static bool ExtractTriMesh(PolyMeshDetail source , out Vector3[] verts , out int[] tris) { // TODO: EVAL: v0.5: Inefficient. verts = null; tris = null; if (source == null || source.IsDisposed || source.TriCount == 0) { return(false); } // Assume no duplicate verts. Vector3[] tverts = new Vector3[source.VertCount]; tris = new int[source.TriCount * 3]; int vertCount = 0; int triCount = 0; if (PolyMeshDetailEx.rcpdFlattenMesh(source , tverts , ref vertCount , source.VertCount , tris , ref triCount , source.TriCount)) { verts = new Vector3[vertCount]; for (int i = 0; i < vertCount; i++) { verts[i] = tverts[i]; } return(true); } tris = null; return(false); }