2016-04-24 64 views
-1

我已經用C和freeglut編碼了OpenGl Super Bible的例子https://github.com/openglsuperbible/sb7code/blob/master/src/grass/grass.cpp 。結果一直是這些觀點之外的觀點。我是否正確創建外觀和透視矩陣?

我是否正確計算並使用外觀和透視矩陣?渲染功能的

部分:

Matrix proj=CreateProjectionMatrix(45.0f,CurrentWidth/CurrentHeight,0.1f,1000.0f); 

float t=glutGet(GLUT_ELAPSED_TIME)*0.002f; 
float eye[]={sinf(t)*550.0f,25.0f,cosf(t)*550.0f}; 
float center[]={0.0f,-50.0f,0.0f}; 
float up[]={0.0f,1.0f,0.0f}; 
Matrix look=lookAt(eye,center,up); 

Matrix final=MultiplyMatrices(&proj,&look); 

glUniformMatrix4fv(UniformsMvpMatrix,1,GL_FALSE,final.m); 

計算:

typedef struct Matrix{ 
    GLfloat m[16]; 
}Matrix; 

Matrix CreateProjectionMatrix(float fovy,float aspect,float Znear,float Zfar){ 
    // Array index in the matrix 
    // _   _ 
    // | 0 4 8 12 | 
    // | 1 5 9 13 | 
    // | 2 6 10 14 | 
    // |_3 7 11 15_| 
    // 
    Matrix out; 
    float tanhalffovy = tanf(DegreesToRadians(fovy/2)); 
    out.m[ 0]=1/(aspect*tanhalffovy); 
    out.m[ 5]=1/(tanhalffovy); 
    out.m[10]=(Zfar+Znear)/(Znear-Zfar); 
    out.m[11]=(2*Zfar*Znear)/(Znear-Zfar); 
    out.m[14]=-1; 
    out.m[ 1]=0; 
    out.m[ 2]=0; 
    out.m[ 3]=0; 
    out.m[ 4]=0; 
    out.m[ 6]=0; 
    out.m[ 7]=0; 
    out.m[ 8]=0; 
    out.m[ 9]=0; 
    out.m[12]=0; 
    out.m[13]=0; 
    out.m[15]=0; 
    return out; 
} 

Matrix lookAt(float eye[3],float center[3],float up[3]){ 
    // Array index in the matrix 
    // _   _ 
    // | 0 4 8 12 | 
    // | 1 5 9 13 | 
    // | 2 6 10 14 | 
    // |_3 7 11 15_| 
    // 
    double help=sqrt(up[0]*up[0]+up[1]*up[1]+up[2]*up[2]); 
    float upN[3]; 
    upN[0]=up[0]/help; 
    upN[1]=up[1]/help; 
    upN[2]=up[2]/help; 

    float f[3]; 
    f[0]=(center[0]-eye[0]); 
    f[1]=(center[1]-eye[1]); 
    f[2]=(center[2]-eye[2]); 
    help=sqrt(f[0]*f[0]+f[1]*f[1]+f[2]*f[2]); 
    f[0]/=help; 
    f[1]/=help; 
    f[2]/=help; 

    float s[3]; 
    s[0]=f[1]*upN[2]-upN[1]*f[2]; 
    s[1]=f[2]*upN[0]-upN[2]*f[0]; 
    s[2]=f[0]*upN[1]-upN[0]*f[1]; 

    float u[3]; 
    u[0]=s[1]*f[2]-f[1]*s[2]; 
    u[1]=s[2]*f[0]-f[2]*s[0]; 
    u[2]=s[0]*f[1]-f[0]*s[1]; 

    Matrix out={{s[0],s[1],s[2],0, u[0],u[1],u[2],0, f[0],f[1],f[2],0, -eye[0],-eye[1],-eye[2],1}}; 
    return out; 
} 

Matrix MultiplyMatrices(const Matrix* m1, const Matrix* m2){  
    Matrix out; 
    // First column 
    out.m[ 0]=(m1->m[0])*(m2->m[0])+(m1->m[4])*(m2->m[1])+(m1->m[ 8])*(m2->m[2])+(m1->m[12])*(m2->m[3]); 
    out.m[ 1]=(m1->m[1])*(m2->m[0])+(m1->m[5])*(m2->m[1])+(m1->m[ 9])*(m2->m[2])+(m1->m[13])*(m2->m[3]); 
    out.m[ 2]=(m1->m[2])*(m2->m[0])+(m1->m[6])*(m2->m[1])+(m1->m[10])*(m2->m[2])+(m1->m[14])*(m2->m[3]); 
    out.m[ 3]=(m1->m[3])*(m2->m[0])+(m1->m[7])*(m2->m[1])+(m1->m[11])*(m2->m[2])+(m1->m[15])*(m2->m[3]); 
    // Second column 
    out.m[ 4]=(m1->m[0])*(m2->m[4])+(m1->m[4])*(m2->m[5])+(m1->m[ 8])*(m2->m[6])+(m1->m[12])*(m2->m[7]); 
    out.m[ 5]=(m1->m[1])*(m2->m[4])+(m1->m[5])*(m2->m[5])+(m1->m[ 9])*(m2->m[6])+(m1->m[13])*(m2->m[7]); 
    out.m[ 6]=(m1->m[2])*(m2->m[4])+(m1->m[6])*(m2->m[5])+(m1->m[10])*(m2->m[6])+(m1->m[14])*(m2->m[7]); 
    out.m[ 7]=(m1->m[3])*(m2->m[4])+(m1->m[7])*(m2->m[5])+(m1->m[11])*(m2->m[6])+(m1->m[15])*(m2->m[7]); 
    // Third column 
    out.m[ 8]=(m1->m[0])*(m2->m[8])+(m1->m[4])*(m2->m[9])+(m1->m[ 8])*(m2->m[10])+(m1->m[12])*(m2->m[11]); 
    out.m[ 9]=(m1->m[1])*(m2->m[8])+(m1->m[5])*(m2->m[9])+(m1->m[ 9])*(m2->m[10])+(m1->m[13])*(m2->m[11]); 
    out.m[10]=(m1->m[2])*(m2->m[8])+(m1->m[6])*(m2->m[9])+(m1->m[10])*(m2->m[10])+(m1->m[14])*(m2->m[11]); 
    out.m[11]=(m1->m[3])*(m2->m[8])+(m1->m[7])*(m2->m[9])+(m1->m[11])*(m2->m[10])+(m1->m[15])*(m2->m[11]); 
    // Fourth 
    out.m[12]=(m1->m[0])*(m2->m[12])+(m1->m[4])*(m2->m[13])+(m1->m[ 8])*(m2->m[14])+(m1->m[12])*(m2->m[15]); 
    out.m[13]=(m1->m[1])*(m2->m[12])+(m1->m[5])*(m2->m[13])+(m1->m[ 9])*(m2->m[14])+(m1->m[13])*(m2->m[15]); 
    out.m[14]=(m1->m[2])*(m2->m[12])+(m1->m[6])*(m2->m[13])+(m1->m[10])*(m2->m[14])+(m1->m[14])*(m2->m[15]); 
    out.m[15]=(m1->m[3])*(m2->m[12])+(m1->m[7])*(m2->m[13])+(m1->m[11])*(m2->m[14])+(m1->m[15])*(m2->m[15]); 

    return out; 
} 

我99.9%肯定着色器相同的例子。

回答

0

我看到兩個問題與您的代碼:

  1. 這是不是真的清楚你所使用的矩陣存儲佈局約定。

    您的lookAt代碼將-eye轉換爲元素12至14,這意味着您在着色器中使用列主版面和標準GL的matrix * vector乘法順序。但是,您的投影矩陣被定義爲轉換爲該慣例。元素11和14應該交換。

  2. lookAt功能失常:

    視圖矩陣應該改造世界的空間眼睛空間,攝像頭是在中心尋找到-z方向。這可以解釋爲相對於固定相機移動所有對象,或者相對於世界座標定義新的視圖座標系。在這兩種情況下,您最終都會得到公式R * T(-eye)。在第一種解釋中,這意味着我們首先將所有對象移動-eye(使得點eye結束於中心),然後圍繞該新中心旋轉,以便將lookAt方向旋轉到-z軸,並將up矢量到+y

    但是,您的lookAt矩陣不這樣做。你的矩陣可以分解爲T(-eye) * R^-1。所以首先,你的R不是你需要的旋轉:如果你通過-z軸矢量(0,0,-1,0)^T來複制你的矩陣,你只需要選擇第三列並取消它,所以你最終會得到-f。但是你的正向矢量應該是f,所以你在把它放入矩陣之前忘記了否定f

    第二個問題是,旋轉實際上是反轉。如果你否定第三欄,你將以V * (0 0 -1 0)^T = (f 0)^T結尾,但那是你需要的相反轉變方向。你必須建立一個結果爲V * (f 0)^T = (0 0 -1 0)的輪換。現在關於旋轉矩陣的好處是它們是正交的,所以R^-1 = R^T。這意味着你可以簡單地轉置你的旋轉矩陣來反轉它。

    但是,您不能只是轉置您的視圖矩陣。這引出了最後一個問題:您只需將翻譯部分-eye寫入第四欄。從概念上講,這意味着你做V=T(-eye) * R,也就是說,你應用翻譯作爲最近的步驟。但是,正如我們以前所見,我們必須首先應用。因此,要徹底解決你的矩陣,你建立R^T首先,通過轉旋轉部件,也就是寫su-f載體爲rows到矩陣,最後你該矩陣與T(-eye)簡單的翻譯矩陣。

+0

謝謝derhass:D – lohikaarme2