How to achieve good looking surface net normals?

EDIT After Victor T.'s suggestion (ignore seams):

I'm using elastic surface nets to convert a 3D voxels into a nice smooth mesh. The mesh part, is great, however, I can't seem to find a decent looking method of getting proper vertex normals for each voxel. I've been reading a couple of forums, like this one from reddit and this one from Stack Overflow. Using the method described in the stack overflow one, I got normals that looked like this:

(Scaled Normals)

While this might seem okay, it doesn't work very well with flat surfaces, and if I try to add methods for dealing with flat surfaces, it messes everything else up. And yet it still doesn't look ideal.

Using cross products of the vertices to get the normal, I was only able to get a hard shaded mesh, that did look decent, however, it can't distinguish up and down, so it doesn't look right in overhangs. It also is hardshaded, and I want smooth shading.

Question : What are ways I can achieve a better looking normal? What techniques are common for this? Is there any way modified methods I can use that are better than the ones I am doing? I am okay if the best looking method is expensive.

I can post source code if needed.

Thanks

UPDATE

After Victor T.'s suggestion, I managed to get great looking surface normals! One problem, the corners don't look right, I was unable to find any correlation between why is the normals on the corners need to be flipped (0 - normal).

Here is a picture :

EDIT 2: Managed to particially solve the problem, however, when the vertice is on a 45 degree angle on all axises, it seems to mess up and needs to be flipped:

• It seems like you only generate axis aligned faces amd slopes in 45 degrees. In that case, the normals are completely fine, try making it gemerate smoother stuff (I think you can do that by using values between 0 and 1 in the grid instead of boolean values or only 0 and 1) May 8 '17 at 5:35

A common way of generating vertex normals for a mesh is to sum the normals of the faces that touch each vertex, then normalize those sums. You're part-way there with taking cross-products from the faces.

A reasonable procedure would be:

• set all vertex normals to (0,0,0)
• iterate over the faces
• calculate the face normal: (vertex1 - vertex0) x (vertex2 - vertex0)
• add the face normal into the normal for each vertex of the face
• normalize the vertex normals

Note: This assumes that you can tell which direction the face normals should point, and part of your question says that this may not be the case. Mesh generation algorithms (in general, not specifically for elastic surface nets) are usually designed keep the order (sometimes called "winding order") consistent. Please try the procedure I outlined, to see if things are OK without further modification. If the mesh doesn't have consistent winding, you can address that next.

• Thanks for the suggestion, the normals look great! But for some strange reason, the corners need to be flipped (0 - normal). Have a look at the picture I added, is there anything you can think as to why this is the case?
– J4S
May 11 '17 at 0:32
• The exact shape of the black areas makes it seem like there are still some faces that don't have the same winding order; this would cause some of the face normals to point inward, which would mess with the vertex normals. I think you might need to take a look at the mesh generation code to figure out if the faces have inconsistent vertex order. May 11 '17 at 14:00
• Hi, sorry for late reply, but I'm not to sure how to get a correct winding order. The approach I'm using right now is a sort of connect-the-dots to create a triangle method, so it doesn't keep the order. I could just brute force check and flip if necessary, but I'm sure there is a correct way to get winding order.
– J4S
May 13 '17 at 23:33
• From your comments, it sounds like those triangles on the corners are always wrong, and the others are always right. Can you change the vertex order that's used in the bit of code that generates the corner triangles? If not, can you detect a corner triangle as it is created and switch the vertex order then? May 14 '17 at 20:08
• Turns out the order was fine for everything, just had some old deprecated code for checking if a side needs to be inverted that wasn't commented out. I added to that code and now the normals are looking great!
– J4S
May 15 '17 at 0:28