plot3djuliamakie.jl

Animated rotation of 3D plot in GLMakie


Using GLMakie, I want to incrementally rotate a 3D plot, saving an animation of the result.

Each frame should rotate the plot by a small angle (say, 1 degree). Over the course of the animation, the plot should rotate 360 degrees.

Here is a video example of what I mean (ish): https://imgur.com/a/ggTCVVm

Here's what I currently have:

using GLMakie

xs = -10:0.5:10
ys = -10:0.5:10
zs = [cos(x) * sin(y) for x in xs, y in ys]

# Explicitly create figure and axes - is this necessary?
fig = GLMakie.Figure()
ax = GLMakie.Axis3(fig[1, 1])
Makie.surface!(xs, ys, zs)
camera = Makie.cam3d!(fig.scene) # Ensure we have a 3D camera - is this necessary?

N_camera_steps = 100

GLMakie.record(
    fig,
    "test.mp4",
    [2π/N_camera_steps for _ = 1:N_camera_steps];
    framerate = 30,
) do angle 
    GLMakie.rotate_cam!(fig.scene, camera, (angle, 0, 0)) # Only rotate about one axis
end

However, this produces an .mp4 that shows a static plot only.

I might be misunderstanding how complex this is - I haven't really considered frames of reference, or whether I should be trying to rotate the camera or the plot.

How can I achieve my desired result in GLMakie?


Solution

  • After asking around on the GLMakie Slack, I came up with the following solution:

    using GLMakie
    
    xs = -10:0.5:10
    ys = -10:0.5:10
    zs = [cos(x) * sin(y) for x in xs, y in ys]
    
    fig = GLMakie.Figure()
    ax = GLMakie.Axis3(fig[1, 1])
    Makie.surface!(xs, ys, zs)
    
    start_angle = π / 4
    n_frames = 120
    ax.viewmode = :fit # Prevent axis from resizing during animation
    record(fig, "test.mp4", 1:n_frames) do frame
        ax.azimuth[] = start_angle + 2pi * frame / n_frames
    end
    

    I found that explicitly creating the axes and figure was necessary, as I couldn't figure out how to get the axis and figure object from the call to surface.

    The key thing was to modify the ax.aximuth variable.