# Spatial Vectors¶

Minetest stores 3-dimensional spatial vectors in Lua as tables of 3 coordinates, and has a class to represent them (`vector.*`), which this chapter is about. For details on what a spatial vectors is, please refer to Wikipedia: https://en.wikipedia.org/wiki/Euclidean_vector.

Spatial vectors are used for various things, including, but not limited to:

• any 3D spatial vector (x/y/z-directions)
• Euler angles (pitch/yaw/roll in radians) (Spatial vectors have no real semantic meaning here. Therefore, most vector operations make no sense in this use case.)

Note that they are not used for:

• n-dimensional vectors where n is not 3 (ie. n=2)
• arrays of the form `{num, num, num}`

The API documentation may refer to spatial vectors, as produced by `vector.new`, by any of the following notations:

• `(x, y, z)` (Used rarely, and only if it's clear that it's a vector.)
• `vector.new(x, y, z)`
• `{x=num, y=num, z=num}` (Even here you are still supposed to use `vector.new`.)

## Compatibility notes¶

Vectors used to be defined as tables of the form `{x = num, y = num, z = num}`. Since Minetest 5.5.0, vectors additionally have a metatable to enable easier use. Note: Those old-style vectors can still be found in old mod code. Hence, mod and engine APIs still need to be able to cope with them in many places.

Manually constructed tables are deprecated and highly discouraged. This interface should be used to ensure seamless compatibility between mods and the Minetest API. This is especially important to callback function parameters and functions overwritten by mods. Also, though not likely, the internal implementation of a vector might change in the future. In your own code, or if you define your own API, you can, of course, still use other representations of vectors.

Vectors provided by API functions will provide an instance of this class if not stated otherwise. Mods should adapt this for convenience reasons.

## Special properties of the class¶

Vectors can be indexed with numbers and allow method and operator syntax.

All these forms of addressing a vector `v` are valid: `v`, `v`, `v.x`, `v = 42`, `v.y = 13` Note: Prefer letter over number indexing for performance and compatibility reasons.

Where `v` is a vector and `foo` stands for any function name, `v:foo(...)` does the same as `vector.foo(v, ...)`, apart from deprecated functionality.

`tostring` is defined for vectors, see `vector.to_string`.

The metatable that is used for vectors can be accessed via `vector.metatable`. Do not modify it!

All `vector.*` functions allow vectors `{x = X, y = Y, z = Z}` without metatables. Returned vectors always have a metatable set.

## Common functions and methods¶

For the following functions (and subchapters), `v`, `v1`, `v2` are vectors, `p1`, `p2` are position vectors, `s` is a scalar (a number), vectors are written like this: `(x, y, z)`:

• `vector.new([a[, b, c]])`:
• Returns a new vector `(a, b, c)`.
• Deprecated: `vector.new()` does the same as `vector.zero()` and `vector.new(v)` does the same as `vector.copy(v)`
• `vector.zero()`:
• Returns a new vector `(0, 0, 0)`.
• `vector.copy(v)`:
• Returns a copy of the vector `v`.
• `vector.from_string(s[, init])`:
• Returns `v, np`, where `v` is a vector read from the given string `s` and `np` is the next position in the string after the vector.
• Returns `nil` on failure.
• `s`: Has to begin with a substring of the form `"(x, y, z)"`. Additional spaces, leaving away commas and adding an additional comma to the end is allowed.
• `init`: If given starts looking for the vector at this string index.
• `vector.to_string(v)`:
• Returns a string of the form `"(x, y, z)"`.
• `tostring(v)` does the same.
• `vector.direction(p1, p2)`:
• Returns a vector of length 1 with direction `p1` to `p2`.
• If `p1` and `p2` are identical, returns `(0, 0, 0)`.
• `vector.distance(p1, p2)`:
• Returns zero or a positive number, the distance between `p1` and `p2`.
• `vector.length(v)`:
• Returns zero or a positive number, the length of vector `v`.
• `vector.normalize(v)`:
• Returns a vector of length 1 with direction of vector `v`.
• If `v` has zero length, returns `(0, 0, 0)`.
• `vector.floor(v)`:
• Returns a vector, each dimension rounded down.
• `vector.round(v)`:
• Returns a vector, each dimension rounded to nearest integer.
• At a multiple of 0.5, rounds away from zero.
• `vector.apply(v, func)`:
• Returns a vector where the function `func` has been applied to each component.
• `vector.combine(v, w, func)`:
• Returns a vector where the function `func` has combined both components of `v` and `w` for each component
• `vector.equals(v1, v2)`:
• Returns a boolean, `true` if the vectors are identical.
• `vector.sort(v1, v2)`:
• Returns in order minp, maxp vectors of the cuboid defined by `v1`, `v2`.
• `vector.angle(v1, v2)`:
• Returns the angle between `v1` and `v2` in radians.
• `vector.dot(v1, v2)`:
• Returns the dot product of `v1` and `v2`.
• `vector.cross(v1, v2)`:
• Returns the cross product of `v1` and `v2`.
• `vector.offset(v, x, y, z)`:
• Returns the sum of the vectors `v` and `(x, y, z)`.
• `vector.check(v)`:
• Returns a boolean value indicating whether `v` is a real vector, eg. created by a `vector.*` function.
• Returns `false` for anything else, including tables like `{x=3,y=1,z=4}`.

For the following functions `x` can be either a vector or a number:

• `vector.add(v, x)`:
• Returns a vector.
• If `x` is a vector: Returns the sum of `v` and `x`.
• If `x` is a number: Adds `x` to each component of `v`.
• `vector.subtract(v, x)`:
• Returns a vector.
• If `x` is a vector: Returns the difference of `v` subtracted by `x`.
• If `x` is a number: Subtracts `x` from each component of `v`.
• `vector.multiply(v, s)`:
• Returns a scaled vector.
• Deprecated: If `s` is a vector: Returns the Schur product.
• `vector.divide(v, s)`:
• Returns a scaled vector.
• Deprecated: If `s` is a vector: Returns the Schur quotient.

## Operators¶

Operators can be used if all of the involved vectors have metatables: * `v1 == v2`: * Returns whether `v1` and `v2` are identical. * `-v`: * Returns the additive inverse of v. * `v1 + v2`: * Returns the sum of both vectors. * Note: `+` can not be used together with scalars. * `v1 - v2`: * Returns the difference of `v1` subtracted by `v2`. * Note: `-` can not be used together with scalars. * `v * s` or `s * v`: * Returns `v` scaled by `s`. * `v / s`: * Returns `v` scaled by `1 / s`.

For the following functions `a` is an angle in radians and `r` is a rotation vector (`{x = <pitch>, y = <yaw>, z = <roll>}`) where pitch, yaw and roll are angles in radians.

• `vector.rotate(v, r)`:
• Applies the rotation `r` to `v` and returns the result.
• `vector.rotate(vector.new(0, 0, 1), r)` and `vector.rotate(vector.new(0, 1, 0), r)` return vectors pointing forward and up relative to an entity's rotation `r`.
• `vector.rotate_around_axis(v1, v2, a)`:
• Returns `v1` rotated around axis `v2` by `a` radians according to the right hand rule.
• `vector.dir_to_rotation(direction[, up])`:
• Returns a rotation vector for `direction` pointing forward using `up` as the up vector.
• If `up` is omitted, the roll of the returned vector defaults to zero.
• Otherwise `direction` and `up` need to be vectors in a 90 degree angle to each other.

## Further helpers¶

There are more helper functions involving vectors, but they are listed elsewhere because they only work on specific sorts of vectors or involve things that are not vectors.

For example:

• `minetest.hash_node_position` (Only works on node positions.)
• `minetest.dir_to_wallmounted` (Involves wallmounted param2 values.)