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

2D — DoubleVector2, LengthVector2, SpeedVector2, AccelerationVector2, ForceVector2, JerkVector2, ImpulseVector2, MagneticFieldVector2, MagnetizationVector2, LinearDensityVector2, ElectricFieldVector2

3D — DoubleVector3, 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.