簡體   English   中英

法線在openGL中表現得很奇怪

[英]Normals acting weird in openGL

我一直在為openGl編寫一個.obj加載器。 幾何加載很好,但法線總是搞砸了。 我試圖在2個不同的程序中導出模型,似乎沒有任何工作。 據我所知,這就是你如何處理GL_TRIANGLES的法線

     glNormal3fv(norm1);   
     glVertex3fv(vert1);
     glNormal3fv(norm2);
     glVertex3fv(vert2);
     glNormal3fv(norm3);
     glVertex3fv(vert3);

(法線在其余代碼中引用GLfloats。)

編輯:這是一個破碎法線的isohedron圖片 在此輸入圖像描述

這是完整的obj加載器代碼和文件:

    void loadOBJFromFile(NSString *path,float movex,float movey)
{
    NSString *contentns = [[NSString alloc]initWithContentsOfFile:path encoding:NSASCIIStringEncoding error:NULL];
    NSArray *pieces = [contentns componentsSeparatedByString:@"#"];
    //creating the arrays to read the vertecies and normals from.
    NSArray *normals = [[pieces objectAtIndex:3]componentsSeparatedByString:@"\n"];
    NSArray *vertecies = [[pieces objectAtIndex:2]componentsSeparatedByString:@"\n"];
    //The +1 is to make sure we ignore the texture/ material definition that vomes before the faces.
    int normalCount = [[normals objectAtIndex:0]intValue]+2;
    int faceCount = [[normals objectAtIndex:normalCount]intValue];
    //glTranslatef(movex, 0, movey);

glBegin(GL_TRIANGLES);
{
for (int i = 0; i < faceCount;i++)
{
    //aquires all the numbers in thye current face.
    NSArray *currentFace = [[normals objectAtIndex:normalCount+i+1]componentsSeparatedByString:@" "];
    NSArray *v1 = [[currentFace objectAtIndex:1]componentsSeparatedByString:@"//"];
    NSArray *v2 = [[currentFace objectAtIndex:2]componentsSeparatedByString:@"//"];
    NSArray *v3 = [[currentFace objectAtIndex:3]componentsSeparatedByString:@"//"];

    //crewatres the arrays to contain the vertecies
    NSArray *vertex1 = [[vertecies objectAtIndex:[[v1 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];
    NSArray *vertex2 = [[vertecies objectAtIndex:[[v2 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];
    NSArray *vertex3 = [[vertecies objectAtIndex:[[v3 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];
    //creates all the arrays for the normals
    NSArray *normal1 = [[normals objectAtIndex:[[v1 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];
    NSArray *normal2 = [[normals objectAtIndex:[[v2 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];
    NSArray *normal3 = [[normals objectAtIndex:[[v3 objectAtIndex:1]intValue]]componentsSeparatedByString:@" "];

    //creates the vertecies coordinates
    GLfloat vert1[] = {[[vertex1 objectAtIndex:1]floatValue],[[vertex1 objectAtIndex:2]floatValue],[[vertex1 objectAtIndex:3]floatValue]};
    GLfloat vert2[] = {[[vertex2 objectAtIndex:1]floatValue],[[vertex2 objectAtIndex:2]floatValue],[[vertex2 objectAtIndex:3]floatValue]};
    GLfloat vert3[] = {[[vertex3 objectAtIndex:1]floatValue],[[vertex3 objectAtIndex:2]floatValue],[[vertex3 objectAtIndex:3]floatValue]};
    //creates the normals coordinates

    GLfloat norm1[] = {[[normal1 objectAtIndex:1]floatValue],[[normal1 objectAtIndex:2]floatValue],[[normal1 objectAtIndex:3]floatValue]};
    GLfloat norm2[] = {[[normal2 objectAtIndex:1]floatValue],[[normal2 objectAtIndex:2]floatValue],[[normal2 objectAtIndex:3]floatValue]};
    GLfloat norm3[] = {[[normal3 objectAtIndex:1]floatValue],[[normal3 objectAtIndex:2]floatValue],[[normal3 objectAtIndex:3]floatValue]};

     glNormal3fv(norm1);   
     glVertex3fv(vert1);
     glNormal3fv(norm2);
     glVertex3fv(vert2);
     glNormal3fv(norm3);
     glVertex3fv(vert3);
}}
glEnd();

}

obj文件:

#Wavefront OBJ file created by Hexagon 2 
mtllib object.mtl
g Form0
usemtl def_surf_mat
# 12 
v -12.533 4.78719 0 
v -12.533 20.2788 0 
v -7.74583 12.533 -12.533 
v -7.74583 12.533 12.533 
v 0 0 -7.74583 
v 0 0 7.74583 
v 0 25.066 -7.74583 
v 0 25.066 7.74583 
v 7.74583 12.533 -12.533 
v 7.74583 12.533 12.533 
v 12.533 4.78719 0 
v 12.533 20.2788 0 
# 12 
vn -0.850651 -0.525731 0 
vn -0.850651 0.525731 1.50014e-08 
vn -0.525731 -1.50014e-08 -0.850651 
vn -0.525731 0 0.850651 
vn 1.50014e-08 -0.850651 -0.525731 
vn -1.50014e-08 -0.850651 0.525731 
vn -1.50014e-08 0.850651 -0.525731 
vn 1.50014e-08 0.850651 0.525731 
vn 0.525731 0 -0.850651 
vn 0.525731 7.5007e-09 0.850651 
vn 0.850651 -0.525731 1.50014e-08 
vn 0.850651 0.525731 -1.50014e-08 
usemtl def_surf_mat
20
f 7//7 8//8 12//12 
f 7//7 2//2 8//8 
f 8//8 4//4 10//10 
f 6//6 10//10 4//4 
f 7//7 9//9 3//3 
f 5//5 3//3 9//9 
f 6//6 5//5 11//11 
f 6//6 1//1 5//5 
f 1//1 4//4 2//2 
f 1//1 2//2 3//3 
f 12//12 11//11 9//9 
f 12//12 10//10 11//11 
f 2//2 4//4 8//8 
f 10//10 12//12 8//8 
f 12//12 9//9 7//7 
f 3//3 2//2 7//7 
f 3//3 5//5 1//1 
f 4//4 1//1 6//6 
f 9//9 11//11 5//5 
f 11//11 10//10 6//6 

有了你在問題中添加的額外信息,我的想法已經不多了。 我也不能真正閱讀Objective-C,但我建議仔細檢查你所有的數組索引和行計數代碼(也許打印出來看看它們是否真的是你所期望的),因為解析基於信任確切的布局和注釋一個出口商創造看起來很毛茸茸。

原始答案:

如果沒有看到您的加載程序代碼或.obj文件,請查看以下幾項:

  • 怎么搞砸了? 完全錯了,或者只是平坦的陰影而不是光滑的陰影?
  • 那些norm1,norm2等三個GLfloats陣列?
  • 普通數組是否包含合理的值(因此從文件中讀取它們有效)?
  • 您的法線是否標准化為長度1?
  • 法線索引是否正確,即正確的頂點是否正確?

tl; dr但是 - 檢查你的法線的標志是否正確。 在計算中很容易使法線指向與您預期相反的方向。 例如,它們沿着正確的線,但指向內部而不是外部。 您的圖像與該類型或錯誤一致。

據我所知,在計算法線時,你必須采用兩條邊的矢量交叉乘積。 計算的順序決定了法線是否進入或退出。 因此,請確保按正確的順序進行計算。

在我看來OBJ文件是有效的,你的OBJ解析器正確讀取頂點位置和法線。 所以,我認為渲染問題來自不同的原因。

圖像中的視覺瑕疵看起來像是不正確的深度測試。 (僅繪制三角形的一半)我猜你在IB(Interface Builder)中使用了NSOpenGLView的子類。 確保在IB Attribute Inspector中 啟用 NSOpenGLView的深度緩沖區 (默認情況下,它為none)。 深度緩沖區的公共值是24位,加上Stencil緩沖區的8位。


並且,以下是一些改進計划的建議;

  • 繪圖和解析必須在單獨的函數中執行。 因為您只需要加載一次文件,但您可以多次繪制模型。

  • 對頂點,法線和面使用NSMutableArray。

  • 您的OBJ加載程序不是解析OBJ文件的最佳方法,因為它取決於注釋行(以#開頭)。 我會做:

    1. 逐行讀取並將它們存儲到一個行數組中。
    2. 遍歷每一行並測試以下內容:
    3. 如果它以#開頭,則跳過解析該行。
    4. 如果它以“v”開頭,則在同一行將以下3個數字添加到頂點數組。
    5. 如果它以“vn”開頭,則將該行的后3個數字添加到正常數組。
    6. 如果以“f”開頭,則將3個面部索引添加到面部數組。

答案很簡單。 正在從目標文件中正確加載對象。 加載器代碼可以進行更多優化。 打電話后,

glEnable(GL_CULL_FACE | GL_CULL_FACE_MODE);

編輯我不敢相信我當時犯了這樣一個新手的錯誤。 剔除的臉有所幫助,但只有一點點。 真正的問題是我忘記清除深度緩沖區。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

如果其他人也遇到同樣的事情,那應該解決問題。

一些問題得到解決,我實際上需要清除另一個緩沖區或彈出矩陣或其他東西。 現在,照明幾何體正好加載它在編輯器和建模程序中的顯示方式。 感謝大家的幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM