Math module
This module provides essential math functions for common calculations, such as angle conversions, interpolation, movement, and vector operations.
To add this module to your project, add the following line to your project file:
require engine.math.math_utils // or require engine.core
Constants
- HALF_PI = 1.5707964f
An angle in radians equal to 90 degrees
- TWO_PI = 6.2831855f
An angle in radians equal to 360 degrees
- TO_DEG = 57.295776f
A multiplier to convert radians to degrees
- TO_RAD = 0.017453292f
A multiplier to convert degrees to radians
- RIGHT = float3(1f, 0f, 0f)
The right direction vector.
- UP = float3(0f, 1f, 0f)
The up direction vector.
- FORWARD = float3(0f, 0f, 1f)
The forward direction vector.
- LEFT = float3(-1f, -0f, -0f)
The left direction vector.
- DOWN = float3(-0f, -1f, -0f)
The down direction vector.
- BACKWARD = float3(-0f, -0f, -1f)
The backward direction vector.
- ONE = float3(1f, 1f, 1f)
The one vector.
- ZERO = float3(0f, 0f, 0f)
The zero vector.
Structures
- Ray
Represents a ray in 3D space.
- Fields:
origin : float3 - The origin point of the ray
direction : float3 - The direction vector of the ray
- BBox3D
Represents an axis-aligned bounding box in 3D space.
- Fields:
min : float3 - The minimum point of the bounding box
max : float3 - The maximum point of the bounding box
- BSphere3D
Represents a bounding sphere in 3D space.
- Fields:
center : float3 - The center of the bounding sphere
radius : float - The radius of the bounding sphere
Functions
move_to (from: float; to: float; dt: float; velocity: float) : float
angle_move_to (from: float; to: float; dt: float; velocity: float) : float
angle_approach (from_radians: float; to_radians: float; dt: float; half_life: float) : float
move_to (from: float2|float3|float4; to: float2|float3|float4; dt: float; velocity: float) : auto
distance_to_segment (a: float2|float3; b: float2|float3; point: float2|float3) : float
ray_intersect_plane (ray: Ray; planePoint: float3; planeNormal: float3; var res: float3&) : bool
triangulate_poly (points: array<Point2>; block: block<(array<uint3>#):void>)
- Ray(origin: float3; direction: float3): Ray
Creates a new Ray instance with the given origin and direction
- Arguments:
origin : float3 - the origin point of the ray
direction : float3 - the direction vector of the ray. The direction argument is not normalized internally
- Returns:
Ray - a new Ray instance
- BBox3D(min: float3; max: float3): BBox3D
Creates a new BBox3D instance with the given minimum and maximum points
- Arguments:
min : float3 - the minimum point of the bounding box
max : float3 - the maximum point of the bounding box
- Returns:
BBox3D - a new BBox3D instance
- BBox3D(): BBox3D
Creates a new BBox3D instance with default values (min = float3(FLT_MAX), max = float3(-FLT_MAX))
- Returns:
BBox3D - a new BBox3D instance with default values
- reset(box: BBox3D)
Sets the bounding box to a default invalid state (min = float3(FLT_MAX), max = float3(-FLT_MAX)).
- Arguments:
box : BBox3D - the bounding box to set to default
- valid(box: BBox3D): bool
Checks if the bounding box is valid (non-degenerate).
- Arguments:
box : BBox3D - the bounding box to check
- Returns:
bool - true if the bounding box is valid, false otherwise
- BBox3D.center(box: BBox3D): float3
Returns the center point of the bounding box.
- Arguments:
box : BBox3D
- BBox3D.size(box: BBox3D): float3
Returns the size of the bounding box.
- Arguments:
box : BBox3D
- add_point(box: BBox3D; point: float3)
Adds a point to the bounding box, expanding it if necessary.
- Arguments:
box : BBox3D - the bounding box to add the point to
point : float3 - the point to add to the bounding box
- add_box(box: BBox3D; other: BBox3D)
Adds another bounding box to the current bounding box, expanding it if necessary.
- Arguments:
- contains(box: BBox3D; point: float3): bool
Checks if the bounding box contains a point.
- Arguments:
box : BBox3D - the bounding box to check
point : float3 - the point to check
- Returns:
bool - true if the bounding box contains the point, false otherwise
- intersects(box1: BBox3D; box2: BBox3D): bool
Checks if two bounding boxes intersect.
- Arguments:
- Returns:
bool - true if the bounding boxes intersect, false otherwise
- intersection(box1: BBox3D; box2: BBox3D): BBox3D
Returns the intersection of two bounding boxes. If they do not intersect, the result will be an invalid bounding box.
- Arguments:
- Returns:
BBox3D - a new BBox3D representing the intersection of the two bounding boxes
- BSphere3D(center: float3; radius: float): BSphere3D
Creates a new BSphere3D instance with the given center and radius
- Arguments:
center : float3 - the center of the bounding sphere
radius : float - the radius of the bounding sphere
- Returns:
BSphere3D - a new BSphere3D instance
- BSphere3D(): BSphere3D
Creates a new BSphere3D instance with default values (center = float3(0), radius = -FLT_MAX)
- Returns:
BSphere3D - a new BSphere3D instance with default values
- reset(sphere: BSphere3D)
Sets the bounding sphere to a default invalid state (center = float3(0), radius = -FLT_MAX).
- Arguments:
sphere : BSphere3D - the bounding sphere to set to default
- valid(sphere: BSphere3D): bool
Checks if the bounding sphere is valid (non-degenerate).
- Arguments:
sphere : BSphere3D - the bounding sphere to check
- Returns:
bool - true if the bounding sphere is valid, false otherwise
- add_point(sphere: BSphere3D; point: float3)
Adds a point to the bounding sphere, expanding it if necessary.
- Arguments:
sphere : BSphere3D - the bounding sphere to add the point to
point : float3 - the point to add to the bounding sphere
- add_sphere(sphere: BSphere3D; other: BSphere3D)
Adds another bounding sphere to the current bounding sphere, expanding it if necessary.
- Arguments:
- contains(sphere: BSphere3D; point: float3): bool
Checks if the bounding sphere contains a point.
- Arguments:
sphere : BSphere3D - the bounding sphere to check
point : float3 - the point to check
- Returns:
bool - true if the bounding sphere contains the point, false otherwise
- intersects(sphere1: BSphere3D; sphere2: BSphere3D): bool
Checks if two bounding spheres intersect.
- Arguments:
- Returns:
bool - true if the bounding spheres intersect, false otherwise
- move_to(from: float; to: float; dt: float; velocity: float): float
Returns the position after moving from one point in the direction of another with given velocity during the time interval. Note that the velocity should be non-negative
- Arguments:
from : float - the starting point
to : float - the target point
dt : float - the time interval
velocity : float - the velocity of the movement
- Returns:
float - the new position after moving from the starting point in the direction of the target point with the given velocity during the time interval
Usage example:
let from = 0.0
let to = 10.0
let new_position = move_to(from, to, 0.5, 6.) // new_position == 3.0
- smoothstep(edge0: float; edge1: float; x: float): float
Performs smooth Hermite interpolation between two values
- Arguments:
edge0 : float - the lower edge of the interpolation range
edge1 : float - the upper edge of the interpolation range
x : float - the value to interpolate
- Returns:
float - the interpolated value
Usage example:
let edge0 = 1.0
let edge1 = 2.0
let interpolated_value = smoothstep(edge0, edge1, 0.2) // interpolated_value == 1.104
- smoothstep(x: float): float
Performs smooth Hermite interpolation between 0 and 1
- Arguments:
x : float - the value to interpolate
- Returns:
float - the interpolated value
Usage example:
let interpolated_value = smoothstep(0.2) // interpolated_value == 0.104
- angle_to_direction(angle: float): float2
Converts an angle in radians to a direction vector
- Arguments:
angle : float - the angle in radians
- Returns:
float2 - the direction vector
Usage example:
let direction1 = angle_to_direction(PI * 0.5) // direction1 == float2(0, 1)
let direction2 = angle_to_direction(PI) // direction2 == float2(-1, 0)
- normalize_angle(angle: float): float
Clamps an angle to the range [-PI, PI]
- Arguments:
angle : float - the angle to normalize
- Returns:
float - the normalized angle
Usage example:
let normalized_angle = normalize_angle(7.5 * PI) // normalized_angle == -0.5 * PI
- angle_diff(source: float; target: float): float
Returns the difference between two angles in radians in the range [-PI, PI]
- Arguments:
source : float - the source angle
target : float - the target angle
- Returns:
float - the difference between the source and target angles
Usage example:
let angle = angle_diff(PI / 6., 1.5 * PI) // angle == 2. * PI / 3.
- angle_move_to(from: float; to: float; dt: float; velocity: float): float
Returns the angle after moving from one angle to another with given angular velocity during the time interval. Note that the velocity should be non-negative
- Arguments:
from : float - the starting angle
to : float - the target angle
dt : float - the time interval
velocity : float - the angular velocity of the movement
- Returns:
float - the new angle after moving from the starting angle to the target angle with the given angular velocity during the time interval
Usage example:
let from = 0.0
let to = PI
let new_angle = angle_move_to(from, to, 0.5, PI) // new_angle == PI / 2.
- angle_approach(from_radians: float; to_radians: float; dt: float; half_life: float): float
Returns the angle after moving from one angle to another with given half-life during the time interval, using exponential time-independent approach. It is used to smoothly move an angle, so that in a half_life period of time the angle will pass half of the path
- Arguments:
from_radians : float - the starting angle in radians
to_radians : float - the target angle in radians
dt : float - the time interval
half_life : float - the half-life of the approach
- Returns:
float - the new angle after moving from the starting angle to the target angle with the given half-life during the time interval
- project(vec: float2; normal: float2): float2
Projects the two-dimensional vector onto the line defined by the normal (note that the normal must be normalized)
- Arguments:
vec : float2 - the vector to project
normal : float2 - the normal of the line to project onto
- Returns:
float2 - the projected vector
Usage example:
let vec = float2(4, 2)
let normal = float2(0.6, 0.8)
let projected_vec = project(vec, normal) // projected_vec == float2(1.6, -1.2)
- project(vec: float3; normal: float3): float3
Projects the three-dimensional vector onto the plane defined by the normal (note that the normal must be normalized)
- Arguments:
vec : float3 - the vector to project
normal : float3 - the normal of the plane to project onto
- Returns:
float3 - the projected vector
Usage example:
let vec = float3(4, 2, 1)
let normal = float3(0.6, 0.8, 0)
let projected_vec = project(vec, normal) // projected_vec == float3(1.6, -1.2, 1)
- safediv(a: float; b: float): float
Safely divides two floats, returning 0 if the denominator is zero to avoid division by zero errors.
- Arguments:
a : float
b : float
- safediv(a: float2; b: float): float2
Safely divides a float2 by a float, returning a zero vector if the denominator is zero to avoid division by zero errors.
- Arguments:
a : float2
b : float
- safediv(a: float3; b: float): float3
Safely divides a float3 by a float, returning a zero vector if the denominator is zero to avoid division by zero errors.
- Arguments:
a : float3
b : float
- safediv(a: float4; b: float): float4
Safely divides a float4 by a float, returning a zero vector if the denominator is zero to avoid division by zero errors.
- Arguments:
a : float4
b : float
- convert_world_to_screen(resolution: int2; viewport: float4; znear: float; zfar: float; worldToScreen: float4x4; orthographic: bool; worldPosition: float3): float3
Converts a world position to screen coordinates.
- Arguments:
resolution : int2 - the resolution of the screen
viewport : float4 - the viewport
znear : float - the near clipping plane
zfar : float - the far clipping plane
worldToScreen : float4x4 - the world to screen matrix
orthographic : bool - whether the projection is orthographic
worldPosition : float3 - the world position to convert
- Returns:
float3 - a float3 representing the converted screen coordinates, z component is linear depth from camera
- convert_screen_to_world(resolution: int2; viewport: float4; znear: float; zfar: float; screenToWorld: float4x4; orthographic: bool; screenPosition: float3): float3
Converts screen coordinates to a world position.
- Arguments:
resolution : int2 - the resolution of the screen
viewport : float4 - the viewport
znear : float - the near clipping plane
zfar : float - the far clipping plane
screenToWorld : float4x4 - the screen to world matrix
orthographic : bool - whether the projection is orthographic
screenPosition : float3 - the screen coordinates to convert, z component is linear depth from camera
- Returns:
float3 - a float3 representing the converted world position
- deg_to_rad(deg: float|float2|float3|float4): auto
Converts degrees to radians
- Arguments:
deg : option<float|float2|float3|float4>
- rad_to_deg(rad: float|float2|float3|float4): auto
Converts radians to degrees
- Arguments:
rad : option<float|float2|float3|float4>
- sqr(x: int|double|float|float2|float3|float4): auto
Returns the square of the value
- Arguments:
x : option<int|double|float|float2|float3|float4>
- cvt(t: float; min_t: float; max_t: float; from: float|float2|float3|float4; to: float|float2|float3|float4): auto
Linearly interpolates between two points, returning the point between them that corresponds to the given value in the given range. The result is clamped to the segment between the two points
- Arguments:
t : float - the value in the range [min_t, max_t]
min_t : float - the minimum value of the range
max_t : float - the maximum value of the range
from : option<float|float2|float3|float4> - the starting point
to : option<float|float2|float3|float4> - the target point
- Returns:
auto - the point between the starting and target points that has the same relative position as the given value in the given range
Usage example:
let from = float2(1, 1)
let to = float2(4, 5)
let point = cvt(0.5, 0., 1., from, to) // point == float2(2.5, 3)
- approach(from: float|float2|float3|float4; to: float|float2|float3|float4; dt: float; half_life: float): auto
Returns the position after moving from one point to another with given half-life during the time interval, using exponential time-independent approach. It is used to smoothly move a point, so that in a half_life period of time the point will pass half of the path
- Arguments:
from : option<float|float2|float3|float4> - the starting point
to : option<float|float2|float3|float4> - the target point
dt : float - the time interval
half_life : float - the half-life of the approach
- Returns:
auto - the new position after moving from the starting point to the target point with the given half-life during the time interval
- move_to(from: float2|float3|float4; to: float2|float3|float4; dt: float; velocity: float): auto
Returns the position after moving from one point in the direction of another with given velocity during the time interval. Note that the velocity should be non-negative
- Arguments:
from : option<float2|float3|float4> - the starting point
to : option<float2|float3|float4> - the target point
dt : float - the time interval
velocity : float - the velocity of the movement
- Returns:
auto - the new position after moving from the starting point in the direction of the target point with the given velocity during the time interval
Usage example:
let from = float2(0, 0)
let to = float2(10, 10)
let new_position = move_to(from, to, 0.5, 6.) // new_position == float2(3, 3)
- distance_to_segment(a: float2|float3; b: float2|float3; point: float2|float3): float
Returns the distance between a point and a segment defined by two points
- Arguments:
a : option<float2|float3> - the starting point of the segment
b : option<float2|float3> - the ending point of the segment
point : option<float2|float3> - the point to calculate distance from
- Returns:
float - the distance between the point and the segment
- ray_intersect_plane(ray: Ray; planePoint: float3; planeNormal: float3; res: float3&): bool
Intersects a ray with a plane.
- Arguments:
ray : Ray - The ray to intersect
planePoint : float3 - A point on the plane
planeNormal : float3 - The normal of the plane
res : float3& - The intersection point
- Returns:
bool - True if the ray intersects the plane, false otherwise
- triangulate_poly(points: array<Point2>; block: block<(array<uint3>#):void>)
Triangulates the polygon and returns the indices of the vertices that make up each triangle.
- Arguments:
points : array< Point2 > implicit - the points of the polygon
block : block<(array<uint3>#):void> implicit - the block to call for the resulting array of indices
Usage example:
triangulate_poly(polygonPoints) $(triangulationIndices) {
for (triangle in triangulationIndices) {
// do something with each triangle
}
}