From f0d413a2a77d66232ca7a0bd9fa5a080afb48af2 Mon Sep 17 00:00:00 2001 From: benrob0329 Date: Tue, 4 Jan 2022 19:24:42 -0500 Subject: [PATCH] Document `vector` (#11) --- doc/classes/vector.adoc | 269 ++++++++++++++++++++++++++++++++++++++++ include/config.adoc | 2 + 2 files changed, 271 insertions(+) create mode 100644 doc/classes/vector.adoc diff --git a/doc/classes/vector.adoc b/doc/classes/vector.adoc new file mode 100644 index 0000000..3ce471d --- /dev/null +++ b/doc/classes/vector.adoc @@ -0,0 +1,269 @@ += Vector API +include::../../include/config.adoc[] +:description: Documentation for the Vector class and API +:keywords: mod, library, vector, x, y, z, pos, position + +TIP: The respective source code is located https://github.com/minetest/minetest/blob/master/builtin/common/vector.lua[here]. + +== `vector` Namespace + +NOTE: The `vector` type used to be a simple `table` with `x`, `y`, and `z` values. +However it has more recently been given metatable methods for convenience. +Unless otherwise noted, the `vector` type always refers to the metatable-enhanced variety. +Do note that functions here will accept an old-style (non-metatable) `vector`, but you cannot perform metatable operations with said `vector`. + +=== `vector.new(a, b, c) -> vector` +* `a`: `number`, `vector`, or `nil` +* `b`, `c`: `number` or `nil` + +If `a`, `b`, and `c` are `number`:: Returns a new `vector` where `{x = a, y = b, z = c}` + +NOTE: {deprecated} + +If `a` is a `vector`:: Returns `vector.copy(a)` +If all parameters are `nil`:: Returns `vector.zero()` + +=== `vector.zero() -> vector` +Returns a new `vector` where `{x = 0, y = 0, z = 0}` + +=== `vector.copy(v) -> vector` +* `v`: `vector` + +Returns a new `vector` where `{x = v.x, y = v.y, z = v.z}`. This is *not* equivalent to `table.copy`, as that does not set the `vector` metatable. + +=== `vector.from_string(s, init) -> vector, number` +* `s`: `string` +* `init`: `number` + +Returns a new `vector` parsed from `s` using `string.match`, followed by the position of the first character following the parsed data. + +Expects `s` to be in the following format: `(x, y, z)` where `x`, `y`, and `z` are all valid numbers passed to `tonumber`. +There are some allowances in the parsing rules for extra whitespace as padding around elements. +You may set the position in `s` where `string.match` will begin parsing via `init`. + +=== `vector.to_string(v) -> string` +* `v`: `vector` + +Returns a `string` representation of `v` in the format: `(v.x, v.y, v.z)`. + +Each component is formatted with the printf-style `%g` flag (either floating-point or scientific notation, whichever is shorter). + +=== `vector.equals(a, b) -> bool` +* `a`, `b`: `vector` + +Returns `true` if `a` is equivalent to `b` (all components are the same). + +Returns `false` otherwise. + +=== `vector.length(v) -> number` +* `v`: `vector` + +Returns the vectorial length (total traveled traveled distance from the origin to the end) of `v`. + +The formula for the length is: stem:[sqrt(x^2 + y^2 + z^2)]. + +=== `vector.normalize(v) -> vector` +* `v`: `vector` + +Returns a new `vector` which is the normalized form of `v` (the vectorial length is equal to 1). +Uses `vector.length(v)` to get the vectorial length. + +Specifically, if the length is 0, returns a new `vector` with all components being `0`. +Otherwise, returns `vector.divide(v, length)`. + +=== `vector.floor(v) -> vector` +* `v`: `vector` + +Returns a new `vector` where each component of `v` has had `math.floor` applied to it. + +Literally `vector.apply(v, math.floor)`. + +=== `vector.round(v) -> vector` +* `v`: `vector` + +Returns a new `vector` where each component of `v` has had `math.round` applied to it. + +Equivalent to `vector.apply(v, math.round)` + +=== `vector.apply(v, func) -> vector` +* `v`: `vector` +* `func`: `function` + +Returns a new `vector` where each component of `v` has had `func` applied to it. + +=== `vector.distance(a, b) -> number` +* `a`, `b`: `vector` + +Returns a `number` which is equal to the distance between `a` and `b`. + +Distance is equal to the scalar (single number) result of stem:[|bar a - bar b|]. + +=== `vector.direction(pos1, pos2) -> vector` +* `pos1`, `pos2`: `vector` + +Returns a new, normalized `vector` equal to the direction from `pos1` to `pos2`. + +=== `vector.angle(a, b) -> number` +* `a`, `b`: `vector` + +Returns a `number` which is equal to the angle (in radians) between `a` and `b`. + +Formula used is stem:[tan^-1(|bar a xx bar b|, bar a * bar b)]. + +=== `vector.dot(a, b) -> number` +* `a`, `b`: `vector` + +Returns a `number` equal to the dot product of `a` and `b`. + +=== `vector.cross(a, b) -> vector` +* `a`, `b`: `vector` + +Returns a new `vector` which is equal to the cross product of `a` and `b`. + +=== `vector.add(a, b) -> vector` +* `a`: `vector` +* `b`: `vector` or `number` + +If `b` is a `vector`:: Returns a new `vector` where each component of `b` is added to each component of `a` +If `b` is a `number`:: Returns a new `vector` where `b` is added to each component of `a` + +=== `vector.subtract(a, b) -> vector` +* `a`: `vector` +* `b`: `vector` or `number` + +If `b` is a `vector`:: Returns a new `vector` where each component of `b` is subtracted from each component of `a` +If `b` is a `number`:: Returns a new `vector` where `b` is subtracted from each component of `a` + +=== `vector.multiply(a, b) -> vector` +* `a`: `vector` +* `b`: `vector` or `number` + +If `b` is a `vector`:: Returns a new `vector` where each component of `a` is multiplied by component of `b` +If `b` is a `number`:: Returns a new `vector` where each component of `a` is multiplied by `b` + +=== `vector.divide(a, b) -> vector` +* `a`: `vector` +* `b`: `vector` or `number` + +If `b` is a `vector`:: Returns a new `vector` where each component of `a` is divided by component of `b` +If `b` is a `number`:: Returns a new `vector` where each component of `a` is divided by `b` + +=== `vector.offset(v, x, y, z) -> vector` +* `v`: `vector` +* `x`, `y`, `z`: `number` + +Returns a new `vector` where each component of `x`, `y`, and `z` are added to the respective components of `v`. + +Equivalent to `vector.add(v, {x = x, y = y, z = z})`. + +=== `vector.sort(a, b) -> vector, vector` +* `a`: `vector` +* `b`: `vector` + +Returns two new `vector` values. + +The first consists of the smaller components of `a` and `b`, where each is equal to `math.min(a.N, b.N)` (N being one of x, y, or z). + +The second is similar to the first, but consisting of the larger components instead. + +=== `vector.check(v) -> bool` +* `v`: `vector` + +Returns `true` if `v` is a valid, metatable-enhanced vector. + +Returns `false` otherwise. + +=== `vector.rotate_around_axis(v, axis, angle) -> vector` +* `v`, `axis`: `vector` +* `angle`: `number` + +Returns a new `vector` which is equal to `v` rotated around `axis` by `angle` radians counter-clockwise. + +=== `vector.rotate(v, rot) -> vector` +* `v`, `rot`: `vector` + +Returns a new `vector` which is equal to `v` rotated by `rot` counter-clockwise. + +The way that the components of `rot` map is as follows: + +* `rot.x` is pitch +* `rot.y` is yaw +* `rot.z` is roll + +=== `vector.dir_to_rotation(forward, up) -> vector` +* `forward`: `vector` +* `up`: `vector` or `nil` + +Returns a new rotational `vector` (the same kind as `rot` in `vector.rotate`) equal to the rotation from `up` to `forward`. + +If `up` is `nil` then the returned rotational `vector` assumed that `y = 1` is up. + +Both `up` and `forward` are normalized by the function before calculations are made with them, so a call with or without normalization by the caller will be the same. + +== Metatable Functions + +Metatable-enhanced `vector` values have some convenience features to help make vector math more readable. +They can have be used with normal math operations rather than needing to call the equivalent namespaced function. +They also can be indexed either with named keys (`v.x` and `v["x"]`) or they can be indexed with numeric keys (`v[1]` being `v.x`, `v[2]` being `v.y`, and `v[3]` being `v.z`). + +.Using Metatable `vectors` +==== + +[source, lua] +---- +local v1 = vector.new(1, 2, 3) +local v2 = vector.new(4, 5, 6) +local v3 + +-- This: +v3 = vector.add(v1, v2) +-- Is equivalent to: +v3 = v1 + v2 + +-- You can also use do more lengthy calculations: +v3 = ((v1 + v2) / 2) * 3 +-- The equivalent using the namespaced functions would be rather unwieldy: +v3 = vector.multiply(vector.divide(vector.add(v1, v2), 2), 3) +---- + +==== + +=== `metatable.__eq(a, b) -> bool` +* `a`, `b`: `vector` + +Literally `vector.equals(a, b)`. + +=== `metatable.__unm(v) -> vector` +* `v`: `vector` + +Returns a new `vector` which is the inverse of `v`. + +=== `metatable.__add(a, b) -> vector` +* `a`, `b`: `vector` + +Returns a new `vector` where each component of `a` is added to each respective component of `b`. + +NOTE: Unlike `vector.add()` this does not support adding `number` values. + +=== `metatable.__sub(a, b) -> vector` +* `a`, `b`: `vector` + +Returns a new `vector` where each component of `a` is subtracted from each respective component of `b`. + +NOTE: Unlike `vector.subtract()` this does not support subtracting `number` values. + +=== `metatable.__mul(a, b) -> vector` +* `a`: `vector` or `number` +* `b`: `number` or `vector` + +Returns a new `vector` where each component of `a` is multiplied by each respective component of `b`. Because of the way metatables work, either argument can be a `number` or a `vector` without any practical difference. + +CAUTION: This function assumes that one just one argument is a number, and will probably return confusing errors about "accessing a `nil` value" if two `vector` arguments are passed to it. + +=== `metatable.__div(a, b) -> vector` +* `a`: `vector` +* `b`: `number` + +Returns a new `vector` where each component of `a` is divided by `b`. + +CAUTION: This function assumes `b` is a number, and will probably return confusing errors about "accessing a `nil` value" if it is not. diff --git a/include/config.adoc b/include/config.adoc index 6490f79..0710108 100644 --- a/include/config.adoc +++ b/include/config.adoc @@ -12,3 +12,5 @@ Minetest-Docs and contributors :url-docs-repo: https://github.com/minetest/minetest_docs :url-lua-api: https://github.com/minetest/minetest/blob/master/doc/lua_api.txt :url-reference-manual: https://www.lua.org/manual/5.1/manual.html + +:deprecated: The following call(s) are deprecated, please don't use them as they will be removed in a future version of the engine. \ No newline at end of file