Exporting a surface

Hi, I could not find any resources online about exporting a surface as a mesh in Julia. To be more precise, suppose at the end of some computation I have a surface only known as the three matrices X,Y,Z.
I can visualize it in Makie using scene = surface(X,Y,Z) and save the plot as an image. However, I would like to obtain the actual mesh corresponding to the surface.
Initially, I thought that it would be contained somewhere in scene.plots[2]? But I cannot figure out where though.

In short, is there a way in Julia to create the mesh of a surface (or retrieve the one build by Makie) and save it via FileIO/MeshIO as (for instance) .obj?

Makie’s OpenGL backend uses an optimized shader, that doesn’t actually create a mesh, but renders the surface directly from the matrix.
I was lazy in WGLMakie and just create a mesh:
https://github.com/JuliaPlots/WGLMakie.jl/blob/master/src/imagelike.jl#L67
Without all the WGLMakie shenanigans, this comes out as:

px, py, pz = plot[1], plot[2], plot[3]
x, y, z = px[], py[], pz[] # get the values

positions = vec(map(CartesianIndices(z)) do i
    GeometryBasics.Point{3, Float32}(
        get_dim(x, i, 1, size(z)),
        get_dim(y, i, 2, size(z)),
        z[i]
    )
end)

faces = decompose(GLTriangleFace, Rect2D(0f0, 0f0, 1f0, 1f0), size(z))

normals = WGLMakie.surface_normals(x, y, z)

vertices = GeometryBasics.meta(positions; normals=normals)

mesh = GeometryBasics.Mesh(vertices, faces)
using FileIO, MeshIO

# and save it in your favorite format
FileIO.save("mesh.obj", mesh)
1 Like

Thanks for the complete answer :slight_smile:
Unfortunately, the last command does not work, I get the error

Error encountered while saving “mesh.obj”.
Fatal error:
ERROR: MethodError: no method matching save(::Stream{DataFormat{:OBJ},IOStream}, ::GeometryBasics.Mesh{3,Float32,GeometryBasics.Ngon{3,Float32,3,PointMeta{3,Float32,Point{3,Float32},(:normals,),Tuple{Vec{3,Float32}}}},FaceView{GeometryBasics.Ngon{3,Float32,3,PointMeta{3,Float32,Point{3,Float32},(:normals,),Tuple{Vec{3,Float32}}}}}})
Closest candidates are:
save(::Stream{DataFormat{:OFF},IOtype} where IOtype<:IO, ::AbstractArray{Element,1} where Element) at /Users/olivier/.julia/packages/MeshIO/zr3db/src/io/off.jl:5
save(::Stream{DataFormat{:PLY_BINARY},IOtype} where IOtype<:IO, ::AbstractArray{Element,1} where Element) at /Users/olivier/.julia/packages/MeshIO/zr3db/src/io/ply.jl:2
save(::Stream{DataFormat{:PLY_ASCII},IOtype} where IOtype<:IO, ::AbstractArray{Element,1} where Element) at /Users/olivier/.julia/packages/MeshIO/zr3db/src/io/ply.jl:29

I haven’t run the code, but my first guess is, that you need to update meshio

I ran ]up, re-executed the code but still no luck (btw I use Julia 1.4.1).
The code you provided work for .ply though :slight_smile: