MakieOrg / Makie.jl

Interactive data visualizations and plotting in Julia
https://docs.makie.org/stable
MIT License
2.4k stars 310 forks source link

`mesh` fails on quadrilateral mesh #1677

Open BambOoxX opened 2 years ago

BambOoxX commented 2 years ago

It seems Makie assumes that a mesh should have triangular elements.

On the example below Makie (v0.5.1) works fine with triangular faces.

using GLMakie

u1 = LinRange(0, 2 * pi, 100) .* ones(100)'
v1 = LinRange(0, 2 * pi, 100)' .* ones(100)
u2 = cos.(u1) .* sin.(v1)

nl, nc = size(u1)

vertices = hcat(vec(u1), vec(v1), vec(u2))

v = collect(1:(nl-1))

faces = Matrix{Int64}(undef, (nl - 1) * (nc - 1), 3)
for c in 0:(nc-2)
    for (index, vval) in enumerate(v)
        faces[index+c*(nl-1), :] = [vval vval + 1 vval + nl + 1] .+ c * (nl)
    end
end

msh = mesh(vertices, faces, color = vec(u2), shading = false, axis = (type=Axis3,))
wireframe!(msh.axis, msh.plot[1][], color = :black)

image

If the triangular faces are replaced with quadrangular ones, Makie fails on a to_triangles. Is there a specific reason why ? Code with quadrangular faces

using GLMakie

u1 = LinRange(0, 2 * pi, 100) .* ones(100)'
v1 = LinRange(0, 2 * pi, 100)' .* ones(100)
u2 = cos.(u1) .* sin.(v1)

nl, nc = size(u1)

vertices = hcat(vec(u1), vec(v1), vec(u2))

v = collect(1:(nl-1))

faces = Matrix{Int64}(undef, (nl - 1) * (nc - 1), 4)
for c in 0:(nc-2)
    for (index, vval) in enumerate(v)
        faces[index+c*(nl-1), :] = [vval vval + 1 vval + nl + 1 vval + nl] .+ c * (nl)
    end
end

msh = mesh(vertices, faces, color = vec(u2), shading = false, axis = (type=Axis3,))
wireframe!(msh.axis, msh.plot[1][], color = :black)
SimonDanisch commented 2 years ago

This is definitely a case of "didn't get around to fully implement it"... Meanwhile, you can skip the Makie conversion pipeline and construct a GeometryBasics.Mesh directly:

using GLMakie, GeometryBasics
u1 = LinRange(0, 2 * pi, 100) .* ones(100)'
v1 = LinRange(0, 2 * pi, 100)' .* ones(100)
u2 = cos.(u1) .* sin.(v1)
nl, nc = size(u1)
vertices = Point3f.(vec(u1), vec(v1), vec(u2))
v = collect(1:(nl-1))
faces = Vector{QuadFace{GLIndex}}(undef, (nl - 1) * (nc - 1))
for c in 0:(nc-2)
    for (index, vval) in enumerate(v)
        faces[index+c*(nl-1)] = QuadFace{GLIndex}(vval, vval + 1, vval + nl + 1, vval + nl) .+ c * (nl)
    end
end

m = GeometryBasics.Mesh(vertices, faces)
f, ax, pl = mesh(m, color = vec(u2), shading = false, axis = (type=Axis3,))
wireframe!(ax, m, color = (:black,0.5), transparency=true)
f
BambOoxX commented 2 years ago

Thanks for the help, I'm very new to Makie and GeometryBasics. It works very well.

ffreyer commented 2 months ago

I think this should be relatively easy to add. This hits https://github.com/MakieOrg/Makie.jl/blob/2b5931ee92c00603a669d02b8103bff49315024b/src/conversions.jl#L606-L628 and then https://github.com/MakieOrg/Makie.jl/blob/2b5931ee92c00603a669d02b8103bff49315024b/src/conversions.jl#L784-L789 which would just need to create a QuadFace or two GLTriangleFaces instead. (I wouldn't bother generalizing this further. Quads are common, larger Polygons are not)