2012-11-22 112 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]); 

這隻能爲每張臉提供一個正常值。每個頂點需要一個法線。