2017-05-11 18 views
1

私はコンピュータサイエンスの学位のために私の棺のプロジェクトに取り組んでいます。 ちょうど、カメラが原点にあると仮定して、-z座標(またはワールド座標で正のz)の を投影します。また、私の投影行列は、40度垂直fovの16x9アスペクト比に基づいています。 zfarは1000、znearは1です。z_far平面の頂点をワールド座標で計算する。

私は2つの異なる角度からこの問題に近づいてきました。私は行列の数学とtrigを使ってそれを計算しようとしました。しかし、どちらのアプローチもこれまで私のために正しく働いていませんでした。

私の最初の本能は、私の投影行列を取り、zfar平面を構成する同次座標を掛けるよりも、その行列の逆行列を得ることでした。例えば :

以下
vec4(-1.0,1.0,-1.0,1.0) * inverse_projection// calculates top left vertex of z_far plane in world coords etc.. 

は、私が何を意味するかを示すコードです。理論的には、{-1,1、-1}に逆射影行列を掛けた後の結果ベクトルは、射影行列の構成に使用されるzfarであるため、z座標が1000でなければなりません。

glm::vec4 pp = glm::vec4(-1, 1, -1, 1.0); 


printf("zfar[0] = %.2f, %.2f, %.2f, %.2f\n", pp.x, pp.y, pp.z, pp.w); 
pp = pp * inverse_projection; 
printf("zfar[0] * inverse_projection = %.2f, %.2f, %.2f, w=%.2f\n", pp.x/pp.w ,pp.y/pp.w ,pp.z/pp.w ,pp.w); 
pp = pp * projection; 
printf("zfar[0] * projection = %.2f, %.2f, %.2f, w=%.2f\n", pp.x/pp.w ,pp.y/pp.w ,pp.z/pp.w ,pp.w); 

出力:

zfar[0] = -1.00, 1.00, -1.00, 1.00 
zfar[0] * inverse_projection = -0.21, 0.12, -0.33, w=1.50 
zfar[0] * projection = -1.00, 1.00, -1.00, w=1.00 

しかし、あなたが見ることができるように、それは世界座標と言う、z_farは、それが右であることにさえ近くない-1000その時にあるべきとき、-0.33であります。私の推測では、W座標が正常にワールド座標に変換されていないということです。

また、trfでzfarを計算してみました。

void test_getFrustumInWorld(double height, double width, double v_fov, double z_near, double z_far, glm::mat4 projection) 
{ 
    //height and width refer to height and width of screen 
    glm::vec4 z_far_world[4]; 
    double z_far_height = (tan(v_fov/2)*z_far)*2; 
    double aspect_ratio = height/width; //how many heights there are in one width 
    double z_far_width = z_far_height * aspect_ratio; 

    double zf_right = z_far_width/2.0; 
    double zf_top = z_far_height/2.0; 

    z_far_world[0] = glm::vec4(-zf_right, zf_top, 1000.0, 1.0); 
    z_far_world[1] = glm::vec4(-zf_right,-zf_top, 1000.0, 1.0); 
    z_far_world[2] = glm::vec4(zf_right,-zf_top, 1000.0, 1.0); 
    z_far_world[3] = glm::vec4(zf_right, zf_top, 1000.0, 1.0); 



    for(int i=0; i< 4; i++) 
    { 
     double w = z_far_world[i].w; 
     printf("z_far_world[%d] = {%.2f, %.2f, %.2f, w=%.2f}\n",i,z_far_world[i].x/w, z_far_world[i].y/w, z_far_world[i].z/w, z_far_world[i].w); 

    } 

    printf("\nprojected:\n"); 
    for(int i=0; i< 4; i++) 
    { 
     z_far_world[i] = z_far_world[i] * projection; 
     double w = z_far_world[i].w; 
     printf("z_far_world[%d] = {%.2f, %.2f, %.2f, w=%.2f}\n",i,z_far_world[i].x/w, z_far_world[i].y/w, z_far_world[i].z/w, z_far_world[i].w); 

    } 
} 

出力:

z_far_world[0] = {-1258.40, 2237.16, 1000.00, w=1.00} 
z_far_world[1] = {-1258.40, -2237.16, 1000.00, w=1.00} 
z_far_world[2] = {1258.40, -2237.16, 1000.00, w=1.00} 
z_far_world[3] = {1258.40, 2237.16, 1000.00, w=1.00} 

projected: 
z_far_world[0] = {0.16, -0.50, 0.50, w=-2002.00} 
z_far_world[1] = {0.16, 0.50, 0.50, w=-2002.00} 
z_far_world[2] = {-0.16, 0.50, 0.50, w=-2002.00} 
z_far_world[3] = {-0.16, -0.50, 0.50, w=-2002.00} 

出力の最初のブロック内の数字は、iがビューTRIG計算に到着座標です。 数値の2番目のブロックは、投影行列が適用された後の頂点です。投影行列が適用されると、結果の座標はすべて1と-1の何らかの組み合わせになるはずです。 {0.16、0.5、0.5}のようなものを据え付けました。それは全く間違っています。 また、明確にするために、出力はWで除算した後の座標です。 何が欠けていますか?これは簡単だったはずですが、何の意味もありません。

どこが間違っていますか?何かを誤解していますか?イムは完全に立ち往生した。あなたのGLMのコードで

答えて

1

、2つの大きな問題があります。

GLMは、私たちが列ベクトルで作業していることを(少なくとも行列演算用)を前提としています。つまり、デフォルトの操作順序はM * tです。行ベクトルと演算をt * Mの形式で使用する場合は、Mを転置して正しく動作させる必要があります。

投影されたz座標が-1.0は、遠い平面上にはなく、近い平面上に位置する。また、OpenGLは、(デフォルトでは)値が遠くにある場合に大きくなることを期待しています。だから遠くの平面上の点を望むなら、それは1.0のz座標を持たなければならない。

+0

Aaah yeah。私は間違っていたと思うか、あるいは私が最初にOpenGL座標系について学んだときに何が聞かれたのか誤解していると思います。 私の主な問題は、少なくともtrigのアプローチでは、私のFOVはラジアンではない度であることがわかりました。 – shalnon

関連する問題