VecUtil
Version History
Build Version | Change Date | Change Type | Description |
---|---|---|---|
676042 | 2025-06-21 | stable | Current version |
Overview
The vecutil.lua
module provides high-performance utility functions for 2D vector operations on the XZ plane. These functions are optimized for Don't Starve Together's primary gameplay coordinate system where Y represents height and XZ represents the ground plane. All functions operate directly on coordinate parameters without requiring object instantiation.
Usage Example
-- Basic 2D vector operations on XZ plane
local x1, z1 = 1, 3
local x2, z2 = 4, 6
-- Add two vectors
local result_x, result_z = VecUtil_Add(x1, z1, x2, z2)
-- result: 5, 9
-- Calculate distance between points
local distance = VecUtil_Dist(x1, z1, x2, z2)
-- Get normalized direction vector
local dir_x, dir_z = VecUtil_NormalizeNoNaN(x2 - x1, z2 - z1)
Functions
VecUtil_Add(p1_x, p1_z, p2_x, p2_z)
Status: stable
Description: Adds two 2D vectors component-wise on the XZ plane.
Parameters:
p1_x
(number): X component of first vectorp1_z
(number): Z component of first vectorp2_x
(number): X component of second vectorp2_z
(number): Z component of second vector
Returns:
- (number, number): The sum vector components (x, z)
Example:
local x, z = VecUtil_Add(1, 3, 4, 6)
-- Result: x=5, z=9
VecUtil_Sub(p1_x, p1_z, p2_x, p2_z)
Status: stable
Description: Subtracts the second 2D vector from the first vector component-wise.
Parameters:
p1_x
(number): X component of first vectorp1_z
(number): Z component of first vectorp2_x
(number): X component of second vectorp2_z
(number): Z component of second vector
Returns:
- (number, number): The difference vector components (x, z)
Example:
local x, z = VecUtil_Sub(5, 9, 1, 3)
-- Result: x=4, z=6
VecUtil_Scale(p1_x, p1_z, scale)
Status: stable
Description: Scales a 2D vector by a scalar value.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vectorscale
(number): Scalar multiplier
Returns:
- (number, number): The scaled vector components (x, z)
Example:
local x, z = VecUtil_Scale(2, 4, 1.5)
-- Result: x=3, z=6
VecUtil_LengthSq(p1_x, p1_z)
Status: stable
Description: Calculates the squared length (magnitude) of a 2D vector. This is more efficient than calculating the actual length when comparing distances.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number): The squared length of the vector
Example:
local lengthSq = VecUtil_LengthSq(3, 4)
-- Result: 25 (3² + 4² = 9 + 16 = 25)
VecUtil_Length(p1_x, p1_z)
Status: stable
Description: Calculates the length (magnitude) of a 2D vector.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number): The length of the vector
Example:
local length = VecUtil_Length(3, 4)
-- Result: 5 (√25)
VecUtil_DistSq(p1_x, p1_z, p2_x, p2_z)
Status: stable
Description: Calculates the squared distance between two 2D points. More efficient than calculating actual distance for comparison purposes.
Parameters:
p1_x
(number): X coordinate of first pointp1_z
(number): Z coordinate of first pointp2_x
(number): X coordinate of second pointp2_z
(number): Z coordinate of second point
Returns:
- (number): The squared distance between the points
Example:
local distSq = VecUtil_DistSq(0, 0, 3, 4)
-- Result: 25
VecUtil_Dist(p1_x, p1_z, p2_x, p2_z)
Status: stable
Description: Calculates the actual distance between two 2D points.
Parameters:
p1_x
(number): X coordinate of first pointp1_z
(number): Z coordinate of first pointp2_x
(number): X coordinate of second pointp2_z
(number): Z coordinate of second point
Returns:
- (number): The distance between the points
Example:
local distance = VecUtil_Dist(0, 0, 3, 4)
-- Result: 5
VecUtil_Dot(p1_x, p1_z, p2_x, p2_z)
Status: stable
Description: Calculates the dot product of two 2D vectors. Useful for determining angles between vectors and for projection calculations.
Parameters:
p1_x
(number): X component of first vectorp1_z
(number): Z component of first vectorp2_x
(number): X component of second vectorp2_z
(number): Z component of second vector
Returns:
- (number): The dot product of the two vectors
Example:
local dot = VecUtil_Dot(1, 0, 0, 1)
-- Result: 0 (perpendicular vectors)
local dot2 = VecUtil_Dot(2, 3, 4, 5)
-- Result: 23 (2*4 + 3*5 = 8 + 15 = 23)
VecUtil_Lerp(p1_x, p1_z, p2_x, p2_z, percent)
Status: stable
Description: Performs linear interpolation between two 2D vectors.
Parameters:
p1_x
(number): X component of start vectorp1_z
(number): Z component of start vectorp2_x
(number): X component of end vectorp2_z
(number): Z component of end vectorpercent
(number): Interpolation factor (0.0 to 1.0)
Returns:
- (number, number): The interpolated vector components (x, z)
Example:
-- Interpolate halfway between two points
local x, z = VecUtil_Lerp(0, 0, 10, 20, 0.5)
-- Result: x=5, z=10
-- Get 25% of the way from start to end
local x2, z2 = VecUtil_Lerp(0, 0, 10, 20, 0.25)
-- Result: x2=2.5, z2=5
VecUtil_NormalizeNoNaN(p1_x, p1_z)
Status: stable
Description: Normalizes a 2D vector to unit length, returning (0, 0) if the input vector has zero length. This prevents NaN results that could occur with zero-length vectors.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number, number): The normalized vector components (x, z) or (0, 0) if input was zero-length
Example:
local x, z = VecUtil_NormalizeNoNaN(3, 4)
-- Result: x=0.6, z=0.8 (unit vector)
local x2, z2 = VecUtil_NormalizeNoNaN(0, 0)
-- Result: x2=0, z2=0 (safe handling of zero vector)
VecUtil_Normalize(p1_x, p1_z)
Status: stable
Description: Normalizes a 2D vector to unit length. Note: This function does not handle zero-length vectors safely - use VecUtil_NormalizeNoNaN for safer normalization.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number, number): The normalized vector components (x, z)
Example:
local x, z = VecUtil_Normalize(6, 8)
-- Result: x=0.6, z=0.8 (unit vector in same direction)
VecUtil_NormalAndLength(p1_x, p1_z)
Status: stable
Description: Normalizes a 2D vector and returns both the normalized vector and its original length. More efficient than calling normalize and length separately.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number, number, number): The normalized vector components (x, z) and the original length
Example:
local norm_x, norm_z, length = VecUtil_NormalAndLength(6, 8)
-- Result: norm_x=0.6, norm_z=0.8, length=10
VecUtil_GetAngleInDegrees(p1_x, p1_z)
Status: stable
Description: Calculates the angle of a 2D vector in degrees (0-360). The angle is measured from the positive X-axis.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number): The angle in degrees (0-360)
Example:
local angle = VecUtil_GetAngleInDegrees(1, 0)
-- Result: 0 (pointing along positive X-axis)
local angle2 = VecUtil_GetAngleInDegrees(0, 1)
-- Result: 90 (pointing along positive Z-axis)
local angle3 = VecUtil_GetAngleInDegrees(-1, 0)
-- Result: 180 (pointing along negative X-axis)
VecUtil_GetAngleInRads(p1_x, p1_z)
Status: stable
Description: Calculates the angle of a 2D vector in radians (0-2π). The angle is measured from the positive X-axis.
Parameters:
p1_x
(number): X component of vectorp1_z
(number): Z component of vector
Returns:
- (number): The angle in radians (0-2π)
Example:
local angle = VecUtil_GetAngleInRads(1, 0)
-- Result: 0 (pointing along positive X-axis)
local angle2 = VecUtil_GetAngleInRads(0, 1)
-- Result: π/2 (pointing along positive Z-axis)
VecUtil_Slerp(p1_x, p1_z, p2_x, p2_z, percent)
Status: stable
Description: Performs spherical linear interpolation between two 2D vectors. This interpolates the angle between the vectors, maintaining unit length throughout the interpolation.
Parameters:
p1_x
(number): X component of start vectorp1_z
(number): Z component of start vectorp2_x
(number): X component of end vectorp2_z
(number): Z component of end vectorpercent
(number): Interpolation factor (0.0 to 1.0)
Returns:
- (number, number): The interpolated unit vector components (x, z)
Example:
-- Slerp between two unit vectors
local x, z = VecUtil_Slerp(1, 0, 0, 1, 0.5)
-- Result: x≈0.707, z≈0.707 (45-degree angle)
VecUtil_RotateAroundPoint(a_x, a_z, b_x, b_z, theta)
Status: stable
Description: Rotates point B around point A by a given angle in radians.
Parameters:
a_x
(number): X coordinate of rotation center (point A)a_z
(number): Z coordinate of rotation center (point A)b_x
(number): X coordinate of point to rotate (point B)b_z
(number): Z coordinate of point to rotate (point B)theta
(number): Rotation angle in radians
Returns:
- (number, number): The rotated point coordinates (x, z)
Example:
-- Rotate point (1, 0) around origin by 90 degrees (π/2 radians)
local x, z = VecUtil_RotateAroundPoint(0, 0, 1, 0, math.pi / 2)
-- Result: x≈0, z≈1
VecUtil_RotateDir(dir_x, dir_z, theta)
Status: stable
Description: Rotates a direction vector by a given angle in radians.
Parameters:
dir_x
(number): X component of direction vectordir_z
(number): Z component of direction vectortheta
(number): Rotation angle in radians
Returns:
- (number, number): The rotated direction vector components (x, z)
Example:
-- Rotate direction vector (1, 0) by 45 degrees
local x, z = VecUtil_RotateDir(1, 0, math.pi / 4)
-- Result: x≈0.707, z≈0.707
Performance Considerations
VecUtil functions are optimized for:
- High-frequency pathfinding and movement calculations
- Distance checking for AI behaviors
- Collision detection on the ground plane
- Entity positioning and orientation
- Minimal memory allocation overhead
Common Usage Patterns
Entity Movement and Pathfinding
-- Calculate direction to target
local dir_x, dir_z = VecUtil_Sub(target_x, target_z, current_x, current_z)
local norm_x, norm_z = VecUtil_NormalizeNoNaN(dir_x, dir_z)
-- Move towards target with speed
local speed = 5
local new_x = current_x + norm_x * speed * dt
local new_z = current_z + norm_z * speed * dt
Range Checking
-- Check if entity is within interaction range
local INTERACT_RANGE = 3
local INTERACT_RANGE_SQ = INTERACT_RANGE * INTERACT_RANGE
if VecUtil_DistSq(player_x, player_z, entity_x, entity_z) <= INTERACT_RANGE_SQ then
-- Entity is in range
end
Angle-Based AI Behaviors
-- Calculate angle to target for AI facing
local angle_to_target = VecUtil_GetAngleInDegrees(target_x - self_x, target_z - self_z)
-- Smooth rotation towards target
local current_angle = self:GetAngleToPoint(Vector3(target_x, 0, target_z))
local rotated_x, rotated_z = VecUtil_RotateDir(1, 0, math.rad(current_angle))
Circular Movement Patterns
-- Create circular patrol pattern
local time = GetTime()
local radius = 10
local speed = 0.5
local center_x, center_z = 0, 0
local x = center_x + radius * math.cos(time * speed)
local z = center_z + radius * math.sin(time * speed)