Precise control of navigation in 3D scene in Makie?

Hi,
I’m starting to visualize a collection of meshes in Makie, currently using the mouse to navigate the content. However, after a while the rotate, drag and zoom performed usually make me end up with parts of the content getting clipped (i assume there is a frustum defined somewhere) when I try to take a closer look.
I believe that what I would need is essentially better camera control, preferably by a combination of mous and keyboard eg right/left/forward/back/up/down (strafe?) to control both position and orientation. I guess someone has dome something simliar - or even cooler - already, but searching for something like it I failed find something.
When I did try the keyboard example from documentation I ran into events not liking being called with a ::Make.Scene
Currently I use GLMakie from the REPL for this, but I could see it moving to WGLMakie eventually.

I have some ancient code that added some keyboard controls, though not the ones you want. I also don’t know how well it works on other operating systems. Maybe it’s helpful anyway, so here’s a version that should work with the current version of Makie:

Code
using GLMakie, LinearAlgebra

function key_controls!(
        ax::LScene;
        tilt_up                 = Keyboard.w,
        tilt_down               = Keyboard.s,
        roll_clockwise          = Keyboard.e,
        roll_counterclockwise   = Keyboard.q,
        pan_left                = Keyboard.a,
        pan_right               = Keyboard.d,
        step_size::AbstractFloat = Float32(pi/180)
    )

    camera = ax.scene.camera_controls[]

    map(events(ax.scene).keyboardbutton) do event
        event.action == Keyboard.release && return false

        # Get camera information
        eyepos  = camera.eyeposition[]
        lookat  = camera.lookat[]
        up      = camera.upvector[]

        # camera coordinate system
        dir         = eyepos - lookat
        dir_norm    = normalize(dir)
        right       = normalize(cross(dir, up))

        # compute combined rotation
        rotation = Makie.Quaternion{Float32}(0, 0, 0, 1)
        for key in events(ax.scene).keyboardstate
            if key in (pan_left, pan_right)
                rotation *= qrotation(up, step_size * ((pan_left == key) - (pan_right == key)))
            end
            if key in (tilt_down, tilt_up)
                rotation *= qrotation(right, step_size * ((tilt_down == key) - (tilt_up == key)))
            end
            if key in (roll_clockwise, roll_counterclockwise)
                rotation *= qrotation(dir_norm, 
                    step_size * ((roll_clockwise == key) - (roll_counterclockwise == key))
                )
            end
        end

        # Set values, update camera
        camera.eyeposition[] = lookat + rotation * dir
        camera.upvector[] = normalize(rotation * up)
        update_cam!(ax.scene, camera)

        return false
    end
end

fig, ax, p = scatter(rand(Point3f0, 10))
controls = key_controls!(ax)
fig

I also started a pull request for a more controllable/adjustable camera:

2 Likes

Nice job, I did use the version in the PR with pretty good results. But now that it’s merged into 0.15.0, how do I continue to use it - the keyboard controls don’t seem to be active as default and mesh no longer takes a camera attribute?

It should be the default in an LScene. If not you can try calling Camera3D(lscene.scene) (or cam3d! or cam3d_cad!).

Tried the example at https://makie.juliaplots.org/stable/makielayout/lscene.html with GLMakie rather than WGLMakie, but no keyboard controls working in the Makie window (mouse works as before).
My env:
(annotell) pkg> st
Status ~/proj/julia/annotell/Project.toml
[cd3eb016] HTTP v0.9.12
[682c06a0] JSON v0.21.1
[ee78f7c6] Makie v0.15.0

(annotell) pkg>

Trying to call Camera3D(lscene.scene) fails:
julia> Camera3D(lscene.scene)

ERROR: MethodError: no method matching Camera3D(::Scene)

ping @ffreyer

I don’t know what’s wrong. 0.15 has Camera3D, with GLMakie you should be getting keyboard controls unless you explicitly use old_cam3d! etc…