Hello,
I adapted the following code to synchronize rotations, translations, and zoom between two 3D LScene volumeslices! at in the MNWE code below:
https://discourse.julialang.org/t/makie-linking-cameras-in-multiple-3d-plots/83309/7
I then added sliders and toggles and encountered an issue.
The original startup display:
After rotation:
After changing the displayed slices by moving a slider bar:
The issue: the 3D display on the right [or left] reverts to its original orientation after changing the displayed slices using the slider bar.
If I then click on one of the 3D displays it switches to the orientation of the other image.
Q: How can I prevent the reversion in orientation in the 3D displays when moving a slider bar?
The MNWE code:
# test_synchronize_LScene_3D.jl
using GLMakie
using Random
# Ref. https://discourse.julialang.org/t/makie-linking-cameras-in-multiple-3d-plots/83309/7
function link_cameras_lscene(f; step=.01)
scenes = filter(x -> x isa LScene, f.content)
cameras = map(x -> cameracontrols(x.scene), scenes)
n_cameras = length(cameras)
for i ∈ 1:n_cameras
on(cameras[i].eyeposition) do eye
for j ∈ 1:n_cameras
i == j && continue
if sum(abs, eye - cameras[j].eyeposition[]) > step
update_cam!(scenes[j].scene, cameras[i])
end
end
end
end
return f
end
function test_lscene()
f = Figure()
n_rows = 10
n_cols = 10
n_slcs = 10
axs_1 = LScene(
f[1, 1:2],
scenekw = (;
aspect = :data,
backgroundcolor = :white,
camera = cam3d!,
center = true,
clear = true,
raw = false
)
)
x = LinRange(1, n_rows, n_rows)
y = LinRange(1, n_cols, n_cols)
z = LinRange(1, n_slcs, n_slcs)
alpha = 0.7
plt_1 = volumeslices!(
axs_1,
x, y, z,
randn(5 * n_rows, 5 * n_cols, 5 * n_slcs),
alpha = alpha,
bbox_visible = true,
colormap = :thermal,
lowclip = :transparent,
space = :data,
transparency = true
)
axs_2 = LScene(
f[1, 3:4],
scenekw = (;
aspect = :data,
backgroundcolor = :white,
camera = cam3d!,
center = true,
clear = true,
raw = false
)
)
plt_2 = volumeslices!(
axs_2,
x, y, z,
randn(5 * n_rows, 5 * n_cols, 5 * n_slcs),
alpha = alpha,
bbox_visible = true,
colormap = :viridis,
lowclip = :transparent,
space = :data,
transparency = true
)
# Sliders
dspl_sldr_grid = SliderGrid(
f[2, 2:3],
(label = "Sagittal - yz plane", range = 1:length(x)),
(label = "Coronal - xz plane", range = 1:length(y)),
(label = "Axial - xy plane", range = 1:length(z)),
)
dspl_sldr_layout = dspl_sldr_grid.layout
dspl_sldr_n_cols = ncols(dspl_sldr_layout)
# Connect sliders to `volumeslices`! update methods
dspl_sl_yz, dspl_sl_xz, dspl_sl_xy = dspl_sldr_grid.sliders
# Sagittal slider
on(dspl_sl_yz.value) do v;
plt_1[:update_yz][](v)
plt_2[:update_yz][](v)
end
# Coronal slider
on(dspl_sl_xz.value) do v;
plt_1[:update_xz][](v)
plt_2[:update_xz][](v)
end
# Axial slider
on(dspl_sl_xy.value) do v;
plt_1[:update_xy][](v)
plt_2[:update_xy][](v)
end
set_close_to!(dspl_sl_yz, .5length(x))
set_close_to!(dspl_sl_xz, .5length(y))
set_close_to!(dspl_sl_xy, .5length(z))
# Toggles
# Add toggles to show/hide heatmaps
hmap_1 = [plt_1[Symbol(:heatmap_, s)][] for s ∈ (:yz, :xz, :xy)]
toggles_dspl = [Toggle(dspl_sldr_layout[i, dspl_sldr_n_cols + 1], active = true) for i ∈ 1:length(hmap_1)]
map(zip(hmap_1, toggles_dspl)) do (h, t)
on(t.active) do active
h.visible = active
end
end
hmap_2 = [plt_2[Symbol(:heatmap_, s)][] for s ∈ (:yz, :xz, :xy)]
map(zip(hmap_2, toggles_dspl)) do (h, t)
on(t.active) do active
h.visible = active
end
end
resize_to_layout!(f)
link_cameras_lscene(f)
wait(display(f))
end
function main()
test_lscene()
end
begin
main()
end
GLMakie version: 0.13.11
Makie version: v0.24.11
Julia version: 1.12.6
Windows 11



