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.
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)
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.