Herramientas de usuario

Herramientas del sitio


wiki2:oglmaths

OpenGL Maths

Quaternions and gimbal lock

  • The math used by the implementation of GLKMatrix4MakeLookAt() cannot produce a useful point of view that looks directly along the “up” vector. The limitation exists because when looking directly “up” or “down,” the math used by GLKMatrix4MakeLookAt() attempts to calculate the tangent of 90 degrees, which is mathematically undefined.
  • Quaternions take advantage of 4D space to represent 3D angles.
  • Gimbal lock is the loss of one degree of freedom in a three-dimensional, three-gimbal mechanism that occurs when the axes of two of the three gimbals are driven into a parallel configuration, “locking” the system into rotation in a degenerate two-dimensional space.
  • Gimbal with 3 axes of rotation. A set of three gimbals mounted together to allow three degrees of freedom: roll, pitch and yaw. When two gimbals rotate around the same axis, the system loses one degree of freedom.

Matrices

Coordenadas homogeneas

Partiendo del concepto de coordenadas homogeneas (x, y, z, w). Donde w…

  • … Vale 1 si es una posición en el espaco.
  • … Vale 0 si es una dirección.

Las coordenadas homogeneas son las que nos permiten trabajar con matrices de traslación, rotación y escalado.

La w es el valor de perspectiva, se utilizará para divir X, Y, y Z entre este. The Advantages of Dividing by W You might be wondering why we don’t simply divide by z instead. After all, if we interpret z as the distance and had two coordinates, (1, 1, 1) and (1, 1, 2) , we could then divide by z to get two normalized coordinates of (1, 1) and (0.5, 0.5). While this can work, there are additional advantages to adding w as a fourth component. We can decouple the perspective effect from the actual z coordinate, so we can switch between an orthographic and a perspective projection. There’s also a benefit to preserving the z component as a depth buffer.

Orden de operaciones

Recuerda, es importante el orden de operaciones. Al multiplicar una matriz por un vector el primer operando siempre será el vector:

transformedVector = myMatrix * myVector;

El orden para acumular (multiplicar) matrices de transformación:

 TransformedVector = TranslationMatrix * RotationMatrix * ScaleMatrix * OriginalVector;

Tipos de matrices

Matriz identidad (identity matrix)

Cualquier vector que multipliquemos por ella queda igual.

The reason this is called an identity matrix is because we can multiply this matrix with any vector and we’ll always get back the same vector, just like we get back the same number if we multiply any number by 1.

glm::mat4 myIdentityMatrix = glm::mat4(1.0f);

Matriz de traslación


Matriz de escalado


Matrices de rotación

Model matrix

Es la matriz que surge de aplicar todas las transformaciones. Al multiplicarla a un punto este pasa a tener las coordenadas del mundo.

The model matrix transforms a position in a model to the position in the world. This position is affected by the position, scale and rotation of the model that is being drawn. It is generally a combination of the simple transformations you've seen before. If you are already specifying your vertices in world coordinates (common when drawing a simple test scene), then this matrix can simply be set to the identity matrix.

View matrix

Es la que mueve el mundo para colocarlo en la posición de la cámara (porque en ogl no es la cámara la que se mueve sino el mundo). Una vez es multiplicada a un punto, este pasa a tener las coordenadas de cámara.

So initially your camera is at the origin of the World Space. In order to move the world, you simply introduce another matrix. Let’s say you want to move your camera of 3 units to the right (+X). This is equivalent to moving your whole world (meshes included) 3 units to the LEFT ! (-X).

glm::mat4 CameraMatrix = glm::lookAt(
    cameraPosition, // the position of your camera, in world space
    cameraTarget,   // where you want to look at, in world space
    upVector        // probably glm::vec3(0,1,0), but (0,-1,0) would make you looking upside-down, which can be great too
);

Projection matrix

Es la matriz que deforma los puntos para colocarlos en la proyección deseada.

glm::mat4 projectionMatrix = glm::perspective(
    FoV,         // The horizontal Field of View, in degrees : the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in)
    4.0f / 3.0f, // Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar ?
    0.1f,        // Near clipping plane. Keep as big as possible, or you'll get precision issues.
    100.0f       // Far clipping plane. Keep as little as possible.
7 );

ModelViewProjection matrix

Cumulating transformations appears the ModelViewProjection matrix.

// C++ : compute the matrix
glm::mat4 MVPmatrix = projection * view * model; // Remember : inverted !
// GLSL : apply it
transformed_vertex = MVP * in_vertex;

Coordenadas

Cartesianas

En el que las coordenadas se plasman en un plano (cartesiano) a partir de los valores X, Y.

Polares

Las coordenadas polares o sistemas polares son un sistema de coordenadas bidimensional en el cual cada punto del plano se determina por una distancia y un ángulo, ampliamente utilizados en física y trigonometría.

Esféricas

El sistema de coordenadas esféricas se basa en la misma idea que las coordenadas polares y se utiliza para determinar la posición espacial de un punto mediante una distancia y dos ángulos. En consecuencia, un punto P queda representado por un conjunto de tres magnitudes: el radio r, el ángulo polar o colatitud φ y el azimut θ (r, phi, theta).

Figuras geométricas

Esfera

void renderSphere(float cx, float cy, float cz, float r, int p)
{
    float theta1 = 0.0, theta2 = 0.0, theta3 = 0.0;
    float ex = 0.0f, ey = 0.0f, ez = 0.0f;
    float px = 0.0f, py = 0.0f, pz = 0.0f;
    GLfloat vertices[p*6+6], normals[p*6+6], texCoords[p*4+4];
 
    if( r < 0 )
        r = -r;
 
    if( p < 0 )
        p = -p;
 
    for(int i = 0; i < p/2; ++i)
    {
        theta1 = i * (M_PI*2) / p - M_PI_2;
        theta2 = (i + 1) * (M_PI*2) / p - M_PI_2;
 
        for(int j = 0; j <= p; ++j)
        {
            theta3 = j * (M_PI*2) / p;
 
            ex = cosf(theta2) * cosf(theta3);
            ey = sinf(theta2);
            ez = cosf(theta2) * sinf(theta3);
            px = cx + r * ex;
            py = cy + r * ey;
            pz = cz + r * ez;
 
            vertices[(6*j)+(0%6)] = px;
            vertices[(6*j)+(1%6)] = py;
            vertices[(6*j)+(2%6)] = pz;
 
            normals[(6*j)+(0%6)] = ex;
            normals[(6*j)+(1%6)] = ey;
            normals[(6*j)+(2%6)] = ez;
 
            texCoords[(4*j)+(0%4)] = -(j/(float)p);
            texCoords[(4*j)+(1%4)] = 2*(i+1)/(float)p;
 
 
            ex = cosf(theta1) * cosf(theta3);
            ey = sinf(theta1);
            ez = cosf(theta1) * sinf(theta3);
            px = cx + r * ex;
            py = cy + r * ey;
            pz = cz + r * ez;
 
            vertices[(6*j)+(3%6)] = px;
            vertices[(6*j)+(4%6)] = py;
            vertices[(6*j)+(5%6)] = pz;
 
            normals[(6*j)+(3%6)] = ex;
            normals[(6*j)+(4%6)] = ey;
            normals[(6*j)+(5%6)] = ez;
 
            texCoords[(4*j)+(2%4)] = -(j/(float)p);
            texCoords[(4*j)+(3%4)] = 2*i/(float)p;
        }
        glVertexPointer(3, GL_FLOAT, 0, vertices);
        glNormalPointer(GL_FLOAT, 0, normals);
        glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, (p+1)*2);
    }
}

Billboarding

wiki2/oglmaths.txt · Última modificación: 2020/05/09 09:25 (editor externo)