Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change camera variables to Float64 #3984

Merged
merged 9 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [Unreleased]

- Changed camera variables to Float64 for increased accuracy [#3984](https://github.com/MakieOrg/Makie.jl/pull/3984)
- Allow CairoMakie to render `poly` overloads that internally don't use two child plots [#3986](https://github.com/MakieOrg/Makie.jl/pull/3986).
- Fixes for Menu and DataInspector [#3975](https://github.com/MakieOrg/Makie.jl/pull/3975).
- Add line-loop detection and rendering to GLMakie and WGLMakie [#3907](https://github.com/MakieOrg/Makie.jl/pull/3907).
Expand Down
18 changes: 9 additions & 9 deletions GLMakie/src/drawing_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ function to_glvisualize_key(k)
end

function connect_camera!(plot, gl_attributes, cam, space = gl_attributes[:space])
for key in (:pixel_space, :eyeposition)
# Overwrite these, user defined attributes shouldn't use those!
gl_attributes[key] = lift(identity, plot, getfield(cam, key))
end
# Overwrite these, user defined attributes shouldn't use those!
gl_attributes[:pixel_space] = lift(Mat4f, plot, cam.pixel_space)
gl_attributes[:eyeposition] = lift(identity, plot, cam.eyeposition)

get!(gl_attributes, :view) do
# get!(cam.calculated_values, Symbol("view_$(space[])")) do
return lift(plot, cam.view, space) do view, space
return is_data_space(space) ? view : Mat4f(I)
return is_data_space(space) ? Mat4f(view) : Mat4f(I)
end
# end
end
Expand All @@ -169,14 +169,14 @@ function connect_camera!(plot, gl_attributes, cam, space = gl_attributes[:space]
get!(gl_attributes, :projection) do
# return get!(cam.calculated_values, Symbol("projection_$(space[])")) do
return lift(plot, cam.projection, cam.pixel_space, space) do _, _, space
return Makie.space_to_clip(cam, space, false)
return Mat4f(Makie.space_to_clip(cam, space, false))
end
# end
end
get!(gl_attributes, :projectionview) do
# get!(cam.calculated_values, Symbol("projectionview_$(space[])")) do
return lift(plot, cam.projectionview, cam.pixel_space, space) do _, _, space
Makie.space_to_clip(cam, space, true)
return Mat4f(Makie.space_to_clip(cam, space, true))
end
# end
end
Expand Down Expand Up @@ -391,7 +391,7 @@ function draw_atomic(screen::Screen, scene::Scene, @nospecialize(plot::Union{Sca
cam = scene.camera
gl_attributes[:preprojection] = lift(plot, space, mspace, cam.projectionview,
cam.resolution) do space, mspace, _, _
return Makie.clip_to_space(cam, mspace) * Makie.space_to_clip(cam, space)
return Mat4f(Makie.clip_to_space(cam, mspace) * Makie.space_to_clip(cam, space))
end
# fast pixel does its own setup
if !(marker[] isa FastPixel)
Expand Down Expand Up @@ -574,7 +574,7 @@ function draw_atomic(screen::Screen, scene::Scene,
cam = scene.camera
# gl_attributes[:preprojection] = Observable(Mat4f(I))
gl_attributes[:preprojection] = lift(plot, space, markerspace, cam.projectionview, cam.resolution) do s, ms, pv, res
Makie.clip_to_space(cam, ms) * Makie.space_to_clip(cam, s)
Mat4f(Makie.clip_to_space(cam, ms) * Makie.space_to_clip(cam, s))
end

return draw_scatter(screen, (DISTANCEFIELD, positions), gl_attributes)
Expand Down
2 changes: 1 addition & 1 deletion RPRMakie/src/scene.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function to_rpr_light(context::RPR.Context, rpr_scene, light::Makie.DirectionalL
else
dir = normalize(dir)
end
quart = Makie.rotation_between(dir, Vec3f(0,0,-1))
quart = Makie.rotation_between(Vec3f(dir), Vec3f(0,0,-1))
transform!(directionallight, Makie.rotationmatrix4(quart))
end
map(light.color) do c
Expand Down
2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/short_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,4 @@ end
# f.scene.events.scroll[] = (0, -10)
# # reference test the zoomed out plot
# f
# end
# end
4 changes: 2 additions & 2 deletions WGLMakie/src/serialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ function serialize_scene(scene::Scene)

cam3d_state = if cam_controls isa Camera3D
fields = (:lookat, :upvector, :eyeposition, :fov, :near, :far)
dict = Dict((f => lift(serialize_three, scene, getfield(cam_controls, f)) for f in fields))
dict = Dict((f => lift(x -> serialize_three(Float32.(x)), scene, getfield(cam_controls, f)) for f in fields))
dict[:resolution] = lift(res -> Int32[res...], scene, scene.camera.resolution)
dict
else
Expand Down Expand Up @@ -377,6 +377,6 @@ function serialize_camera(scene::Scene)
# eyeposition updates with viewmatrix, since an eyepos change will trigger
# a view matrix change!
ep = cam.eyeposition[]
return [vec(collect(view)), vec(collect(proj)), Int32[res...], Float32[ep...]]
return [vec(collect(Mat4f(view))), vec(collect(Mat4f(proj))), Int32[res...], Float32[ep...]]
end
end
4 changes: 2 additions & 2 deletions src/basic_recipes/contours.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ with z-elevation for each level.
MakieCore.documented_attributes(Contour)...
end

angle(p1::Union{Vec2f,Point2f}, p2::Union{Vec2f,Point2f})::Float32 =
atan(p2[2] - p1[2], p2[1] - p1[1]) # result in [-π, π]
# result in [-π, π]
angle(p1::VecTypes{2}, p2::VecTypes{2}) = Float32(atan(p2[2] - p1[2], p2[1] - p1[1]))

function label_info(lev, vertices, col)
mid = ceil(Int, 0.5f0 * length(vertices))
Expand Down
12 changes: 6 additions & 6 deletions src/camera/camera.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ end

function Camera(viewport)
pixel_space = lift(viewport) do window_size
nearclip = -10_000f0
farclip = 10_000f0
w, h = Float32.(widths(window_size))
return orthographicprojection(0f0, w, 0f0, h, nearclip, farclip)
nearclip = -10_000.0
farclip = 10_000.0
w, h = Float64.(widths(window_size))
return orthographicprojection(0.0, w, 0.0, h, nearclip, farclip)
end
view = Observable(Mat4f(I))
proj = Observable(Mat4f(I))
view = Observable(Mat4d(I))
proj = Observable(Mat4d(I))
proj_view = map(*, proj, view)
return Camera(
pixel_space,
Expand Down
76 changes: 38 additions & 38 deletions src/camera/camera2d.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
struct Camera2D <: AbstractCamera
area::Observable{Rect2f}
zoomspeed::Observable{Float32}
area::Observable{Rect2d}
zoomspeed::Observable{Float64}
zoombutton::Observable{IsPressedInputType}
panbutton::Observable{IsPressedInputType}
padding::Observable{Float32}
padding::Observable{Float64}
last_area::Observable{Vec{2, Int}}
update_limits::Observable{Bool}
end
Expand All @@ -17,16 +17,16 @@ selections.

## Keyword Arguments

- `zoomspeed = 0.1f0` sets the zoom speed.
- `zoomspeed = 0.1` sets the zoom speed.
- `zoombutton = true` sets a button (combination) which needs to be pressed to enable zooming. By default no button needs to be pressed.
- `panbutton = Mouse.right` sets the button used to translate the camera. This must include a mouse button.
- `selectionbutton = (Keyboard.space, Mouse.left)` sets the button used for rectangle selection. This must include a mouse button.
"""
function cam2d!(scene::SceneLike; kw_args...)
cam_attributes = merged_get!(:cam2d, scene, Attributes(kw_args)) do
Attributes(
area = Observable(Rectf(0, 0, 1, 1)),
zoomspeed = 0.10f0,
area = Observable(Rectd(0, 0, 1, 1)),
zoomspeed = 0.1,
zoombutton = true,
panbutton = Mouse.right,
selectionbutton = (Keyboard.space, Mouse.left),
Expand Down Expand Up @@ -73,7 +73,7 @@ Useful when using the `Observable` pipeline.
update_cam!(scene::SceneLike) = update_cam!(scene, cameracontrols(scene), data_limits(scene))

function update_cam!(scene::Scene, cam::Camera2D, area3d::Rect)
area = Rect2f(area3d)
area = Rect2d(area3d)
area = positive_widths(area)
# ignore rects with width almost 0
any(x-> x ≈ 0.0, widths(area)) && return
Expand All @@ -89,18 +89,18 @@ function update_cam!(scene::Scene, cam::Camera2D, area3d::Rect)
# so we make the minimum 1.0, and grow in the other dimension
s = ratio ./ minimum(ratio)
newwh = s .* widths(area)
cam.area[] = Rectf(minimum(area), newwh)
cam.area[] = Rect2d(minimum(area), newwh)
end
update_cam!(scene, cam)
end

function update_cam!(scene::SceneLike, cam::Camera2D)
x, y = minimum(cam.area[])
w, h = widths(cam.area[]) ./ 2f0
x, y = Float64.(minimum(cam.area[]))
w, h = Float64.(0.5 .* widths(cam.area[]))
# These observables should be final, no one should do map(cam.projection),
# so we don't push! and just update the value in place
view = translationmatrix(Vec3f(-x - w, -y - h, 0))
projection = orthographicprojection(-w, w, -h, h, -10_000f0, 10_000f0)
view = translationmatrix(Vec3d(-x - w, -y - h, 0))
projection = orthographicprojection(-w, w, -h, h, -10_000.0, 10_000.0)
set_proj_view!(camera(scene), projection, view)
cam.last_area[] = Vec(size(scene))
return
Expand All @@ -112,7 +112,7 @@ function correct_ratio!(scene, cam)
change = neww .- cam.last_area[]
if !(change ≈ Vec(0.0, 0.0))
s = 1.0 .+ (change ./ cam.last_area[])
camrect = Rectf(minimum(cam.area[]), widths(cam.area[]) .* s)
camrect = Rect2d(minimum(cam.area[]), widths(cam.area[]) .* s)
cam.area[] = camrect
update_cam!(scene, cam)
end
Expand Down Expand Up @@ -142,7 +142,7 @@ function add_pan!(scene::SceneLike, cam::Camera2D)
startpos[] = mp
area = cam.area[]
diff = Vec(diff) .* wscale(viewport(scene)[], area)
cam.area[] = Rectf(minimum(area) .+ diff, widths(area))
cam.area[] = Rect2d(minimum(area) .+ diff, widths(area))
update_cam!(scene, cam)
active[] = false
return Consume(true)
Expand All @@ -160,7 +160,7 @@ function add_pan!(scene::SceneLike, cam::Camera2D)
startpos[] = pos
area = cam.area[]
diff = Vec(diff) .* wscale(viewport(scene)[], area)
cam.area[] = Rectf(minimum(area) .+ diff, widths(area))
cam.area[] = Rect2d(minimum(area) .+ diff, widths(area))
update_cam!(scene, cam)
return Consume(true)
end
Expand All @@ -172,17 +172,17 @@ function add_zoom!(scene::SceneLike, cam::Camera2D)
e = events(scene)
on(camera(scene), e.scroll) do x
@extractvalue cam (zoomspeed, zoombutton, area)
zoom = Float32(x[2])
zoom = Float64(x[2])
if zoom != 0 && ispressed(scene, zoombutton) && is_mouseinside(scene)
pa = viewport(scene)[]
z = (1f0 - zoomspeed)^zoom
mp = Vec2f(e.mouseposition[]) - minimum(pa)
z = (1.0 - zoomspeed)^zoom
mp = Vec2d(e.mouseposition[]) - minimum(pa)
mp = (mp .* wscale(pa, area)) + minimum(area)
p1, p2 = minimum(area), maximum(area)
p1, p2 = p1 - mp, p2 - mp # translate to mouse position
p1, p2 = z * p1, z * p2
p1, p2 = p1 + mp, p2 + mp
cam.area[] = Rectf(p1, p2 - p1)
cam.area[] = Rect2d(p1, p2 - p1)
update_cam!(scene, cam)
return Consume(true)
end
Expand All @@ -200,13 +200,13 @@ function absrect(rect)
xy = ntuple(Val(2)) do i
wh[i] < 0 ? xy[i] + wh[i] : xy[i]
end
return Rectf(Vec2f(xy), Vec2f(abs.(wh)))
return Rect2(Vec2(xy), Vec2(abs.(wh)))
end


function selection_rect!(scene, cam, key)
rect = RefValue(Rectf(NaN, NaN, NaN, NaN))
lw = 2f0
lw = 2.0
scene_unscaled = Scene(
scene, transformation = Transformation(),
cam = copy(camera(scene)), clear = false
Expand Down Expand Up @@ -274,14 +274,14 @@ function reset!(cam, boundingbox, preserveratio = true)
ratio = w2 ./ w1
w1 = if ratio[1] > ratio[2]
s = w2[1] ./ w2[2]
Vec2f(s * w1[2], w1[2])
Vec2(s * w1[2], w1[2])
else
s = w2[2] ./ w2[1]
Vec2f(w1[1], s * w1[1])
Vec2(w1[1], s * w1[1])
end
end
p = minimum(w1) .* 0.001 # 2mm padding
update_cam!(cam, Rectf(-p, -p, w1 .+ 2p))
update_cam!(cam, Rect(-p, -p, w1 .+ 2p))
return
end

Expand All @@ -290,7 +290,7 @@ function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec)
restrict_action = paused_action(1.0) do t
o = lerp(origin(area_ref[]), origin(cam[Area]), t)
wh = lerp(widths(area_ref[]), widths(cam[Area]), t)
update_cam!(cam, Rectf(o, wh))
update_cam!(cam, Rect2d(o, wh))
end
on(window, Mouse.Drag) do drag
if drag == Mouse.up && !isplaying(restrict_action)
Expand All @@ -302,13 +302,13 @@ function add_restriction!(cam, window, rarea::Rect2, minwidths::Vec)
maxi = maxi - newmax
newo = newo - maxi
newwh = newmax - newo
scale = 1f0
scale = 1.0
for (w1, w2) in zip(minwidths, newwh)
stmp = w1 > w2 ? w1 / w2 : 1f0
stmp = w1 > w2 ? w1 / w2 : 1.0
scale = max(scale, stmp)
end
newwh = newwh * scale
area_ref[] = Rectf(newo, newwh)
area_ref[] = Rect2d(newo, newwh)
if area_ref[] != cam[Area]
play!(restrict_action)
end
Expand All @@ -324,25 +324,25 @@ get_space(::PixelCamera) = :pixel

struct UpdatePixelCam
camera::Camera
near::Float32
far::Float32
near::Float64
far::Float64
end
get_space(::UpdatePixelCam) = :pixel

function (cam::UpdatePixelCam)(window_size)
w, h = Float32.(widths(window_size))
projection = orthographicprojection(0f0, w, 0f0, h, cam.near, cam.far)
set_proj_view!(cam.camera, projection, Mat4f(I))
w, h = Float64.(widths(window_size))
projection = orthographicprojection(0.0, w, 0.0, h, cam.near, cam.far)
set_proj_view!(cam.camera, projection, Mat4d(I))
end

"""
campixel!(scene; nearclip=-1000f0, farclip=1000f0)
campixel!(scene; nearclip=-1000.0, farclip=1000.0)

Creates a pixel camera for the given `scene`. This means that the positional
data of a plot will be interpreted in pixel units. This camera does not feature
controls.
"""
function campixel!(scene::Scene; nearclip=-10_000f0, farclip=10_000f0)
function campixel!(scene::Scene; nearclip=-10_000.0, farclip=10_000.0)
disconnect!(camera(scene))
camera(scene).view_direction[] = Vec3f(0, 0, -1)
update_once = Observable(false)
Expand All @@ -365,11 +365,11 @@ get_space(::RelativeCamera) = :relative
Creates a camera for the given `scene` which maps the scene area to a 0..1 by
0..1 range. This camera does not feature controls.
"""
function cam_relative!(scene::Scene; nearclip=-10_000f0, farclip=10_000f0)
function cam_relative!(scene::Scene; nearclip=-10_000.0, farclip=10_000.0)
disconnect!(camera(scene))
camera(scene).view_direction[] = Vec3f(0, 0, -1)
projection = orthographicprojection(0f0, 1f0, 0f0, 1f0, nearclip, farclip)
set_proj_view!(camera(scene), projection, Mat4f(I))
projection = orthographicprojection(0.0, 1.0, 0.0, 1.0, nearclip, farclip)
set_proj_view!(camera(scene), projection, Mat4d(I))
cam = RelativeCamera()
cameracontrols!(scene, cam)
cam
Expand Down
Loading
Loading