Table of Contents

Struct Camera2

Namespace
Thunder.UnitsNET.Vectors.MonoGame
Assembly
Thunder.UnitsNET.Vectors.MonoGame.dll

An immutable 2D camera that converts between world-space LengthPoint2 positions and screen-space Microsoft.Xna.Framework.Vector2 pixel coordinates.

Value type: Camera2 is a readonly record struct. Declare camera fields as Camera2 (not Camera2?) and initialise them before first use — an unassigned Camera2 field is default, not null, and a default camera has Scale of zero.

public readonly record struct Camera2 : IEquatable<Camera2>
Implements
Inherited Members

Remarks

All "mutating" operations (such as ZoomBy(double)) return a new instance. Late-bound camera state (e.g. a field set after construction) will be default, not null — guard against Scale being zero before calling WorldToScreen(LengthPoint2, Vector2).

The camera is centred on Position in world space. The centre of the screen always displays the camera's world position. Points to the right of the camera appear to the right on screen; points above the camera appear higher on screen (subject to the YAxis convention).

The Scale defines the zoom level: more pixels per world unit means the world appears larger on screen (zoomed in). Use ZoomBy(double) to adjust zoom and Lerp(PixelScale, PixelScale, double) to animate it smoothly.

screenSize pattern: WorldToScreen(LengthPoint2, Vector2) and ScreenToWorld(Vector2, Vector2) require the render-target size on every call. Compute it once per frame from GraphicsDevice.Viewport and store it as a local variable rather than recalculating on every draw call:

// Compute once per frame; pass to every WorldToScreen / ScreenToWorld call:
var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);
Vector2 screenPos = camera.WorldToScreen(LengthPoint2.FromMeters(5, 3), screenSize);
// Camera centred on (5, 5) at 32 px/m, Y-down (MonoGame default).
var camera = new Camera2(LengthPoint2.FromMeters(5, 5), PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);

// Convert a world position to a screen pixel coordinate: Vector2 screenPos = camera.WorldToScreen(LengthPoint2.FromMeters(6, 6), screenSize);

// Smooth zoom toward a target scale — call each update frame: var currentScale = PixelScale.PerMeter(32); var targetScale = PixelScale.PerMeter(64); currentScale = PixelScale.Lerp(currentScale, targetScale, 0.016 * 5.0); camera = camera with { Scale = currentScale };

Constructors

Camera2(LengthPoint2, PixelScale, YAxisMode)

An immutable 2D camera that converts between world-space LengthPoint2 positions and screen-space Microsoft.Xna.Framework.Vector2 pixel coordinates.

Value type: Camera2 is a readonly record struct. Declare camera fields as Camera2 (not Camera2?) and initialise them before first use — an unassigned Camera2 field is default, not null, and a default camera has Scale of zero.

public Camera2(LengthPoint2 Position, PixelScale Scale, YAxisMode YAxis = YAxisMode.YDown)

Parameters

Position LengthPoint2

The world-space point that maps to the centre of the screen.

Scale PixelScale

The zoom level expressed as a PixelScale. For example, PixelScale.PerMeter(32) means one metre occupies 32 pixels.

YAxis YAxisMode

Whether the screen Y axis increases downward (YDown, the MonoGame default) or upward (YUp). Defaults to YDown.

Remarks

All "mutating" operations (such as ZoomBy(double)) return a new instance. Late-bound camera state (e.g. a field set after construction) will be default, not null — guard against Scale being zero before calling WorldToScreen(LengthPoint2, Vector2).

The camera is centred on Position in world space. The centre of the screen always displays the camera's world position. Points to the right of the camera appear to the right on screen; points above the camera appear higher on screen (subject to the YAxis convention).

The Scale defines the zoom level: more pixels per world unit means the world appears larger on screen (zoomed in). Use ZoomBy(double) to adjust zoom and Lerp(PixelScale, PixelScale, double) to animate it smoothly.

screenSize pattern: WorldToScreen(LengthPoint2, Vector2) and ScreenToWorld(Vector2, Vector2) require the render-target size on every call. Compute it once per frame from GraphicsDevice.Viewport and store it as a local variable rather than recalculating on every draw call:

// Compute once per frame; pass to every WorldToScreen / ScreenToWorld call:
var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);
Vector2 screenPos = camera.WorldToScreen(LengthPoint2.FromMeters(5, 3), screenSize);
// Camera centred on (5, 5) at 32 px/m, Y-down (MonoGame default).
var camera = new Camera2(LengthPoint2.FromMeters(5, 5), PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);

// Convert a world position to a screen pixel coordinate: Vector2 screenPos = camera.WorldToScreen(LengthPoint2.FromMeters(6, 6), screenSize);

// Smooth zoom toward a target scale — call each update frame: var currentScale = PixelScale.PerMeter(32); var targetScale = PixelScale.PerMeter(64); currentScale = PixelScale.Lerp(currentScale, targetScale, 0.016 * 5.0); camera = camera with { Scale = currentScale };

Properties

Position

The world-space point that maps to the centre of the screen.

public LengthPoint2 Position { get; init; }

Property Value

LengthPoint2

Scale

The zoom level expressed as a PixelScale. For example, PixelScale.PerMeter(32) means one metre occupies 32 pixels.

public PixelScale Scale { get; init; }

Property Value

PixelScale

YAxis

Whether the screen Y axis increases downward (YDown, the MonoGame default) or upward (YUp). Defaults to YDown.

public YAxisMode YAxis { get; init; }

Property Value

YAxisMode

Methods

ClampZoom(double, double)

Clamps the zoom level so that PixelsPerUnit stays within [min, max]. Position and YAxis are unchanged.

public Camera2 ClampZoom(double min, double max)

Parameters

min double

The minimum allowed pixels-per-unit value (most zoomed out). Must be positive.

max double

The maximum allowed pixels-per-unit value (most zoomed in). Must be ≥ min.

Returns

Camera2

A new Camera2 whose Scale is clamped to the given range. Returns the receiver unchanged when its zoom is already within range.

Examples

var camera  = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(128));
// Restrict zoom to between 16 and 64 px/m:
var clamped = camera.ClampZoom(16, 64);

Remarks

Prefer the ClampZoom(PixelScale, PixelScale) overload when bounds come from typed game configuration. This overload is a convenience for raw double values.

ClampZoom(PixelScale, PixelScale)

Clamps the zoom level so that PixelsPerUnit stays within [min, max]. Position and YAxis are unchanged.

public Camera2 ClampZoom(PixelScale min, PixelScale max)

Parameters

min PixelScale

The minimum allowed zoom level (most zoomed out) expressed as a PixelScale.

max PixelScale

The maximum allowed zoom level (most zoomed in) expressed as a PixelScale.

Returns

Camera2

A new Camera2 whose Scale is clamped to the given range. Returns the receiver unchanged when its zoom is already within range.

Examples

var camera  = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(128));
var clamped = camera.ClampZoom(PixelScale.PerMeter(16), PixelScale.PerMeter(64));

Remarks

Bounds are normalised to the camera's Unit before comparison, so min/max can be in any length unit. For raw pixel-per-unit double bounds, use ClampZoom(Double, Double).

Lerp(Camera2, double)

Returns a new Camera2 linearly interpolated between this instance and other at parameter t.

public Camera2 Lerp(Camera2 other, double t)

Parameters

other Camera2

The target camera state (t = 1).

t double

Interpolation parameter. 0.0 returns the receiver; 1.0 returns other. Values outside [0, 1] extrapolate.

Returns

Camera2

The interpolated Camera2.

Examples

var a = new Camera2(LengthPoint2.FromMeters(0, 0), PixelScale.PerMeter(32));
var b = new Camera2(LengthPoint2.FromMeters(10, 0), PixelScale.PerMeter(64));
var current = a.Lerp(b, 0.016 * 5.0);

Remarks

Both Position and PixelsPerUnit are interpolated. YAxis is taken from the receiver and is not interpolated. Prefer the Lerp(Camera2, Ratio) overload when the interpolation factor comes from typed game state.

Lerp(Camera2, Ratio)

Returns a new Camera2 linearly interpolated between this instance and other at parameter t.

public Camera2 Lerp(Camera2 other, Ratio t)

Parameters

other Camera2

The target camera state (t = 1).

t Ratio

Interpolation parameter as a UnitsNet.Ratio. A decimal-fraction value of 0 returns the receiver; 1 returns other.

Returns

Camera2

The interpolated Camera2.

Examples

var a = new Camera2(LengthPoint2.FromMeters(0, 0), PixelScale.PerMeter(32));
var b = new Camera2(LengthPoint2.FromMeters(10, 0), PixelScale.PerMeter(64));
var current = a.Lerp(b, Ratio.FromDecimalFractions(0.08));

Remarks

Both Position and PixelsPerUnit are interpolated. YAxis is taken from the receiver and is not interpolated.

ScreenToWorld(Vector2, Vector2)

Converts a screen-space pixel coordinate back to a world-space position.

public LengthPoint2 ScreenToWorld(Vector2 screenPoint, Vector2 screenSize)

Parameters

screenPoint Vector2

The pixel coordinate on the screen.

screenSize Vector2

The size of the render target in pixels (width, height). Must match the value passed to WorldToScreen(LengthPoint2, Vector2) to get an exact inverse.

Returns

LengthPoint2

The world-space LengthPoint2 corresponding to the screen pixel, expressed in Unit.

Examples

var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);
LengthPoint2 worldMouse = camera.ScreenToWorld(new Vector2(960, 540), screenSize);

Remarks

This is the exact inverse of WorldToScreen(LengthPoint2, Vector2): ScreenToWorld(WorldToScreen(p, size), size) ≈ p within floating-point precision. Typical use is mouse picking — convert the cursor's screen position to a world coordinate to test against game objects.

TranslateBy(LengthVector2)

Returns a new Camera2 with Position shifted by delta. Scale and YAxis are unchanged.

public Camera2 TranslateBy(LengthVector2 delta)

Parameters

delta LengthVector2

The world-space displacement to apply.

Returns

Camera2

A new Camera2 with the adjusted Position.

Examples

var camera = new Camera2(LengthPoint2.FromMeters(5, 3), PixelScale.PerMeter(32));
var moved = camera.TranslateBy(LengthVector2.FromMeters(0.1, 0));

TranslateTo(LengthPoint2)

Returns a new Camera2 with Position set to destination. Scale and YAxis are unchanged.

public Camera2 TranslateTo(LengthPoint2 destination)

Parameters

destination LengthPoint2

The world-space point to centre the camera on.

Returns

Camera2

A new Camera2 centred on destination.

Examples

var camera  = new Camera2(LengthPoint2.FromMeters(2, 3), PixelScale.PerMeter(32));
var focused = camera.TranslateTo(LengthPoint2.FromMeters(7, -1));

Remarks

Complements TranslateBy(LengthVector2) for absolute positioning: use TranslateTo when you know the target world coordinate, and TranslateBy when you have an incremental displacement.

WorldToScreen(LengthPoint2, Vector2)

Converts a world-space position to a screen-space pixel coordinate.

public Vector2 WorldToScreen(LengthPoint2 worldPoint, Vector2 screenSize)

Parameters

worldPoint LengthPoint2

The position in world space to project.

screenSize Vector2

The size of the render target in pixels (width, height). The screen centre is at screenSize / 2.

Returns

Vector2

The pixel coordinate on screen. The screen centre corresponds to Position. Values outside [0, screenSize] are off-screen but valid — callers may clip as needed.

Examples

var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
Vector2 px = camera.WorldToScreen(LengthPoint2.FromMeters(1, 0), new Vector2(1920, 1080));

WorldToScreenScale(Length)

Converts a world-space length (such as a shape radius) to a pixel size for rendering.

public float WorldToScreenScale(Length worldLength)

Parameters

worldLength Length

The length in world space to convert.

Returns

float

The equivalent size in pixels as a float. Lengths in units other than Unit are automatically converted.

Examples

var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
Single pixelRadius = camera.WorldToScreenScale(Length.FromMeters(2));

Remarks

Use this when you need a scalar pixel size rather than a position — for example, to compute the pixel radius of a Circle2 for drawing. Y-axis mode does not affect this result; lengths are always positive.

ZoomBy(double)

Returns a new Camera2 with the zoom level multiplied by factor. Position and YAxis are unchanged.

public Camera2 ZoomBy(double factor)

Parameters

factor double

The zoom multiplier. Values greater than 1.0 zoom in (more pixels per unit); values between 0 and 1.0 zoom out (fewer pixels per unit).

Returns

Camera2

A new Camera2 with the adjusted Scale.

Examples

var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
// Zoom in 10%
camera = camera.ZoomBy(1.1);

ZoomBy(double, Vector2, Vector2)

Returns a new Camera2 zoomed by factor, adjusted so that screenFocus remains at the same world position before and after the zoom.

public Camera2 ZoomBy(double factor, Vector2 screenFocus, Vector2 screenSize)

Parameters

factor double

The zoom multiplier. Values greater than 1.0 zoom in; values between 0 and 1.0 zoom out. Must be positive and non-zero.

screenFocus Vector2

The screen-space pixel coordinate that should stay fixed during the zoom — typically the cursor position or the centre of a pinch gesture.

screenSize Vector2

The size of the render target in pixels (width, height). For high-frequency render loops, compute this once per frame and pass it in rather than recalculating it on every call.

Returns

Camera2

A new Camera2 whose Scale has been multiplied by factor and whose Position has been adjusted so that the world point under screenFocus is unchanged.

Examples

var camera = new Camera2(LengthPoint2.Origin, PixelScale.PerMeter(32));
var screenSize = new Vector2(1920, 1080);
// Zoom in 2× toward the screen centre
var zoomed = camera.ZoomBy(2.0, new Vector2(960, 540), screenSize);

Remarks

The adjustment formula is: newPosition = worldFocus + (oldPosition − worldFocus) / factor, where worldFocus = ScreenToWorld(screenFocus, screenSize) on the pre-zoom camera.

factor is a raw double multiplier rather than a Ratio because it represents a scale change, not a fractional quantity.

v0.7.0 ▼