Vergeo2D.Mesh 1.2.0

dotnet add package Vergeo2D.Mesh --version 1.2.0
                    
NuGet\Install-Package Vergeo2D.Mesh -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Vergeo2D.Mesh" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Vergeo2D.Mesh" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Vergeo2D.Mesh" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Vergeo2D.Mesh --version 1.2.0
                    
#r "nuget: Vergeo2D.Mesh, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Vergeo2D.Mesh@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Vergeo2D.Mesh&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Vergeo2D.Mesh&version=1.2.0
                    
Install as a Cake Tool

Vergeo2D.Mesh

Vergeo2D logo

NuGet Downloads Docs .NET 8.0 .NET Standard License: GPL v3

A lightweight C# library for editing 2D texture meshes - vertices, edges, faces and UV mapping - built as a foundation for 2D rigging tools.

This library was originally created for my own projects, but if you find it useful, feel free to use it in yours as well.

Preview

Preview 1 Preview 2
Vergeo2D.Mesh preview 1 Vergeo2D.Mesh preview 2

Install

dotnet add package Vergeo2D.Mesh

Framework Support

Vergeo2D.Mesh targets net8.0, netstandard2.1, and netstandard2.0.

Target Use when
net8.0 You are building a modern .NET 8+ app or tool
netstandard2.1 You need to consume the mesh core from .NET Core 3.x, .NET 5+, or other runtimes that support .NET Standard 2.1
netstandard2.0 You need compatibility with older hosts, including legacy .NET Standard 2.0 consumers

The net8.0 target is the primary modern path. The netstandard2.0 target is provided for compatibility and includes small internal fallbacks for APIs that older runtimes do not provide. For .NET Framework consumers, .NET Framework 4.7.2+ is recommended when consuming the netstandard2.0 asset.

The core library is dependency-light. netstandard2.0 uses System.Memory, System.Numerics.Vectors, and System.Text.Json package dependencies; netstandard2.1 uses System.Text.Json for mesh serialization.

When implementing a custom IMeshDeformer2D, implement both Deform() and DeformInto() if you need source compatibility with netstandard2.0. Modern targets provide the default DeformInto() implementation on the interface.

Usage

using System.Numerics;
using Vergeo2D.Mesh;

var mesh = new Mesh2D();
var v0 = mesh.AddVertex(new Vector2(0, 0));
var v1 = mesh.AddVertex(new Vector2(256, 0));
var v2 = mesh.AddVertex(new Vector2(256, 128));
var v3 = mesh.AddVertex(new Vector2(0, 128));

mesh.AddFace(v0, v1, v2);
mesh.AddFace(v0, v2, v3);

var texture = Texture2D.LoadFromFile("character.png");
mesh.SetTexture(texture);
mesh.GenerateUVsFromPositions(flipY: false);
mesh.RemoveFace(0);
mesh.RemoveVertex(v3);
var clone = mesh.Clone();

var json = Mesh2DSerializer.ToJson(mesh);
var loaded = Mesh2DSerializer.FromJson(json);
Mesh2DSerializer.SaveToFile(mesh, "character.mesh.json");

var strictLoaded = Mesh2DSerializer.LoadFromFile("character.mesh.json", new Mesh2DSerializationOptions
{
    TextureBaseDirectory = "assets",
    ThrowOnTextureLoadFailure = true
});
// Common mesh setup for textured sprites.
var quad = MeshPrimitives2D.CreateTexturedQuad(texture);

// Build a connected grid for deformation. Provide a mask when you want
// diagonals to follow the visible shape while keeping the mesh connected.
var mask = MeshMask2D.FromPredicate(point => alphaMask.IsOpaqueAt(point.X, point.Y));
var grid = MeshGridGenerator2D.GenerateConnectedGrid(
    texture,
    new MeshGridOptions2D { Spacing = 64 },
    mask);

// Build a contour mesh for overlays, picking, or visualizing the masked shape.
var contour = MeshGridGenerator2D.GenerateMaskedContourGrid(texture, mask);

// Drag deformation with a smooth radial falloff.
var drag = new RadialDragDeformer2D { Radius = 180f };
drag.SetDrag(origin, offset);
grid.ApplyDeformer(drag);
// Editor helpers for validating generated/imported meshes and picking handles.
var validation = mesh.Validate();
if (!validation.IsValid)
{
    foreach (var issue in validation.Issues)
        Console.WriteLine(issue);
}

if (MeshPicking2D.FindNearestVertex(mesh, mousePosition, 12f, out var vertexIndex, out _))
{
    mesh.Vertices[vertexIndex].Position += dragOffset;
}

if (MeshPicking2D.FindNearestEdge(mesh, mousePosition, 8f, out var edge, out var closest, out _))
{
    // edge and closest point can be used for insert/selection tools.
}

// Build a mask from alpha bytes decoded by your app/UI layer.
var alphaMask = MeshMask2D.FromAlphaMap(alphaBytes, width, height, threshold: 8);

Features

  • Vertex / edge / face mesh structure - add, remove, clone, adjacency queries, point-in-face hit testing
  • Dependency-free PNG / JPEG / BMP / GIF dimension reader with pixel to UV conversion
  • Textured quad and grid mesh generators for common sprite/deformation setup
  • Mask-driven contour mesh generation through IMeshMask2D, predicate adapters, and alpha byte maps
  • JSON serialization with optional texture loading behavior and base-directory resolution
  • Mesh validation diagnostics for editor/import pipelines
  • Picking helpers for nearest vertex, nearest edge, barycentric coordinates, and face UV lookup
  • IMeshDeformer2D extension point for custom deformation logic - ships with VertexOffsetDeformer2D and RadialDragDeformer2D reference implementations
  • Handle-based mesh manager for tracking large numbers of live meshes with generation-checked handles, dirty-only re-extraction, and texture batching
  • A pluggable rendering abstraction (IMeshRenderBackend2D) with optional OpenGL, Direct3D11, and Vulkan backends

Mesh Management

Vergeo2D.Management provides a pooled way to own many meshes at once without hunting for lifetime bugs yourself.

  • MeshHandle - a lightweight, generation-checked reference to a mesh slot. A handle from a removed/replaced slot is automatically detected as invalid instead of silently pointing at the wrong mesh.
  • MeshManager2D - add/remove meshes and their optional IMeshDeformer2D, then call PrepareFrame() once per frame. Only meshes whose Mesh2D.Version changed (or that are marked dirty via MarkDirty) get re-extracted into render data; parallel: true extracts dirty slots with Parallel.For once the pool is large.
  • MeshBatch2D - the result of GetBatches(), which groups all currently alive handles by their shared Texture2D so you can issue one draw call per texture instead of one per mesh.
using Vergeo2D.Management;

var manager = new MeshManager2D();
var handle = manager.Add(mesh, deformer: new VertexOffsetDeformer2D());

// once per frame
manager.PrepareFrame(parallel: true);

foreach (var batch in manager.GetBatches())
{
    // batch.Texture is shared by every handle in batch.Handles
    foreach (var meshHandle in batch.Handles)
    {
        manager.TryGetRenderData(meshHandle, out var renderData);
        // hand renderData.Vertices / renderData.Indices to your render backend
    }
}

manager.Remove(handle); // handle becomes invalid immediately, generation is bumped on reuse

Rendering

Vergeo2D.Rendering turns a Mesh2D into GPU-ready buffers and defines the contract a render backend implements - the core library stays engine-agnostic.

Type Description
MeshRenderExtractor Converts a Mesh2D (+ optional deformer) into a MeshRenderData2D, applying deformation via a pooled scratch buffer
MeshRenderData2D Growable vertex (x, y, u, v) and index buffers with independent dirty flags for vertices/indices
MeshRenderData2DExtensions Helpers such as ExpandIndexedTriangles() for APIs that draw non-indexed triangle lists
MeshViewportLayout2D Fits mesh/image content into a viewport and converts between screen and content coordinates
IMeshRenderBackend2D Interface a graphics backend implements: create/update/destroy a GPU resource, bind a texture, draw with a RenderTransform2D
RenderTransform2D Position + rotation (radians) + scale, convertible to a Matrix3x2
RenderResourceHandle Generation-checked handle returned by a backend for a GPU-side resource

MeshManager2D calls MeshRenderExtractor internally, so most consumers only interact with this layer through the manager - use it directly if you're managing a single mesh outside of MeshManager2D.

The extracted MeshRenderData2D buffers are plain interleaved floats (x, y, u, v) plus triangle indices, so you can also upload them into your own renderer. Veldrid works well for this path: create a vertex buffer from renderData.Vertices, an index buffer from renderData.Indices, and refresh only the buffers whose dirty flags changed.

Render Backends

Three reference IMeshRenderBackend2D implementations ship under Vergeo2D.Rendering.Backends. Unlike the core mesh library, these are not dependency-free - each is guarded behind a compilation symbol and requires its own third-party package, so nothing extra is pulled in unless you opt in.

These backend classes are optional references, not the only supported route. If your application already uses Veldrid or another renderer, you can keep Vergeo2D.Mesh as the mesh/deformation layer and map MeshRenderData2D into that renderer's own resource pipeline.

Backend Requires (NuGet) Define constant
OpenGLMeshRenderBackend2D Silk.NET.OpenGL VERGEO_OPENGL
Direct3D11MeshRenderBackend2D Vortice.Direct3D11 VERGEO_DIRECTX
VulkanMeshRenderBackend2D Silk.NET.Vulkan VERGEO_VULKAN

Add the relevant PackageReference and DefineConstants to your project to enable one:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);VERGEO_OPENGL</DefineConstants>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="Silk.NET.OpenGL" Version="x.x.x" />
</ItemGroup>

Without the matching define constant, the backend class simply isn't compiled in - the core library (Mesh2D, Texture2D, Mesh2DSerializer, management types) has zero third-party dependencies either way.

API

Type Description
Vertex2D Position + UV
Edge2D Undirected pair of vertex indices
Face2D Triangle of three vertex indices
Mesh2D Vertex/edge/face collection with editing and query methods; exposes a Version counter (bumped via TouchGeometry()) used for dirty tracking; can commit an IMeshDeformer2D via ApplyDeformer(); can run validation via Validate()
Texture2D Image dimensions plus pixel/UV conversion
MeshPrimitives2D, MeshGridGenerator2D, MeshGridOptions2D, IMeshMask2D, MeshMask2D Common textured quad, connected grid, and mask contour generation helpers
IMeshDeformer2D, VertexOffsetDeformer2D, RadialDragDeformer2D Optional deformation extension point and built-in reference deformers
MeshValidator2D, MeshValidationOptions2D, MeshValidationResult2D, MeshValidationIssue2D Mesh diagnostics for invalid faces, small triangles, duplicate faces, orphan vertices, non-manifold edges, and inconsistent winding
MeshPicking2D Editor helpers for nearest vertex/edge picking, barycentric coordinates, and face UV interpolation
Mesh2DSerializer, Mesh2DSerializationOptions JSON import/export with configurable texture loading
MeshHandle, MeshManager2D, MeshBatch2D Pooled mesh ownership, dirty-only extraction, texture batching
MeshRenderExtractor, MeshRenderData2D, MeshRenderData2DExtensions, MeshViewportLayout2D, IMeshRenderBackend2D, RenderTransform2D, RenderResourceHandle Backend-agnostic rendering pipeline
OpenGLMeshRenderBackend2D, Direct3D11MeshRenderBackend2D, VulkanMeshRenderBackend2D Optional backend implementations (see Render Backends)

Contributing

Issues and PRs are welcome at github.com/TamKungZ/Vergeo2D.Mesh.

License

GPLv3 (c) 2026 TamKungZ_

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 41 8/1/2026
1.1.2 35 8/1/2026
1.1.1 37 8/1/2026
1.1.0 46 7/29/2026
1.0.2 40 7/29/2026
1.0.1 39 7/28/2026
1.0.0 55 7/27/2026

Add editor-focused mesh validation, picking helpers, alpha-map mask creation, and serializer options for safer app integration.