2011-11-13 9 views
21

私は、次のコードがないかを理解しようとしています:GLM ::斜視説明

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

それはprojection matrixを作成していますか?ユーザーの視点にないものを切り取りますか? 私はAPI page上で何かを見つけることができませんでした、と私は彼らのウェブサイト上でPDFに見つけることができる唯一のことは、このでした:

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> 

しかし、それはパラメータを説明していません。たぶん私は何かを逃した。

答えて

21

投影行列、すなわち視空間からクリップ空間にベクトルを変換する一次方程式の集合を記述する行列を作成する。行列は本当に黒い魔法ではありません。クリップに到達した後

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 

:あなたは、4×4行列で4ベクトルをmultplyでき

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 

:のOpenGLの場合、それらは、数字の4×4配列であることが起こります(すなわち、投影ステップ後)、プリミティブはクリップされる。クリッピングから得られた頂点は、透視分割、すなわち

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) 

となります。それだけです。通常の行列 - ベクトル乗算よりも、すべての変換ステップで実際には何も進んでいません。

ここではクールなことは、マトリックスを使って座標系の相対的な位置合わせを別の座標系で記述することができるということです。透視変換では、z値が投影されたw値に「スリップ」するようにします。そして、透視図を分割することによって、非単調wは頂点座標の「ゆがみ」を引き起こす。小さいzの頂点は小さなwで分割され、その座標は「吹き飛ばし」ますが、大きなzの頂点は「圧迫」され、これが視点効果を引き起こします。

0

これは同じ機能のスタンドアロンバージョンです。これはおおよそ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); 
}