A small 3D math library for Lua.
Features
- Single file
- Uses optimized LuaJIT structs if available
- Supports vectors and quaternions
- Provides an ugly API that is garbage-free as well as a pretty API that generates garbage.
Check out cpml if you're looking for something with more features.
local maf = require 'maf'
local a = maf.vector(1, 2, 3)
local b = maf.vector(4, 5, 6)
local c = a + b
local d = maf.rotation.between(a, b)
print(c:unpack())
print(d:getAngleAxis())
In general, any function that returns a vector or a rotation will write its result into the last
parameter, out
. The function also returns out
for convenience, to allow for method chaining.
If out
is unspecified, then the result will be written into the first parameter instead.
Create a new vector. Omitted elements will be set to zero.
The x
, y
, and z
keys contain the individual components of the vector.
The following metamethods are defined for vectors:
v + v
- Add two vectors.v - v
- Subtract two vectors.v * v
- Multiply two vectors.v * n
- Scale a vector by a number.v / v
- Divide two vectors.-v
- Negate a vector.#v
- Get the length of a vector.
Get the individual components of the vector.
Set the individual components of a vector. x
can also be a vector.
Add two vectors.
Subtract two vectors.
Multiply two vectors.
Divide two vectors.
Multiply each component of the vector by a number s
.
Return the length of the vector.
Set the length of a vector to 1.
Return the distance between two vectors.
Return the angle between two vectors, in radians.
Return the dot product of two vectors, defined as v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
.
Return the cross product of two vectors. The cross product is a vector that is perpendicular to the two input vectors.
Mixes two vectors together using linear interpolation. The parameter t
controls how they are
mixed (0 will return vector
, 1 will return v2
, .5 will return a 50/50 blend of the two vectors,
etc.).
Projects vector
onto u
, storing the result in out
.
Applies a rotation r
to the vector.
Creates a new rotation (quaternion) from x, y, z, w components. Unless you are some sort of wizard
that understands quaternions, it's probably easier to use .fromAngleAxis
, .fromDirection
, or
.between
.
The following metamethods are defined for rotations:
q + q
- Add two rotations.q - q
- Subtract two rotations.q * q
- Multiply two rotations, resulting in a rotation that is equivalent to applying the first rotation followed by the second.q * v
- Multiply a rotation by a vector, returning the rotated vector.-q
- Negate a rotation.#q
- Get the length of a rotation.
Get the individual components of the rotation.
Set the individual components of a rotation. x
can also be a rotation.
Creates a new rotation from an angle/axis pair. This is the same as creating a new rotation and
calling :setAngleAxis
on it. x
can also be a vec3
.
Set the rotation's values using angle/axis representation. x
can also be a vec3
.
Get the angle/axis representation of the rotation.
Create a new rotation that represents the rotation between v1
and v2
. Both vectors should be
normalized.
Update an existing rotation to represent the rotation between v1
and v2
. Both vectors should be
normalized.
Create a new rotation from a direction vector. The rotation will represent the rotation from the
forward vector (0, 0, -1) to the direction vector. x can also be a vec3
.
Set a rotation's value to those of the direction vector. x
can also be a vec3
.
Add two rotations together. To combine two rotations together, multiply them instead.
Subtract two rotations.
Multiply two rotations together, returning a rotation that combines the two.
Multiply each component of the rotation by a number s
.
Return the length of the rotation.
Normalize a rotation, setting its length to 1.
Mix two rotations together using linear interpolation. This is faster than :slerp
but less
accurate.
Mix two rotations together using spherical linear interpolation.
Keep in mind that each time a new vector or rotation is created, a small memory allocation is made. Normally you don't need to worry about this, since Lua has a garbage collector that will clean up after you. However, allocating a large number of objects can put stress on the garbage collector, which can lead to performance problems. This can happen more often that you'd think if you're, for example, creating new vectors in the update loop of a game.
It gets worse. Although it's convenient to be able to write a + b
to add vectors together, a new
vector must be allocated to store the result. This makes it really easy to allocate a bunch of
vectors without even knowing it! To avoid this sneaky performance trap, you can add two vectors
using a:add(b)
, which will reuse a
to store the result. Another strategy is to allocate a set
of reusable temporary vectors and use a:add(b, tmp)
.
MIT, see LICENSE
for details.