按照红皮书中的代码在 OpenGL 中绘制二十面体时缺少面孔
Faces missing when drawing icosahedron in OpenGL following code in redBook
我正在尝试在红皮书 this popular OpenGl tutorial 后面画一个二十面体。
我正在使用 GLUT 来处理窗口化。
这是我的完整代码。它主要是教程中的代码加上一些使用 GLUT
的文书工作
#include <stdio.h>
#include <GL/glut.h>
#define X .525731112119133606
#define Z .850650808352039932
void mouseEventHandler(int button, int state, int x, int y){
}
void display() {
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
static GLfloat vdata[12][3] = {
{-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
{0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
{Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
};
static GLuint tindices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
int i;
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++){
glNormal3fv(&vdata[tindices[i][0]][0]);
glVertex3fv(&vdata[tindices[i][0]][0]);
glNormal3fv(&vdata[tindices[i][1]][0]);
glVertex3fv(&vdata[tindices[i][1]][0]);
glNormal3fv(&vdata[tindices[i][2]][0]);
glVertex3fv(&vdata[tindices[i][2]][0]);
}
glEnd();
glFlush ( );
}
void windowSetup(){
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(80, 80);
glutInitWindowSize(1000,1000);
glutCreateWindow("OpenGL Ico");
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW);
glLoadIdentity();
gluOrtho2D( -2.0, 2.0, -2.0, 2.0 );
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
windowSetup();
glutDisplayFunc(display);
glutMouseFunc(&mouseEventHandler);
glutMainLoop();
}
这是我的输出:
这与预期的输出非常不同:
有人知道为什么这些差异如此之大吗?
差异似乎是:
我的二十面体少了面
我的二十面体被换个角度看
我的二十面体发光不一样
第一个最紧迫。我注意到当我将 glMatrixMode( GL_MODELVIEW);
更改为 glMatrixMode( GL_PROJECTION);
时,未显示的面孔出现了,而当前出现的面孔消失了。有人知道为什么会这样吗?
缺少面孔
很可能你的索引顺序有误。在这种情况下,反转它们将解决问题。要检查这一点,您可以尝试:
glDisable(GL_CULL_FACE);
如果问题消失,我是对的。如果不是,那就是不同的东西(比如 Z_NEAR
太靠近相机切割,但看起来会有点不同)。
要识别正确的面孔,您可以使用基于 i
的 glColor
例如
if (i==5) glColor3f(1.0,0.0,0.0); else glColor3f(1.0,1.0,1.0);
在这种情况下,红脸将是第 6 个 {8,3,10}
灯光
您正在使用顶点坐标作为法线,所以不要期待 FLAT 着色。我也没有看到你在这里设置任何灯(但可以隐藏在 GLUT 某个我不使用它的地方)。为了解决这个问题,每个三角形只使用一个法线。所以平均你得到的 3 个法线并从中制作一个单位向量并使用它(在第一次 glVertex
调用每个三角形之前)。
方向
只需将 GL_MODELVIEW
旋转到所需方向即可。标准视角 GL_PROJECTION
有 z
轴作为观察方向并且 x,y
轴与屏幕匹配(而 GL_MODELVIEW
是单位)
[Edit1] 我试过你的代码
所以问题是你得到了相反的索引顺序然后在 OpenGL 中默认多边形缠绕(至少在我的环境中)并且这里的法线错误固定代码:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
const GLfloat vdata[12][3] =
{
{-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
{0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
{Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
};
const GLuint tindices[20][3] =
{
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
};
int i;
GLfloat nx,ny,nz;
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++)
{
nx =vdata[tindices[i][0]][0];
ny =vdata[tindices[i][0]][1];
nz =vdata[tindices[i][0]][2];
nx+=vdata[tindices[i][1]][0];
ny+=vdata[tindices[i][1]][1];
nz+=vdata[tindices[i][1]][2];
nx+=vdata[tindices[i][2]][0]; nx/=3.0;
ny+=vdata[tindices[i][2]][1]; ny/=3.0;
nz+=vdata[tindices[i][2]][2]; nz/=3.0;
glNormal3f(nx,ny,nz);
glVertex3fv(vdata[tindices[i][0]]);
glVertex3fv(vdata[tindices[i][1]]);
glVertex3fv(vdata[tindices[i][2]]);
}
glEnd();
并预览:
这是一张屏幕截图,我的对象在旋转,所以不要指望方向正确。
我正在尝试在红皮书 this popular OpenGl tutorial 后面画一个二十面体。
我正在使用 GLUT 来处理窗口化。
这是我的完整代码。它主要是教程中的代码加上一些使用 GLUT
的文书工作#include <stdio.h>
#include <GL/glut.h>
#define X .525731112119133606
#define Z .850650808352039932
void mouseEventHandler(int button, int state, int x, int y){
}
void display() {
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
static GLfloat vdata[12][3] = {
{-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
{0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
{Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
};
static GLuint tindices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
int i;
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++){
glNormal3fv(&vdata[tindices[i][0]][0]);
glVertex3fv(&vdata[tindices[i][0]][0]);
glNormal3fv(&vdata[tindices[i][1]][0]);
glVertex3fv(&vdata[tindices[i][1]][0]);
glNormal3fv(&vdata[tindices[i][2]][0]);
glVertex3fv(&vdata[tindices[i][2]][0]);
}
glEnd();
glFlush ( );
}
void windowSetup(){
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(80, 80);
glutInitWindowSize(1000,1000);
glutCreateWindow("OpenGL Ico");
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW);
glLoadIdentity();
gluOrtho2D( -2.0, 2.0, -2.0, 2.0 );
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
windowSetup();
glutDisplayFunc(display);
glutMouseFunc(&mouseEventHandler);
glutMainLoop();
}
这是我的输出:
有人知道为什么这些差异如此之大吗?
差异似乎是:
我的二十面体少了面
我的二十面体被换个角度看
我的二十面体发光不一样
第一个最紧迫。我注意到当我将 glMatrixMode( GL_MODELVIEW);
更改为 glMatrixMode( GL_PROJECTION);
时,未显示的面孔出现了,而当前出现的面孔消失了。有人知道为什么会这样吗?
缺少面孔
很可能你的索引顺序有误。在这种情况下,反转它们将解决问题。要检查这一点,您可以尝试:
glDisable(GL_CULL_FACE);
如果问题消失,我是对的。如果不是,那就是不同的东西(比如
Z_NEAR
太靠近相机切割,但看起来会有点不同)。要识别正确的面孔,您可以使用基于
i
的glColor
例如if (i==5) glColor3f(1.0,0.0,0.0); else glColor3f(1.0,1.0,1.0);
在这种情况下,红脸将是第 6 个
{8,3,10}
灯光
您正在使用顶点坐标作为法线,所以不要期待 FLAT 着色。我也没有看到你在这里设置任何灯(但可以隐藏在 GLUT 某个我不使用它的地方)。为了解决这个问题,每个三角形只使用一个法线。所以平均你得到的 3 个法线并从中制作一个单位向量并使用它(在第一次
glVertex
调用每个三角形之前)。方向
只需将
GL_MODELVIEW
旋转到所需方向即可。标准视角GL_PROJECTION
有z
轴作为观察方向并且x,y
轴与屏幕匹配(而GL_MODELVIEW
是单位)
[Edit1] 我试过你的代码
所以问题是你得到了相反的索引顺序然后在 OpenGL 中默认多边形缠绕(至少在我的环境中)并且这里的法线错误固定代码:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
const GLfloat vdata[12][3] =
{
{-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
{0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
{Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
};
const GLuint tindices[20][3] =
{
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
};
int i;
GLfloat nx,ny,nz;
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++)
{
nx =vdata[tindices[i][0]][0];
ny =vdata[tindices[i][0]][1];
nz =vdata[tindices[i][0]][2];
nx+=vdata[tindices[i][1]][0];
ny+=vdata[tindices[i][1]][1];
nz+=vdata[tindices[i][1]][2];
nx+=vdata[tindices[i][2]][0]; nx/=3.0;
ny+=vdata[tindices[i][2]][1]; ny/=3.0;
nz+=vdata[tindices[i][2]][2]; nz/=3.0;
glNormal3f(nx,ny,nz);
glVertex3fv(vdata[tindices[i][0]]);
glVertex3fv(vdata[tindices[i][1]]);
glVertex3fv(vdata[tindices[i][2]]);
}
glEnd();
并预览:
这是一张屏幕截图,我的对象在旋转,所以不要指望方向正确。