MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NavigationState.cpp
Go to the documentation of this file.
1#include "NavigationState.hpp"
2
3namespace MayaFlux::Kinesis {
4
6{
8 st.eye = config.initial_eye;
9 st.move_speed = config.move_speed;
11 st.scroll_speed = config.scroll_speed;
12 st.fov_radians = config.fov_radians;
13 st.near_plane = config.near_plane;
14 st.far_plane = config.far_plane;
15
16 const glm::vec3 dir = glm::normalize(config.initial_target - config.initial_eye);
17 st.yaw = std::atan2(dir.x, dir.z);
18 st.pitch = std::asin(glm::clamp(dir.y, -1.0F, 1.0F));
19
20 return st;
21}
22
24{
26 return build_view_transform(st, aspect);
27}
28
29void apply_mouse_delta(NavigationState& st, float dx, float dy)
30{
31 st.yaw += dx * st.mouse_sensitivity;
32 st.pitch += dy * st.mouse_sensitivity;
33
34 static constexpr float k_limit = glm::radians(89.0F);
35 st.pitch = glm::clamp(st.pitch, -k_limit, k_limit);
36}
37
38void apply_scroll(NavigationState& st, float ticks)
39{
40 const glm::vec3 forward {
41 std::cos(st.pitch) * std::sin(st.yaw),
42 std::sin(st.pitch),
43 std::cos(st.pitch) * std::cos(st.yaw)
44 };
45 st.eye += forward * (ticks * st.scroll_speed);
46}
47
48void snap_ortho(NavigationState& st, int view)
49{
50 const float dist = glm::length(st.eye);
51
52 switch (view) {
53 case 0: // front: camera on +Z looking toward -Z
54 st.eye = glm::vec3(0.0F, 0.0F, dist);
55 st.yaw = 0.0F;
56 st.pitch = 0.0F;
57 break;
58 case 1: // right: camera on +X looking toward -X
59 st.eye = glm::vec3(dist, 0.0F, 0.0F);
60 st.yaw = glm::radians(-90.0F);
61 st.pitch = 0.0F;
62 break;
63 case 2: // top: camera on +Y looking straight down
64 st.eye = glm::vec3(0.0F, dist, 0.0F);
65 st.yaw = 0.0F;
66 st.pitch = glm::radians(-89.0F);
67 break;
68 case 3: // flip: mirror through origin
69 st.eye = -st.eye;
70 st.yaw = st.yaw + glm::pi<float>();
71 st.pitch = -st.pitch;
72 break;
73 default:
74 break;
75 }
76}
77
79{
80 const auto now = std::chrono::steady_clock::now();
81 const float dt = std::chrono::duration<float>(now - st.last_tick).count();
82 st.last_tick = now;
83
84 const glm::vec3 forward {
85 std::cos(st.pitch) * std::sin(st.yaw),
86 std::sin(st.pitch),
87 std::cos(st.pitch) * std::cos(st.yaw)
88 };
89 const glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0.0F, 1.0F, 0.0F)));
90
91 const float step = st.move_speed * dt;
92
93 glm::vec3 candidate = st.eye;
94
95 if (st.forward_held)
96 candidate += forward * step;
97 if (st.back_held)
98 candidate -= forward * step;
99 if (st.left_held)
100 candidate -= right * step;
101 if (st.right_held)
102 candidate += right * step;
103 if (st.down_held)
104 candidate -= glm::vec3(0.0F, 1.0F, 0.0F) * step;
105 if (st.up_held)
106 candidate += glm::vec3(0.0F, 1.0F, 0.0F) * step;
107
108 st.eye = st.eye_constraint ? st.eye_constraint(candidate) : candidate;
109}
110
112{
113 const glm::vec3 forward {
114 std::cos(st.pitch) * std::sin(st.yaw),
115 std::sin(st.pitch),
116 std::cos(st.pitch) * std::cos(st.yaw)
117 };
118
119 return {
120 .view = glm::lookAt(st.eye, st.eye + forward, glm::vec3(0.0F, 1.0F, 0.0F)),
121 .projection = glm::perspective(st.fov_radians, aspect, st.near_plane, st.far_plane)
122 };
123}
124
125} // namespace MayaFlux::Kinesis
void advance_navigation(NavigationState &st)
Advance eye position by held movement flags against elapsed time.
void apply_scroll(NavigationState &st, float ticks)
Dolly eye along the current forward vector.
NavigationState make_navigation_state(const NavigationConfig &config)
Construct a NavigationState from a NavigationConfig.
ViewTransform compute_view_transform(NavigationState &st, float aspect)
Compute a ViewTransform from the current NavigationState.
void snap_ortho(NavigationState &st, int view)
Snap to a named ortho view.
void apply_mouse_delta(NavigationState &st, float dx, float dy)
Apply a mouse delta to yaw and pitch.
ViewTransform build_view_transform(const NavigationState &st, float aspect)
Build a ViewTransform from the current NavigationState without mutating it.
float mouse_sensitivity
Radians per pixel.
float scroll_speed
World units per scroll tick.
float move_speed
World units per second.
Tuning parameters for a first-person fly-navigation controller.
float pitch
Radians, vertical rotation, clamped to [-89, +89] degrees.
float yaw
Radians, horizontal rotation.
std::chrono::steady_clock::time_point last_tick
std::function< glm::vec3(glm::vec3)> eye_constraint
Optional constraint applied to the proposed eye position after each advance.
Mutable first-person navigation state.
View and projection matrices as a named push constant slot.