diff --git a/CHANGELOG.md b/CHANGELOG.md index a638fc7c38c..a94bd133672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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). diff --git a/GLMakie/src/drawing_primitives.jl b/GLMakie/src/drawing_primitives.jl index ca667c5ca97..0a9e94303e2 100644 --- a/GLMakie/src/drawing_primitives.jl +++ b/GLMakie/src/drawing_primitives.jl @@ -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 @@ -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 @@ -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) @@ -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) diff --git a/RPRMakie/src/scene.jl b/RPRMakie/src/scene.jl index 65ff446771e..84314e1d5df 100644 --- a/RPRMakie/src/scene.jl +++ b/RPRMakie/src/scene.jl @@ -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 diff --git a/ReferenceTests/src/tests/short_tests.jl b/ReferenceTests/src/tests/short_tests.jl index 6f408d355fc..1ff054325e9 100644 --- a/ReferenceTests/src/tests/short_tests.jl +++ b/ReferenceTests/src/tests/short_tests.jl @@ -300,4 +300,4 @@ end # f.scene.events.scroll[] = (0, -10) # # reference test the zoomed out plot # f -# end +# end \ No newline at end of file diff --git a/WGLMakie/src/serialization.jl b/WGLMakie/src/serialization.jl index 3769e3b1f53..05fea169520 100644 --- a/WGLMakie/src/serialization.jl +++ b/WGLMakie/src/serialization.jl @@ -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 @@ -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 diff --git a/src/basic_recipes/contours.jl b/src/basic_recipes/contours.jl index 39b2d6af132..3b0d940d56f 100644 --- a/src/basic_recipes/contours.jl +++ b/src/basic_recipes/contours.jl @@ -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)) diff --git a/src/camera/camera.jl b/src/camera/camera.jl index 3d70c677bd3..fa956e87a42 100644 --- a/src/camera/camera.jl +++ b/src/camera/camera.jl @@ -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, diff --git a/src/camera/camera2d.jl b/src/camera/camera2d.jl index b73b2a000ce..97a8fdc96a4 100644 --- a/src/camera/camera2d.jl +++ b/src/camera/camera2d.jl @@ -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 @@ -17,7 +17,7 @@ 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. @@ -25,8 +25,8 @@ selections. 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), @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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) @@ -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 diff --git a/src/camera/camera3d.jl b/src/camera/camera3d.jl index 3f8ebe68e31..25bd452cb33 100644 --- a/src/camera/camera3d.jl +++ b/src/camera/camera3d.jl @@ -12,15 +12,15 @@ struct Camera3D <: AbstractCamera3D selected::Observable{Bool} # view matrix - eyeposition::Observable{Vec3f} - lookat::Observable{Vec3f} - upvector::Observable{Vec3f} + eyeposition::Observable{Vec3d} + lookat::Observable{Vec3d} + upvector::Observable{Vec3d} # perspective projection matrix - fov::Observable{Float32} - near::Observable{Float32} - far::Observable{Float32} - bounding_sphere::Observable{Sphere{Float32}} + fov::Observable{Float64} + near::Observable{Float64} + far::Observable{Float64} + bounding_sphere::Observable{Sphere{Float64}} end """ @@ -47,13 +47,13 @@ Settings include anything that isn't a mouse or keyboard button. - `:bbox_relative` scales `near` and `far` to the scene bounding box as passed to the camera with `update_cam!(..., bbox)`. (More specifically `far = 1` is scaled to the furthest point of a bounding sphere and `near` is generally overwritten to be the closest point.) - `center = true`: Controls whether the camera placement gets reset when calling `center!(scene)`, which is called when a new plot is added. -- `keyboard_rotationspeed = 1f0` sets the speed of keyboard based rotations. -- `keyboard_translationspeed = 0.5f0` sets the speed of keyboard based translations. -- `keyboard_zoomspeed = 1f0` sets the speed of keyboard based zooms. +- `keyboard_rotationspeed = 1.0` sets the speed of keyboard based rotations. +- `keyboard_translationspeed = 0.5` sets the speed of keyboard based translations. +- `keyboard_zoomspeed = 1.0` sets the speed of keyboard based zooms. -- `mouse_rotationspeed = 1f0` sets the speed of mouse rotations. -- `mouse_translationspeed = 0.5f0` sets the speed of mouse translations. -- `mouse_zoomspeed = 1f0` sets the speed of mouse zooming (mousewheel). +- `mouse_rotationspeed = 1.0` sets the speed of mouse rotations. +- `mouse_translationspeed = 0.5` sets the speed of mouse translations. +- `mouse_zoomspeed = 1.0` sets the speed of mouse zooming (mousewheel). - `update_rate = 1/30` sets the rate at which keyboard based camera updates are evaluated. - `circular_rotation = (true, true, true)` 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.) @@ -95,9 +95,9 @@ Controls include any kind of hotkey setting. Some keyword arguments are used to initialize fields. These include -- `eyeposition = Vec3f(3)`: The position of the camera. -- `lookat = Vec3f(0)`: The point the camera is focused on. -- `upvector = Vec3f(0, 0, 1)`: The world direction corresponding to the up direction of the screen. +- `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.0` is the field of view. This is irrelevant if the camera uses an orthographic projection. - `near = automatic` sets the position of the near clip plane. Anything between the camera and the near clip plane is hidden. Must be greater 0. Usage depends on `clipping_mode`. @@ -105,12 +105,12 @@ Some keyword arguments are used to initialize fields. These include 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 = Vec3f(0,0,1))` is preferred. +`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 world/plot space vector `v`. -- `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 or `Vec3f(0, 0, +-1)` if `fixed_axis = true`, and the third will rotate around the view direction i.e. the axis out of the screen. The rotation respects the current `rotation_center` of the camera. +- `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 or `Vec3d(0, 0, +-1)` if `fixed_axis = true`, and the third will rotate around the view direction i.e. the axis out of the screen. The rotation respects the current `rotation_center` of the camera. - `zoom!(scene, zoom_step)` will change the zoom level of the scene without translating or rotating the scene. `zoom_step` applies multiplicatively to `cam.zoom_mult` which is used as a multiplier to the fov (perspective projection) or width and height (orthographic projection). """ function Camera3D(scene::Scene; kwargs...) @@ -152,13 +152,13 @@ function Camera3D(scene::Scene; kwargs...) replace!(controls, :Camera3D, scene, overwrites) settings = Attributes( - keyboard_rotationspeed = 1f0, - keyboard_translationspeed = 0.5f0, - keyboard_zoomspeed = 1f0, + keyboard_rotationspeed = 1.0, + keyboard_translationspeed = 0.5, + keyboard_zoomspeed = 1.0, - mouse_rotationspeed = 1f0, - mouse_translationspeed = 1f0, - mouse_zoomspeed = 1f0, + mouse_rotationspeed = 1.0, + mouse_translationspeed = 1.0, + mouse_zoomspeed = 1.0, projectiontype = Makie.Perspective, circular_rotation = (true, true, true), @@ -174,11 +174,11 @@ function Camera3D(scene::Scene; kwargs...) replace!(settings, :Camera3D, scene, overwrites) if settings.clipping_mode[] === :view_relative - far_default = 2f0 + far_default = 2.0 elseif settings.clipping_mode[] === :bbox_relative - far_default = 1f0 + far_default = 1.0 else - far_default = 100f0 # will be set when inserting a plot + far_default = 100.0 # will be set when inserting a plot end cam = Camera3D( @@ -189,15 +189,15 @@ function Camera3D(scene::Scene; kwargs...) Observable(true), # Semi-Internal - view matrix - get(overwrites, :eyeposition, Observable(Vec3f(3, 3, 3))), - get(overwrites, :lookat, Observable(Vec3f(0, 0, 0))), - get(overwrites, :upvector, Observable(Vec3f(0, 0, 1))), + get(overwrites, :eyeposition, Observable(Vec3d(3, 3, 3))), + get(overwrites, :lookat, Observable(Vec3d(0, 0, 0))), + get(overwrites, :upvector, Observable(Vec3d(0, 0, 1))), # Semi-Internal - projection matrix get(overwrites, :fov, Observable(45.0)), get(overwrites, :near, Observable(0.1)), get(overwrites, :far, Observable(far_default)), - Sphere(Point3f(0), 1f0) + Sphere(Point3d(0), 1.0) ) disconnect!(camera(scene)) @@ -338,7 +338,7 @@ function on_pulse(scene, cam::Camera3D, timestep) if projectiontype == Perspective viewnorm = norm(cam.lookat[] - cam.eyeposition[]) xynorm = 2 * viewnorm * tand(0.5 * cam.fov[]) - translation = keyboard_translationspeed * timestep * Vec3f( + translation = keyboard_translationspeed * timestep * Vec3d( xynorm * (right - left), xynorm * (up - down), viewnorm * (backward - forward) @@ -346,7 +346,7 @@ function on_pulse(scene, cam::Camera3D, timestep) else # translation in camera space x/y/z direction viewnorm = norm(cam.eyeposition[] - cam.lookat[]) - translation = 2 * viewnorm * keyboard_translationspeed * timestep * Vec3f( + translation = 2 * viewnorm * keyboard_translationspeed * timestep * Vec3d( right - left, up - down, backward - forward ) end @@ -365,7 +365,7 @@ function on_pulse(scene, cam::Camera3D, timestep) if rotating # rotations around camera space x/y/z axes angles = keyboard_rotationspeed * timestep * - Vec3f(up - down, left - right, counterclockwise - clockwise) + Vec3d(up - down, left - right, counterclockwise - clockwise) _rotate_cam!(scene, cam, angles) end @@ -376,7 +376,7 @@ function on_pulse(scene, cam::Camera3D, timestep) zooming = zoom_out || zoom_in if zooming - zoom_step = (1f0 + keyboard_zoomspeed * timestep) ^ (zoom_out - zoom_in) + zoom_step = (1.0 + keyboard_zoomspeed * timestep) ^ (zoom_out - zoom_in) _zoom!(scene, cam, zoom_step, false, false) end @@ -387,7 +387,7 @@ function on_pulse(scene, cam::Camera3D, timestep) if fov_adjustment step = (1 + keyboard_zoomspeed * timestep) ^ (fov_inc - fov_dec) - cam.fov[] = clamp(cam.fov[] * step, 0.1, 179) + cam.fov[] = clamp(cam.fov[] * step, 0.1, 179.0) end # if any are active, update matrices, else stop clock @@ -407,7 +407,7 @@ function add_mouse_controls!(scene, cam::Camera3D) cad, projectiontype, zoom_shift_lookat ) - last_mousepos = RefValue(Vec2f(0, 0)) + last_mousepos = RefValue(Vec2d(0, 0)) dragging = RefValue((false, false)) # rotation, translation e = events(scene) @@ -446,22 +446,22 @@ function add_mouse_controls!(scene, cam::Camera3D) diff = compute_diff(last_mousepos[] .- mousepos) last_mousepos[] = mousepos dragging[] = (false, false) - translate_cam!(scene, cam, mouse_translationspeed[] .* Vec3f(diff[1], diff[2], 0f0)) + translate_cam!(scene, cam, mouse_translationspeed[] .* Vec3d(diff[1], diff[2], 0.0)) consume = true elseif dragging[][2] mousepos = mouseposition_px(scene) dragging[] = (false, false) rot_scaling = mouse_rotationspeed[] * (e.window_dpi[] * 0.005) - mp = (last_mousepos[] .- mousepos) .* 0.01f0 .* rot_scaling + mp = (last_mousepos[] .- mousepos) .* 0.01 .* rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(-mp[2], mp[1], 0f0), true) + rotate_cam!(scene, cam, Vec3d(-mp[2], mp[1], 0.0), true) consume = true end # reposition if ispressed(scene, reposition_button[], event.button) && is_mouseinside(scene) plt, _, p = ray_assisted_pick(scene) - p3d = to_ndim(Point3f, p, 0f0) + p3d = to_ndim(Point3d, p, 0.0) if !isnan(p3d) && to_value(get(plt, :space, :data)) == :data && parent_scene(plt) == scene # if translation/rotation happens with on-click reposition, # try uncommenting this @@ -484,14 +484,14 @@ function add_mouse_controls!(scene, cam::Camera3D) mousepos = screen_relative(scene, mp) diff = compute_diff(last_mousepos[] .- mousepos) last_mousepos[] = mousepos - translate_cam!(scene, cam, mouse_translationspeed[] * Vec3f(diff[1], diff[2], 0f0)) + translate_cam!(scene, cam, mouse_translationspeed[] * Vec3d(diff[1], diff[2], 0.0)) return Consume(true) elseif dragging[][1] && ispressed(scene, rotation_button[]) mousepos = screen_relative(scene, mp) rot_scaling = mouse_rotationspeed[] * (e.window_dpi[] * 0.005) - mp = (last_mousepos[] .- mousepos) * 0.01f0 * rot_scaling + mp = (last_mousepos[] .- mousepos) * 0.01 * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(-mp[2], mp[1], 0f0), true) + rotate_cam!(scene, cam, Vec3d(-mp[2], mp[1], 0.0), true) return Consume(true) end return Consume(false) @@ -500,7 +500,7 @@ function add_mouse_controls!(scene, cam::Camera3D) #zoom on(camera(scene), e.scroll) do scroll if is_mouseinside(scene) && ispressed(scene, scroll_mod[]) - zoom_step = (1f0 + 0.1f0 * mouse_zoomspeed[]) ^ -scroll[2] + zoom_step = (1.0 + 0.1 * mouse_zoomspeed[]) ^ -scroll[2] zoom!(scene, cam, zoom_step, cad[], zoom_shift_lookat[]) return Consume(true) end @@ -588,7 +588,7 @@ function _translate_cam!(scene, cam::Camera3D, t) fix_y = ispressed(scene, fix_y_key)::Bool fix_z = ispressed(scene, fix_z_key)::Bool if fix_x || fix_y || fix_z - trans = Vec3f(fix_x, fix_y, fix_z) .* trans + trans = Vec3d(fix_x, fix_y, fix_z) .* trans end cam.eyeposition[] = eyepos + trans @@ -610,7 +610,7 @@ function _rotate_cam!(scene, cam::Camera3D, angles::VecTypes, from_mouse=false) right = cross(viewdir, up) # +x x_axis = right - y_axis = fixed_axis ? Vec3f(0, 0, ifelse(up[3] < 0, -1, 1)) : up + y_axis = fixed_axis ? Vec3d(0, 0, ifelse(up[3] < 0, -1, 1)) : up z_axis = -viewdir fix_x = ispressed(scene, fix_x_key)::Bool @@ -632,14 +632,14 @@ function _rotate_cam!(scene, cam::Camera3D, angles::VecTypes, from_mouse=false) # recontextualize the (dy, dx, 0) from mouse rotations so that # drawing circles creates continuous rotations around the fixed axis mp = mouseposition_px(scene) - past_half = 0.5f0 .* size(scene) .> mp - flip = 2f0 * past_half .- 1f0 + past_half = 0.5 .* size(scene) .> mp + flip = 2.0 * past_half .- 1.0 angle = flip[1] * angles[1] + flip[2] * angles[2] - angles = Vec3f(-angle, -angle, angle) + angles = Vec3d(-angle, -angle, angle) # only one fix is true so this only rotates around one axis rotation *= qrotation( - Vec3f(fix_x, fix_y, fix_z) .* Vec3f(sign(right[1]), viewdir[2], sign(up[3])), - dot(Vec3f(fix_x, fix_y, fix_z), angles) + Vec3d(fix_x, fix_y, fix_z) .* Vec3d(sign(right[1]), viewdir[2], sign(up[3])), + dot(Vec3d(fix_x, fix_y, fix_z), angles) ) else # restrict total quaternion rotation to one axis @@ -678,7 +678,7 @@ function _zoom!(scene, cam::Camera3D, zoom_step, cad = false, zoom_shift_lookat u_x = normalize(cross(u_z, cam.upvector[])) u_y = normalize(cross(u_x, u_z)) - rel_pos = 2.0f0 * mouseposition_px(scene) ./ scene_width .- 1.0f0 + rel_pos = 2.0 * mouseposition_px(scene) ./ scene_width .- 1.0 shift = rel_pos[1] * u_x + rel_pos[2] * u_y shift *= 0.1 * sign(1 - zoom_step) * norm(viewdir) @@ -734,12 +734,13 @@ function update_cam!(scene::Scene, cam::Camera3D) far = far_dist * far elseif cam.settings.clipping_mode[] === :adaptive view_dist = norm(eyeposition - lookat) - near = view_dist * near; far = max(radius(bounding_sphere) / tand(0.5f0 * cam.fov[]), view_dist) * far + near = view_dist * near + far = max(radius(bounding_sphere) / tand(0.5 * cam.fov[]), view_dist) * far elseif cam.settings.clipping_mode[] !== :static @error "clipping_mode = $(cam.settings.clipping_mode[]) not recognized, using :static." end - aspect = Float32((/)(widths(scene)...)) + aspect = Float64((/)(widths(scene)...)) if cam.settings.projectiontype[] == Makie.Perspective proj = perspectiveprojection(fov, aspect, near, far) else @@ -749,8 +750,8 @@ function update_cam!(scene::Scene, cam::Camera3D) set_proj_view!(camera(scene), proj, view) - scene.camera.eyeposition[] = cam.eyeposition[] - scene.camera.view_direction[] = normalize(cam.lookat[] - cam.eyeposition[]) + scene.camera.eyeposition[] = Vec3f(cam.eyeposition[]) + scene.camera.view_direction[] = Vec3f(normalize(cam.lookat[] - cam.eyeposition[])) end @@ -758,14 +759,14 @@ end function update_cam!(scene::Scene, cam::Camera3D, area3d::Rect, recenter::Bool = cam.settings.center[]) bb = Rect3f(area3d) width = widths(bb) - center = maximum(bb) - 0.5f0 * width - radius = 0.5f0 * norm(width) + center = maximum(bb) - 0.5 * width + radius = 0.5 * norm(width) (isnan(radius) || (radius == 0)) && return - cam.bounding_sphere[] = Sphere(Point3f(center), radius) + cam.bounding_sphere[] = Sphere(Point3d(center), radius) old_dir = normalize(cam.eyeposition[] .- cam.lookat[]) if cam.settings.projectiontype[] == Makie.Perspective - dist = radius / tand(0.5f0 * cam.fov[]) + dist = radius / tand(0.5 * cam.fov[]) else dist = radius end @@ -777,11 +778,11 @@ function update_cam!(scene::Scene, cam::Camera3D, area3d::Rect, recenter::Bool = end if cam.settings.clipping_mode[] === :static - cam.near[] = 0.1f0 * dist - cam.far[] = 2f0 * dist + cam.near[] = 0.1 * dist + cam.far[] = 2.0 * dist elseif cam.settings.clipping_mode[] === :adaptive - cam.near[] = 0.1f0 - cam.far[] = 2f0 + cam.near[] = 0.1 + cam.far[] = 2.0 end update_cam!(scene, cam) @@ -791,9 +792,9 @@ end # Update camera position via camera Position & Orientation function update_cam!(scene::Scene, camera::Camera3D, eyeposition::VecTypes, lookat::VecTypes, up::VecTypes = camera.upvector[]) - camera.lookat[] = Vec3f(lookat) - camera.eyeposition[] = Vec3f(eyeposition) - camera.upvector[] = Vec3f(up) + camera.lookat[] = Vec3d(lookat) + camera.eyeposition[] = Vec3d(eyeposition) + camera.upvector[] = Vec3d(up) update_cam!(scene, camera) return end @@ -813,8 +814,8 @@ function update_cam!( ) st, ct = sincos(theta) sp, cp = sincos(phi) - v = Vec3f(ct * cp, ct * sp, st) - u = Vec3f(-st * cp, -st * sp, ct) + v = Vec3d(ct * cp, ct * sp, st) + u = Vec3d(-st * cp, -st * sp, ct) camera.lookat[] = center camera.eyeposition[] = center .+ radius * v camera.upvector[] = u diff --git a/src/camera/old_camera3d.jl b/src/camera/old_camera3d.jl index 4d1ace33bcf..1039f356491 100644 --- a/src/camera/old_camera3d.jl +++ b/src/camera/old_camera3d.jl @@ -2,14 +2,14 @@ @enum ProjectionEnum Perspective Orthographic struct OldCamera3D <: AbstractCamera - rotationspeed::Observable{Float32} - translationspeed::Observable{Float32} - eyeposition::Observable{Vec3f} - lookat::Observable{Vec3f} - upvector::Observable{Vec3f} - fov::Observable{Float32} - near::Observable{Float32} - far::Observable{Float32} + rotationspeed::Observable{Float64} + translationspeed::Observable{Float64} + eyeposition::Observable{Vec3d} + lookat::Observable{Vec3d} + upvector::Observable{Vec3d} + fov::Observable{Float64} + near::Observable{Float64} + far::Observable{Float64} projectiontype::Observable{ProjectionEnum} pan_button::Observable{ButtonTypes} rotate_button::Observable{ButtonTypes} @@ -28,12 +28,12 @@ function old_cam3d_cad!(scene::Scene; kw_args...) Attributes( rotationspeed = 0.01, translationspeed = 1.0, - eyeposition = Vec3f(3), - lookat = Vec3f(0), - upvector = Vec3f(0, 0, 1), - fov = 45f0, - near = 0.01f0, - far = 100f0, + eyeposition = Vec3d(3), + lookat = Vec3d(0), + upvector = Vec3d(0, 0, 1), + fov = 45.0, + near = 0.01, + far = 100.0, projectiontype = Perspective, pan_button = Mouse.right, rotate_button = Mouse.left, @@ -66,12 +66,12 @@ function old_cam3d_turntable!(scene::Scene; kw_args...) Attributes( rotationspeed = 0.01, translationspeed = 1.0, - eyeposition = Vec3f(3), - lookat = Vec3f(0), - upvector = Vec3f(0, 0, 1), - fov = 45f0, - near = 0.01f0, - far = 100f0, + eyeposition = Vec3d(3), + lookat = Vec3d(0), + upvector = Vec3d(0, 0, 1), + fov = 45.0, + near = 0.01, + far = 100.0, projectiontype = Perspective, pan_button = Mouse.right, rotate_button = Mouse.left, @@ -145,7 +145,7 @@ end # TODO switch button and key because this is the wrong order function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) - last_mousepos = RefValue(Vec2f(0, 0)) + last_mousepos = RefValue(Vec2d(0, 0)) dragging = RefValue(false) on(camera(scene), scene.events.mousebutton) do event if event.button == key[] && ispressed(scene, button[]) @@ -158,7 +158,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) dragging[] = false diff = (last_mousepos[] - mousepos) * cam.translationspeed[] last_mousepos[] = mousepos - translate_cam!(scene, cam, Vec3f(0f0, diff[1], diff[2])) + translate_cam!(scene, cam, Vec3d(0.0, diff[1], diff[2])) return Consume(true) end end @@ -170,7 +170,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) mousepos = screen_relative(scene, mp) diff = (last_mousepos[] .- mousepos) * cam.translationspeed[] last_mousepos[] = mousepos - translate_cam!(scene, cam, Vec3f(0f0, diff[1], diff[2])) + translate_cam!(scene, cam, Vec3d(0.0, diff[1], diff[2])) return Consume(true) end return Consume(false) @@ -178,9 +178,9 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) on(camera(scene), scene.events.scroll) do scroll if ispressed(scene, button[]) && is_mouseinside(scene) - cam_res = Vec2f(widths(scene)) + cam_res = Vec2d(widths(scene)) mouse_pos_normalized = mouseposition_px(scene) ./ cam_res - mouse_pos_normalized = 2*mouse_pos_normalized .- 1f0 + mouse_pos_normalized = 2*mouse_pos_normalized .- 1.0 zoom_step = scroll[2] zoom!(scene, mouse_pos_normalized, zoom_step, zoom_shift_lookat) return Consume(true) @@ -190,7 +190,7 @@ function add_translation!(scene, cam, key, button, zoom_shift_lookat::Bool) end function add_rotation!(scene, cam, button, key, fixed_axis::Bool) - last_mousepos = RefValue(Vec2f(0, 0)) + last_mousepos = RefValue(Vec2d(0, 0)) dragging = RefValue(false) e = events(scene) @@ -206,7 +206,7 @@ function add_rotation!(scene, cam, button, key, fixed_axis::Bool) rot_scaling = cam.rotationspeed[] * (e.window_dpi[] * 0.005) mp = (last_mousepos[] - mousepos) * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(mp[1], -mp[2], 0f0), fixed_axis) + rotate_cam!(scene, cam, Vec3d(mp[1], -mp[2], 0.0), fixed_axis) return Consume(true) end end @@ -219,7 +219,7 @@ function add_rotation!(scene, cam, button, key, fixed_axis::Bool) rot_scaling = cam.rotationspeed[] * (e.window_dpi[] * 0.005) mp = (last_mousepos[] .- mousepos) * rot_scaling last_mousepos[] = mousepos - rotate_cam!(scene, cam, Vec3f(mp[1], -mp[2], 0f0), fixed_axis) + rotate_cam!(scene, cam, Vec3d(mp[1], -mp[2], 0.0), fixed_axis) return Consume(true) end return Consume(false) @@ -233,17 +233,17 @@ Translate the camera by a translation vector given in camera space. """ translate_cam!(scene::Scene, translation::VecTypes) = translate_cam!(scene, cameracontrols(scene), translation) function translate_cam!(scene::Scene, cam::OldCamera3D, _translation::VecTypes) - translation = Vec3f(_translation) - translation == Vec3f(0) && return + translation = Vec3d(_translation) + translation == Vec3d(0) && return @extractvalue cam (projectiontype, lookat, eyeposition, upvector) dir = eyeposition - lookat dir_len = norm(dir) - cam_res = Vec2f(widths(scene)) + cam_res = Vec2d(widths(scene)) z, x, y = translation - z *= 0.1f0 * dir_len + z *= 0.1 * dir_len - x, y = (Vec2f(x, y) ./ cam_res) .* dir_len + x, y = (Vec2d(x, y) ./ cam_res) .* dir_len dir_norm = normalize(dir) right = normalize(cross(dir_norm, upvector)) @@ -270,9 +270,9 @@ function zoom!(scene, point::VecTypes, zoom_step, shift_lookat::Bool) # split zoom into two components: # the offset perpendicular to `eyeposition - lookat`, based on mouse offset ~ ray_dir # the offset parallel to `eyeposition - lookat` ~ dir - ray_eye = inv(scene.camera.projection[]) * Vec4f(point[1],point[2],0,0) - ray_eye = Vec4f(ray_eye[Vec(1, 2)]...,0,0) - ray_dir = Vec3f((inv(scene.camera.view[]) * ray_eye)) + ray_eye = inv(scene.camera.projection[]) * Vec4d(point[1],point[2],0,0) + ray_eye = Vec4d(ray_eye[Vec(1, 2)]...,0,0) + ray_dir = Vec3d((inv(scene.camera.view[]) * ray_eye)) dir = eyeposition - lookat @@ -281,13 +281,13 @@ function zoom!(scene, point::VecTypes, zoom_step, shift_lookat::Bool) if projectiontype == Perspective ray_dir *= norm(dir) end - cam.eyeposition[] = eyeposition + (ray_dir - dir) * (1f0 - 0.9f0 ^ zoom_step) - cam.lookat[] = lookat + (1f0 - 0.9f0 ^ zoom_step) * ray_dir + cam.eyeposition[] = eyeposition + (ray_dir - dir) * (1.0 - 0.9 ^ zoom_step) + cam.lookat[] = lookat + (1.0 - 0.9 ^ zoom_step) * ray_dir else # Rotations need more extreme eyeposition shifts step = zoom_step - while abs(step) > 0f0 - cam.eyeposition[] = cam.eyeposition[] + sign(zoom_step) * (ray_dir - dir * 0.1f0) + while abs(step) > 0.0 + cam.eyeposition[] = cam.eyeposition[] + sign(zoom_step) * (ray_dir - dir * 0.1) dir = cam.eyeposition[] - lookat step -= sign(step) end @@ -306,14 +306,14 @@ the camera according to the Euler angles (α, β, γ). rotate_cam!(scene::Scene, theta_v::Number...) = rotate_cam!(scene, cameracontrols(scene), theta_v) rotate_cam!(scene::Scene, theta_v::VecTypes) = rotate_cam!(scene, cameracontrols(scene), theta_v) function rotate_cam!(scene::Scene, cam::OldCamera3D, _theta_v::VecTypes, fixed_axis::Bool = true) - theta_v = Vec3f(_theta_v) - theta_v == Vec3f(0) && return #nothing to do! + theta_v = Vec3d(_theta_v) + theta_v == Vec3d(0) && return #nothing to do! @extractvalue cam (eyeposition, lookat, upvector) dir = normalize(eyeposition - lookat) right_v = normalize(cross(upvector, dir)) upvector = normalize(cross(dir, right_v)) - axis = fixed_axis ? Vec3f(0, 0, sign(upvector[3])) : upvector + axis = fixed_axis ? Vec3d(0, 0, sign(upvector[3])) : upvector rotation = rotate_cam(theta_v, right_v, axis, dir) r_eyepos = lookat + rotation * (eyeposition - lookat) r_up = normalize(rotation * upvector) @@ -329,44 +329,44 @@ function update_cam!(scene::Scene, cam::OldCamera3D) zoom = norm(lookat - eyeposition) # TODO this means you can't set FarClip... SAD! # TODO use boundingbox(scene) for optimal far/near - far = max(zoom * 5f0, 30f0) + far = max(zoom * 5.0, 30.0) proj = projection_switch(scene.viewport[], fov, near, far, projectiontype, zoom) view = Makie.lookat(eyeposition, lookat, upvector) set_proj_view!(camera(scene), proj, view) - scene.camera.eyeposition[] = cam.eyeposition[] - scene.camera.view_direction[] = normalize(cam.lookat[] - cam.eyeposition[]) + scene.camera.eyeposition[] = Vec3f(cam.eyeposition[]) + scene.camera.view_direction[] = Vec3f(normalize(cam.lookat[] - cam.eyeposition[])) end function update_cam!(scene::Scene, camera::OldCamera3D, area3d::Rect) @extractvalue camera (fov, near, lookat, eyeposition, upvector) bb = Rect3f(area3d) width = widths(bb) - half_width = width/2f0 + half_width = 0.5 * width middle = maximum(bb) - half_width old_dir = normalize(eyeposition .- lookat) camera.lookat[] = middle neweyepos = middle .+ (1.2*norm(width) .* old_dir) camera.eyeposition[] = neweyepos - camera.upvector[] = Vec3f(0,0,1) - camera.near[] = 0.1f0 * norm(widths(bb)) - camera.far[] = 3f0 * norm(widths(bb)) + camera.upvector[] = Vec3d(0,0,1) + camera.near[] = 0.1 * norm(widths(bb)) + camera.far[] = 3.0 * norm(widths(bb)) update_cam!(scene, camera) return end """ - update_cam!(scene::Scene, eyeposition, lookat, up = Vec3f(0, 0, 1)) + update_cam!(scene::Scene, eyeposition, lookat, up = Vec3d(0, 0, 1)) Updates the camera's controls to point to the specified location. """ -function update_cam!(scene::Scene, eyeposition::VecTypes{3}, lookat::VecTypes{3}, up::VecTypes{3} = Vec3f(0, 0, 1)) +function update_cam!(scene::Scene, eyeposition::VecTypes{3}, lookat::VecTypes{3}, up::VecTypes{3} = Vec3d(0, 0, 1)) return update_cam!(scene, cameracontrols(scene), eyeposition, lookat, up) end -function update_cam!(scene::Scene, camera::OldCamera3D, eyeposition, lookat, up = Vec3f(0, 0, 1)) - camera.lookat[] = Vec3f(lookat) - camera.eyeposition[] = Vec3f(eyeposition) - camera.upvector[] = Vec3f(up) +function update_cam!(scene::Scene, camera::OldCamera3D, eyeposition, lookat, up = Vec3d(0, 0, 1)) + camera.lookat[] = Vec3d(lookat) + camera.eyeposition[] = Vec3d(eyeposition) + camera.upvector[] = Vec3d(up) update_cam!(scene, camera) return end diff --git a/src/camera/projection_math.jl b/src/camera/projection_math.jl index 8f4fa2c7dc1..a9f99a676d4 100644 --- a/src/camera/projection_math.jl +++ b/src/camera/projection_math.jl @@ -216,9 +216,9 @@ function transformationmatrix(translation, scale) ) end -function transformationmatrix(translation, scale, rotation::Quaternion) +function transformationmatrix(translation, scale, rotation::Quaternion{T}) where T trans_scale = transformationmatrix(translation, scale) - rotation = Mat4f(rotation) + rotation = Mat4{T}(rotation) trans_scale*rotation end @@ -314,8 +314,8 @@ function project(proj_view::Mat4{T1}, resolution::Vec2, point::Point{N, T2}) whe clip = proj_view * p4d # at this point the visible range is strictly -1..1 so FLoat64 doesn't matter p = (clip ./ clip[4])[Vec(1, 2)] - p = Vec2f(p[1], p[2]) - return (((p .+ 1f0) ./ 2f0) .* (resolution .- 1f0)) .+ 1f0 + p = Vec2{T}(p[1], p[2]) + return (0.5 .* (p .+ 1) .* (resolution .- 1)) .+ 1 end # TODO: consider warning here to discourage risky functions @@ -341,9 +341,9 @@ function space_to_clip(cam::Camera, space::Symbol, projectionview::Bool=true) elseif is_pixel_space(space) return cam.pixel_space[] elseif is_relative_space(space) - return Mat4f(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, -1, -1, 0, 1) + return Mat4d(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, -1, -1, 0, 1) elseif is_clip_space(space) - return Mat4f(I) + return Mat4d(I) else error("Space $space not recognized. Must be one of $(spaces())") end @@ -354,11 +354,11 @@ function clip_to_space(cam::Camera, space::Symbol) return inv(cam.projectionview[]) elseif is_pixel_space(space) w, h = cam.resolution[] - return Mat4f(0.5w, 0, 0, 0, 0, 0.5h, 0, 0, 0, 0, -10_000, 0, 0.5w, 0.5h, 0, 1) # -10_000 + return Mat4d(0.5w, 0, 0, 0, 0, 0.5h, 0, 0, 0, 0, -10_000, 0, 0.5w, 0.5h, 0, 1) # -10_000 elseif is_relative_space(space) - return Mat4f(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0.5, 0.5, 0, 1) + return Mat4d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0.5, 0.5, 0, 1) elseif is_clip_space(space) - return Mat4f(I) + return Mat4d(I) else error("Space $space not recognized. Must be one of $(spaces())") end diff --git a/src/types.jl b/src/types.jl index a619d0510bb..e53696c0992 100644 --- a/src/types.jl +++ b/src/types.jl @@ -218,22 +218,22 @@ struct Camera """ projection used to convert pixel to device units """ - pixel_space::Observable{Mat4f} + pixel_space::Observable{Mat4d} """ View matrix is usually used to rotate, scale and translate the scene """ - view::Observable{Mat4f} + view::Observable{Mat4d} """ Projection matrix is used for any perspective transformation """ - projection::Observable{Mat4f} + projection::Observable{Mat4d} """ just projection * view """ - projectionview::Observable{Mat4f} + projectionview::Observable{Mat4d} """ resolution of the canvas this camera draws to diff --git a/test/issues.jl b/test/issues.jl new file mode 100644 index 00000000000..c1c817ecd12 --- /dev/null +++ b/test/issues.jl @@ -0,0 +1,23 @@ + +@testset "Issues" begin + @testset "#659 Volume errors if data is not a cube" begin + fig, ax, vplot = volume(1..8, 1..8, 1..10, rand(8, 8, 10)) + lims = Makie.data_limits(vplot) + lo, hi = extrema(lims) + @test all(lo .<= 1) + @test all(hi .>= (8,8,10)) + end + + @testset "#3979 lossy matrix multiplication" begin + ps = Point{3, Float64}[[436132.5523666298, 7.002123574681671e6, 505.0239189387989], [436132.5523666298, 7.002123574681671e6, 1279.2437345933633], [436132.5523666298, 7.002884453296079e6, 505.0239189387989], [436132.5523666298, 7.002884453296079e6, 1279.2437345933633], [437151.16775504407, 7.002123574681671e6, 505.0239189387989], [437151.16775504407, 7.002123574681671e6, 1279.2437345933633], [437151.16775504407, 7.002884453296079e6, 505.0239189387989], [437151.16775504407, 7.002884453296079e6, 1279.2437345933633]] + f, a, p = scatter(ps) + Makie.update_state_before_display!(f) + # sanity check: old behavior should fail + M = Makie.Mat4f(Makie.clip_to_space(a.scene.camera, :data)) * + Makie.Mat4f(Makie.space_to_clip(a.scene.camera, :data)) + @test !(M ≈ I) + # this should not + M = Makie.clip_to_space(a.scene.camera, :data) * Makie.space_to_clip(a.scene.camera, :data) + @test M ≈ I atol = 1e-4 + end +end \ No newline at end of file diff --git a/test/primitives.jl b/test/primitives.jl index 92fe8a054b3..7824b8d59ae 100644 --- a/test/primitives.jl +++ b/test/primitives.jl @@ -3,9 +3,9 @@ f, ax, pl = ablines(fill(0), fill(1)) reset_limits!(ax) points = pl.plots[1][1] - @test points[] == [Point2f(0), Point2f(10)] + @test Point2f.(points[]) == [Point2f(0), Point2f(10)] limits!(ax, 5, 15, 6, 17) - @test points[] == [Point2f(5), Point2f(15)] + @test Point2f.(points[]) == [Point2f(5), Point2f(15)] end @testset "arrows" begin diff --git a/test/runtests.jl b/test/runtests.jl index b73563e695f..1616c19fac3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,14 +12,6 @@ using Makie: volume # COV_EXCL_STOP @testset "Unit tests" begin - @testset "#659 Volume errors if data is not a cube" begin - fig, ax, vplot = volume(1..8, 1..8, 1..10, rand(8, 8, 10)) - lims = Makie.data_limits(vplot) - lo, hi = extrema(lims) - @test all(lo .<= 1) - @test all(hi .>= (8,8,10)) - end - include("deprecated.jl") include("specapi.jl") include("primitives.jl") @@ -40,6 +32,8 @@ using Makie: volume include("barplot.jl") include("bezier.jl") include("hist.jl") + # for short tests of resolved issues + include("issues.jl") # TODO: move some things in here include("convert_arguments.jl")