MeshLib has its own types for representing small vectors and matrices (of dimensions 2, 3, 4):
The vector types are: MR::Vector2f, MR::Vector3f, MR::Vector4f, defined in <MRMesh/MRVector[2|3|4].h> respectively.
f in MR::Vector[2|3|4]f stands for float. Use …d for double, …i for int, or pass an arbitrary type to the MR::Vector[2|3|4]<T> templates.
Similarly, the matrices are: MR::Matrix2f, MR::Matrix3f, MR::Matrix4f, defined in <MRMesh/MRMatrix[2|3|4].h> respectively.
They support the same type suffixes, and are similarly templated.
The matrices are row-major, meaning each row is contiguous, and matrix[i] refers to the ith row.
Vectors and matrices overload the common operators, including + for vectors, and * for matrix-matrix and matrix-vector multiplication.
We use the "matrix · vector" convention (OpenGL-style), rather than "vector · matrix" (DirectX-style). The * operator isn't overloaded for the latter case at all.
Construction:
Element access is vec[i] or vec.x, vec.y, vec.z, vec.w.
Overloaded operators:
Various vector products:
Some other operations:
Construction:
Element access:
Overloaded operators:
Some basic operations:
Predefined matrices:
MR::Matrix3f::rotation(axis, angle) — rotation around an axis (the axis doesn't need to be normalized, the angle is in radians).
MR::Matrix3f::rotation(dir1, dir2) — shortest rotation from one direction to another (neither needs to be normalized).
Interpolation:
Most transformations in MeshLib are represented using a matrix-vector pair — MR::AffineXf3f, defined in <MRMesh/MRAffineXf.h>.
This this pair, the vector holds the translation (offset) and the matrix holds rotation (and also scale and shear).
Those work in 2 and 3 dimensions, and like everythine else above are templated.
MR::AffineXf3f are very similar to 4x4 matrices widely used in computer graphics, but without the last row, which is assumed to be (0,0,0,1) (since it's not useful if you're not computing perspective projection matrices). It can be converted to and from MR::Matrix4f, more on that below.
Etymology:
"XF" is an abbreviation of "transform".
"X" can means "cross-" (as in "xing" = "crossing") or in this case "trans-" (as in "xfer" = "transfer").
"F" in this case is short for "-form".
Construction:
Element access:
Combining and applying transformations:
xf1 * xf2 combines two transformations, like matrix multiplication.
Note that we're using "matrix · vector" convention (OpenGL-style), rather than "vector · matrix" (DirectX-style). This means that adding ... * xf on the right acts in local space, while adding xf * ... on the left acts in world space.
Some common operations:
Conversion to and from matrices:
MR::AffineXf3f can be converted to and from MR::Matrix4f (directly, without calling any functions).
When converting to a matrix, the last row is set to (0,0,0,1) and the rest is copied as is. The opposite conversion checks that the last row is (0,0,0,1) before discarding it.
If you're using MR::Object to hold data (and the classes derived from it, such as MR::ObjectMesh), each MR::Object holds its own MR::AffineXf3f.
obj.xf() returns the current XF, and obj.setXf(...) sets a new one.
If you have an object hierarchy, the XF of each object is relative to its parent() object. An object's XF maps points from the coordinate system of that object to the coordinate system of its parent.
obj.worldXf() returns the combined XF of this object and all parents, as if by ... * obj.parent()->parent()->xf() * obj.parent()->xf() * obj.xf().
obj.setWorldXf(...) acts like obj.setXf(...), but multiplies the incoming XF by parent()->worldXf().inverse() so that the resulting obj.worldXf() produces the XF you specified.
MeshLib supports some other types not documented here:
Consult the respective headers for details.