2012-01-17 92 views
0

我的問題是關於OpenGL和法線,我理解他們背後的數學,並且我取得了一些成功。OpenGL計算法線(四邊形)

我在下面附加的函數接受交錯的頂點數組,並計算每4個頂點的法線。這些代表QUADS具有相同的方向。根據我的理解,這4個頂點應該共享相同的Normal。只要他們面對同樣的道路。

我遇到的問題是我的QUADS渲染時有一個對角線漸變,非常像這樣:Light Effect - 除了陰影在中間,角落中的燈光。

我以一致的方式畫出我的QUADS。 TopLeft,TopRight,BottomRight,BottomLeft和我用來計算法線的頂點是TopRight - TopLeft和BottomRight - TopLeft。

希望有人可以看到我犯了一個錯誤的東西,但我已經在這幾個小時沒有佔上風。

爲了記錄我呈現了一個立方體和一個茶壺旁邊的我的對象來檢查我的照明功能,所以我相當確定沒有關於光位置的問題。

void CalculateNormals(point8 toCalc[], int toCalcLength) 
{ 
    GLfloat N[3], U[3], V[3];//N will be our final calculated normal, U and V will be the subjects of cross-product 
    float length; 

for (int i = 0; i < toCalcLength; i+=4) //Starting with every first corner QUAD vertice 
{ 
    U[0] = toCalc[i+1][5] - toCalc[i][5]; U[1] = toCalc[i+1][6] - toCalc[i][6]; U[2] = toCalc[i+1][7] - toCalc[i][7]; //Calculate Ux Uy Uz 
    V[0] = toCalc[i+3][5] - toCalc[i][5]; V[1] = toCalc[i+3][6] - toCalc[i][6]; V[2] = toCalc[i+3][7] - toCalc[i][7]; //Calculate Vx Vy Vz 

    N[0] = (U[1]*V[2]) - (U[2] * V[1]); 
    N[1] = (U[2]*V[0]) - (U[0] * V[2]); 
    N[2] = (U[0]*V[1]) - (U[1] * V[0]); 

    //Calculate length for normalising 
    length = (float)sqrt((pow(N[0],2)) + (pow(N[1],2)) + (pow(N[2],2))); 

    for (int a = 0; a < 3; a++) 
    { 
     N[a]/=length; 
    } 

    for (int j = 0; i < 4; i++) 
    { 
        //Apply normals to QUAD vertices (3,4,5 index position of normals in interleaved array) 
     toCalc[i+j][3] = N[0]; toCalc[i+j][4] = N[1]; toCalc[i+j][5] = N[2]; 
    } 
} 
} 
+0

這是C++;你有沒有考慮過使用數學庫,比如[GLM](http://glm.g-truc.net/)? – 2012-01-17 16:24:20

+0

不幸的是,這是一個任務,因此我們不鼓勵使用庫。 – LBHoward 2012-01-17 16:38:58

回答

2

好像你是從指數5,6以使用的頂點位置值計算,7,然後在指數3,4寫出法線和5注指數5如何兩者都使用。我想其中一個是不正確的。

+0

非常感謝你,我有一種感覺,那就是在我面前盯着我的幾個小問題。截止日期是星期四,所以我一直在不停地努力解決最終的問題。 – LBHoward 2012-01-17 16:57:36

2

它看起來像你的for-loops咬你。

for (int i = 0; i < toCalcLength; i+=4) //Starting with every first corner QUAD vertice 
{ 
    ... 
    for (int j = 0; i < 4; i++) 
    { //   ^ ^
    // Should you be using 'j' instead of 'i' here? 
    // j will never increment 
    // This loop won't be called at all after the first time through the outer loop 
    ... 
    } 
} 
+0

好吧,這個問題引發了一個巨大的問題。謝謝! – LBHoward 2012-01-17 16:56:17

2

您使用索引3,4,和用於存儲正常:

toCalc[i+j][3] = N[0]; toCalc[i+j][4] = N[1]; toCalc[i+j][5] = N[2]; 

您使用索引,6和7獲得點座標:

U[0] = toCalc[i+1][5] - toCalc[i][5]; U[1] = toCalc[i+1][6] - toCalc[i][6]; U[2] = toCalc[i+1][7] - toCalc[i][7]; 

這些索引重疊(normal.x共享與position.z相同的索引),w這不應該發生。


建議:

  1. 把一切都變成結構。
  2. 要麼:
    1. 使用數學庫。或者將矢量算術放入單獨的適當命名的子程序中。
  3. 使用命名變量而不是索引。

通過這樣做,您可以減少代碼中的錯誤數量。 a.position.xquad[0][5]更容易閱讀,並且在代碼未被複制粘貼時更容易在矢量操作中修復拼寫錯誤。


可以使用工會雙方指數和名稱來訪問矢量分量:

struct Vector3{ 
    union{ 
     struct{ 
      float x, y, z; 
     }; 
     float v[3]; 
    }; 
};  

對於四ABCD calcualting正常

A--B 
| | 
C--D 

使用公式:

normal = normalize((B.pos ition - A.position)X(C.position - A.position))。

OR

正常=正常化((D.position - A.position)X(C.position - B.position))。

其中「X」表示「交叉產品」。

無論哪種方式將正常工作。

+0

感謝您的意見,數學全部到位,但正如您正確指出的那樣,我的法線與我的頂點重疊。 – LBHoward 2012-01-17 17:00:07