No description
Find a file
Thunder 7749595905
All checks were successful
Release / push-nuget (push) Successful in 29s
Release / deploy-docs (push) Successful in 1m27s
Release / merge-to-main (push) Successful in 5s
Release / build (push) Successful in 1m52s
chore: merge Phase 7 (v0.7.0) to main
Phase 7 — Smooth Traversal

- M35: Camera2.TranslateTo, ClampZoom, Lerp(Ratio), PixelScale.PerUnit, PixelScale.Clamp
- M36: Angular dynamics SI-only <remarks> docs (DocSnippets-tested)
- M37: EvaluateAtLength/TangentAtLength on BezierCurve2 and CatmullRomSpline2; LengthPath2.FromArc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 12:20:15 -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 7 post-phase completion steps 2026-05-05 12:20:09 -05:00
samples M21.2 S1 GREEN: generator emits From* factories for all 23 vector types 2026-04-19 05:56:21 -05:00
src feat(GREEN): M37-S3 LengthPath2.FromArc 2026-05-04 21:40:59 -05:00
tests test(RED): M37-S3 LengthPath2.FromArc 2026-05-04 21:40:08 -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.