【问题标题】:OpenGL calculating Normal of a custom shapeOpenGL计算自定义形状的法线
【发布时间】:2013-11-05 21:06:40
【问题描述】:

我有一个具有以下顶点和面的形状:

static Vec3f cubeVerts[24] = {
{ -0.5,  0.5, -0.5 },   /* backside */
{ -0.5, -0.5, -0.5 },   
{ -0.3,  4.0, -0.5 },
{ -0.3,  3.0, -0.5 },
{ -0.1,  5.5, -0.5 },
{ -0.1,  4.5, -0.5 },
{  0.1,  5.5, -0.5 },
{  0.1,  4.5, -0.5 },
{  0.3,  4.0, -0.5 },           
{  0.3,  3.0, -0.5 },
{  0.5,  0.5, -0.5 },   
{  0.5, -0.5, -0.5 },   

{ -0.5,  0.5,  0.5 },   /* frontside */
{ -0.5, -0.5,  0.5 },   
{ -0.3,  4.0,  0.5 },
{ -0.3,  3.0,  0.5 },
{ -0.1,  5.5,  0.5 },
{ -0.1,  4.5,  0.5 },
{  0.1,  5.5,  0.5 },
{  0.1,  4.5,  0.5 },
{  0.3,  4.0,  0.5 },           
{  0.3,  3.0,  0.5 },
{  0.5,  0.5,  0.5 },   
{  0.5, -0.5,  0.5 }
};

static GLuint cubeFaces[] = {
0, 1, 3, 2,     /*backfaces*/
2, 3, 5, 4,
4, 5, 7, 6, 
6, 7, 9, 8, 
8, 9, 11, 10,

12, 13, 15, 14, /*frontfaces*/
14, 15, 17, 16,
16, 17, 19, 18,
18, 19, 21, 20,
20, 21, 23, 22,

0, 2, 14, 12,   /*topfaces*/
2, 4, 16, 14,
4, 6, 18, 16, 
6, 8, 20, 18,
8, 10, 22, 20,

1, 3, 15, 13,   /*bottomfaces*/
3, 5, 17, 15,
5, 7, 19, 17,
7, 9, 21, 19,
9, 11, 23, 21,

0, 1, 13, 12,   /*sidefaces*/
10, 11, 23, 22
};

我想像这样恢复正常:

static Vec3f cubeNorms[] = {
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 }
};

谁能告诉我如何计算它的法线并将其放入一个数组中,这样我就可以像这样一起使用所有这些,我知道我的法线有问题,因为我的形状上的照明不正确,我也不正确确定它是否是设置法线的正确方法,仅举一个例子就可以了,我已经阅读了大量的法线计算,但仍然无法弄清楚如何去做。

static void drawCube()
{
//vertexes
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cubeVerts);
//norms
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, cubeNorms);
//faces
glDrawElements(GL_QUADS, 22 * 4, GL_UNSIGNED_INT, cubeFaces);
}

【问题讨论】:

  • 使用索引绘图时,每个顶点都需要一个法线 - 当面共享一个顶点时,您想要什么行为?
  • @Brett Hale,谢谢,形状是一个面连接的曲线,我知道我必须为每个顶点计算法线,但我不知道如何计算它,可以你给我看我代码中的一个顶点范数示例?

标签: opengl glut glu


【解决方案1】:

我会假设你的脸是counter-clockwise front-facing——我不知道是不是这样——当然,四边形是凸面和平面的。

对于面,取顶点 {0, 1, 2}。我不知道 Vec3f 规范(或者它是类还是 C 结构),但我们可以找到四边形中 all 顶点的法线:

Vec3f va = v0 - v1; // quad vertex 1 -> 0
Vec3f vb = v2 - v1; // quad vertex 1 -> 2
Vec3f norm = cross(vb, va); // cross product.

float norm_len = sqrt(dot(norm, norm));
norm /= norm_len; // divide each component of norm by norm_len.

这会给你一个unit normal 来代表那张脸。如果顶点是共享的,并且您希望使用光照为模型提供曲率感知,则您必须决定应该“同意”法线的哪个值。也许最好的起点是简单地取该顶点处的面法线的平均值 - 并根据需要将结果重新缩放为单位长度。

【讨论】:

  • 我认为您的顺序有误,如果使用 ccw 面孔,您的代码会产生向后指向的法线。否则当然正确答案。
  • @BrettHale 谢谢布雷特和克里斯蒂安
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多