My vertex normals appear to be messed up.

Hello! I've been learning the Java binding of OpenGL (Jogl) and have been having trouble with lighting.

I've been writing an .OBJ file loader for the past week and have been getting pretty far. I decided to calculate the surface normals rather than rely on the file including them. The surface normals appear to be working accurately, but my vertex normals look quite off. Here are some screenshots of the smooth shading off and on.
I can't write a link yet, so please copy and paste this to the url bar to see the pictures: imgur.com/a/hzS9i

I'm not sure what exactly is wrong with my code to produce issues like that, but here are the parts that I think might be contributing.

sNormals_* are array lists of vertex normals. It loops through everything vertex of the object, then loops through every vertex again to look for matches (adjacent faces). when it does, it adds the face normal to the temporary "vertNorm*." After doing this it normalizes vertNorm* and adds it to the smooth normals at the index that faces.get(i).get(j) returns (the same index that a call to the list of vertices would require. it just pairs them up)

The surface normals appear to be working accurately, but my vertex normals look quite off.

Just from the pictures, I'd guess that you aren't normalising the normals to unit length, and aren't using glEnable(GL_NORMALIZE) either. That would result in the lighting intensity values typically being far outside the -1..1 range, so that any positive intensity is clamped to 1.0 and any negative intensity to 0.0. IOW, all faces are either fully lit or unlit.

The fact remains that the lighting appears to be saturated, i.e. most faces are either fully lit or unlit, with very little in between.

If GL_LIGHT0 is getting enabled, that will be a problem, as it starts out with a diffuse colour of (1,1,1,1).

The material shininess of 0.5 will result in specular highlights covering much of the object. Typical shininess values are greater than 1.0.

There may be other issues with parts of the code not shown. Initially, I'd suggest commenting out all references to materials and lighting. Enable GL_LIGHTING and GL_LIGHT0, leaving all light and material parameters at their defaults, except for the light position.

And because some model files export weirdly and duplicate vertices, making each vertex index different. "faces[f].vertices[i]" would give different references than it should. Instead, I have to check if they're equal instead of using their index value.
I do need to make it better, however.

And because some model files export weirdly and duplicate vertices, making each vertex index different. "faces[f].vertices[i]" would give different references than it should. Instead, I have to check if they're equal instead of using their index value.

If you need to weld coincident vertices, that should probably be a distinct step, performed before you calculate normals.

But that isn't always desirable. If you ignore the normals in the file and generate your own, and you always weld coincident vertices, it's impossible for a model to have corners.

Now that I think about it, that would probably make quite a few things easier. For most models I have however, this will suffice until I get around to implementing that.

Originally Posted by GClements

If you ignore the normals in the file and generate your own, and you always weld coincident vertices, it's impossible for a model to have corners.

I don't fully understand what you're saying, but I believe the problem you are describing can be solved using the smoothing groups in the .obj file. If I were to follow them correctly, it would prevent smoothing between faces that share a hard edge.

Edit: My light works now! I didn't think about glScale at all, and didn't realize it would screw up my normals. I read the docs and took their advice to use GL_NORMALIZE

Last edited by Aroymart; 07-25-2013 at 12:17 PM.
Reason: Fixed issue with lighting