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
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