2011-11-13 8 views
21

J'essaie de comprendre ce que le code suivant fait:GLM :: explication en perspective

glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f); 

-t-il créer un projection matrix? Découpe tout ce qui n'est pas dans la vue de l'utilisateur? Je n'ai pas pu trouver quoi que ce soit sur le API page, et la seule chose que je pouvais trouver dans le pdf sur leur site web était le suivant:

gluPerspective:

glm::mat4 perspective(float fovy, float aspect, float zNear, 
float zFar); 
glm::dmat4 perspective(
double fovy, double aspect, double zNear, 
double zFar); 
From GLM_GTC_matrix_transform extension: <glm/gtc/matrix_transform.hpp> 

Mais il ne précise pas les paramètres . Peut-être que j'ai raté quelque chose.

Répondre

21

Il crée une matrice de projection, c'est-à-dire la matrice qui décrit l'ensemble d'équations linéaires qui transforme les vecteurs de l'espace des yeux en espace de clip. Les matrices ne sont vraiment pas de la magie noire. Dans le cas d'OpenGL ils se trouvent un arrangement 4 par 4 chiffres:

X_x Y_x Z_x T_x 
X_y Y_y Z_y T_y 
X_z Y_z Z_z T_z 
X_w Y_w Z_w W_w 

Vous pouvez multply un 4-vecteur par une matrice 4 × 4:

v' = M * v 

v'_x = M_xx * v_x + M_yx * v_y + M_zx * v_z + M_tx * v_w 
v'_y = M_xy * v_x + M_yy * v_y + M_zy * v_z + M_ty * v_w 
v'_z = M_xz * v_x + M_yz * v_y + M_zz * v_z + M_tz * v_w 
v'_w = M_xw * v_x + M_yw * v_y + M_zw * v_z + M_tw * v_w 

Après avoir atteint pince espace (c'est-à-dire après l'étape de projection), les primitives sont écrêtées. Les sommets résultant de l'écrêtage subissent alors la division de perspective, c'est-à-dire

v'_x = v_x/v_w 
v'_y = v_y/v_w 
v'_z = v_z/v_w 
(v_w = 1 = v_w/v_w) 

Et c'est tout. Il n'y a vraiment rien de plus dans toutes ces étapes de transformation que la multiplication matricielle-vectorielle ordinaire. Maintenant, la chose intéressante à ce sujet est que les matrices peuvent être utilisées pour décrire l'alignement relatif d'un système de coordonnées dans un autre système de coordonnées. Ce que fait la transformation de perspective, c'est qu'elle laisse les valeurs z des sommets "glisser" dans leurs valeurs w projetées. Et par la division de la perspective, une non-unité w provoquera une "distorsion" des coordonnées du vertex. Les sommets avec petit z seront divisés par un petit w, donc leurs coordonnées "exploseront", alors que les sommets avec grand z seront "pressés", ce qui est à l'origine de l'effet de perspective.

0

Ceci est une version autonome de la même fonction. Ceci est à peu près une version de pâte de copie de the original.

# include <math.h> 
# include <stdlib.h> 
# include <string.h> 

typedef struct s_mat { 
    float *array; 
    int width; 
    int height; 
} t_mat; 

t_mat *mat_new(int width, int height) 
{ 
    t_mat *to_return; 

    to_return = (t_mat*)malloc(sizeof(t_mat)); 
    to_return->array = malloc(width * height * sizeof(float)); 
    to_return->width = width; 
    to_return->height = height; 
    return (to_return); 
} 

void mat_zero(t_mat *dest) 
{ 
    bzero(dest->array, dest->width * dest->height * sizeof(float)); 
} 

void mat_set(t_mat *m, int x, int y, float val) 
{ 
    if (m == NULL || x > m->width || y > m->height) 
     return ; 
    m->array[m->width * (y - 1) + (x - 1)] = val; 
} 

t_mat *mat_perspective(float angle, float ratio, 
     float near, float far) 
{ 
    t_mat *to_return; 
    float tan_half_angle; 

    to_return = mat_new(4, 4); 
    mat_zero(to_return); 
    tan_half_angle = tan(angle/2); 
    mat_set(to_return, 1, 1, 1/(ratio * tan_half_angle)); 
    mat_set(to_return, 2, 2, 1/(tan_half_angle)); 
    mat_set(to_return, 3, 3, -(far + near)/(far - near)); 
    mat_set(to_return, 4, 3, -1); 
    mat_set(to_return, 3, 4, -(2 * far * near)/(far - near)); 
    return (to_return); 
}