面部没有被正确绘制

时间:2012-11-22 09:15:00

标签: c++ opengl glut

更新

看起来好像我的法线正常工作,而且这是我画脸的方式(只画了一半),我无法弄明白为什么 -

Vertices, normals are drawn properly

如果您可以查看我之前的代码(如下所示)


原帖

我目前正在研究.obj文件类型的解析器/渲染器。我遇到了显示法线向量的问题:

没有法线:

有法线:

出于某种原因,我无法弄清楚为什么只有一半的法线载体有效,而另一半则表现得好像根本没有脸。

这是我在obj文件中加载的代码:

    void ObjModel::Load(string filename){
    ifstream file(filename.c_str());

    if(!file) return;

    stringstream ss;
    string param, line;
    float nparam, cur;

    vector<vector<float> > coords;
    vector<float> point;

    while(getline(file, line)){ 
        ss.clear();
        ss.str(line);

        ss >> param;

        //vertex
        if(param == "v"){
            for(int i = 0; i < 3; i++){
                ss >> nparam;
                this->vertices.push_back(nparam);
            }
        }

        //face
        else if(param == "f"){
            coords.clear();
            point.clear();

            for(int i = 0; i < 3; i++){
                ss >> nparam;
                nparam--;

                for(int j = 0; j < 3; j++){
                    cur = this->vertices[nparam * 3 + j];

                    this->faces.push_back(cur);
                    point.push_back(cur);
                }

                coords.push_back(point);
            }

            point = this->ComputeNormal(coords[0], coords[1], coords[2]);

            for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);
        }

        else continue;
    }
}
void ObjModel::Render(){
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, &this->faces[0]);
    glNormalPointer(GL_FLOAT, 0, &this->normals[0]);

    glDrawArrays(GL_TRIANGLES, 0, this->faces.size() / 3);

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

这是计算法线向量的函数:

vector<float> ObjModel::ComputeNormal(vector<float> v1, vector<float> v2, vector<float> v3){
vector<float> vA, vB, vX;
float mag;

vA.push_back(v1[0] - v2[0]);
vA.push_back(v1[1] - v2[1]);
vA.push_back(v1[2] - v2[2]);

vB.push_back(v1[0] - v3[0]);
vB.push_back(v1[1] - v3[1]);
vB.push_back(v1[2] - v3[2]);

vX.push_back(vA[1] * vB[2] - vA[2] * vB[1]);
vX.push_back(vA[2] * vB[0] - vA[0] * vB[2]);
vX.push_back(vA[0] * vB[1] - vA[1] * vB[0]);

mag = sqrt(vX[0] * vX[0] + vX[1] * vX[1] + vX[2] * vX[2]);

for(int i = 0; i < 3; i++) vX[i] /= mag;

return vX;}

我已经检查过以确保有相同数量的法向量和面(如果我是正确的话,那应该是这样的。)

提前谢谢! :)

编辑以下是我启用/禁用OpenGL功能的方法:

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLfloat amb_light[] =  0.1, 0.1, 0.1, 1.0 ;
GLfloat diffuse[] = {0.6, 0.6, 0.6, 1};
GLfloat specular[] = {0.7, 0.7, 0.3, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_light);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glLightModeli(L_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDisable(GL_CULL_FACE);

3 个答案:

答案 0 :(得分:1)

你在使用元素吗? Obj文件从1开始计数,但OpenGL从0开始计数。只需从每个元素中减去1即可得到正确的渲染。

答案 1 :(得分:1)

法线的方向很重要。看起来你的物体的面部方向不一致,所以具有相似平面的相邻面的法线指向相反的方向。

如果您从模型文件导入该模型,我建议您不要计算代码中的法线 - 无论如何都不应该这样做,因为艺术家可能会手动调整法线来局部微调照明 - 但是存储它们也在模型文件中。所有3D建模器都具有将法线翻转为共同方向的功能。在Blender中,例如在编辑模式下使用热键CTRL + N可以访问此功能。

答案 2 :(得分:0)

for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);

仅为每张脸提供一个法线。每个顶点需要一个法线。