Module dslib:rotnum
Numbers for 90 degree rotations.
This module provides so-called rotnums: numbers that can represent rotations of multiples of 90°, mirrorings and compositions of those.
Rotnums can be used to rotate arbitrary spatial vectors. They can be converted to and from facedir and wallmounted values and euler angles.
Note: Rotnums are numbers, not tables, so you can't do method calls and similar on them.
For every rotation or other transformation, there is one unique rotnum. So,
one can compare rotnums using == and use rotnums as table keys.
How they work
Rotnums are actually a compact representation for a special kind of 3x3 matrices,
which have in each row only one element that is non-zero, and this element is
either 1 or -1, for example:
( 0 -1 0 ) ( 0 1 0 ) is equivalent to 0x415 (-1 0 0 )
comp and apply are just matrix multiplication.
See also [Bit representation] for details.
Bit representation
A rotnum is a 11-bit integral number that the following bits (in MSBF (most significant bit first) notation):
sz z1 z0 0 sy y1 y0 0 sx x1 x0
A vector v_in is transformed to a vector v_out using these bits in the
following way:
- The
0-bits are padding. - Let
wbe any ofx, y, z. w1 w0says forv_out.wwhich component ofv_init should be:0b00forx,0b01foryand0b10forz.- If
sw == 1, thewcomponent inv_outis negated. - Example: For
0 sx x1 x0 == 0b0110,v_out.x = -v_in.z.
You may assume that the representation of rotnums stays the same (until a major version change, see Versioning.md). Hence, storing rotnums in meta and similar is valid.
Caching
Some functions, such as rotnum.rjw(), are documented to return a constant.
You can cache the return values instead of the functions:
local r2x = rotnum.r2x -- what you would normally do local r2x = rotnum.r2x() -- valid
Functions
| comp (a, b) | Composition of two rotnums. |
| apply (n, vec) | Apply a rotnum to a vector. |
| inv (rn) | The inverse. |
| can_inv (rn) | Checks whether a rotnum is invertible. |
| is_rotnum (obj) | Checks whether something is a valid rotnum. |
| compj (rn1, ...) | Composition of j rotnums. |
| compn (rns) | Composition of many rotnums. |
| compjapply (rn1, ..., vec) | Composition of j rotnums and application on a vector. |
| compnapply (rns, vec) | Composition of many rotnums and application on a vector. |
| id () | Identity. |
| rjw () | Rotates j*90 degrees around the +w axis. |
| rljw () | Alias for rotnum.rjw(). |
| rrjw () | Alias for rotnum.r(4-j)w(). |
| rnw (n) | Rotates a multiple of 90 degrees around the +w axis. |
| rlnw (n) | Alias for rotnum.rnw(n). |
| rrnw (n) | Alias for rotnum.rnw(-n). |
| rn_around (n, dir) | Rotate a multiple of 90 degrees around the given axis. |
| rln_around (n, dir) | Alias for rotnum.rn_around(n, dir). |
| rrn_around (n, dir) | Alias for rotnum.rn_around(-n, dir). |
| mirror_w () | Mirrors along the w axis. |
| mirror_along (dir) | Mirror along given axis. |
| from_facedir (facedir) | Converts a facedir number to a rotnum. |
| to_facedir (rn) | Tries to convert a rotnum to a facedir number. |
| wallmounted_to_facedir (wallmounted) | Converts a wallmounted number to a facedir number. |
| facedir_to_wallmounted (facedir) | Tries to convert a facedir number to a wallmounted number. |
| from_wallmounted (wallmounted) | Converts a wallmounted number to a rotnum. |
| to_wallmounted (rn) | Tries to convert a rotnum to a wallmounted number. |
| apply_facedir (facedir, vec) | Apply a facedir number to a vector. |
| apply_wallmounted (wallmounted, vec) | Apply a wallmounted number to a vector. |
| from_euler (euler_vec) | (Rounds and) converts an euler angle vector to a rotnum. |
| to_euler (rn) | Tries to convert a rotnum to euler angles. |
Functions
- comp (a, b) line 105
-
Composition of two rotnums.
Applying the returned rotnum is the same as first applying
band thena.This operation is:
- associative:
rotnum.comp(a, rotnum.comp(b, c)) == rotnum.comp(rotnum.comp(a, b), c) - not commutative:
rotnum.comp(a, b) ~= rotnum.comp(b, a)
Parameters:
- a rotnum
- b rotnum
Returns:
-
rotnum
The composition (
aafterb). - associative:
- apply (n, vec) line 128
-
Apply a rotnum to a vector.
This operation is:
- associative with
rotnum.comp:rotnum.apply(a, rotnum.apply(b, v)) == rotnum.apply(rotnum.comp(a, b), v) - distributive with vector addition:
rotnum.apply(a, v1 + v2) == rotnum.apply(a, v1) + rotnum.apply(a, v2)
Parameters:
- n rotnum The rotnum to apply.
- vec vector The vector to transform.
Returns:
-
vector
The transformed vector.
- associative with
- inv (rn) line 163
-
The inverse.
Applying the result undoes the given rotnum's transformation.
Warning: Not all rotnums have an inverse (see can_inv for details). If the given rotnum has no inverse, the output is some integral number with undefined properties.
Example:
assert(rotnum.id() == rotnum.comp(rn, rotnum.inv(rn))) assert(rotnum.inv(rotnum.comp(rn1, rn2)) == rotnum.comp(rotnum.inv(rn2), rotnum.inv(rn1)))This operation just transposes the rotnum (because invertible rotnums are orthonormal).
This function can also be used to find out where each of the
+x,+yand+zwould be transformed to by the given rotnum:- In the input rotnum,
sw w1 w0says from what thew-component will be created. - In the output rotnum,
sw w1 w0says to what thew-component will be transformed.
Parameters:
- rn rotnum
Returns:
-
rotnum
- In the input rotnum,
- can_inv (rn) line 187
-
Checks whether a rotnum is invertible.
The following statements are equivalent:
rnis invertible.rnis a rotation, a mirroring or a composition of those.- The matrix represented by
rnhas1or-1in each column. - The matrix represented by
rnis orthonormal. - The inverse of
rnis its transposed. - The transposed of the matrix represented by
rncan be represented by a rotnum. - The matrix represented by
rnhas full rank. - The determinant of the matrix represented by
rnis either1or-1.
Parameters:
- rn rotnum The rotnum to check.
Returns:
-
bool
trueifrnis invertible,falseotherwise. - is_rotnum (obj) line 199
-
Checks whether something is a valid rotnum.
Parameters:
- obj Some value.
Returns:
-
bool
trueifobjis a rotnum,falseotherwise. - compj (rn1, ...) line 230
-
Composition of
jrotnums.Read this as a template. The
compj()function doesn't exist itself.jcan be any of2, 3, 4, 5.These functions can be used as shortcut for multiple calls of comp, ie.:
-- both do the same: rotnum.comp(rotnum.comp(rn1, rn2), rn3) rotnum.comp3(rn1, rn2, rn3)Parameters:
- rn1 rotnum
- ...
rotnum
More rotnums. Number depends on
j.
Returns:
-
rotnum
The compositon of all rotnums.
- compn (rns) line 251
-
Composition of many rotnums.
Example:
rotnum.compn{rn1, rn2, ...}Parameters:
- rns table List of rotnums (can be empty).
Returns:
-
rotnum
The compositon of all rotnums.
- compjapply (rn1, ..., vec) line 276
-
Composition of
jrotnums and application on a vector.Read this as a template. The
compjapply()function doesn't exist itself.jcan be any of2, 3, 4, 5.These functions can be used as shortcut for multiple calls of comp, followed by a call to apply, ie.:
-- both do the same: rotnum.apply(rotnum.comp(rn1, rn2), vec) rotnum.comp2apply(rn1, rn2, vec)Parameters:
- rn1 rotnum
- ...
rotnum
More rotnums. Number depends on
j. - vec vector The vector to transform.
Returns:
-
vector
The transformed vector.
- compnapply (rns, vec) line 302
-
Composition of many rotnums and application on a vector.
Example:
rotnum.compnapply({rn1, rn2, ...}, vector.new(1, 0, 0))Parameters:
- rns table List of rotnums (can be empty).
- vec vector The vector to transform.
Returns:
-
vector
The transformed vector.
- id () line 312
-
Identity.
A vector stays unmodified if you apply the returned rotnum to it.
Returns:
-
rotnum
A constant.
- rjw () line 330
-
Rotates
j*90degrees around the +w axis.Read this as a template. The
rjw()function doesn't exist itself.jcan be any of1, 2, 3.wcan be any ofx, y, z. Example:rotnum.r1x()This is a left-handed rotation in left-handed coord system (equals right-handed rotation in right-handed system). Hence, it's a left-handed rotation in Minetest's left-handed system. (Left-handed rotation is clockwise if you look from the
+wside.)Returns:
-
rotnum
A constant.
- rljw () line 383
-
Alias for
rotnum.rjw().The
lstands for left-handed rotation in a left-handed coordinate system.Example:
rotnum.rl1x == rotnum.r1x - rrjw () line 391
-
Alias for
rotnum.r(4-j)w().The second
rstands for right-handed rotation in a left-handed coordinate system.Example:
rotnum.rr1x == rotnum.r3x - rnw (n) line 424
-
Rotates a multiple of
90degrees around the +w axis.Read this as a template. The
rnw()function doesn't exist itself.wcan be any ofx, y, z. Example:rotnum.rnx()nwill be taken modulo4and rounded to the nearest integer.Parameters:
- n number How often to rotate.
Returns:
-
rotnum
One of
rotnum.rjw()'s return values, depending onn. - rlnw (n) line 448
-
Alias for
rotnum.rnw(n).Example:
rotnum.rlnx == rotnum.rnxParameters:
- n number
Returns:
-
rotnum
- rrnw (n) line 460
-
Alias for
rotnum.rnw(-n).Example:
rotnum.rrnxParameters:
- n number
Returns:
-
rotnum
- rn_around (n, dir) line 481
-
Rotate a multiple of
90degrees around the given axis.The semantics for
nare the same as inrotnum.rnw.Parameters:
- n number How often to rotate.
- dir
string
"x","y"or"z".
Returns:
-
rotnum
An output of
rotnums.rjw, depending onnanddir. - rln_around (n, dir) line 490
-
Alias for
rotnum.rn_around(n, dir).Parameters:
- n number
- dir string
Returns:
-
rotnum
- rrn_around (n, dir) line 496
-
Alias for
rotnum.rn_around(-n, dir).Parameters:
- n number
- dir string
Returns:
-
rotnum
- mirror_w () line 509
-
Mirrors along the w axis.
Read this as a template. The
mirror_w()function doesn't exist itself.wcan be any ofx, y, z. Example:rotnum.mirror_x()Returns:
-
rotnum
A constant.
- mirror_along (dir) line 526
-
Mirror along given axis.
Parameters:
- dir
string
"x","y"or"z".
Returns:
-
rotnum
One of
rotnum.mirror_w()'s return values, depending ondir. - dir
string
- from_facedir (facedir) line 562
-
Converts a facedir number to a rotnum.
Parameters:
- facedir int The facedir number.
Returns:
-
rotnum
The rotnum.
- to_facedir (rn) line 573
-
Tries to convert a rotnum to a facedir number.
Facedir values can represent any compositions of 90° rotations, but not mirrorings for example. Hence, this can fail.
Parameters:
- rn rotnum The rotnum.
Returns:
-
Facedir number or
falseon failure. - wallmounted_to_facedir (wallmounted) line 603
-
Converts a wallmounted number to a facedir number.
Parameters:
- wallmounted int The wallmounted value.
Returns:
-
int
The facedir value.
- facedir_to_wallmounted (facedir) line 610
-
Tries to convert a facedir number to a wallmounted number.
Parameters:
- facedir int The facedir value.
Returns:
-
The wallmounted value or
falseon failure. - from_wallmounted (wallmounted) line 624
-
Converts a wallmounted number to a rotnum.
Parameters:
- wallmounted int The wallmounted number.
Returns:
-
rotnum
The rotnum.
- to_wallmounted (rn) line 631
-
Tries to convert a rotnum to a wallmounted number.
Parameters:
- rn rotnum The rotnum.
Returns:
-
Wallmounted number or
falseon failure. - apply_facedir (facedir, vec) line 644
-
Apply a facedir number to a vector.
Shortcut for:
rotnum.apply(rotnum.from_facedir(facedir), vec)Parameters:
- facedir int The facedir number.
- vec vector The vector to transform.
Returns:
-
vector
The transformed vector.
- apply_wallmounted (wallmounted, vec) line 656
-
Apply a wallmounted number to a vector.
Shortcut for:
rotnum.apply(rotnum.from_wallmounted(wallmounted), vec)Parameters:
- wallmounted int The wallmounted number.
- vec vector The vector to transform.
Returns:
-
vector
The transformed vector.
- from_euler (euler_vec) line 663
-
(Rounds and) converts an euler angle vector to a rotnum.
Parameters:
- euler_vec vector The euler vectors.
Returns:
-
rotnum
- to_euler (rn) line 728
-
Tries to convert a rotnum to euler angles.
Note: Euler angles can just rotate, hence this call can fail.
Parameters:
- rn rotnum The rotnum to convert.
Returns:
-
The vector of euler angles or
falseon failure.