2012-08-27 127 views
0

我有存儲數據這樣一個OBJ文件:OBJ文件 - 平均法線

v value1 value2 value3 
f value1 value2 value3 

首先我計算一個正常的臉,然後分配給該人臉的每個頂點:

for(int i = 0; i < verticesInd.size(); i+=3) 
{ 
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]]))); 
    out_Normals[i] = normal; 
    out_Normals[i + 1] = normal; 
    out_Normals[i + 2] = normal; 
} 

對於實現的平面遮蔽我可以複製頂點:

for(int i = 0; i < verticesInd.size(); i++) 
{ 
    out_Vertices.push_back(vertices[verticesInd[i]]); 
} 

並且使用glDrawArrays繪製對象:

glDrawArrays(GL_TRIANGLES, 0, out_Vertices.size()); 

爲了獲得平滑的陰影,我需要爲每個頂點平均法線,但我不知道如何找到相鄰的面。

EDIT1:我沒有注意到˚F前一個s參數:

v value1 value2 value3 
s 1 
f value1 value2 value3 

EDIT2:法線平均

glm::vec3 tNormal; 
for(int i = 0; i < vertices.size(); i++) 
{ 
    for(int j = 0; j < verticesInd.size(); j++) 
    { 
     if(verticesInd[j] == i) 
     { 
      tNormal += faceNormals[j/3]; 
     } 
    } 
    aNormals.push_back(glm::normalize(tNormal)); 
    tNormal = glm::vec3(0,0,0); 
} 

編輯3個面法線:

for(int i = 0; i < verticesInd.size(); i+=3) 
{ 
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]]))); 
    faceNormals.push_back(normal); 
} 

回答

1

在大多數對象格式中,相鄰的面應該是共享頂點。在頂點找到平滑的陰影法線應該是對使用該頂點的任何面的法線進行平均的問題。

我建議你創建一個與現有頂點數組大小相同的額外新數組。

迭代每個面,併爲每個頂點索引,將該頂點的面添加到新陣列的法線。

在過程結束時,對結果法向量進行歸一化,然後使用該法線代替先前計算的面法線。

如果我正確理解你的數據結構,它會是這個樣子:

glm::vec3 aNormals[]; // one for each vertex - use the appropriate constructor 

for (int i = 0; i < verticesInd.size(); ++i) { 
    int f = i/3;     // which face is this index part of (3 per face?) 
    int v = verticesInd[i];  // which vertex number is being used 
    aNormals[v] += faceNormals[f]; // add the face normal to this vertex 
} 

// now normalise aNormals 
+0

該對象有50000個頂點和100000個面。對於每個頂點我需要檢查每個面,計算需要15分鐘在我的CPU上。 – Irbis

+0

@Irbis這聽起來像是你正在以錯誤的方式迭代結構。查看更新。 – Alnitak

+0

「@Irbis它聽起來像是你在錯誤的方向上遍歷結構」 - 請看看Edit2,它會帶來正確的結果。 – Irbis

0

按照這個傢伙 https://www.youtube.com/watch?v=MRD_zN0SWh0&feature=plcp每個碎片照明。就我所知,它包含用於在每個頂點基礎上查找法線的相同方程。

您需要一張臉部列表。如果你曾經見過波前物體。它們包含多個三角形索引4,7,2 1,2,3。每3個數字代表一張臉。使用正常的網格,每個點只能使用3次。如果你發現每個組有3個,你可以找到每個面。找到他們相應的正常值,然後平均。

Alnitak也有有效的信息。你有一個頂點列表,然後將它們列爲3個組,以便可以重複使用頂點(共享)作爲面數據。

+0

我的每個片段照明工作正常,您在上面附着的視頻無關的問題。在將它們發送給着色器之前,我需要平均法線。 – Irbis

+0

我不明白爲什麼你不能在着色器中平均它們。如果你的物體是靜態的,那麼預先計算法線是有用的。否則你可以用很多方式將你的法線提供給着色器。制服,屬性,頂點數組,緩衝區對象並在那裏取平均值。更多關於您在編輯中的當前問題。 – Kaliber64

+0

我的對象是靜態的,所以預先計算的法線應該更快,但否則我應該在着色器中執行它? – Irbis

0

我不知道如何找到相鄰的面孔。

將面的列表添加到臨時的in-OBJ加載程序頂點存儲中。在處理臉部線條時,將新臉部添加到其引用的每個頂點的臉部列表中。

通過這種方式,您可以旋轉結尾的所有頂點,查找它所屬的面,抓取面法線並對其進行平均。

如果你的OBJ沒有這樣好的烘焙連接信息(並且沒有必要),那麼你將不得不在每個頂點上進行最近鄰搜索以找到頂點(和相應的面)在它附近。使用你最喜歡的spatial index來加速這些查詢。