首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL计算法线(四边形)

OpenGL计算法线(四边形)
EN

Stack Overflow用户
提问于 2012-01-18 00:21:18
回答 3查看 2.5K关注 0票数 1

我的问题是关于OpenGL和Normals,我理解它们背后的数学原理,并且我正在取得一些成功。

下面附加的函数接受交错顶点数组,并计算每4个顶点的法线。这些表示具有相同方向的四边形。根据我的理解,这4个顶点应该共享相同的法线。只要他们面朝同样的方向。

我遇到的问题是,我的四边形是用对角线渐变渲染的,就像这样:Light Effect --除了阴影在中间,光线在角落。

我以一致的方式绘制我的四边形。TopLeft、TopRight、BottomRight、BottomLeft,我用来计算法线的顶点是TopRight - TopLeft和BottomRight - TopLeft。

希望有人能看到我犯了错误的东西,但我已经在这几个小时了,但没有成功。

为了记录,我渲染了一个立方体,并且在我的对象旁边有一个茶壶来检查我的照明是否正常工作,所以我相当确定没有关于光位置的问题。

代码语言:javascript
复制
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];
    }
}
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-18 00:45:41

看起来您是在从索引5、6和7中获取用于计算的顶点位置值,然后写出索引3、4和5处的法线。请注意索引5是如何在这两个位置上使用的。我想他们中有一个是错的。

票数 2
EN

Stack Overflow用户

发布于 2012-01-18 00:46:05

看起来你的for-loops在咬你。

代码语言:javascript
复制
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
    ...
  }
}
票数 2
EN

Stack Overflow用户

发布于 2012-01-18 00:47:52

您可以使用索引3、4和5来存储正常:

代码语言:javascript
复制
toCalc[i+j][3] = N[0]; toCalc[i+j][4] = N[1]; toCalc[i+j][5] = N[2];

您可以使用索引5、6和7来获取点坐标:

代码语言:javascript
复制
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];

这些索引是重叠的(Norm.x与position.z.z共享相同的索引),这是不应该发生的。

建议:

  1. 把所有的东西都放到了结构中。
  2. OR:
    1. 使用数学库。
    2. OR将向量算术放入单独的适当命名的subroutines.

  1. 使用命名变量而不是索引。

通过这样做,您将减少代码中的错误数量。a.position.xquad[0][5]更容易阅读,而且在没有复制粘贴代码的情况下,修复向量操作中的拼写错误也更容易。

您可以使用联合按索引和名称访问向量组件:

代码语言:javascript
复制
struct Vector3{
    union{
        struct{
            float x, y, z;
        };
        float v[3];
    };
};    

用于计算四边形中的法线

代码语言:javascript
复制
A--B
|  |
C--D

使用公式:

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

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

其中"X“表示”叉积“。

任何一种方式都可以很好地工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8898053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档