cameras.cpp
| #include <planet/camera/orthogonal_birdseye.hpp>
#include <planet/camera/target3d.hpp>
#include <planet/log.hpp>
using namespace std::literals;
|
planet::camera::orthogonal_birdseye
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | void planet::camera::orthogonal_birdseye::tick_update() {
auto const scale_difference = target_scale - current_scale;
current_scale += scale_difference * 0.15f;
auto const rotation_difference = target_rotation - current_rotation;
current_rotation += rotation_difference * 0.1f;
auto const direction = target_looking_at - current_looking_at;
if (direction.mag2() <= 0.0001f) {
current_looking_at = target_looking_at;
} else {
auto const translate = planet::affine::point2d::from_polar(
std::sqrt(direction.mag2()) * 0.15f, direction.theta());
current_looking_at = current_looking_at + translate;
}
view = {};
view.translate(-current_looking_at)
.rotate(current_rotation)
.scale(1.0f / current_scale);
}
felspar::coro::task<void> planet::camera::orthogonal_birdseye::updates(
felspar::io::warden &warden) {
while (true) {
tick_update();
co_await warden.sleep(25ms);
}
}
|
planet::camera::target3dxy
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 | planet::camera::target3dxy::target3dxy(parameters const &p) : target{p} {
tick_update();
}
planet::affine::point2d
planet::camera::target3dxy::into(affine::point3d const &p) {
auto const p2 = perspective.into() * view.into(p);
return {p2.x(), p2.y()};
}
planet::affine::point3d planet::camera::target3dxy::out_of_for_z(
affine::point2d const &xy, float const z) {
static affine::point3d constexpr xynormal{0, 0, 1};
|
Centre of the plane in world coordinates
| affine::point3d const plane_centre{0, 0, z};
|
Start and end of the camera ray in camera coordinates
| float const fov_rad = current.perspective_fov * pi / 2.0f;
float const focal_length =
current.perspective_scale / std::tan(fov_rad / 2.0f);
affine::point3d const start_camera{0, 0, 0};
affine::point3d const end_camera{xy, -focal_length};
|
Convert start & end to world coordinates
| auto const start_world = view.outof(start_camera);
auto const end_world = view.outof(end_camera);
|
Direction of the ray
| auto const dir{(end_world - start_world).normalise()};
|
Ray intersection algorithm
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 | auto const dot_normal = dir.dot(xynormal);
if (dot_normal == 0.0f) {
planet::log::warning(
"Camera ray is parallel to xy plane. Position", xy,
"start_world", start_world, "end_world", end_world, "direction",
dir);
return plane_centre;
} else {
auto const numerator = xynormal.dot(plane_centre - start_world);
auto const t = numerator / dot_normal;
if (t > 0.00001f) {
return {(start_world + dir * t).xy(), z};
} else {
planet::log::warning(
"Camera ray points away from the plane. Position", xy,
"start_world", start_world, "end_world", end_world,
"direction", dir);
return plane_centre;
}
}
}
void planet::camera::target3dxy::tick_update() {
initial.tick_update();
|
TODO Do the animated current update from the target
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 | current = target;
view = {initial.view.into(), initial.view.outof()};
view.scale(1.0f, 1.0f, 1.0f / initial.current_scale)
.translate(current.view_offset)
.rotate_x(current.view_angle)
.translate(current.view_direction * current.distance);
perspective = affine::transform3d::perspective(
current.perspective_scale, current.perspective_fov);
}
felspar::coro::task<void>
planet::camera::target3dxy::updates(felspar::io::warden &warden) {
while (true) {
tick_update();
co_await warden.sleep(25ms);
}
}
|