libs/render/src/eu/render/camera.cc
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "eu/render/camera.h" | ||
| 2 | |||
| 3 | #include <cmath> | ||
| 4 | |||
| 5 | namespace eu::render | ||
| 6 | { | ||
| 7 | |||
| 8 | // todo(Gustav): this bit is weird, build a matrix directly and extract the in vector from it is probably better | ||
| 9 | |||
| 10 | ✗ | m4 create_view_from_world_mat(const v3& pos, const CameraVectors& cv) | |
| 11 | { | ||
| 12 | ✗ | const auto trans = m4::from_translation(-pos); | |
| 13 | ✗ | const auto rot = m4::from(Q::look_in_direction(cv.front, kk::up)).value_or(m4_identity); | |
| 14 | ✗ | return trans * rot; | |
| 15 | } | ||
| 16 | |||
| 17 | ✗ | CompiledCamera compile(const Camera& cam, const Size& window_size) | |
| 18 | { | ||
| 19 | // todo(Gustav): use the near and far from the camera struct | ||
| 20 | ✗ | const float aspect = static_cast<float>(window_size.width) / static_cast<float>(window_size.height); | |
| 21 | ✗ | const auto clip_from_view = m4::create_perspective(cam.fov, aspect, cam.near, cam.far); | |
| 22 | |||
| 23 | ✗ | const auto camera_space = create_vectors(cam.rotation); | |
| 24 | ✗ | const auto view_from_world = create_view_from_world_mat(cam.position, camera_space); | |
| 25 | |||
| 26 | return CompiledCamera{ | ||
| 27 | .clip_from_view = clip_from_view, | ||
| 28 | .view_from_world = view_from_world, | ||
| 29 | .position = cam.position, | ||
| 30 | .in = camera_space.front | ||
| 31 | ✗ | }; | |
| 32 | } | ||
| 33 | |||
| 34 | ✗ | CompiledCamera compile(const OrthoCamera& cam, const Size& window_size) | |
| 35 | { | ||
| 36 | ✗ | const float aspect = static_cast<float>(window_size.width) / static_cast<float>(window_size.height); | |
| 37 | |||
| 38 | ✗ | const float width = cam.size * aspect; | |
| 39 | ✗ | const float height = cam.size; | |
| 40 | |||
| 41 | ✗ | const auto clip_from_view = m4::create_ortho_lrud(-width/2.0f, width/2.0f, height/2.0f, -height/2.0f, cam.near, cam.far); | |
| 42 | |||
| 43 | ✗ | const auto camera_space = create_vectors(cam.rotation); | |
| 44 | ✗ | const auto view_from_world = create_view_from_world_mat(cam.position, camera_space); | |
| 45 | |||
| 46 | return CompiledCamera{ | ||
| 47 | .clip_from_view = clip_from_view, | ||
| 48 | .view_from_world = view_from_world, | ||
| 49 | .position = cam.position, | ||
| 50 | .in = camera_space.front | ||
| 51 | ✗ | }; | |
| 52 | } | ||
| 53 | |||
| 54 | /** Convert from -1..1 to 0..1 | ||
| 55 | */ | ||
| 56 | ✗ | float r01_from_r11(float f) | |
| 57 | { | ||
| 58 | ✗ | return (f + 1.0f) / 2.0f; | |
| 59 | } | ||
| 60 | |||
| 61 | ✗ | v2 screen_from_clip(const v2& resolution, const v4& clip_pos) | |
| 62 | { | ||
| 63 | ✗ | const auto ndc = clip_pos.to_vec3_persp_div(); | |
| 64 | ✗ | return v2{r01_from_r11(ndc.x), r01_from_r11(ndc.y)} * resolution; | |
| 65 | } | ||
| 66 | |||
| 67 | ✗ | v2 screen_from_world(const CompiledCamera& cam, const v3& world_pos, const v2& resolution) | |
| 68 | { | ||
| 69 | ✗ | const auto clip_pos = cam.clip_from_view * cam.view_from_world * v4(world_pos, 1.0f); | |
| 70 | ✗ | return screen_from_clip(resolution, clip_pos); | |
| 71 | } | ||
| 72 | |||
| 73 | } // namespace eu::render | ||
| 74 |