glNormal opengl - 方形示例

时间:2013-11-05 17:28:37

标签: opengl

我很难弄清楚如何计算正常,我想我有一些误解所以我想举一个简单几何的例子并找出正常情况,在这种情况下它应该更清楚如何用更硬的几何形状做到这一点。

    glBegin(GL_QUADS);
       glVertex3f(1,1,-1);
       glVertex3f(1,1,1);
       glVertex3f(-1,1,1);
       glVertex3f(-1,1,-1);
    glEnd();

在每个顶点,我知道我需要放入一个正常的值(我想点亮它)所以这代表一个正面方形(2 x 2)。那么在每个顶点之前,我的法线是否为(0,1.0,0)?

1 个答案:

答案 0 :(得分:12)

当您需要计算 quad normal 时,您需要计算四边形4个顶点的交叉积

A = (1, 1, -1)
B = (1, 1, 1)
C = (-1, 1, 1)
D = (-1, 1, -1)

这就是你的四边形顶点的布局方式。我之所以添加这个,是因为你计算下面顶点的顺序很重要!

A----B
|    |
|    |
D----C

所以现在当你想要计算法线时,你只需要这样做。

normal = (C - A) x (D - B)

其中x表示交叉产品。

跨产品

如果您不知道交叉产品是什么或如何计算它,那么我将在此向您展示如何计算它。

V1 = (C - A)
V2 = (D - B)

然后我们通过执行以下操作来计算交叉产品

normal.x = V1.y * V2.z - V1.z * V2.y
normal.y = V2.x * V1.z - V2.z * V1.x
normal.z = V1.x * V2.y - V1.y * V2.x

上述3行相当于写作。

normal = V1 x V2

现在我们计算了跨产品,在本例中是3D矢量。

附加

如果您不知道交叉产品是什么,并希望了解更多信息,那么您可以在这两个链接上阅读更多相关内容。

修改

  

我做了十字架产品,它是正常的=(0,8,0),如果我将它标准化我得到(0,1,0)

为了澄清一些事情,我们需要对法线进行标准化的原因是因为我们在x, y, z,

之间计算0 <-> 1的正态分布

如果要标准化矢量,可以执行以下操作。

length = sqrt(x * x + y * y + z * z)

if (length > 0) {
    x /= length
    y /= length
    z /= length
}

此外,如果您想检查是否需要对矢量进行标准化,可以执行以下操作。

if ((x * x + y * y + z * z) != 1) {
    // NORMALIZE THE VECTOR
}
  

现在这意味着我只需要在顶点上放置一次,或者我是否需要为四边形中的每个顶点提及它。

第一种方式

glBegin(GL_QUADS);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, -1);
    glVertex3f(1, 1, 1);
    glVertex3f(-1, 1, 1);
    glVertex3f(-1, 1, -1);
glEnd();

第二种方式

glBegin(GL_QUADS);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, -1);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, 1);
    glNormal3f(0, 1, 0);
    glVertex3f(-1, 1, 1);
    glNormal3f(0, 1, 0);
    glVertex3f(-1, 1, -1);
glEnd();

如果你是第一种或第二种方式,这并不重要。 只要你的四边形是普通的,所以如果它是完全平坦的,你可以做第一种或第二种方式。

虽然如果你的四边形不完全平坦,那么你需要做第二种方式,因为四边形的每个顶点将/可能有不同的法线。

  

许多资源表示你需要为每个顶点计算法线。

这是事实,虽然如上所述,如果你计算一个完全平坦的四边形的法线,那么每个顶点的法线将是相同的,因此你可以通过简单地只计算一个计算来节省一些计算/时间/ CPU正常一次,并尽可能长时间地为每个顶点使用它。