Mirror makie elements

Hey folks, I’m using GLMakie to make some videos with contours, and it would be nice to be able to apply mirroring to a given axis (or two, in my case).

My data is all in one quadrant, and I could make an array four times as big and then copy into it, mirroring the data as needed, and then use contour!(bigarray). However, it seems like a waste since it will need to repeat all the work of identifying the iso-surface, which only takes up a small fraction of the array domain. Is there a way to reflect the contours themselves into the other quadrants? Paraview and Tecplot both have this feature and I use it all the time in visualization.

Would showing a video improve the interest a little?

1 Like

Hm, it is somewhat possible to copy an OpenGL object and render it a second time, and modify the uniforms to be flipped…
Sadly, I think the model matrix that does the flipping isn’t 100% implemented correctly for volume, so the flipping causes it to sample incorrectly from the volume:

using GLMakie

function rewrap(robj::GLMakie.RenderObject{Pre}) where {Pre}
    GLMakie.ShaderAbstractions.switch_context!(robj.context)
    GLMakie.RenderObject{Pre}(
        robj.context,
        copy(robj.uniforms),
        robj.observables,
        robj.vertexarray,
        robj.prerenderfunction,
        robj.postrenderfunction,
        Observable(robj.visible),
        false
    )
end

function copy_plot!(screen::GLMakie.Screen, plot)
    robj = screen.cache[objectid(plot)]
    cpy = rewrap(robj)
    screenid = screen.screen2scene[WeakRef(parent(plot))]
    screen.cache2plot[cpy.id] = plot
    push!(screen.renderlist, (0, screenid, cpy))
    return cpy
end

GLMakie.activate!(float=true)
begin 
    N = 50
    r = LinRange(-1, 1, N)
    r2 = LinRange(0, 1, N)
    cube = Float32[(x .^ 2 + y .^ 2 + z .^ 2) for x = r, y = r, z = r2]
    fig, ax, pl = volume(cube, algorithm=:iso);
    if isdefined(Main, :screen)
        # messing with the internal renderlist will not clean up correctly, so we need to cleanup manually
        screen.renderlist |> empty!
        screen.cache2plot |> empty!
    end
    GLMakie.closeall()
    screen = display(fig)
end

cpy = copy_plot!(scren, pl)
robj = scren.cache[objectid(pl)]
model = Makie.scalematrix(Vec3f(1, -1, -1)) * robj[:model][]
cpy.uniforms[:model] = model
cpy.uniforms[:modelinv] = inv(model)

image

But the correct flip (1, 1, -1) doesn’t work -.-

1 Like