What is wrong with my normals?

I am trying to build a cube as a composition of many quads, with each quad being composed of two triangles. All the triangles have the same size. I am dong this (instead of drawing a single cube with just six faces) in order to have better lighting effects.

The final cube itself looks perfect however when I calculate the normals the final result looks weird. Really weird as you can see in the picture.

That's how I am calculating the normals:

For every triangle:

• calculate the normal by doing the cross product. The result is then normalized.

For each vertex of this triangle:

• Assign the same normal to all the three vertices

• if a normal was previously assigned to the same vertex, sum it with the newly calculated value. Keep track on how many times that vertex is "shared"

• Once the loop over the vertex is finished, divide each component of the normal vector with the number of times the vertex was shared.

In this picture the front face of the cube:

Also, I am adding some code:

//in vertices(which is an ArrayList<Float[]>) I have all my vertices.

public ArrayList<Float[]> getNormals()
{

normals = new ArrayList<Float[]>();

LinkedHashMap<String, ArrayList<Float[]>> map = new LinkedHashMap<String, ArrayList<Float[]>>();

for(int i=0; i<(vertices.size()-2); i=i+3)
{
float x1 = vertices.get(i)[0];   float y1 = vertices.get(i)[1];   float z1 = vertices.get(i)[2];
float x2 = vertices.get(i+1)[0]; float y2 = vertices.get(i+1)[1]; float z2 = vertices.get(i+1)[2];
float x3 = vertices.get(i+2)[0]; float y3 = vertices.get(i+2)[1]; float z3 = vertices.get(i+2)[2];

float[] U;
float[] V;

U = new float[]{x1-x2, y1-y2, z1-z2};
V = new float[]{x1-x3, y1-y3, z1-z3};

Float[] normal = new Float[]
{
(U[1] * V[2]) - (U[2]-V[1]),
(U[2] * V[0]) - (U[0]-V[2]),
(U[0] * V[1]) - (U[1]-V[0])
};

normal = normalize(normal);

ArrayList<Float[]> newList = new ArrayList<Float[]>();

ArrayList<Float[]> list = map.get(x1+" "+y1+" "+z1);
if(list==null) map.put(x1+" "+y1+" "+z1, newList);
else{
map.put(x1+" "+y1+" "+z1, list);
}

list = map.get(x2+" "+y2+" "+z2);
if(list==null) map.put(x2+" "+y2+" "+z2, newList);
else{
map.put(x2+" "+y2+" "+z2, list);
}

list = map.get(x3+" "+y3+" "+z3);
if(list==null) map.put(x3+" "+y3+" "+z3, newList);
else{
map.put(x3+" "+y3+" "+z3, list);
}

}

//averaging normals

for(int i=0; i<vertices.size(); i++)
{

String key = vertices.get(i)[0]+" "+vertices.get(i)[1]+" "+vertices.get(i)[2];

Float[] newNormal = new Float[]{0f,0f,0f};

ArrayList<Float[]> lists = map.get(key);

for(int j=0; j<lists.size(); j++)
{
newNormal[0] += lists.get(j)[0];
newNormal[1] += lists.get(j)[1];
newNormal[2] += lists.get(j)[2];
}

newNormal[0] /= ((float)lists.size());
newNormal[1] /= ((float)lists.size());
newNormal[2] /= ((float)lists.size());

}

return normals;
}

• With no code posted this might be a bit hard.. Could you try enabling this calculations step by step to see what step starts causing the issue. Begin with setting a static normal values per vertex. Also at least a description of expected result may be very helpful. – Matic Oblak Oct 3 '14 at 12:06
• Question is edited. It has now code and a better explanation. – alefzero Oct 3 '14 at 12:46
• How many vertices are you using? Also, averaging the normals for the vertices at the corners causes the lighting to, well, no longer look like a cube. – XNargaHuntress Oct 3 '14 at 15:02
• Are you doing averaging so that the cube edges and corners appear rounded? Also, and average of two normalized vectors is no longer normalized (unless they were same). From picture, looks like there's some glitch where not all vertices are treated the same. – david van brink Oct 3 '14 at 17:48

if a normal was previously assigned to the same vertex, average it with the newly calculated value

Let's say you have normals n1, n2 and n3 that you want to add to a vertex. The vertex's normal shall be N;

Your method: apply n1: N = n1; apply n2: N = ( N + n2 ) / 2. So, N = ( n1 + n2 ) / 2. It's still fine until now. apply n3: N = ( N + n3 ) / 2. Let's do a little math: N = ( ( n1 + n2 ) / 2 + n3 ) / 2. That means N = n1 / 4 + n2 / 4 + n3 / 2 That is not the average normal. You should not be averaging N and n3. Instead, do it so when applying a triangle's normal to a vertex:

You need another integer value, initialized at 0: int number = 0; and when applying a triangle's normal n to a vertex:

if ( number == 0 )
N = n;
else
{
N = N + n;
number = number + 1
}


When you are finished do so: N = N / number; // first check that number is not 0 That way, the real average will be computed.

Hope it helps!

• Yes, you're right. And I did as you described in the first place. I just wrote the whole thing wrong. However, I added some code. Thanks – alefzero Oct 3 '14 at 12:47