Skip to content

Yocto/Math: Math types

Yocto/Math defines the basic math primitives used in graphics, including small-sized vectors, matrices, frames and quaternions, and their transforms. Yocto/Math is implemented in yocto_math.h.

Vectors

The most basic types defined in Yocto/Math are fixed-length vectors in 1 to 4 dimensions with either float or int coordinates, namely vec1f, vec2f, vec3f, vec4f, vec1i, vec2i, vec3i, vec4i. One-dimensional vectors are defined for completeness.

Vectors coordinates are default-initialized to zeros. Vectors are constructed by specifying all their coordinates. For convenience, Yocto/Math defines common constants, i.e. zeroXX, to initialize zero vectors. Vector coordinates are accessed by index, e.g. v[0], or by name, using v.x, v.y, v.z, v.w. While in graphics it is common to use the latter, we suggest to instead use the former since it better generalizes to different cases.

Vectors support component-wise arithmetic, equality and assignment operators. For arithmetic operators, both vector and scalar operands are supported. Yocto/Math also overrides many common math function to work on vectors by component-wise evaluation, including trigonometric and exponentiation functions, and component-wise abs, max, min and clamp. Real vector types additionally support vector products and lengths. For 3D vectors, we also define reflection and refraction vectors following GLSL.

Matrices

Yocto/Math supports 2-4 dimensional square matrices, namely mat2f, mat3f and mat4f. Matrices are stored on column-major order. Matrices are initialized to the identity matrix and constructed by passing matrix columns. Matrix columns are accessed using indexing, i.e. mat[col]. Yocto/Math defines convenience constants for common matrices, e.g. indentity3x3f, etc.

Matrices support linear algebra summation and scaling operations, component-wise equality, matrix-matrix and matrix-vector products. All these operators use standard math notation. Matrices also support the computation of transpose, inverse and adjoint matrices, with transpose(a), inverse(a) and adjoint(a).

Frames

To represent transformations, most of the library facilities prefer the use coordinate frames, aka rigid transforms, represented as frame2f and frame3f. Frames are represented in column-major order, with columns defined as the axis of the coordinate frame followed by the origin. This is equivalent to representing rigid transformations as column-major affine matrices. Use mat_to_frame(mat) and frame_to_mat(frame) to convert between these types.

Frames support only multiplication operations with other frames, to chain transforms, the computation of their inverses, with inverse(f), and the creation of frames aligned with one ot two axis, i.e. frame_fromz(o,z) and frame_fromxz(o,z,x). For the inverse computation, the default is to assume that the frame is orthonormal to get a fast answer. This can be overridden as shown in the example.

auto f1 = frame3f{x, y, z, o}; // construct a frame from axes and origin
auto of = inverse(f1);         // assume f is orthonormal
auto gf = inverse(f1,true);    // treat f as a generic affine matrix

Quaternions

Quaternions are represented as quat4f. Quaternions support is minimal and focuses on representing rotations, i.e. unit quaternions. Quaternions are initialized to a unit quaternion, that can also be set with the convenience constant identityq4f.

Quaternions support addition, multiplication and scaling, together with dot(q1,q2), length(q) and normalize(q). For unit quaternions, Yocto/Math also defines the quaternion inverse inverse(q) and several interpolation function including linear interpolation, normalized linear interpolation and spherical interpolation, respectively with lerp(a,bt), nlerp(a,b,t) and slerp(a,b,t).

Transforms

Yocto/Math uses linear algebra vectors for holding different geometric quantities, such as points, vectors, directions and normals. For this reason, we define different functions to transform these quantities, namely transform_point(f,p) to transform points, transform_vector(f,v) to transform vectors, transform_direction(f,d) to transform directions intended as normalized vectors, and transform_normal(f,n) to transform normals.

Yocto/Math provides overrides to transforms for both frames and matrices, but the preferred transform representation in Yocto/GL are frames. When transforming normals by matrices, the inverse transform is computed on the fly for correctness. When transforming normals by frames, frames are assumed to be orthonormal and used as is, unless specifically requested as for inverses.

For convenience, Yocto/Math provides several functions to construct transform frames and matrices. Translation, rotation and scaling frames are created with
translation_frame(t), rotation_frame(r) and scaling_frame(s). Rotation frames can be derived from axis-angle, quaternion and matrix representations. To define camera frames, one can use lookat_frame(from,to,up).

auto f = tranlation_frame({1,0,0}) * rotation_frame({0,1,0},pi/2); // transform
auto lp = vec3f{1,2,3}, lv = vec3f{0,2,3}; // point and vector in local coords
auto wp = transform_point(f, lp);          // point in world coords
auto wv = transform_vector(f, lv);         // vector in world coords

For use in GPU programming, Yocto/Math also defines various projection matrices in the style of GLU/GLM, namely frustum_mat(...), ortho_mat(...), ortho2d_mat(...), and perspective_mat(...).

User-Interface Transforms

Yocto/Math provides a few utilities for writing user interfaces for 2D images and 3D environments. For images, we assume that image are scaled and than translated to be place oin screen. User interfaces can directly manipulate the translation and zoom without further helpers. Yocto/Math just provides convenience functions for centering an image and compute a mouse to image coordinate transformation.

auto image_size = vec2i{512,512}, window_size = vec2i{1024,768};
auto image_center = vec2f{100,100}; auto image_scale = float{1};
// get image coordinates from mouse
auto ij = get_image_coords(mouse_pos, image_center, image_scale, image_size);
// center image by setting image_center and image_scale
update_imview(image_center, image_scale, image_size, window_size, false);
// center image and for to screen by setting image_center and image_scale
update_imview(image_center, image_scale, image_size, window_size, true);

For 3D cameras, Yocto/Math supports a turntable interface, inspired by many 3D editors, with update_turntable(...), and the camera's rays generation with camera_ray(...).

auto camera_frame = identity3x4f; auto camera_focus = float{10};
// update camera position and focus
update_turntable(camera_frame, camera_focus, rotate, dolly, pan);
// turntable udpates works also for camera with explicit lookat parametrizations
update_turntable(camera_from, camera_to, camera_up, rotate, dolly, pan);
// generation of camera rays
auto ray = camera_ray(camera_frame, lens, aspect, film, image_uv);