pub struct Vec2 {
pub x: Fixed,
pub y: Fixed,
}Expand description
A two-dimensional vector.
§Contract
- Every operation is deterministic, because every operation is
Fixedarithmetic and nothing else. - Saturating throughout, inheriting the scalar’s behaviour: a component that overflows clamps and is counted rather than wrapping.
EqandHash, so a vector can be a map key or enter a state hash directly — which is the thing a float vector cannot offer.
Fields§
§x: Fixed§y: FixedImplementations§
Source§impl Vec2
impl Vec2
Sourcepub const fn from_ints(x: i32, y: i32) -> Self
pub const fn from_ints(x: i32, y: i32) -> Self
From whole numbers, which is how most call sites write a constant.
Sourcepub fn cross(self, other: Self) -> Fixed
pub fn cross(self, other: Self) -> Fixed
The 2D cross product: a scalar, the z of the 3D cross of these vectors
lifted into the plane. Positive when other is counter-clockwise of
self, which is what a winding test reads.
Sourcepub fn length_squared(self) -> Fixed
pub fn length_squared(self) -> Fixed
The squared length.
Preferred over Vec2::length wherever a comparison will do, and not
only for speed: this is exact where the length is rounded, so two
vectors that compare equal by squared length may compare unequal by
length.
Sourcepub fn length_squared_wide(self) -> Wide
pub fn length_squared_wide(self) -> Wide
The squared length at full width, which cannot overflow and cannot round.
The form to compare with. Vec2::length_squared narrows to a
Fixed and therefore has a floor: a vector whose components are all
below 182 raw units squares to zero there, which is how a direction
can appear to have no length at all. Nothing is lost here.
Sourcepub fn length(self) -> Fixed
pub fn length(self) -> Fixed
The length, floored to the representable value below the exact one.
Computed through the full-width square, so it is exact for short vectors where narrowing first would have lost them entirely — a one-raw-unit vector has length one here and had length zero before.
Sourcepub fn normalize(self) -> Option<Self>
pub fn normalize(self) -> Option<Self>
A unit vector in the same direction, or None for the zero vector.
Fallible rather than asserting, because the zero vector is a value a simulation legitimately produces — a body at rest, a contact between coincident points — and refusing it would put an assertion on a path that runs every frame.
The result is unit-length to within four parts in 65536, which is
asserted by a property test over every magnitude including the
shortest. Callers wanting an exact equality should compare squared
lengths against a tolerance rather than expecting Fixed::ONE.
The direction is scaled up before its length is taken, and that is not an optimisation. Shifting a fixed-point value left is exact, and without it a short direction is divided by a length that rounded to something far too coarse: before this, a direction of 41 raw units came back as a normal forty-one per cent too long, and anything whose components were all below 181 raw had no direction at all.
Sourcepub fn lerp(self, other: Self, t: Fixed) -> Self
pub fn lerp(self, other: Self, t: Fixed) -> Self
Linear interpolation, t clamped to [0, 1].
Written as a + (b - a) * t rather than a*(1-t) + b*t: the second is
the numerically better form in floating point and the worse one here,
because it rounds twice as often and neither form gains anything from
exactness at the endpoints — this one is exact at both by construction.
Sourcepub fn project_onto_unit(self, direction: Self) -> Self
pub fn project_onto_unit(self, direction: Self) -> Self
The component of self along direction, which must be unit-length.
The building block of move-and-slide: removing this from a displacement is what makes a body slide along a wall rather than stop at it.
Sourcepub fn slide_along(self, normal: Self) -> Self
pub fn slide_along(self, normal: Self) -> Self
self with its component along normal removed.
normal must be unit-length. This is the slide operation itself, named
so the physics implementation does not spell it out at each call site
and get the sign wrong at one of them.
Sourcepub fn rotate(self, angle: Angle) -> Self
pub fn rotate(self, angle: Angle) -> Self
Rotated counter-clockwise by angle.
The standard rotation, in fixed point: (x cos − y sin, x sin + y cos). Each component is two rounded products, so a rotated vector
keeps its length to a few parts in 65536 rather than exactly — the
tests state the bound.
Vec2::perpendicular remains for the quarter turn, and is not the
same thing: it is exact, where this rounds.
Sourcepub fn perpendicular(self) -> Self
pub fn perpendicular(self) -> Self
Perpendicular, rotated a quarter turn counter-clockwise.
Exact — a quarter turn is a swap and a negation, needing no trigonometry, which is why this is available when general rotation is not.
Trait Implementations§
impl Copy for Vec2
impl Eq for Vec2
Source§impl Mul<Fixed> for Vec2
Scaled by a scalar. Saturating componentwise, like everything else here.
impl Mul<Fixed> for Vec2
Scaled by a scalar. Saturating componentwise, like everything else here.