Makie: Linking cameras in multiple 3d plots

For posterity, here is two functions linking all views in a figure ! Functions work either with Axis3 or with Lscene.

In axis3 there is no zoom, so azimuth and elevation of all axis in a figure are linked with this function

function link_cameras_axis3(f; step=0.01)
    axes = f.content[findall(x -> typeof(x) == Axis3,f.content)]

    for i in 1:length(axes)
        on(axes[i].attributes.azimuth) do x
            for j in collect(1:length(axes))[1:end .!= i]
                if abs(x - axes[j].attributes.azimuth[])>step
                    axes[j].attributes.azimuth = x
                end
            end
        end
        on(axes[i].attributes.elevation) do x
            for j in collect(1:length(axes))[1:end .!= i]
                if abs(x - axes[j].attributes.elevation[])>step
                    axes[j].attributes.elevation = x
                end
            end
        end
    end
    return f
end

In Lscene there is a complete camera object, so when a eye position is changed, it will update all the parameters of the other LScenes of the figure with this function:

function link_cameras_lscene(f; step=0.01)
    scenes = f.content[findall(x -> typeof(x) == LScene,f.content)]
    cameras = [x.scene.camera_controls for x in scenes]

    for i in 1:length(cameras)
        on(cameras[i].eyeposition) do x
            for j in collect(1:length(cameras))[1:end .!= i]
                if sum(abs.(x - cameras[j].eyeposition[]))>step
                    cameras[j].lookat[]       = cameras[i].lookat[]
                    cameras[j].eyeposition[]  = cameras[i].eyeposition[]
                    cameras[j].upvector[]     = cameras[i].upvector[]
                    cameras[j].zoom_mult[]    = cameras[i].zoom_mult[]
        
                    update_cam!(scenes[j].scene, cameras[j])
                end
            end
        end
    end
    return f
end

Finally, here is a MWE:

using GLMakie
f = Figure()
ax1 = Axis3(f[1, 1],aspect=:data, viewmode=:fitzoom)
meshscatter!(ax1,rand(20,3))
ax2 = Axis3(f[1, 2],aspect=:data, viewmode=:fitzoom)
meshscatter!(ax2,rand(20,3))
ax3 = Axis3(f[2, 1],aspect=:data, viewmode=:fitzoom)
meshscatter!(ax3,rand(20,3))
ax4 = Axis3(f[2, 2],aspect=:data, viewmode=:fitzoom)
meshscatter!(ax4,rand(20,3))
f = link_cameras_axis3(f)


f = Figure()
ax1 = LScene(f[1, 1],aspect=:data)
meshscatter!(ax1,rand(20,3))
ax2 = LScene(f[1, 2],aspect=:data)
meshscatter!(ax2,rand(20,3))
ax3 = LScene(f[2, 1],aspect=:data)
meshscatter!(ax3,rand(20,3))
ax4 = LScene(f[2, 2],aspect=:data)
meshscatter!(ax4,rand(20,3))
f = link_cameras_lscene(f)
2 Likes