#vec3( x, y, z )
Makes a vector. vec3() is the zero vector; vec3( other ) copies one.
Vectors, colours, and the extra maths functions - with the angle and unit conventions the rest of the API uses.
Positions, directions, angles and colours are passed around as small tables with a few methods. They are ordinary Lua tables underneath, so { x = 1, y = 2, z = 3 } is accepted wherever a vec3 is wanted, and { 255, 0, 0 } wherever a colour is.
A point or a direction in the world, or a set of angles. x, y and z are plain fields you can read and write.
local a = vec3( 100, 0, 0 )
local b = vec3( 100, 50, 0 )
print( a:dist( b ) ) --> 50
print( ( a + b ) * 0.5 ) --> the point between themvec3( x, y, z )Makes a vector. vec3() is the zero vector; vec3( other ) copies one.
| Expression | Result |
|---|---|
a + b, a - b | component-wise sum and difference |
a * b, a / b | component-wise product and quotient |
a * n, n * a, a / n | every component scaled by the number n |
a + n, a - n | n added to or subtracted from every component |
-a | every component negated |
a == b | true when all three components are equal |
tostring( a ) gives vec3(x, y, z).
v:unpack() → x, y, zThe three components as three values.
v:copy() → vec3A new vector with the same components.
v:set( x, y, z ) / v:set( other ) → vChanges v in place and returns it. The only method that does; everything else returns a new vector.
v:len() → numberThe length of the vector.
v:len2d() → numberThe length ignoring z - the horizontal part.
v:len_sq() → numberThe length squared. Cheaper than len() when you only compare lengths.
v:dist( other ) → numberThe distance to another point.
v:dist2d( other ) → numberThe horizontal distance.
v:dist_sq( other ) → numberThe distance squared.
v:dot( other ) → numberv:cross( other ) → vec3v:norm() → vec3The vector scaled to length 1; the zero vector stays zero.
v:lerp( other, t ) → vec3The point t of the way from v to other: t = 0 is v, 1 is other, and the range is not limited.
v:is_zero() → booleanv:angles() → vec3Treating v as a direction, the pitch and yaw that look along it - angles with z (roll) 0.
v:forward() → vec3v:right() → vec3v:up() → vec3Treating v as a set of angles, the direction the view looks along, to its right, and upward. These are what turn "where am I looking" into a ray.
local ahead = me:eye_angles( ):forward( ) * 1000 -- a point 1000 units ahead of the view directionv:wrapped() → vec3Angles brought into the legal range: yaw to -180..180, pitch limited to -89..89, roll 0.
vec3.angle_to( from, to ) → vec3The angles that look from the point from at the point to.
A point on the screen, or any pair of numbers. Fields x and y. The operators + - * /, -a and == work as for vec3.
vec2( x, y )vec2() is 0, 0; vec2( other ) copies.
v:unpack() → x, yv:len() → numberv:dist( other ) → numberv:dot( other ) → numberv:norm() → vec2v:lerp( other, t ) → vec2A colour with four channels, each 0 to 255: r, g, b and a (alpha, 255 is opaque). Colours are immutable in practice - every method returns a new one.
color( r, g, b [, a] )Makes a colour. Channels outside 0..255 are clamped; alpha is 255 if left out. color() is opaque white.
color.hex( text )From a hex string: "ff8800", "#ff8800", or with alpha "ff8800cc".
color.hsv( h, s, v [, a] )From hue (degrees, any number - it wraps), saturation and value (0 to 1), and an optional alpha in 0 to 255.
color.floats( r, g, b [, a] )From channels given as 0 to 1, with alpha 1 if left out.
c:unpack() → r, g, b, ac:copy() → colorc == dtrue when all four channels are equal.
c:alpha( a ) → colorThe same colour with a new alpha, 0 to 255.
c:fade( f ) → colorThe alpha multiplied by f (0 to 1) - the way to fade something in and out.
c:mix( other, t ) → colorA blend, t from 0 (this colour) to 1 (the other); alpha is blended too.
c:lighten( f ), c:darken( f ) → colorToward white, or toward black, by f from 0 to 1.
c:hex( [with_alpha] ) → string"rrggbb", or "rrggbbaa" with with_alpha = true.
c:hsv() → h, s, v, aHue in degrees, saturation and value from 0 to 1, and the alpha as it is.
local base = color.hex( "#a855f7" )
local dim = base:darken( 0.4 )
local glass = base:fade( 0.25 )The standard math library is all there, plus:
math.clamp( v, lo, hi ) → numberv limited to the range.
math.lerp( a, b, t ) → numbermath.inv_lerp( a, b, v ) → numberWhere v sits between a and b, as t for lerp: the inverse of lerp. Not clamped; 0 if a == b.
math.remap( v, from_lo, from_hi, to_lo, to_hi ) → numberMaps v from one range to another, clamped to the new range.
local alpha = math.remap( distance, 500, 2000, 255, 40 ) -- fades from 255 to 40 as it gets farthermath.round( v [, digits] ) → numberRounds to the nearest integer, or to digits decimals (0 to 12).
math.sign( v ) → integer-1, 0 or 1.
math.smoothstep( t ) → numberAn S-curve from 0 to 1 for t in 0..1.
math.approach( current, target, step ) → numberMoves current toward target by at most step and never past it - for smooth following, with step = speed * render.dt().
math.wrap( v, lo, hi ) → numberv brought into the range [lo, hi), wrapping around.
math.wrap_angle( degrees ) → numberAn angle brought into -180..180.
math.angle_diff( from, to ) → numberThe shortest signed turn from one angle to the other, in degrees, in -180..180.
math.lerp_angle( a, b, t ) → numberlerp that takes the short way round a circle.
math.fov( view_angles, target_angles ) → numberThe angle in degrees between two directions given as angle sets - how far a target is from the crosshair.
math.ease holds easing functions. Each takes t from 0 to 1 (values outside are clamped) and returns the eased value, 0 at the start and 1 at the end:
math.ease.linear( t ) | no easing |
math.ease.in_quad( t ), out_quad, in_out_quad | quadratic: slow start, slow end, or both |
math.ease.in_cubic( t ), out_cubic, in_out_cubic | the same, steeper |
math.ease.in_sine( t ), out_sine, in_out_sine | gentle, sine-shaped |
math.ease.out_expo( t ) | fast start, very soft landing |
math.ease.out_back( t ) | overshoots a little, then settles |
local started = render.time( )
on( "frame", function( canvas )
local t = math.ease.out_cubic( ( render.time( ) - started ) / 0.4 ) -- 0.4 seconds
canvas:fill( 20, 20, 200 * t, 10, color( 168, 85, 247 ) )
end )