.. _stdlib_math_utils: =========== 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 +++++++++ .. _global-math_utils-HALF_PI: .. das:attribute:: HALF_PI = 1.5707964f An angle in radians equal to 90 degrees .. _global-math_utils-TWO_PI: .. das:attribute:: TWO_PI = 6.2831855f An angle in radians equal to 360 degrees .. _global-math_utils-TO_DEG: .. das:attribute:: TO_DEG = 57.295776f A multiplier to convert radians to degrees .. _global-math_utils-TO_RAD: .. das:attribute:: TO_RAD = 0.017453292f A multiplier to convert degrees to radians .. _global-math_core-RIGHT: .. das:attribute:: RIGHT = float3(1f,0f,0f) The right direction vector. .. _global-math_core-UP: .. das:attribute:: UP = float3(0f,1f,0f) The up direction vector. .. _global-math_core-FORWARD: .. das:attribute:: FORWARD = float3(0f,0f,1f) The forward direction vector. .. _global-math_core-LEFT: .. das:attribute:: LEFT = float3(-1f,-0f,-0f) The left direction vector. .. _global-math_core-DOWN: .. das:attribute:: DOWN = float3(-0f,-1f,-0f) The down direction vector. .. _global-math_core-BACKWARD: .. das:attribute:: BACKWARD = float3(-0f,-0f,-1f) The backward direction vector. .. _global-math_core-ONE: .. das:attribute:: ONE = float3(1f,1f,1f) The one vector. .. _global-math_core-ZERO: .. das:attribute:: ZERO = float3(0f,0f,0f) The zero vector. ++++++++++ Structures ++++++++++ .. _struct-math_utils-Ray: .. das:attribute:: Ray Represents a ray in 3D space. :Fields: * **origin** : float3 - The origin point of the ray * **direction** : float3 - The direction vector of the ray .. _struct-math_utils-BBox3D: .. das:attribute:: 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 .. _struct-math_utils-BSphere3D: .. das:attribute:: 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 +++++++++ * :ref:`Ray (origin: float3; direction: float3) : Ray ` * :ref:`BBox3D (min: float3; max: float3) : BBox3D ` * :ref:`BBox3D () : BBox3D ` * :ref:`reset (var box: BBox3D) ` * :ref:`valid (box: BBox3D) : bool ` * :ref:`BBox3D.center (box: BBox3D) : float3 ` * :ref:`BBox3D.size (box: BBox3D) : float3 ` * :ref:`add_point (var box: BBox3D; point: float3) ` * :ref:`add_box (var box: BBox3D; other: BBox3D) ` * :ref:`contains (box: BBox3D; point: float3) : bool ` * :ref:`intersects (box1: BBox3D; box2: BBox3D) : bool ` * :ref:`intersection (box1: BBox3D; box2: BBox3D) : BBox3D ` * :ref:`BSphere3D (center: float3; radius: float) : BSphere3D ` * :ref:`BSphere3D () : BSphere3D ` * :ref:`reset (var sphere: BSphere3D) ` * :ref:`valid (sphere: BSphere3D) : bool ` * :ref:`add_point (var sphere: BSphere3D; point: float3) ` * :ref:`add_sphere (var sphere: BSphere3D; other: BSphere3D) ` * :ref:`contains (sphere: BSphere3D; point: float3) : bool ` * :ref:`intersects (sphere1: BSphere3D; sphere2: BSphere3D) : bool ` * :ref:`move_to (from: float; to: float; dt: float; velocity: float) : float ` * :ref:`smoothstep (edge0: float; edge1: float; x: float) : float ` * :ref:`smoothstep (x: float) : float ` * :ref:`angle_to_direction (angle: float) : float2 ` * :ref:`normalize_angle (angle: float) : float ` * :ref:`angle_diff (source: float; target: float) : float ` * :ref:`angle_move_to (from: float; to: float; dt: float; velocity: float) : float ` * :ref:`angle_approach (from_radians: float; to_radians: float; dt: float; half_life: float) : float ` * :ref:`project (vec: float2; normal: float2) : float2 ` * :ref:`project (vec: float3; normal: float3) : float3 ` * :ref:`safediv (a: float; b: float) : float ` * :ref:`safediv (a: float2; b: float) : float2 ` * :ref:`safediv (a: float3; b: float) : float3 ` * :ref:`safediv (a: float4; b: float) : float4 ` * :ref:`convert_world_to_screen (resolution: int2; viewport: float4; znear: float; zfar: float; worldToScreen: float4x4; orthographic: bool; worldPosition: float3) : float3 ` * :ref:`convert_screen_to_world (resolution: int2; viewport: float4; znear: float; zfar: float; screenToWorld: float4x4; orthographic: bool; screenPosition: float3) : float3 ` * :ref:`deg_to_rad (deg: float|float2|float3|float4) : auto ` * :ref:`rad_to_deg (rad: float|float2|float3|float4) : auto ` * :ref:`sqr (x: int|double|float|float2|float3|float4) : auto ` * :ref:`cvt (t: float; min_t: float; max_t: float; from: float|float2|float3|float4; to: float|float2|float3|float4) : auto ` * :ref:`approach (from: float|float2|float3|float4; to: float|float2|float3|float4; dt: float; half_life: float) : auto ` * :ref:`move_to (from: float2|float3|float4; to: float2|float3|float4; dt: float; velocity: float) : auto ` * :ref:`distance_to_segment (a: float2|float3; b: float2|float3; point: float2|float3) : float ` * :ref:`ray_intersect_plane (ray: Ray; planePoint: float3; planeNormal: float3; var res: float3&) : bool ` * :ref:`triangulate_poly (points: array\; block: block\<(array\#):void\>) ` .. _function-math_utils_Ray_float3_float3: .. das:function:: 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: * :ref:`Ray ` - a new Ray instance .. _function-math_utils_BBox3D_float3_float3: .. das:function:: 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: * :ref:`BBox3D ` - a new BBox3D instance .. _function-math_utils_BBox3D: .. das:function:: BBox3D() : BBox3D Creates a new BBox3D instance with default values (min = float3(FLT_MAX), max = float3(-FLT_MAX)) :Returns: * :ref:`BBox3D ` - a new BBox3D instance with default values .. _function-math_utils_reset_BBox3D: .. das:function:: reset(box: BBox3D) Sets the bounding box to a default invalid state (min = float3(FLT_MAX), max = float3(-FLT_MAX)). :Arguments: * **box** : :ref:`BBox3D ` - the bounding box to set to default .. _function-math_utils_valid_BBox3D: .. das:function:: valid(box: BBox3D) : bool Checks if the bounding box is valid (non-degenerate). :Arguments: * **box** : :ref:`BBox3D ` - the bounding box to check :Returns: * bool - true if the bounding box is valid, false otherwise .. _function-math_utils__dot__rq_center_BBox3D: .. das:function:: BBox3D.center(box: BBox3D) : float3 Returns the center point of the bounding box. :Arguments: * **box** : :ref:`BBox3D ` .. _function-math_utils__dot__rq_size_BBox3D: .. das:function:: BBox3D.size(box: BBox3D) : float3 Returns the size of the bounding box. :Arguments: * **box** : :ref:`BBox3D ` .. _function-math_utils_add_point_BBox3D_float3: .. das:function:: add_point(box: BBox3D; point: float3) Adds a point to the bounding box, expanding it if necessary. :Arguments: * **box** : :ref:`BBox3D ` - the bounding box to add the point to * **point** : float3 - the point to add to the bounding box .. _function-math_utils_add_box_BBox3D_BBox3D: .. das:function:: add_box(box: BBox3D; other: BBox3D) Adds another bounding box to the current bounding box, expanding it if necessary. :Arguments: * **box** : :ref:`BBox3D ` - the bounding box to add the other bounding box to * **other** : :ref:`BBox3D ` - the other bounding box to add .. _function-math_utils_contains_BBox3D_float3: .. das:function:: contains(box: BBox3D; point: float3) : bool Checks if the bounding box contains a point. :Arguments: * **box** : :ref:`BBox3D ` - the bounding box to check * **point** : float3 - the point to check :Returns: * bool - true if the bounding box contains the point, false otherwise .. _function-math_utils_intersects_BBox3D_BBox3D: .. das:function:: intersects(box1: BBox3D; box2: BBox3D) : bool Checks if two bounding boxes intersect. :Arguments: * **box1** : :ref:`BBox3D ` - the first bounding box * **box2** : :ref:`BBox3D ` - the second bounding box :Returns: * bool - true if the bounding boxes intersect, false otherwise .. _function-math_utils_intersection_BBox3D_BBox3D: .. das:function:: 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: * **box1** : :ref:`BBox3D ` - the first bounding box * **box2** : :ref:`BBox3D ` - the second bounding box :Returns: * :ref:`BBox3D ` - a new BBox3D representing the intersection of the two bounding boxes .. _function-math_utils_BSphere3D_float3_float: .. das:function:: 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: * :ref:`BSphere3D ` - a new BSphere3D instance .. _function-math_utils_BSphere3D: .. das:function:: BSphere3D() : BSphere3D Creates a new BSphere3D instance with default values (center = float3(0), radius = -FLT_MAX) :Returns: * :ref:`BSphere3D ` - a new BSphere3D instance with default values .. _function-math_utils_reset_BSphere3D: .. das:function:: reset(sphere: BSphere3D) Sets the bounding sphere to a default invalid state (center = float3(0), radius = -FLT_MAX). :Arguments: * **sphere** : :ref:`BSphere3D ` - the bounding sphere to set to default .. _function-math_utils_valid_BSphere3D: .. das:function:: valid(sphere: BSphere3D) : bool Checks if the bounding sphere is valid (non-degenerate). :Arguments: * **sphere** : :ref:`BSphere3D ` - the bounding sphere to check :Returns: * bool - true if the bounding sphere is valid, false otherwise .. _function-math_utils_add_point_BSphere3D_float3: .. das:function:: add_point(sphere: BSphere3D; point: float3) Adds a point to the bounding sphere, expanding it if necessary. :Arguments: * **sphere** : :ref:`BSphere3D ` - the bounding sphere to add the point to * **point** : float3 - the point to add to the bounding sphere .. _function-math_utils_add_sphere_BSphere3D_BSphere3D: .. das:function:: add_sphere(sphere: BSphere3D; other: BSphere3D) Adds another bounding sphere to the current bounding sphere, expanding it if necessary. :Arguments: * **sphere** : :ref:`BSphere3D ` - the bounding sphere to add the other bounding sphere to * **other** : :ref:`BSphere3D ` - the other bounding sphere to add .. _function-math_utils_contains_BSphere3D_float3: .. das:function:: contains(sphere: BSphere3D; point: float3) : bool Checks if the bounding sphere contains a point. :Arguments: * **sphere** : :ref:`BSphere3D ` - the bounding sphere to check * **point** : float3 - the point to check :Returns: * bool - true if the bounding sphere contains the point, false otherwise .. _function-math_utils_intersects_BSphere3D_BSphere3D: .. das:function:: intersects(sphere1: BSphere3D; sphere2: BSphere3D) : bool Checks if two bounding spheres intersect. :Arguments: * **sphere1** : :ref:`BSphere3D ` - the first bounding sphere * **sphere2** : :ref:`BSphere3D ` - the second bounding sphere :Returns: * bool - true if the bounding spheres intersect, false otherwise .. _function-math_utils_move_to_float_float_float_float: .. das:function:: 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 .. _function-math_utils_smoothstep_float_float_float: .. das:function:: 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 .. _function-math_utils_smoothstep_float: .. das:function:: 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 .. _function-math_utils_angle_to_direction_float: .. das:function:: 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) .. _function-math_utils_normalize_angle_float: .. das:function:: 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 .. _function-math_utils_angle_diff_float_float: .. das:function:: 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. .. _function-math_utils_angle_move_to_float_float_float_float: .. das:function:: 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. .. _function-math_utils_angle_approach_float_float_float_float: .. das:function:: 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 .. _function-math_utils_project_float2_float2: .. das:function:: 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) .. _function-math_utils_project_float3_float3: .. das:function:: 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) .. _function-math_utils_safediv_float_float: .. das:function:: 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 .. _function-math_utils_safediv_float2_float: .. das:function:: 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 .. _function-math_utils_safediv_float3_float: .. das:function:: 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 .. _function-math_utils_safediv_float4_float: .. das:function:: 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 .. _function-math_utils_convert_world_to_screen_int2_float4_float_float_float4x4_bool_float3: .. das:function:: 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** : :ref:`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 .. _function-math_utils_convert_screen_to_world_int2_float4_float_float_float4x4_bool_float3: .. das:function:: 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** : :ref:`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 .. _function-math_utils_deg_to_rad_floatfloat2float3float4: .. das:function:: deg_to_rad(deg: float|float2|float3|float4) : auto Converts degrees to radians :Arguments: * **deg** : option .. _function-math_utils_rad_to_deg_floatfloat2float3float4: .. das:function:: rad_to_deg(rad: float|float2|float3|float4) : auto Converts radians to degrees :Arguments: * **rad** : option .. _function-math_utils_sqr_intdoublefloatfloat2float3float4: .. das:function:: sqr(x: int|double|float|float2|float3|float4) : auto Returns the square of the value :Arguments: * **x** : option .. _function-math_utils_cvt_float_float_float_floatfloat2float3float4_floatfloat2float3float4: .. das:function:: 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 - the starting point * **to** : option - 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) .. _function-math_utils_approach_floatfloat2float3float4_floatfloat2float3float4_float_float: .. das:function:: 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 - the starting point * **to** : option - 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 .. _function-math_utils_move_to_float2float3float4_float2float3float4_float_float: .. das:function:: 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 - the starting point * **to** : option - 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) .. _function-math_utils_distance_to_segment_float2float3_float2float3_float2float3: .. das:function:: 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 - the starting point of the segment * **b** : option - the ending point of the segment * **point** : option - the point to calculate distance from :Returns: * float - the distance between the point and the segment .. _function-math_core_ray_intersect_plane_Ray_float3_float3_float3: .. das:function:: ray_intersect_plane(ray: Ray; planePoint: float3; planeNormal: float3; res: float3&) : bool Intersects a ray with a plane. :Arguments: * **ray** : :ref:`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 .. _function-public_math_triangulate_poly_array_ls_Point2_gr__block_ls_array_ls_uint3_gr__hh__c_void_gr_: .. das:function:: triangulate_poly(points: array; block: block<(array#):void>) Triangulates the polygon and returns the indices of the vertices that make up each triangle. :Arguments: * **points** : array< :ref:`Point2 ` > implicit - the points of the polygon * **block** : block<(array#):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 } }