83 lines
2.5 KiB
C#
83 lines
2.5 KiB
C#
|
|
namespace VdeSharp;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Managed wrapper for VDE SDF (Signed Distance Function) modeling.
|
|||
|
|
/// Provides an expression-tree based CSG modeling approach.
|
|||
|
|
/// </summary>
|
|||
|
|
public class SdfEngine : IDisposable
|
|||
|
|
{
|
|||
|
|
private readonly nint _ctx;
|
|||
|
|
internal nint _handle;
|
|||
|
|
private bool _disposed;
|
|||
|
|
|
|||
|
|
internal SdfEngine(nint ctx, nint handle)
|
|||
|
|
{
|
|||
|
|
_ctx = ctx;
|
|||
|
|
_handle = handle;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>Create a sphere SDF node.</summary>
|
|||
|
|
public static SdfEngine Sphere(nint ctx, double radius)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_sphere(ctx, radius);
|
|||
|
|
return new SdfEngine(ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>Create a box SDF node with half-extents (hx, hy, hz).</summary>
|
|||
|
|
public static SdfEngine Box(nint ctx, double hx, double hy, double hz)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_box(ctx, hx, hy, hz);
|
|||
|
|
return new SdfEngine(ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>Create a cylinder SDF node.</summary>
|
|||
|
|
public static SdfEngine Cylinder(nint ctx, double radius, double height)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_cylinder(ctx, radius, height);
|
|||
|
|
return new SdfEngine(ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>CSG union: this ∪ other</summary>
|
|||
|
|
public SdfEngine Union(SdfEngine other)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_union(_ctx, _handle, other._handle);
|
|||
|
|
return new SdfEngine(_ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>CSG intersection: this ∩ other</summary>
|
|||
|
|
public SdfEngine Intersection(SdfEngine other)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_intersection(_ctx, _handle, other._handle);
|
|||
|
|
return new SdfEngine(_ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>CSG difference: this \ other</summary>
|
|||
|
|
public SdfEngine Difference(SdfEngine other)
|
|||
|
|
{
|
|||
|
|
nint hdl = NativeMethods.vde_sdf_difference(_ctx, _handle, other._handle);
|
|||
|
|
return new SdfEngine(_ctx, hdl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Convert the SDF tree to a triangle mesh using Marching Cubes.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="resolution">Grid resolution per axis (e.g., 64 for 64³ voxels)</param>
|
|||
|
|
public MeshData ToMesh(int resolution = 64)
|
|||
|
|
{
|
|||
|
|
nint mh = NativeMethods.vde_sdf_to_mesh(_ctx, _handle, resolution);
|
|||
|
|
var mesh = new MeshData(mh, ownsHandle: true);
|
|||
|
|
mesh.ExtractFromNative();
|
|||
|
|
return mesh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Dispose()
|
|||
|
|
{
|
|||
|
|
if (!_disposed && _handle != nint.Zero)
|
|||
|
|
{
|
|||
|
|
NativeMethods.vde_sdf_free(_handle);
|
|||
|
|
_handle = nint.Zero;
|
|||
|
|
_disposed = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|