Normals acting weird in openGL

I wrote a .obj loader for openGl. The geometry loads fine, but the normals are always mixed up. I tried to export models in 2 different programs and nothing works. As far as I know, this is how you set the normal mode for GL_TRIANGLES

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

(Normals refer to GLfloats in the rest of the code.)

EDITOR: Here is a picture of an isohedron with broken normals enter image description here

This is the complete code and obj loader file:

  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 file:

 #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 
+4
source share
4 answers

The answer is very simple. The object loaded correctly from the object file. The loader encoder can be optimized much more. After the call

glEnable (GL_CULL_FACE | GL_CULL_FACE_MODE);

EDIT I can't believe that then I made such a novice mistake. The cleaning face helped, but only a little. The real problem was that I forgot to clear the depth buffer.

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

This should solve the problem if anyone else is experiencing the same things.

Some problem was fixed, I really needed to clear another buffer or pop matrix or something like that. Now the lighting geometry is loaded exactly as it appears in editors and modeling programs. Thank you all for your help.

0
source

With the additional information you added to the question, I'm running out of ideas. I also can't read Objective-C, but I would suggest double checking all indexing and row counting indices (maybe print everything to make sure that they are really what you expect), because the parsing is based on trust in the exact layout and commenting on one exporter creates a very hairy look.

Original answer:

Without looking at your bootloader code or your .obj file, here are a few things to check:

  • How messed up? Absolutely wrong, or just for example. flat shaded instead of smooth shading?
  • Are these norms1, norm2, etc. arrays of three GLfloats?
  • Normal arrays contain normal values โ€‹โ€‹(so reading them from a file works)?
  • Are normals normal to length 1?
  • Are normals indexed correctly, i.e. Are you right for the right top?
+1
source

tl; dr, but --- check the sign of your normals. In calculations, it is easy to have normals pointing in the opposite direction than you planned. For instance. they follow the right line, but point inside, not outside. Your image matches this view or error.

As far as I remember when calculating normals, you need to take the vector transverse product of two edges. The order in which you perform the calculation determines whether the normal point is in or out. Therefore, make sure that you perform the calculations in the correct order.

+1
source

It seems to me that the OBJ file is valid, and your OBJ parser correctly reads the vertex positions and normals. So, I believe that the rendering problem arises for another reason.

Visual artifacts in your image look like an incorrect depth test. (I draw only half a triangle) I assume that you are using a subclass of NSOpenGLView in IB (Interface Builder). Make sure to enable the depth buffer for NSOpenGLView in IB Attribute Inspector (by default it is not). The total depth buffer is 24 bits, plus 8 bits for the Stencil buffer.


And here are some suggestions for improving your program;

  • Drawing and parsing should be performed in separate functions. Since you only need to upload the file once, but you can draw the model several times.

  • Use NSMutableArray for vertices, normals, and faces.

  • Your OBJ downloader is not the best way to parse an OBJ file because it depends on the comment line (starting in C #). I would do:

    • Read line by line and save them in an array of lines.
    • Scroll through each line and check the following:
    • If it starts with C #, then skip to parse the string.
    • If it starts with "v", add the following 3 numbers on one line to the vertex array.
    • If it starts with "vn", add the following 3 numbers to the string to the normal array.
    • If it starts with "f", add 3 facial indexes to the array of faces.
+1
source

All Articles