关于C ++:圆锥体的OpenGL / GLUT表面法线

OpenGL/GLUT surface normals of cone

我用GL_TRIANGLE_FAN创建了一个圆锥体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 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();

如何获得表面法线? 我到底想说正常是指向下方吗?

更新

我尝试使用

1
2
3
4
for (int angle = 0; angle < 360; angle++) {
    glNormal3f(sin(angle), cos(angle), 0);
    glVertex3f(sin(angle) * radius, cos(angle) * radius, 0);
}

但是从某些角度来看看起来很奇怪...

enter image description here

enter image description here

第二张图像看起来像只是一种纯色?


假设您的圆锥体的高度为h,半径为r,并且圆锥体的竖立状态(例如,其尖端指向+ Y方向),则侧面法线取决于两个角度:圆形地面区域的角度和圆锥体尖端的角度(我们称其为锥角或α)。锥角又取决于hr的比率。

观察圆锥的横截面,我们基本上看到一个直角三角形,其一个斜面的长度为h,另一个斜面的长度为r。假设h导管从原点开始沿Y轴笔直向上移动,而r导管沿X轴相同。现在我们要向外计算假设点的法线。

Angle proof and normal coordinates

在三角形上做一些角度数学运算,我们可以看到斜边的法线具有以下形式:

1
(cos(coneAngle), sin(coneAngle))

1
coneAngle = atan(r / h)

当然,这仅在2D中,我们需要3D等效项。
首先,我们需要XZ平面中的圆法线。
这可以写成

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

现在,我们可以将这两个方程合并为一个方程。我们的坡度法线具有水平和垂直部分。垂直部分直接进入Y坐标,而水平部分同时对两个水平方向(X和Z)起作用:

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

基本上有两个向量:指向圆锥体顶端的向上向量和水平向量(由圆法线生成的向量)。这两个向量构成一个基础,我在这里所做的是应用从(圆锥体法线的)XY 2D空间到由圆法线和上向量(Y轴)跨越的空间的线性变换。要进行此转换,您需要将XY空间向量的分量与另一个空间的各个基本向量相乘,并将结果求和,因此基本上可以计算出:

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

更新资料

我只是注意到,假设法线图像中的两个三角形是相似的,这意味着一个人可以不用三角函数就能计算法线:
给定假设c = sqrt(h * h + r * r)的长度,我们从三角形的相似性中知道:

1
n_x / 1 = n_x = h / c

1
n_y / 1 = n_y = r / c

因此,假设正常为:

1
1/c * (h, r)

顺便提及,乘以因子1/c仅仅是矢量(h, r)的归一化。