Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 9 of 9

Thread: My vertex normals appear to be messed up.

  1. #1
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    5

    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.

    Code :
    private void averageNormals() {
     
     
     
    		long time = System.currentTimeMillis();
     
     
    		sNormals_x = new Float[vertices_x.size()];
    		sNormals_y = new Float[vertices_y.size()];
    		sNormals_z = new Float[vertices_z.size()];
     
    		for(int i = 0; i < faces.size(); i++){//each face of the polygon
    			vertex:
    				for(int j = 0; j < faces.get(i).size(); j++){//each vertex call of each face
     
     
    					float vertNorm_x = 0,vertNorm_y = 0,vertNorm_z = 0;
     
    					if(sNormals_x[faces.get(i).get(j)] != null)
    						continue vertex;
     
     
    					for(int x = i; x < faces.size(); x++){
    						for(int y = 0; y < faces.get(x).size(); y++){
     
    							if(vertices_x.get(faces.get(x).get(y)) == vertices_x.get(faces.get(i).get(j)) 
    									&& vertices_y.get(faces.get(x).get(y)) == vertices_y.get(faces.get(i).get(j)) 
    									&& vertices_z.get(faces.get(x).get(y)) == vertices_z.get(faces.get(i).get(j)) 
    									){
     
     
    								//if(faces.get(i).get(j) == faces.get(x).get(y)){
     
    								vertNorm_x += faceNormals.get(x)[0];
    								vertNorm_y += faceNormals.get(x)[1];
    								vertNorm_z += faceNormals.get(x)[2];
     
     
     
     
     
    							}
     
    						}
    					}
     
    					float total = (float) Math.pow(	Math.pow(vertNorm_x,2) + 
    							Math.pow(vertNorm_y,2) +
    							Math.pow(vertNorm_z,2) 
    							,.5);
     
    					sNormals_x[faces.get(i).get(j)] = (vertNorm_x / total);
    					sNormals_y[faces.get(i).get(j)] = (vertNorm_y / total);
    					sNormals_z[faces.get(i).get(j)] = (vertNorm_z / total);
     
     
     
     
     
     
    				}}
    		System.out.println("It took " + (System.currentTimeMillis() - time) + " milliseconds.");
     
     
    	}

    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)



    Code :
    	float SHINE_ALL_DIRECTIONS = 1;
    		float[] lightPos = {20 + offset_x,20 + offset_y,20 + offset_z, SHINE_ALL_DIRECTIONS};
    		//float[] lightColorAmbient = {0.4f, 0.4f, 0.4f, 1f};
    		float[] lightColorSpecular = {1f, 1f, 1f, 1f};
     
    		// Set light parameters.
    		gl.glLightfv(GL_LIGHT1, GL_POSITION, lightPos, 0);
    	//	gl.glLightfv(GL_LIGHT1, GL_AMBIENT, lightColorAmbient, 0);
    		gl.glLightfv(GL_LIGHT1, GL_SPECULAR, lightColorSpecular, 0);
     
    		// Enable lighting in GL.
    		gl.glEnable(GL_LIGHT1);
    		gl.glEnable(GL_LIGHTING);
     
    		// Set material properties.
    		float[] rgba = {1, 1, 1};
    		gl.glMaterialfv(GL_FRONT, GL_AMBIENT, rgba, 0);
    		gl.glMaterialfv(GL_FRONT, GL_SPECULAR, rgba, 0);
    		gl.glMaterialf(GL_FRONT, GL_SHININESS, 0.5f);


    This part was taken from a jogl tutorial.




    If that wasn't enough, I can get some more of my code.



    But should the lighting look like that? I don't think so, but I'm fairly new to this. I'm fairly certain that Link is incorrect, but I'm not sure why it is.

    Also I apologize if this has been asked, I searched the forums for "light" but couldn't come up with a better search term for it.

  2. #2
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Aroymart View Post
    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.

  3. #3
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    5
    Thanks for the help!

    I believe I've normalized it with
    Code :
    	float total = (float) Math.pow(	Math.pow(vertNorm_x,2) + 
    							Math.pow(vertNorm_y,2) +
    							Math.pow(vertNorm_z,2) 
    							,.5);
     
    					sNormals_x[faces.get(i).get(j)] = (vertNorm_x / total);
    					sNormals_y[faces.get(i).get(j)] = (vertNorm_y / total);
    					sNormals_z[faces.get(i).get(j)] = (vertNorm_z / total);
    and I printed the normals for everything, and I believe they mostly look correct.

    Code :
    ---------
    x Normal:0.0652547
    y Normal:0.6629226
    z Normal:0.74583876
    ---------
    x Normal:0.4228353
    y Normal:0.6056943
    z Normal:0.674051
    ---------
    x Normal:0.029017318
    y Normal:0.9948907
    z Normal:0.09669842
    ---------
    x Normal:-0.5769266
    y Normal:0.8094493
    z Normal:0.109304525
    ---------
    x Normal:-0.36956686
    y Normal:0.51802975
    z Normal:0.77140486
    ---------
    x Normal:0.0652547
    y Normal:0.6629226
    z Normal:0.74583876
    ---------
    x Normal:-0.5769266
    y Normal:0.8094493
    z Normal:0.109304525
    ---------
    x Normal:-0.84950495
    y Normal:0.49310163
    z Normal:0.18759586
    ---------
    x Normal:-0.6336471
    y Normal:0.27636924
    z Normal:0.7225728
    ---------
    x Normal:-0.36956686
    y Normal:0.51802975
    z Normal:0.77140486
    ---------
    x Normal:-0.84950495
    y Normal:0.49310163
    z Normal:0.18759586
    ---------
    x Normal:-0.903545
    y Normal:0.32187897
    z Normal:0.28284326
    ---------
    x Normal:-0.6913337
    y Normal:0.18393901
    z Normal:0.6987304
    ---------
    x Normal:-0.6336471
    y Normal:0.27636924
    z Normal:0.7225728
    ---------
    x Normal:-0.903545
    y Normal:0.32187897
    z Normal:0.28284326
    ---------
    x Normal:-0.89845586
    y Normal:0.27665398
    z Normal:0.34093925
    ---------
    x Normal:-0.66959554
    y Normal:0.2797173
    z Normal:0.68804073
    ---------
    x Normal:-0.6913337
    y Normal:0.18393901
    z Normal:0.6987304
    ---------
    x Normal:0.8056257
    y Normal:-0.28696525
    z Normal:0.51828384
    ---------
    x Normal:0.7915004
    y Normal:-0.14076306
    z Normal:0.5947377
    ---------
    x Normal:0.41655508
    y Normal:-0.014255802
    z Normal:0.9089987
    ---------
    x Normal:0.41371974
    y Normal:-0.020337181
    z Normal:0.9101771
    ---------
    x Normal:0.7915004
    y Normal:-0.14076306
    z Normal:0.5947377
    ---------
    x Normal:0.80526567
    y Normal:0.083248034
    z Normal:0.58704084
    ---------
    x Normal:0.4599735
    y Normal:0.10497045
    z Normal:0.8817061
    ---------
    x Normal:0.41655508
    y Normal:-0.014255802
    z Normal:0.9089987
    ---------
    x Normal:0.80526567
    y Normal:0.083248034
    z Normal:0.58704084
    ---------
    x Normal:0.7734537
    y Normal:0.2717568
    z Normal:0.57264096
    ---------
    x Normal:0.49563178
    y Normal:0.22927073
    z Normal:0.8377256
    ---------
    x Normal:0.4599735
    y Normal:0.10497045
    z Normal:0.8817061
    ---------
    x Normal:0.7734537
    y Normal:0.2717568
    z Normal:0.57264096
    ---------
    x Normal:0.66004086
    y Normal:0.44558245
    z Normal:0.60481596
    ---------
    x Normal:0.4522171
    y Normal:0.33794355
    z Normal:0.82540524
    ---------
    x Normal:0.49563178
    y Normal:0.22927073
    z Normal:0.8377256
    ---------
    x Normal:0.66004086
    y Normal:0.44558245
    z Normal:0.60481596
    ---------
    x Normal:0.4228353
    y Normal:0.6056943
    z Normal:0.674051
    ---------
    x Normal:0.3127996
    y Normal:0.40948018
    z Normal:0.8570194
    ---------
    x Normal:0.4522171
    y Normal:0.33794355
    z Normal:0.82540524
    ---------
    x Normal:0.4228353
    y Normal:0.6056943
    z Normal:0.674051
    ---------
    x Normal:0.0652547
    y Normal:0.6629226
    z Normal:0.74583876
    ---------
    x Normal:0.11311255
    y Normal:0.3696725
    z Normal:0.92225146
    ---------
    x Normal:0.3127996
    y Normal:0.40948018
    z Normal:0.8570194
    ---------
    x Normal:0.0652547
    y Normal:0.6629226
    z Normal:0.74583876
    ---------
    x Normal:-0.36956686
    y Normal:0.51802975
    z Normal:0.77140486
    ---------
    x Normal:-0.14152305
    y Normal:0.24042831
    z Normal:0.9602944
    ---------
    x Normal:0.11311255
    y Normal:0.3696725
    z Normal:0.92225146
    ---------
    x Normal:-0.36956686
    y Normal:0.51802975
    z Normal:0.77140486
    ---------
    x Normal:-0.6336471
    y Normal:0.27636924
    z Normal:0.7225728
    ---------
    x Normal:-0.34416345
    y Normal:0.12383199
    z Normal:0.9307079
    ---------
    x Normal:-0.14152305
    y Normal:0.24042831
    z Normal:0.9602944
    ---------
    x Normal:-0.6336471
    y Normal:0.27636924
    z Normal:0.7225728
    ---------
    x Normal:-0.6913337
    y Normal:0.18393901
    z Normal:0.6987304
    ---------
    x Normal:-0.42294383
    y Normal:0.13286038
    z Normal:0.89636296
    ---------
    x Normal:-0.34416345
    y Normal:0.12383199
    z Normal:0.9307079
    ---------
    x Normal:-0.6913337
    y Normal:0.18393901
    z Normal:0.6987304
    ---------
    x Normal:-0.66959554
    y Normal:0.2797173
    z Normal:0.68804073
    ---------
    x Normal:-0.4009233
    y Normal:0.24534404
    z Normal:0.88264763
    ---------
    x Normal:-0.42294383
    y Normal:0.13286038
    z Normal:0.89636296
    ---------
    x Normal:0.41371974
    y Normal:-0.020337181
    z Normal:0.9101771
    ---------
    x Normal:0.41655508
    y Normal:-0.014255802
    z Normal:0.9089987
    ---------
    x Normal:0.09368722
    y Normal:0.053059284
    z Normal:0.9941868
    ---------
    x Normal:0.06595066
    y Normal:0.08613506
    z Normal:0.9940982
    ---------
    x Normal:0.41655508
    y Normal:-0.014255802
    z Normal:0.9089987
    ---------
    x Normal:0.4599735
    y Normal:0.10497045
    z Normal:0.8817061
    ---------
    x Normal:0.18968892
    y Normal:0.12181822
    z Normal:0.9742579
    ---------
    x Normal:0.09368722
    y Normal:0.053059284
    z Normal:0.9941868
    ---------
    x Normal:0.4599735
    y Normal:0.10497045
    z Normal:0.8817061
    ---------
    x Normal:0.49563178
    y Normal:0.22927073
    z Normal:0.8377256
    ---------
    x Normal:0.29667988
    y Normal:0.21751207
    z Normal:0.9298761
    ---------
    x Normal:0.18968892
    y Normal:0.12181822
    z Normal:0.9742579
    ---------
    x Normal:0.49563178
    y Normal:0.22927073
    z Normal:0.8377256
    ---------
    x Normal:0.4522171
    y Normal:0.33794355
    z Normal:0.82540524
    ---------
    x Normal:0.35260683
    y Normal:0.29905915
    z Normal:0.8866973
    ---------
    x Normal:0.29667988
    y Normal:0.21751207
    z Normal:0.9298761
    ---------
    x Normal:0.4522171
    y Normal:0.33794355
    z Normal:0.82540524
    ---------
    x Normal:0.3127996
    y Normal:0.40948018
    z Normal:0.8570194
    ---------
    x Normal:0.27517816
    y Normal:0.3385862
    z Normal:0.8997979
    ---------
    x Normal:0.35260683
    y Normal:0.29905915
    z Normal:0.8866973
    ---------
    x Normal:0.3127996
    y Normal:0.40948018
    z Normal:0.8570194
    ---------
    x Normal:0.11311255
    y Normal:0.3696725
    z Normal:0.92225146
    ---------
    x Normal:0.15692547
    y Normal:0.26293245
    z Normal:0.9519669
    ---------
    x Normal:0.27517816
    y Normal:0.3385862
    z Normal:0.8997979
    ---------
    x Normal:0.11311255
    y Normal:0.3696725
    z Normal:0.92225146
    ---------
    x Normal:-0.14152305
    y Normal:0.24042831
    z Normal:0.9602944
    ---------
    x Normal:-0.003721362
    y Normal:0.15562807
    z Normal:0.98780876
    ---------
    x Normal:0.15692547
    y Normal:0.26293245
    z Normal:0.9519669
    ---------
    x Normal:-0.14152305
    y Normal:0.24042831
    z Normal:0.9602944
    ---------
    x Normal:-0.34416345
    y Normal:0.12383199
    z Normal:0.9307079
    ---------
    x Normal:-0.12946573
    y Normal:0.084074035
    z Normal:0.98801327
    ---------
    x Normal:-0.003721362
    y Normal:0.15562807
    z Normal:0.98780876
    ---------
    x Normal:-0.34416345
    y Normal:0.12383199
    z Normal:0.9307079
    ---------
    x Normal:-0.42294383
    y Normal:0.13286038
    z Normal:0.89636296
    ---------
    x Normal:-0.16307753
    y Normal:0.115943775
    z Normal:0.9797769
    ---------
    x Normal:-0.12946573
    y Normal:0.084074035
    z Normal:0.98801327
    ---------
    x Normal:-0.42294383
    y Normal:0.13286038
    z Normal:0.89636296
    ---------
    x Normal:-0.4009233
    y Normal:0.24534404
    z Normal:0.88264763
    ---------
    x Normal:-0.14297333
    y Normal:0.19504027
    z Normal:0.97031844
    ---------
    x Normal:-0.16307753
    y Normal:0.115943775
    z Normal:0.9797769
    ---------
    x Normal:0.27517816
    y Normal:0.3385862
    z Normal:0.8997979
    ---------
    x Normal:0.15692547
    y Normal:0.26293245
    z Normal:0.9519669

  4. #4
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Okay, those do seem to be normalised.

    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.

  5. #5
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    5
    ah! I didn't even think to change my lighting settings!

    I played around with it and now the specular on the material has been removed and the shininess has been changed to 2f. I've added the resulting models to the imgur album.

    I think link is broken because of a problem with the way I load it in, but if you see any issue, I'd love the help.

    and Thank you very much




    Edit: It looks like the high amounts of light only makes the problem more visible. I think there's still something wrong with my code to calculate vertex normals. Any help would be very appreciated.
    Last edited by Aroymart; 07-24-2013 at 09:42 AM. Reason: More info

  6. #6
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Aroymart View Post
    I've added the resulting models to the imgur album.
    Those all look reasonable.

    Quote Originally Posted by Aroymart View Post
    I think there's still something wrong with my code to calculate vertex normals.
    I can't figure out why you have 4 levels of loops rather than just 2. A typical algorithm looks something like:
    Code :
    //types
    struct Vertex {
        Point3 position;
        Point3 normal;
    };
    struct Face {
        vector<int> vertices;
        Point3 normal;
    };
    // global variables
    vector<Vertex> vertices;
    vector<Face> faces;
     
    // function
    void calculate_vertex_normals()
    {
        for (int v = 0; v < vertices.size(); v++)
            vertices[v].normal = Point3(0, 0, 0);
     
        for (int f = 0; f < faces.size(); f++)
            for (int i = 0; i < faces[f].vertices.size(); i++)
                vertices[faces[f].vertices[i]].normal += faces[f].normal;
     
        for (int v = 0; v < vertices.size(); v++)
            vertices[v].normal /= vertices[v].normal.magnitude();
    }

  7. #7
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    5
    Oh, I thought the shadows looked slightly triangle-y

    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.

  8. #8
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Quote Originally Posted by Aroymart View Post
    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.

  9. #9
    Junior Member Newbie
    Join Date
    Jul 2013
    Posts
    5
    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.

    Quote Originally Posted by GClements View Post
    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

    Click image for larger version. 

Name:	Yoshi best.jpg 
Views:	55 
Size:	6.4 KB 
ID:	1086
    Last edited by Aroymart; 07-25-2013 at 12:17 PM. Reason: Fixed issue with lighting

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •