namespace VdeSharp; /// /// Mesh data structure representing a triangulated surface. /// Contains vertices and triangle indices. /// public class MeshData : IDisposable { /// 3D vertex positions (x,y,z triplets) public double[] Vertices { get; private set; } /// Triangle indices, 3 per face public int[] Indices { get; private set; } /// Axis-aligned bounding box min (x,y,z) public (double X, double Y, double Z) BoundsMin { get; private set; } /// Axis-aligned bounding box max (x,y,z) public (double X, double Y, double Z) BoundsMax { get; private set; } /// Native mesh handle (opaque). internal nint _handle; private bool _ownsHandle; /// /// Wraps an existing native mesh handle. Caller sets ownership. /// internal MeshData(nint handle, bool ownsHandle = true) { _handle = handle; _ownsHandle = ownsHandle; Vertices = Array.Empty(); Indices = Array.Empty(); } /// /// Creates a MeshData from raw vertex and index arrays. /// public MeshData(double[] vertices, int[] indices) { Vertices = vertices; Indices = indices; _handle = nint.Zero; _ownsHandle = false; } /// /// Extracts mesh data from the native handle into managed arrays. /// Call this after receiving a mesh from native code. /// public unsafe void ExtractFromNative() { if (_handle == nint.Zero) return; nuint numVerts = NativeMethods.vde_mesh_num_vertices(_handle); nuint numFaces = NativeMethods.vde_mesh_num_faces(_handle); Vertices = new double[(int)numVerts * 3]; Indices = new int[(int)numFaces * 3]; for (nuint i = 0; i < numVerts; i++) { NativeMethods.vde_mesh_get_vertex(_handle, i, out Vertices[(int)i * 3], out Vertices[(int)i * 3 + 1], out Vertices[(int)i * 3 + 2]); } for (nuint i = 0; i < numFaces; i++) { int* facePtr; int count = NativeMethods.vde_mesh_get_face(_handle, i, &facePtr); if (count >= 3) { Indices[(int)i * 3] = facePtr[0]; Indices[(int)i * 3 + 1] = facePtr[1]; Indices[(int)i * 3 + 2] = facePtr[2]; } NativeMethods.vde_free_buffer(facePtr); } // Bounds NativeMethods.vde_mesh_get_bounds(_handle, out double mx, out double my, out double mz, out double Mx, out double My, out double Mz); BoundsMin = (mx, my, mz); BoundsMax = (Mx, My, Mz); } /// Number of vertices public int VertexCount => Vertices.Length / 3; /// Number of triangles public int TriangleCount => Indices.Length / 3; public void Dispose() { if (_ownsHandle && _handle != nint.Zero) { NativeMethods.vde_mesh_free(_handle); _handle = nint.Zero; } } }