-
Notifications
You must be signed in to change notification settings - Fork 0
Core.Utilities.PrimitivesHelper
The PrimitivesHelper class in the Meatcorps.Engine.Core.Utilities namespace provides a set of high-performance utility functions for geometric calculations, primarily focusing on 2D intersection tests, transformations, and distance calculations involving rectangles and points.
Here is an explanation of each static function with usage examples:
This method implements a 1D ray-slab intersection test. It is typically used as a building block for 2D or 3D Ray-vs-AABB (Axis-Aligned Bounding Box) intersection algorithms (like the Kay-Kajiya slab method). It updates the entry and exit distances of a ray as it passes through a "slab" (the space between two parallel planes).
-
Logic: It calculates where the ray enters and exits the slab on a single axis and narrows the provided
rayMinimumDistanceandrayMaximumDistance. -
Example: Checking if a ray starting at
$x=0$ moving right intersects a slab between$x=10$ and$x=20$ .
float rayMin = float.MinValue;
float rayMax = float.MaxValue;
bool intersects = PrimitivesHelper.IntersectsSlab(
positionCoordinate: 0f,
directionCoordinate: 1f,
slabMinimum: 10f,
slabMaximum: 20f,
ref rayMin,
ref rayMax
);
// Result: intersects = true, rayMin = 10, rayMax = 20Generates an Axis-Aligned Bounding Box (AABB) that perfectly encapsulates a collection of points.
- Logic: It iterates through the list once, finding the minimum and maximum X and Y values.
- Example: Finding the bounds of a polygon or a path.
var points = new List<Vector2> { new(0, 5), new(10, 2), new(-5, 0) };
PrimitivesHelper.CreateRectangleFromPoints(points, out Vector2 min, out Vector2 max);
// Result: min = (-5, 0), max = (10, 5)Applies a transformation matrix to an AABB and outputs a new AABB that encloses the transformed original. Note that if you rotate an AABB, the resulting axis-aligned box will usually be larger to stay aligned with the axes.
- Logic: It transforms the center and then calculates new half-extents based on the absolute values of the matrix components to ensure the box remains axis-aligned.
- Example: Updating a physics hitbox after a character rotates.
Vector2 center = new(10, 10);
Vector2 halfExtents = new(5, 5); // A 10x10 box
Matrix3x2 rotation = Matrix3x2.CreateRotation((float)Math.PI / 4); // 45 degrees
PrimitivesHelper.TransformRectangle(ref center, ref halfExtents, ref rotation);
// halfExtents will be larger now to accommodate the rotated corners while remaining axis-aligned.Transforms the center and the orientation matrix of an Oriented Bounding Box (OBB). Unlike TransformRectangle, this keeps the box "tilted" relative to the axes.
- Logic: It transforms the center point and multiplies the existing orientation matrix by the new transform matrix.
- Example: Moving and rotating a vehicle that has a fixed-size local bounding box.
Vector2 center = new(0, 0);
Matrix3x2 orientation = Matrix3x2.Identity;
Matrix3x2 moveAndRotate = Matrix3x2.CreateRotation(1f) * Matrix3x2.CreateTranslation(10, 5);
PrimitivesHelper.TransformOrientedRectangle(ref center, ref orientation, ref moveAndRotate);Calculates the squared Euclidean distance from a specific point to the nearest edge/corner of an AABB.
-
Logic: It returns
0if the point is inside the rectangle. Using squared distance is a performance optimization to avoid an expensiveMath.Sqrtcall when you only need to compare distances (e.g., "is the point within range?"). - Example: Checking if a player is close to a treasure chest.
Vector2 min = new(0, 0);
Vector2 max = new(10, 10);
Vector2 point = new(12, 0); // 2 units to the right of the box
float distSq = PrimitivesHelper.SquaredDistanceToPointFromRectangle(min, max, point);
// Result: 4.0f (which is 2 squared)Finds the point inside or on the boundary of an AABB that is closest to an external point. This is effectively a "clamp" operation for a 2D vector against a box.
- Logic: If the point is outside, it "snaps" it to the nearest edge. If the point is inside, the result is the point itself.
- Example: Constraining a crosshair within a screen boundary or finding the impact point of an explosion on a wall.
Vector2 min = new(0, 0);
Vector2 max = new(100, 100);
Vector2 mousePos = new(150, 50);
PrimitivesHelper.ClosestPointToPointFromRectangle(min, max, mousePos, out Vector2 result);
// Result: (100, 50) - the point was clamped to the right edge