Help me understand why generating normals creates visible lines on mesh

Godot Version

4.4.1-stable

Question

Trying to understand what is causing a line to appear on my mesh when I enable surface_tool.generate_normals()

I start with an ArrayMesh, like so:

	var mesh = ArrayMesh.new()
	mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, surface, [], {}, format)

For this mesh I populate ARRAY_VERTEX, ARRAY_TEX_UV, ARRAY_TEX_UV2 and CUSTOM0.

I then create a surface tool, and create_from using the mesh.
I use the surface tool to create normals for my mesh, and then commit back to the mesh.

	var surface_tool = SurfaceTool.new()
	surface_tool.create_from(mesh, 0)
	surface_tool.generate_normals()
	mesh = surface_tool.commit()

Here’s what that looks like:

I’m trying to figure out what causes the visible line you see in the bottom-right section of the screen.

Here’s what the mesh looks like with the line containing generate_normals() commented out:

Here’s some extra info:

  • The line appears along the original hexagon edges.
  • Triangulation starts with 6 triangles per hexagon. That line is along the outside edge of one of these triangles. These triangles are subdivided down the line.
  • My current line of thinking is that there are disparities in the vertex positions along that visible line, leading to a big difference in normal values? I tried looking at them with wireframe on, they seem sensible.

There’s a tear in the mesh where those lines appear.

You can’t see the tear since the difference is miniscule, and you can’t really debug it easily either.

Eventually I resorted to walking through the actual code that computed the normals in the engine, to realize that it groups same vertices together.

I replicated a bit of the same “grouping” logic and ran it over my mesh, eventually it produced:

These 2 vertices are different:
4 (36.45, -0.352685, 10.5) - 4 duplications
2 (36.45, -0.352685, 10.5) - 2 duplications
it should be a single group of 6 duplicates

Eventually a google search showed that godot’s print rounds the value, which finally led to:

4: 36.44999694824218800000, -0.35268497467041016000, 10.50000000000000000000
2: 36.45000076293945300000, -0.35268497467041016000, 10.50000000000000000000

I’m going to leave this topic up in the odd chance someone down the line has a similar visual effect and googles into this thread