2012-01-17 115 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