Mesh plotting in GLMakie with GeometryBasics - are normals broken?

I am trying to produce plots using meshes of basic geometry, and the resulting images are poor. I realised that it is very hard to tell the shape of the cylinder, no matter how I place the lighting, and I think it is because the shading is going wrong, possibly because of incorrect normals.

Take this simple example:

using GeometryBasics
using GLMakie

cyl = Cylinder(Point3f(0, 0, 0), Point3f(0, 0, 0.5), 0.3f0)
mesh1 = triangle_mesh(cyl)
mesh2 = normal_mesh(cyl)

fig = Figure()
ls1 = LScene(fig[1, 1]; show_axis=false)
ls2 = LScene(fig[1, 2]; show_axis=false)
grey = RGBAf(0.5, 0.5, 0.5, 1.0)
mesh!(ls1, mesh1; color=grey, specular=0)
mesh!(ls2, mesh2; color=grey, specular=0)

The resulting meshes show no change in shading on the edge of the cylinder: you can hardly tell they are cylinders.

image

For comparison look at this cylinder from here

Does anyone have any idea what’s going wrong and where? Is it an issue with representing normals in GeometryBasics.Mesh? In conversion to an OpenGL mesh? I really would like to help fix this.

I’d guess that when normals are determined automatically, the edge vertices get normals that are a mixture of the wall and the cap normals, which doesn’t make sense for a cylinder. That’s why with interpolation the edge looks round. Maybe it’s better to duplicate the vertices at the edge, so that the caps and the wall are not actually connected, to avoid the interpolation.

That sounds great - do you know a good way to achieve that with the GeometryBasics api, or should I jury rig something.

I don’t know of a good way, maybe it’s easiest to write a custom function to create the mesh manually. A cylinder is at least simple enough to do so

You can copy the code from Makie.jl/src/basic_recipes/arrows.jl at master · MakieOrg/Makie.jl · GitHub with

quality = 16
cylinder = merge([
    _circle(Point3f(0,0,-1), 0.5f0, Vec3f(0,0,-1), quality),
    _mantle(Point3f(0,0,-1), Point3f(0), 0.5f0, 0.5f0, quality),
    _circle(Point3f(0,0,0), 0.5f0, Vec3f(0,0,1), quality)
])

Thank you for the help and pointers! I’ll give it a go.