Cameras
A Camera is simply a viewport through which the Scene is visualized. Makie offers 2D and 3D projections, and 2D plots can be projected in 3D!
To specify the camera you want to use for your Scene, you can set the camera attribute. Currently, we offer the following cameras/constructors
campixel! cam_relative! cam2d! Camera3D cam3d! cam3d_cad!
which will mutate the camera of the Scene into the specified type.
Pixel Camera
The pixel camera (campixel!) projects the scene in pixel space, i.e. each integer step in the displayed data will correspond to one pixel. There are no controls for this camera. The clipping limits are set to (-10_000, 10_000).
Relative Camera
The relative camera (cam_relative!) projects the scene into a 0..1 by 0..1 space. There are no controls for this camera. The clipping limits are set to (-10_000, 10_000).
2D Camera
The 2D camera (cam2d!) uses an orthographic projection with a fixed rotation and aspect ratio. You can set the following attributes via keyword arguments in cam2d! or by accessing the camera struct cam = cameracontrols(scene):
zoomspeed = 0.10f0sets the speed of mouse wheel zooms.zoombutton = nothingsets an additional key that needs to be pressed in order to zoom. Defaults to no key.panbutton = Mouse.rightsets the mouse button that needs to be pressed to translate the view.selectionbutton = (Keyboard.space, Mouse.left)sets a set of buttons that need to be pressed to perform rectangle zooms.
Note that this camera is not used by Axis. It is used, by default, for 2D LScenes and Scenes.
3D Camera
Makie.Camera3D Type
Camera3D(scene[; kwargs...])Sets up a 3D camera with mouse and keyboard controls.
The behavior of the camera can be adjusted via keyword arguments or the fields settings and controls.
Settings
Settings include anything that isn't a mouse or keyboard button.
projectiontype = Perspectivesets the type of the projection. Can beOrthographicorPerspective.rotation_center = :lookatsets the default center for camera rotations. Currently allows:lookator:eyeposition.fixed_axis = true: If true panning uses the (world/plot) z-axis instead of the camera up direction.zoom_shift_lookat = true: If true keeps the data under the cursor when zooming.cad = false: If true rotates the view aroundlookatwhen zooming off-center.clipping_mode = :adaptive: Controls hownearandfarget processed. Options::staticpassesnearandfaras is:adaptivescalesnearbynorm(eyeposition - lookat)and passesfaras is:view_relativescalesnearandfarbynorm(eyeposition - lookat):bbox_relativescalesnearandfarto the scene bounding box as passed to the camera withupdate_cam!(..., bbox). (More specificallyfar = 1is scaled to the furthest point of a bounding sphere andnearis generally overwritten to be the closest point.)
center = true: Controls whether the camera placement gets reset when callingcenter!(scene), which is called when a new plot is added.keyboard_rotationspeed = 1.0sets the speed of keyboard based rotations.keyboard_translationspeed = 0.5sets the speed of keyboard based translations.keyboard_zoomspeed = 1.0sets the speed of keyboard based zooms.mouse_rotationspeed = 1.0sets the speed of mouse rotations.mouse_translationspeed = 0.5sets the speed of mouse translations.mouse_zoomspeed = 1.0sets the speed of mouse zooming (mousewheel).circular_rotation = (false, false, false)enables circular rotations for (fixed x, fixed y, fixed z) rotation axis. (This means drawing a circle with your mouse around the center of the scene will result in a continuous rotation.)
Controls
Controls include any kind of hotkey setting.
up_key = Keyboard.rsets the key for translations towards the top of the screen.down_key = Keyboard.fsets the key for translations towards the bottom of the screen.left_key = Keyboard.asets the key for translations towards the left of the screen.right_key = Keyboard.dsets the key for translations towards the right of the screen.forward_key = Keyboard.wsets the key for translations into the screen.backward_key = Keyboard.ssets the key for translations out of the screen.zoom_in_key = Keyboard.usets the key for zooming into the scene (translate eyeposition towards lookat).zoom_out_key = Keyboard.osets the key for zooming out of the scene (translate eyeposition away from lookat).increase_fov_key = Keyboard.bsets the key for increasing the fov.decrease_fov_key = Keyboard.nsets the key for decreasing the fov.pan_left_key = Keyboard.jsets the key for rotations around the screens vertical axis.pan_right_key = Keyboard.lsets the key for rotations around the screens vertical axis.tilt_up_key = Keyboard.isets the key for rotations around the screens horizontal axis.tilt_down_key = Keyboard.ksets the key for rotations around the screens horizontal axis.roll_clockwise_key = Keyboard.esets the key for rotations of the screen.roll_counterclockwise_key = Keyboard.qsets the key for rotations of the screen.fix_x_key = Keyboard.xsets the key for fixing translations and rotations to the (world/plot) x-axis.fix_y_key = Keyboard.ysets the key for fixing translations and rotations to the (world/plot) y-axis.fix_z_key = Keyboard.zsets the key for fixing translations and rotations to the (world/plot) z-axis.reset = Keyboard.left_control & Mouse.leftsets the key for resetting the camera. This equivalent to callingcenter!(scene).reposition_button = Keyboard.left_alt & Mouse.leftsets the key for focusing the camera on a plot object.translation_button = Mouse.rightsets the mouse button for drag-translations. (up/down/left/right)scroll_mod = truesets an additional modifier button for scroll-based zoom. (true being neutral)rotation_button = Mouse.leftsets the mouse button for drag-rotations. (pan, tilt)
Other kwargs
Some keyword arguments are used to initialize fields. These include
eyeposition = Vec3d(3): The position of the camera.lookat = Vec3d(0): The point the camera is focused on.upvector = Vec3d(0, 0, 1): The world direction corresponding to the up direction of the screen.fov = 45.0is the field of view. This is irrelevant if the camera uses an orthographic projection.near = automaticsets the position of the near clip plane. Anything between the camera and the near clip plane is hidden. Must be greater 0. Usage depends onclipping_mode.far = automaticsets the position of the far clip plane. Anything further away than the far clip plane is hidden. Usage depends onclipping_mode. Defaults to1forclipping_mode = :bbox_relative,2for:view_relativeor a value derived from limits for:static.
Note that updating these observables in an active camera requires a call to update_cam(scene) for them to be applied. For updating eyeposition, lookat and/or upvector update_cam!(scene, eyeposition, lookat, upvector = Vec3d(0,0,1)) is preferred.
The camera position and orientation can also be adjusted via the functions
translate_cam!(scene, v)will translate the camera by the given vectorv.rotate_cam!(scene, angles)will rotate the camera around its axes with the corresponding angles. The first angle will rotate around the cameras "right" that is the screens horizontal axis, the second around the up vector/vertical axis orVec3d(0, 0, +-1)iffixed_axis = true, and the third will rotate around the view direction i.e. the axis out of the screen. The rotation respects the currentrotation_centerof the camera.zoom!(scene, zoom_step)will change the zoom level of the scene without translating or rotating the scene.zoom_stepapplies multiplicatively tocam.zoom_multwhich is used as a multiplier to the fov (perspective projection) or width and height (orthographic projection).
cam3d! and cam3d_cad! but create a Camera3D with some specific options.
Example - Visualizing the cameras view box
using GeometryBasics, LinearAlgebra
function frustum_snapshot(cam)
r = Rect3f(Point3f(-1, -1, -1), Vec3f(2, 2, 2))
rect_ps = coordinates(r) .|> Point3f
insert!(rect_ps, 13, Point3f(1, -1, 1)) # fix bad line
inv_pv = inv(cam.projectionview[])
return map(rect_ps) do p
p = inv_pv * to_ndim(Point4f, p, 1)
return p[Vec(1,2,3)] / p[4]
end
end
ex = Point3f(1,0,0)
ey = Point3f(0,1,0)
ez = Point3f(0,0,1)
fig = Figure()
scene = LScene(fig[1, 1])
cc = Makie.Camera3D(scene.scene, projectiontype = Makie.Perspective)
linesegments!(scene, Rect3f(Point3f(-1), Vec3f(2)), color = :black)
linesegments!(scene,
[-ex, ex, -ey, ey, -ez, ez],
color = [:red, :red, :green, :green, :blue, :blue]
)
center!(scene.scene)
cam = scene.scene.camera
eyeposition = cc.eyeposition
lookat = cc.lookat
frustum = map(pv -> frustum_snapshot(cam), cam.projectionview)
scene = LScene(fig[1, 2])
_cc = Makie.Camera3D(scene.scene, projectiontype = Makie.Orthographic)
lines!(scene, frustum, color = :blue, linestyle = :dot)
scatter!(scene, eyeposition, color = :black)
scatter!(scene, lookat, color = :black)
linesegments!(scene,
[-ex, ex, -ey, ey, -ez, ez],
color = [:red, :red, :green, :green, :blue, :blue]
)
linesegments!(scene, Rect3f(Point3f(-1), Vec3f(2)), color = :black)
figGeneral Remarks
To force a plot to be visualized in 3D, you can set the limits to have a nonzero (z)-axis interval, or ensure that a 3D camera type is used. For example, you could pass the keyword argument limits = Rect([0,0,0],[1,1,1]), or camera = cam3d!.
Often, when modifying the Scene, the camera can get "out of sync" with the Scene. To fix this, you can call the update_cam! function on the Scene.
Buttons passed to the 2D and 3D camera are forwarded to ispressed. As such you can pass false to disable an interaction, true to ignore a modifier, any button, collection of buttons or even logical expressions of buttons. See the events documentation for more details.