2017-05-11 49 views
1

我正在爲我的計算機科學學士學位項目工作,我很難搞清楚如何做題目所說的事情。 假設攝像機在原點向下看-Z在gl座標(或世界座標中的正z) 此外,我的投影矩陣基於16x9縱橫比和40度垂直fov。 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}乘以逆投影矩陣後,得到的向量應該具有1000的z座標,因爲這是構造投影矩陣時使用的zfar。

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爲-0.33,當它應該是在它-1000甚至沒有接近被正確。我的猜測是,我沒有W座標正確的成功翻譯成世界座標。

我也嘗試通過trg計算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} 

在輸出的該第一塊中的數字,是我到達視圖TRIG計算的座標。 第二個數字塊是應用投影矩陣後的頂點。一旦投影矩陣被應用,結果座標應該是所有1和-1的某種組合。但是像{0.16,0.5,0.5}這樣的東西出現了。這是完全錯誤的。 也只是爲了說明,輸出是由W劃分後的座標。 我到底在想什麼?這應該很簡單,但沒有任何意義。

我哪裏錯了?我誤解了什麼?我完全卡住了。

回答

1

在您的GLM代碼中,有兩個主要問題:

GLM假設(至少在矩陣運算),我們與列向量工作。這意味着,默認的操作順序是M * t。如果要使用t * M形式的行向量和操作,則必須將M轉置爲正確工作。

-1.0的投影z座標不位於遠平面上,而是位於近平面上。此外,OpenGL預計(默認情況下)值越大,距離越遠。所以如果你想在遠平面上有一個點,那麼它必須有一個1.0的z座標。

+0

Aaah耶。我認爲我是錯誤的,或者只是誤解了當我第一次學習opengl座標系時被告知的內容。 我發現,雖然我的主要問題,至少在trig方法中,我的FOV是度數而不是弧度。 – shalnon