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;
}
}
}