OpenGL Mathematics
OpenGL Mathematics GLM has become the defacto standard for graphics vector math in C++ in the latest years. It's syntax mimics that of glsl so working with it while working with OpenGL, shaders... makes things easier cause the syntax is almost the same across the different languages.
openFrameworks, since version 0.10 uses GLM as it's default vector math library in the core and although old projects using ofVec* classes should work with minimal changes, if you are starting a new project we recomend to use GLM instead.
Namespace
GLM classes and functions are in the glm
namespace so to use them you need to either prefix them with glm::
:
glm::vec3 v(2.f, 2.f, 2.f);
float l = glm::length(v);
Or in your .cpp
files import the glm
namespace at the very beginning:
using namespace glm;
And then use the classes and functions without prefix:
vec3 v(2.f, 2.f, 2.f);
float l = length(v);
Functions not methods
GLM classes like vectors, matrices or quaternions don't have methods. Instead glm uses functions to operate on those classes so if you want to for example normalize a vector you would do:
glm::vec3 v(2.f, 2.f, 2.f);
glm::vec3 n = glm::normalize(v);
The only exceptions to this rule are operators which you don't use directly but instead allow to do arithmetic operations so you can do things like:
glm::vec3 v1(1.f, 1.f, 1.f);
glm::vec3 v2(2.f, 2.f, 2.f);
glm::vec3 v3 = v1 + v2;
Warning
GLM vector have a static length
function which returns the dimension of the vector type, so glm::vec2::length()
returns 2, glm::vec3::length()
returns 3...
Because C++ allows to call static methods on instances of that class you can make the error of calling:
glm::vec3 v(2.f, 2.f, 2.f);
float length = v.length();
To try and get the length of the vector instead of the number of dimensions of the type. The correct way of doing that would be:
glm::vec3 v(2.f, 2.f, 2.f);
float length = glm::length(v);
Mostly when porting old code form ofVec to glm, because ofVec included such a method, it's easy to try and call that function which will compile without errors but won't do what you expect.
When doing that, most modern compilers should show a warning because of calling a static method on an instance instead of a class, so be on the look for those when porting old code to GLM.
Type strictness
glm has a strict type system, similar to how things work in glsl, meaning that you can't autoconvert from one type to another automatically as it was the case with ofVectorMath.
For example:
glm::vec2 v2(2.f, 2.f);
glm::vec3 v3 = v2;
Won't work anymore, you need to do now:
glm::vec3 v3 = glm::vec3(v2, 0.f);
Or in the opposite case:
glm::vec3 v3(2.f, 2.f, 2.f);
glm::vec2 v2 = glm::vec2(v3)
or even:
glm::vec2 v2(v3)
Constants
GLM has some useful constants but the way to use them might be a little bit weird at first. The main problem comes from the fact that this constants are defined as templated functions so to call them you need to specify the type as in:
float p = glm::pi<float>();
double dp = glm::pi<double>();
Multiplication order
Finally, if you are used to the old openFrameworks vector math classes you would multiply vector and matrices like:
ofVec3 v;
ofVec3f projected = v * model * view * projection;
with glm as in glsl the multiplication order is the opposite so now you would do:
glm::vec3 v;
glm::vec3 projected = projection * view * model * v;
- detail_func_common
- glm::abs()
- glm::ceil()
- glm::clamp()
- glm::floatBitsToInt()
- glm::floatBitsToUint()
- glm::floor()
- glm::fma()
- glm::fract()
- glm::frexp()
- glm::intBitsToFloat()
- glm::isinf()
- glm::isnan()
- glm::ldexp()
- glm::max()
- glm::min()
- glm::mix()
- glm::mod()
- glm::modf()
- glm::round()
- glm::roundEven()
- glm::sign()
- glm::smoothstep()
- glm::step()
- glm::trunc()
- glm::uintBitsToFloat()
- gtc_constants
- glm::e()
- glm::epsilon()
- glm::euler()
- glm::four_over_pi()
- glm::golden_ratio()
- glm::half_pi()
- glm::ln_ln_two()
- glm::ln_ten()
- glm::ln_two()
- glm::one()
- glm::one_over_pi()
- glm::one_over_root_two()
- glm::one_over_two_pi()
- glm::pi()
- glm::quarter_pi()
- glm::root_five()
- glm::root_half_pi()
- glm::root_ln_four()
- glm::root_pi()
- glm::root_three()
- glm::root_two()
- glm::root_two_pi()
- glm::third()
- glm::three_over_two_pi()
- glm::two_over_pi()
- glm::two_over_root_pi()
- glm::two_pi()
- glm::two_thirds()
- glm::zero()
- gtc_matrix_transform
- glm::frustum()
- glm::frustumLH()
- glm::frustumRH()
- glm::infinitePerspective()
- glm::infinitePerspectiveLH()
- glm::infinitePerspectiveRH()
- glm::lookAt()
- glm::lookAtLH()
- glm::lookAtRH()
- glm::ortho()
- glm::orthoLH()
- glm::orthoRH()
- glm::perspective()
- glm::perspectiveFov()
- glm::perspectiveFovLH()
- glm::perspectiveFovRH()
- glm::perspectiveLH()
- glm::perspectiveRH()
- glm::pickMatrix()
- glm::project()
- glm::rotate()
- glm::scale()
- glm::translate()
- glm::tweakedInfinitePerspective()
- glm::unProject()
- gtc_packing
- glm::packF2x11_1x10()
- glm::packF3x9_E1x5()
- glm::packHalf()
- glm::packHalf1x16()
- glm::packHalf4x16()
- glm::packI3x10_1x2()
- glm::packSnorm()
- glm::packSnorm1x16()
- glm::packSnorm1x8()
- glm::packSnorm2x8()
- glm::packSnorm3x10_1x2()
- glm::packSnorm4x16()
- glm::packU3x10_1x2()
- glm::packUnorm()
- glm::packUnorm1x16()
- glm::packUnorm1x5_1x6_1x5()
- glm::packUnorm1x8()
- glm::packUnorm2x3_1x2()
- glm::packUnorm2x4()
- glm::packUnorm2x8()
- glm::packUnorm3x10_1x2()
- glm::packUnorm3x5_1x1()
- glm::packUnorm4x16()
- glm::packUnorm4x4()
- glm::unpackF2x11_1x10()
- glm::unpackF3x9_E1x5()
- glm::unpackHalf()
- glm::unpackHalf1x16()
- glm::unpackHalf4x16()
- glm::unpackI3x10_1x2()
- glm::unpackSnorm()
- glm::unpackSnorm1x16()
- glm::unpackSnorm1x8()
- glm::unpackSnorm2x8()
- glm::unpackSnorm3x10_1x2()
- glm::unpackSnorm4x16()
- glm::unpackU3x10_1x2()
- glm::unpackUnorm()
- glm::unpackUnorm1x16()
- glm::unpackUnorm1x5_1x6_1x5()
- glm::unpackUnorm1x8()
- glm::unpackUnorm2x3_1x2()
- glm::unpackUnorm2x4()
- glm::unpackUnorm2x8()
- glm::unpackUnorm3x10_1x2()
- glm::unpackUnorm3x5_1x1()
- glm::unpackUnorm4x16()
- glm::unpackUnorm4x4()
- gtc_quaternion
- glm::angle()
- glm::angleAxis()
- glm::axis()
- glm::conjugate()
- glm::dot()
- glm::equal()
- glm::eulerAngles()
- glm::greaterThan()
- glm::greaterThanEqual()
- glm::inverse()
- glm::isinf()
- glm::isnan()
- glm::length()
- glm::lerp()
- glm::lessThan()
- glm::lessThanEqual()
- glm::mat3_cast()
- glm::mat4_cast()
- glm::mix()
- glm::normalize()
- glm::notEqual()
- glm::pitch()
- glm::quat_cast()
- glm::roll()
- glm::rotate()
- glm::slerp()
- glm::yaw()
- gtc_type_ptr
- glm::make_mat2()
- glm::make_mat2x2()
- glm::make_mat2x3()
- glm::make_mat2x4()
- glm::make_mat3()
- glm::make_mat3x2()
- glm::make_mat3x3()
- glm::make_mat3x4()
- glm::make_mat4()
- glm::make_mat4x2()
- glm::make_mat4x3()
- glm::make_mat4x4()
- glm::make_quat()
- glm::make_vec2()
- glm::make_vec3()
- glm::make_vec4()
- glm::value_ptr()
- gtx_euler_angles
- glm::eulerAngleX()
- glm::eulerAngleXY()
- glm::eulerAngleXYZ()
- glm::eulerAngleXZ()
- glm::eulerAngleY()
- glm::eulerAngleYX()
- glm::eulerAngleYXZ()
- glm::eulerAngleYZ()
- glm::eulerAngleZ()
- glm::eulerAngleZX()
- glm::eulerAngleZY()
- glm::extractEulerAngleXYZ()
- glm::orientate2()
- glm::orientate3()
- glm::orientate4()
- glm::yawPitchRoll()
- gtx_simd_vec4
- glm::abs()
- glm::ceil()
- glm::clamp()
- glm::cross()
- glm::distance()
- glm::distance4()
- glm::dot4()
- glm::fastInversesqrt()
- glm::fastLength()
- glm::fastLength4()
- glm::fastNormalize()
- glm::fastSqrt()
- glm::floor()
- glm::fma()
- glm::fract()
- glm::inversesqrt()
- glm::length()
- glm::length4()
- glm::max()
- glm::min()
- glm::mix()
- glm::mod()
- glm::niceLength()
- glm::niceLength4()
- glm::niceSqrt()
- glm::normalize()
- glm::reflect()
- glm::refract()
- glm::round()
- glm::sign()
- glm::simdDot()
- glm::simdFaceforward()
- glm::smoothstep()
- glm::sqrt()
- glm::step()
- glm::trunc()
- glm::vec4_cast()