2012-11-22 49 views
2

更新Faces的不正确绘制

看来好像我的法线做工精细,它的东西与我怎么拉我的面(只有一半被绘制),我想不通为什么 -

Vertices, normals are drawn properly

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


Original post

我目前正在研究.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); 
+0

尝试'glDisable(GL_CULL_FACE)' – Kos

+0

尝试启用并禁用它,但结果相同 – mkorcha

+0

并进行了深度测试?它是否启用并设置为GL_LESS?你是否每帧清除深度缓冲区? – Kos

回答

1

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

+0

当我发现我在一张脸,我减少每个元素的位置只要我在 – mkorcha

+0

中读到它,我非常怀疑这是正常的问题。仔细观察,你会发现头部的三角形是对角放置的,这意味着你的顶点解析有问题。你有没有尝试渲染模型没有任何法线?混乱的法线通常不会产生这种效果。 – TheAmateurProgrammer

+0

第一张图片没有法线,第二张图片没有。对不起,我没有在OP中说清楚,我编辑过它。 – mkorcha

1

法线的方向很重要。它看起来像你的物体的脸部取向不是一致的,所以相邻面的法线与相似的平面指向相反的方向。

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

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

这只能为每张脸提供一个正常值。每个顶点需要一个法线。