No description
Find a file
Thunder f8dba5ea67
All checks were successful
Release / build (push) Successful in 2m22s
Release / deploy-docs (push) Successful in 1m26s
Release / push-nuget (push) Successful in 30s
Release / merge-to-main (push) Successful in 6s
docs: bump MonoGame.Framework.DesktopGL to 3.8.5
Update all MonoGame-referencing projects to use MonoGame 3.8.5,
preparing for alignment with Thunder.MonoGame.Avalonia.
2026-07-23 13:56:43 -05:00
.forgejo/workflows M21.1 S3: MonoGame demo + CI run step + AAR 2026-04-18 20:37:13 -05:00
.github Link .github/copilot-instructions.md to CLAUDE.md 2026-04-13 14:17:43 -05:00
api docs: Phase 7 post-phase completion steps 2026-05-05 12:20:09 -05:00
assets Add Thunder logo as NuGet package icon 2026-04-13 15:32:34 -05:00
benchmarks fix: show PID in profiler startup output 2026-04-22 10:55:48 -05:00
docs docs: Phase 8 roadmap and backlog cleanup 2026-05-05 13:38:26 -05:00
samples docs: bump MonoGame.Framework.DesktopGL to 3.8.5 2026-07-23 13:56:43 -05:00
src docs: bump MonoGame.Framework.DesktopGL to 3.8.5 2026-07-23 13:56:43 -05:00
tests docs: bump MonoGame.Framework.DesktopGL to 3.8.5 2026-07-23 13:56:43 -05:00
.gitignore chore: untrack screenshot, add *.png to .gitignore 2026-04-20 08:18:52 -05:00
CHANGELOG.md docs: Phase 5 closeout — phase review, ideas.md, NuGet docs, CHANGELOG 2026-04-22 21:47:17 -05:00
CLAUDE.md docs: Phase 7 post-phase completion steps 2026-05-05 12:20:09 -05:00
docfx.json docs: fix api/index.html redirect and improve AI navigation 2026-04-20 07:16:03 -05:00
LICENSE Docs M7-S2: Repo README and MIT LICENSE 2026-04-13 07:46:37 -05:00
README.md docs(v0.4.0): phase close-out — CHANGELOG, READMEs, NuGet docs, ideas.md 2026-04-21 22:23:13 -05:00
Thunder.UnitsNET.Vectors.sln feat: add hot-path profiling harness (raw-double vs units comparison) 2026-04-22 10:36:05 -05:00
toc.yml docs: fix API docs index page and stale NuGet readmes 2026-04-19 20:45:47 -05:00

Thunder.UnitsNET.Vectors

A unit-aware 2D/3D vector library for physics-driven game loops. Built on UnitsNet, every vector component carries its physical unit — so LengthVector2 / Duration returns a SpeedVector2, not a dimensionless float.

📖 API docs

Packages

Package Purpose NuGet
Thunder.UnitsNET.Vectors Core vector types, physics operators, integration helpers NuGet
Thunder.UnitsNET.Vectors.MonoGame XNA/MonoGame Vector2/Vector3 conversion extensions NuGet
Thunder.UnitsNET.Vectors.Geometry Unit-aware 2D geometry, collision manifolds, raycasting, path following NuGet
Thunder.UnitsNET.Vectors.Geometry.MonoGame Geometry → MonoGame rendering, DebugDraw wireframes NuGet

Quick start

// dotnet add package Thunder.UnitsNET.Vectors
// dotnet add package Thunder.UnitsNET.Vectors.Geometry  (physics/collision)

using Thunder.UnitsNET.Vectors;
using Thunder.UnitsNET.Vectors.Geometry;
using UnitsNet;
using UnitsNet.Units;

// Create a position vector
var position = new LengthVector2(Length.FromMeters(3), Length.FromMeters(4));

// Kinematics: v = Δx / Δt
var velocity = position / Duration.FromSeconds(1);          // SpeedVector2

// Dynamics: F = ma
var accel = new AccelerationVector2(
    Acceleration.FromMetersPerSecondSquared(2),
    Acceleration.FromMetersPerSecondSquared(0));
ForceVector2 force = accel * Mass.FromKilograms(10);

// Dot product: work W = F · d  (returns Energy)
Energy work = force.Dot(position);

// Physics integration (Euler step)
var newPos = PhysicsIntegration.Euler(position, velocity, Duration.FromSeconds(1.0 / 60));

// Collision manifold — all 15 shape pairings, zero allocation
var a = Rectangle2.FromCenterAndSize(LengthPoint2.Origin, Length.FromMeters(2), Length.FromMeters(2));
var b = Rectangle2.FromCenterAndSize(LengthPoint2.FromMeters(1, 0), Length.FromMeters(2), Length.FromMeters(2));
if (a.TryGetManifold(b, out var manifold))
{
    Length depth = manifold.PenetrationDepth;
    Direction2 normal = manifold.ContactNormal;
}

// Raycasting
var ray = new LengthRay2(LengthPoint2.FromMeters(-10, 0), Direction2.East);
if (ray.TryIntersect(a, out var hit))
    Console.WriteLine($"Hit at {hit.Distance} from origin");

// Path following
var path = new LengthPath2(new[] {
    LengthPoint2.FromMeters(0, 0),
    LengthPoint2.FromMeters(5, 0),
    LengthPoint2.FromMeters(5, 5),
});
LengthPoint2 pos = path.Evaluate(Length.FromMeters(3));

// Convert to XNA Vector2 for rendering (pixels per metre = 64)
const double ppm = 64;
var posXna = position.ToXnaVector2(LengthUnit.Meter, ppm);

Architecture

Type model

All concrete vector types are readonly partial record struct values. Component types come from UnitsNet (Length, Speed, Force, …); DoubleVector2/DoubleVector3 hold bare Double components.

Each type is composed from three layers:

Layer Example file What it provides
Stub LengthVector2.cs Declares the type and its primary constructor
Generated LengthVector2.g.cs (build output) Arithmetic, Zero, Magnitude, As, Normalize
Hand-written partials LengthVector2.Kinematics.cs Cross-type physics operators (/ Duration → SpeedVector2)

Source generator

Thunder.UnitsNET.Vectors.Generators is a Roslyn incremental source generator. It reads every [GenerateVector2] / [GenerateVector3] attribute and emits the arithmetic partial. Consumers never reference the generator directly — it is wired as an Analyzer reference and compiled into the core DLL.

Package structure

Thunder.UnitsNET.Vectors.sln
├── src/
│   ├── Thunder.UnitsNET.Vectors/            ← published (core vectors + physics integration)
│   │   ├── Vector2/                         ← 2D quantity types + partials
│   │   └── Vector3/                         ← 3D quantity types + partials
│   ├── Thunder.UnitsNET.Vectors.MonoGame/   ← published
│   │   └── Extensions/                      ← ToXnaVector2 / ToXnaVector3
│   ├── Thunder.UnitsNET.Vectors.Geometry/   ← published (shapes, collision, raycasting, path)
│   ├── Thunder.UnitsNET.Vectors.Geometry.MonoGame/ ← published (DebugDraw, geometry → XNA)
│   ├── Thunder.UnitsNET.Vectors.Generators/ ← not published (Roslyn tooling)
│   └── Thunder.UnitsNET.Vectors.GoDot/      ← not published (incomplete scaffold)
├── tests/
│   ├── Thunder.UnitsNET.Vectors.Tests/
│   ├── Thunder.UnitsNET.Vectors.MonoGame.Tests/
│   └── Thunder.UnitsNET.Vectors.Geometry.Tests/
└── benchmarks/
    └── Thunder.UnitsNET.Vectors.Benchmarks/ ← BDN benchmarks; results in docs/benchmarks/

Supported vector types

2DDoubleVector2, LengthVector2, SpeedVector2, AccelerationVector2, ForceVector2, JerkVector2, ImpulseVector2, MagneticFieldVector2, MagnetizationVector2, LinearDensityVector2, ElectricFieldVector2

3DDoubleVector3, LengthVector3, SpeedVector3, AccelerationVector3, ForceVector3, JerkVector3, ImpulseVector3, MagneticFieldVector3, MagnetizationVector3, MassFluxVector3, ElectricFieldVector3, ElectricCurrentDensityVector3, TemperatureGradientVector3

Building and testing

Requires .NET 10 SDK.

dotnet build
dotnet test

Milestone status

See docs/STATUS.md for the current implementation status.

The full roadmap and design decisions are in docs/v0/phase4-physics/roadmap.md. Future ideas are tracked in docs/ideas.md.

Contributing

  1. Read docs/CLAUDE.md for the project conventions (branch naming, step progression, how decisions are surfaced).
  2. Each feature follows TDD: RED commit (failing build or test) → GREEN commit (passing) → merge to develop.
  3. Open a PR against develop; main is reserved for release-tagged commits.

License

MIT — see LICENSE.