OpenGL/GLUT圆锥的表面法线

5

我使用GL_TRIANGLE_FAN创建了一个圆锥体。

// draw the upper part of the cone
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, height);
for (int angle = 0; angle < 360; angle++) {
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}
glEnd();

// draw the base of the cone
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, 0);
for (int angle = 0; angle < 360; angle++) {
    // normal is just pointing down
    glNormal3f(0, -1, 0);
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}
glEnd();

我该如何获取表面法线?对于底部,我可以说法线只是指向下方的吗?
更新:我尝试使用
for (int angle = 0; angle < 360; angle++) {
    glNormal3f(sin(angle), cos(angle), 0);
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}

但在某些角度看起来很奇怪... 输入图像描述 输入图像描述 第二幅图像看起来只是一个实色?

这个问题可能会有所帮助:https://dev59.com/cHrfs4cB2Jgan1zngjyu - fen
你的披风通常需要(sin, 0, cos)作为“向上”的部分(Y坐标)不变。然而,Y坐标(以及其他两个坐标)取决于锥体斜率的角度,因此更像是(cos(slopeAngle)* sin(angle),sin(slopeAngle),cos(slopeAngle)* cos(angle)) - Nobody moving away from SE
@Nobody,披风在哪里? - Jiew Meng
@JiewMeng:嗯,这是一个翻译错误。我只知道德语术语(Mantelfläche)。我指的是圆锥体的面而不是底部。正确的词可能是侧面。 - Nobody moving away from SE
1
顺便提一下:不要忘记为圆锥的顶部设置正确的法线。由于它对所有三角形都有贡献,因此应该指向正上方。 - Nobody moving away from SE
1个回答

8
假设您的圆锥高度为h,半径为r,并且它是竖立的(即其尖端指向+Y方向),则其侧面法线取决于两个角度:圆形底面的角度和锥体顶部的角度(我们称之为锥角或α)。这个锥角又取决于hr的比率。
观察圆锥的横截面,我们可以看到基本上是一个直角三角形,其中一个直角边长为h,另一个为r。假设h直角边从原点沿Y轴向上延伸,r直角边从原点沿X轴向上延伸。现在我们想计算斜边的法线朝外的点。

Angle proof and normal coordinates

在三角形上进行一些角度计算后,我们可以看到斜边的法向量具有以下形式:

(cos(coneAngle), sin(coneAngle))

使用

coneAngle = atan(r / h)

当然,这只是在二维情况下,我们需要3D对应的版本。 首先,我们需要XZ平面上圆形的法向量。 这可以写成

(cos(circleAngle), 0, sin(circleAngle))

现在我们可以将这两个方程组合成一个普通的方程。我们的斜率法线有水平和垂直两部分。垂直部分直接进入Y坐标,而水平部分对水平方向(X和Z)都有贡献。
(cos(coneAngle) * cos(circleAngle), sin(coneAngle), cos(coneAngle) * sin(circleAngle))

基本上有两个向量:指向锥顶的上向量和由圆形法线生成的水平向量。这两个向量形成一个基础,我在这里所做的是将XY 2D空间(圆锥正常)应用于由圆形法线和上向量(Y轴)跨越的空间中的线性变换。要进行此转换,您需要将XY空间向量的组件与其他空间的相应基向量相乘,并将结果相加,因此您基本上计算:

cos(coneAngle) * (cos(circleAngle), 0, sin(circleAngle)) + sin(coneAngle) * (0, 1, 0)

更新

我刚刚注意到,在斜边法线图像中的两个三角形是相似的,这意味着可以在不使用三角函数的情况下计算法线: 给定斜边长度 c = sqrt(h * h + r * r),我们可以从三角形的相似性得知:

n_x / 1 = n_x = h / c

并且

n_y / 1 = n_y = r / c

因此,斜边法线为:
1/c * (h, r)

顺便提一下,乘以因子1/c只是对向量(h, r)进行归一化的操作。


非常感谢您提供如此详细的解释。有两件事我还没有完全理解。通过圆角,我相信这是代码中的“angle”变量?另外,在最后一步中,合并法线时,为什么要使用乘法(虽然我不知道其他方法,但想要了解为什么要使用它)? - Jiew Meng
是的,circleAngle 就像你的 angle。至于第二个问题:我已经更新了我的答案并给出了解释(因为它无法放入评论中)。 - Nobody moving away from SE
正如我已经解释过的那样,2D圆锥体法线(或更好的斜边法线)的两个坐标是基向量的因子。这两个向量是圆形法线(cos(circleAngle), 0, sin(circleAngle))和上向量(0, 1, 0)。将向量乘以因子会使所有分量乘以该因子。也许这篇维基百科文章可以帮助你。 - Nobody moving away from SE
也许你应该开一个新问题,在那里你可以比较平面着色和光滑着色的代码? - Nobody moving away from SE
@Jiew Meng 看起来你忘记转换你的法线了。 - grisevg
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接