A sphere (root frame: center c, radius r) might be within the tolerance
(plus extra pixels) of the cursor on the screen (false only if it
surely isn't: to skip what it bounds).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(PickCamera), | intent(in) | :: | cam |
the camera and cursor of the pick |
||
| real(kind=wp), | intent(in) | :: | c(3) |
the sphere's center (root frame) and radius (scene units) |
||
| real(kind=wp), | intent(in) | :: | r |
the sphere's center (root frame) and radius (scene units) |
||
| real(kind=wp), | intent(in), | optional | :: | extra |
added to the tolerance (framebuffer pixels) |
logical function sphere_near(cam, c, r, extra) result(near) type(PickCamera), intent(in) :: cam !! the camera and cursor of the pick real(wp), intent(in) :: c(3), r !! the sphere's center (root frame) and radius (scene units) real(wp), intent(in), optional :: extra !! added to the tolerance (framebuffer pixels) real(wp) :: sx, sy, depth, scale, reach near = .true. if (dot_product(c - cam%eye, cam%forward) - r > cam%max_depth) then ! (all deeper than a hit already found) near = .false. return end if if (cam%perspective) then depth = dot_product(c - cam%eye, cam%forward) if (depth <= r + cam%near) then ! (the eye inside it, or close: can't tell) near = depth > -r return end if if (.not. project(cam, c, sx, sy, depth)) return scale = cam%half_h / (cam%tan_y * (depth - r)) ! pixels per scene unit at its nearest else if (.not. project(cam, c, sx, sy, depth)) return scale = 2.0_wp * cam%half_h / (cam%ortho(4) - cam%ortho(3)) end if reach = cam%tolerance if (present(extra)) reach = reach + extra near = hypot(sx, sy) <= r * scale + reach end function sphere_near