Matemáticas OpenGL (GLM)
GLM | ||
---|---|---|
Información general | ||
Tipo de programa | Header-only | |
Desarrollador | G-Truc Creation | |
Licencia | MIT License | |
Estado actual | Activa | |
Información técnica | ||
Programado en | C++ | |
Versiones | ||
Última versión estable | 0.9.5 ( Abril de 2014) | |
Enlaces | ||
Matemáticas OpenGL o Opengl Maths es una librería multiplatforma ligera de sólo cabeceras con plantillas C++ (header-only) desarrollada por G-Truc Creation para realizar cálculos complejos de manera sencilla, intuitiva y centralizada. Trabaja con elementos como vectores, matrices, ángulos, cuaternión... y se encarga de casi todos aquellos cálculos y transformaciones sobre dichos tipos de datos. Principalmente, se usa en conjunto con las nuevas versiones de OpenGL para realizar los cálculos matriciales necesarios para dicha librería.
Del fixed-function pipeline a los shaders
En 2008, apareció la versión 3.0 de OpenGL, en cuyo núcleo se despreció (deprecated) una de las principales características de OpenGL: la tubería de funcionalidad fija, o fixed-function pipeline. A partir de este punto, se empezaron a despreciar características principales de la librería, como la manipulación interna de matrices y las estructuras de datos que usaban.
La característica que que reemplazó a todos estos aspectos fueron los shaders, que permitieron programar de manera cómoda de las acciones de renderizado. Para complementar los cálculos de las matrices principales que utiliza OpenGL, GLM proporciona funciones sencillas y rápidas, como el cálculo de una matriz inversa o una multiplicación de matrices.
Entidades usadas
GLM utiliza, principalmente, las siguientes estructuras de datos:
Vectores
GLM define vectores desde una dimensión hasta 4 dimensiones, de la siguiente manera:
#include <glm/glm.h>
glm::tvec4 vector_1( 1.0, 1.1, 1.2, 1.3 ); // Vector de flotantes (implícito)
glm::vec4 vector_2(1.f, 0.f, 4.f, -5.f ); // Vector de flotantes (implícito)
glm::tvec4<double> vector_3(1.f, 2.0, 1.f, 3.0); // Vector de doubles (explícito)
glm::vec3 v1( 1.0, 0.0, 1.1 ); // Vector de flotantes (por defecto)
glm::vec3 v2( 1.2, 1.3, 0.5 ); // Vector de flotantes (por defecto)
Y puede operar con vectores con acciones varias, por ejemplo:
glm::vec3 = glm::cross(v1, v2); // Producto vectorial
double s = glm::dot(v1, v2); // Producto escalar
Trigonometría
La librería acepta algunas funcionalidades básicas de trigonometría, por ejemplo:
double rad = glm::radians(45); // Grados a radianes
double deg = glm::degrees(0.5); // Radiantes a grados
glm::cos(rad); // Coseno (correcto).
glm::cos(deg); // Coseno (incorrecto, se debe trabajar con radianes).
Matrices
GLM permite matrices de dimensiones desde 2x2 hasta 4x4, incluyendo matrices cuadradas y no-cuadradas. Por ejemplo, podemos definir matrices de la siguiente manera:
glm::mat2x2 m1(2.0, 1.0
1.2, 2.1);
glm::mat2x1 m1(2.0,
1.2);
Y se pueden realizar operaciones incluyendo operaciones como las siguientes:
glm::mat2x1 m3 = m1 * m2; // Producto de matrices
glm::mat2x2 m4 = glm::inverse(m1); // Matriz inversa
glm::mat2x2 m5 = glm::traspose(m1); // Matriz traspuesta
double r = glm::determinant(m1); // Determinante
Además, se pueden realizar transformaciones de matrices propias de OpenGL, como:
const int WINDOW_WIDTH = 800, WINDOW_HEIGHT = 600;
#include <glm/gtc/matrix_transform.hpp>
glm::mat4x4 modelviewMatrix; // Matriz identidad por defecto.
glm::mat4x4 projectionMatrix; // Matriz identidad por defecto.
glm::vec3 translation(0, 2, 0);
modelviewMatrix = glm::translate(modelviewMatrix, translation); // Trasladar la matriz modelview 2 unidades hacia arriba.
// Generar una matriz de proyección con visión de "perspectiva".
projectionMatrix = glm::perspective( glm::radians(45.0) // Field Of View
WINDOW_WIDTH/(double)WINDOW_HEIGHT, // Aspecto
0.1, // near-z clip
200.0, // far-z clip
)
Cuaterniones
Un cuaternión sirve para representar una orientaciób en el mundo sin problemas como Gimbal Lock, producido por representaciones como los Ángulos de Euler. Por ejemplo, se puede definir un objeto de este tipo de la siguiente tipo:
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
glm::vec3 EulerAngles(0.0, glm::radians(45.0), 0.0); // ¡¡Trabajar con radianes!!
glm::quat q(EulerAngles);
glm::vec3 EulerAnges2 = glm::EulerAngles(q); // Extraer ángulos de Euler.
// Rotar (multiplicar) una matriz por un cuaternión.
modelviewMatrix = modelviewMatrix * (glm::toMat4(g));
Ejemplo de uso
Se puede usar GLM para muchos aspectos. Por ejemplo, fuera de OpenGL, puede usarse parar calcular la normal de un triángulo:
// http://glm.g-truc.net/0.9.5/code.html
#include <glm/vec3.hpp>// glm::vec3
#include <glm/geometric.hpp>// glm::cross, glm::normalize
void computeNormal(triangle & Triangle)
{
glm::vec3 const & a = Triangle.Position[0];
glm::vec3 const & b = Triangle.Position[1];
glm::vec3 const & c = Triangle.Position[2];
Triangle.Normal = glm::normalize(glm::cross(c - a, b - a));
}
U orientado a OpenGL, se puede usar para definir las propiedades de un emisor de luz:
// http://glm.g-truc.net/0.9.5/code.html
#include <glm/vec3.hpp>// glm::vec3
#include <glm/geometric.hpp>// glm::normalize, glm::dot, glm::reflect
#include <glm/exponential.hpp>// glm::pow
#include <glm/gtc/random.hpp>// glm::vecRand3
glm::vec3 lighting(intersection const & Intersection, material const & Material, light const & Light, glm::vec3 const & View)
{
glm::vec3 Color(0.0f);
glm::vec3 LightVertor(glm::normalize( Light.position() - Intersection.globalPosition() + glm::vecRand3(0.0f, Light.inaccuracy()));
if(!shadow(Intersection.globalPosition(), Light.position(), LightVertor))
{
float Diffuse = glm::dot(Intersection.normal(), LightVector);
if(Diffuse <= 0.0f)
return Color;
if(Material.isDiffuse())
Color += Light.color() * Material.diffuse() * Diffuse;
if(Material.isSpecular())
{
glm::vec3 Reflect(glm::reflect(
glm::normalize(-LightVector),
glm::normalize(Intersection.normal())));
float Dot = glm::dot(Reflect, View);
float Base = Dot > 0.0f ? Dot : 0.0f;
float Specular = glm::pow(Base, Material.exponent());
Color += Material.specular() * Specular;
}
}
return Color;
}