From 7c8b8a39fd36e190578587d8d92f28f460a1fc4b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 2 Jan 2022 21:07:37 +0000 Subject: Encapsulate Ray --- game/selectable.h | 4 +++- game/vehicles/railVehicle.cpp | 9 +++++---- game/vehicles/railVehicle.h | 3 ++- game/vehicles/train.cpp | 6 ++++-- game/vehicles/train.h | 3 ++- gfx/gl/camera.cpp | 5 +++-- gfx/gl/camera.h | 3 ++- lib/ray.hpp | 11 +++++++++++ test/test-maths.cpp | 43 ++++++++++++++++++++++--------------------- ui/gameMainWindow.cpp | 2 +- 10 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 lib/ray.hpp diff --git a/game/selectable.h b/game/selectable.h index 0104f3d..3d734f3 100644 --- a/game/selectable.h +++ b/game/selectable.h @@ -3,11 +3,13 @@ #include #include +class Ray; + class Selectable { public: Selectable() = default; virtual ~Selectable() = default; DEFAULT_MOVE_COPY(Selectable); - [[nodiscard]] virtual bool intersectRay(const glm::vec3 &, const glm::vec3 &, glm::vec2 *, float *) const = 0; + [[nodiscard]] virtual bool intersectRay(const Ray &, glm::vec2 *, float *) const = 0; }; diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp index 8d7b06f..9ad1ea7 100644 --- a/game/vehicles/railVehicle.cpp +++ b/game/vehicles/railVehicle.cpp @@ -9,6 +9,7 @@ #include #include #include +#include void RailVehicle::render(const Shader & shader) const @@ -29,7 +30,7 @@ RailVehicle::move(const Train * t, float & trailBy) } bool -RailVehicle::intersectRay(const glm::vec3 & pos, const glm::vec3 & dir, glm::vec2 * baryPos, float * eh) const +RailVehicle::intersectRay(const Ray & ray, glm::vec2 * baryPos, float * eh) const { constexpr const auto X = 1.35F; const auto Y = this->rvClass->length / 2.F; @@ -63,8 +64,8 @@ RailVehicle::intersectRay(const glm::vec3 & pos, const glm::vec3 & dir, glm::vec {3, 6, 7}, }}; return std::any_of( - triangles.begin(), triangles.end(), [&cornerVertices, &pos, &dir, &baryPos, &eh](const glm::uvec3 idx) { - return glm::intersectRayTriangle(pos, dir, cornerVertices[idx[0]], cornerVertices[idx[1]], - cornerVertices[idx[2]], *baryPos, *eh); + triangles.begin(), triangles.end(), [&cornerVertices, &ray, &baryPos, &eh](const glm::uvec3 idx) { + return glm::intersectRayTriangle(ray.start, ray.direction, cornerVertices[idx[0]], + cornerVertices[idx[1]], cornerVertices[idx[2]], *baryPos, *eh); }); } diff --git a/game/vehicles/railVehicle.h b/game/vehicles/railVehicle.h index f52b154..5fbe1ed 100644 --- a/game/vehicles/railVehicle.h +++ b/game/vehicles/railVehicle.h @@ -10,6 +10,7 @@ #include class Shader; +class Ray; class Train; class RailVehicle : public Renderable, Selectable { @@ -19,7 +20,7 @@ public: void move(const Train *, float & trailBy); void render(const Shader & shader) const override; - [[nodiscard]] bool intersectRay(const glm::vec3 &, const glm::vec3 &, glm::vec2 *, float *) const override; + [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override; Location location; diff --git a/game/vehicles/train.cpp b/game/vehicles/train.cpp index 4f19bed..05915c4 100644 --- a/game/vehicles/train.cpp +++ b/game/vehicles/train.cpp @@ -9,6 +9,8 @@ #include #include +class Ray; + void Train::render(const Shader & shader) const { @@ -24,9 +26,9 @@ Train::getBogiePosition(float linkDist, float dist) const } bool -Train::intersectRay(const glm::vec3 & pos, const glm::vec3 & dir, glm::vec2 * baryPos, float * eh) const +Train::intersectRay(const Ray & ray, glm::vec2 * baryPos, float * eh) const { - return applyOne(&RailVehicle::intersectRay, pos, dir, baryPos, eh) != end(); + return applyOne(&RailVehicle::intersectRay, ray, baryPos, eh) != end(); } void diff --git a/game/vehicles/train.h b/game/vehicles/train.h index 68f9fbf..0c6a741 100644 --- a/game/vehicles/train.h +++ b/game/vehicles/train.h @@ -14,6 +14,7 @@ #include class Shader; +class Ray; class Train : public Vehicle, public Collection, public Can, public Can { public: @@ -27,7 +28,7 @@ public: void render(const Shader & shader) const override; - [[nodiscard]] bool intersectRay(const glm::vec3 &, const glm::vec3 &, glm::vec2 *, float *) const override; + [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override; void tick(TickDuration elapsed) override; void doActivity(Go *, TickDuration) override; diff --git a/gfx/gl/camera.cpp b/gfx/gl/camera.cpp index 905f78e..c751ba8 100644 --- a/gfx/gl/camera.cpp +++ b/gfx/gl/camera.cpp @@ -1,6 +1,7 @@ #include "camera.h" #include // IWYU pragma: keep #include +#include Camera::Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar) : pos {pos}, forward {::north}, up {::up}, projection {glm::perspective(fov, aspect, zNear, zFar)} @@ -13,9 +14,9 @@ Camera::GetViewProjection() const return projection * glm::lookAt(pos, pos + forward, up); } -glm::vec3 +Ray Camera::unProject(const glm::vec2 & mouse) const { static constexpr const glm::vec4 screen {0, 0, 1, 1}; - return glm::normalize(glm::unProject(mouse ^ 1, glm::lookAt(::origin, forward, up), projection, screen)); + return {pos, glm::normalize(glm::unProject(mouse ^ 1, glm::lookAt(::origin, forward, up), projection, screen))}; } diff --git a/gfx/gl/camera.h b/gfx/gl/camera.h index 9fbb0a1..b4dd0d5 100644 --- a/gfx/gl/camera.h +++ b/gfx/gl/camera.h @@ -1,13 +1,14 @@ #pragma once #include +#include class Camera { public: Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar); [[nodiscard]] glm::mat4 GetViewProjection() const; - [[nodiscard]] glm::vec3 unProject(const glm::vec2 &) const; + [[nodiscard]] Ray unProject(const glm::vec2 &) const; glm::vec3 pos; glm::vec3 forward; diff --git a/lib/ray.hpp b/lib/ray.hpp new file mode 100644 index 0000000..4c0710a --- /dev/null +++ b/lib/ray.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +class Ray { +public: + Ray(glm::vec3 start, glm::vec3 direction) : start {start}, direction {direction} { } + + glm::vec3 start; + glm::vec3 direction; +}; diff --git a/test/test-maths.cpp b/test/test-maths.cpp index 86cb7b8..1f2a096 100644 --- a/test/test-maths.cpp +++ b/test/test-maths.cpp @@ -254,35 +254,36 @@ BOOST_DATA_TEST_CASE(curve1, BOOST_AUTO_TEST_CASE(camera_clicks) { - Camera camera {{0, 0, 0}, ::half_pi, 1.25F, .1F, 10000.F}; + Camera camera {::origin, ::half_pi, 1.25F, .1F, 10000.F}; constexpr float centre {0.5F}, right {0.9F}, left {0.1F}, top {1.F}, bottom {0.F}; camera.forward = ::north; - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}), ::north); - BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}), glm::normalize(::north + ::west)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}), glm::normalize(::north + ::east)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}), glm::normalize(::north + ::up)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, bottom}), glm::normalize(::north + ::down)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({left, top}), glm::normalize(::north + ::west + ::up)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({right, top}), glm::normalize(::north + ::east + ::up)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({left, bottom}), glm::normalize(::north + ::west + ::down)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({right, bottom}), glm::normalize(::north + ::east + ::down)); + BOOST_CHECK_EQUAL(camera.unProject({centre, centre}).start, ::origin); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}).direction, ::north); + BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}).direction, glm::normalize(::north + ::west)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}).direction, glm::normalize(::north + ::east)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}).direction, glm::normalize(::north + ::up)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, bottom}).direction, glm::normalize(::north + ::down)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({left, top}).direction, glm::normalize(::north + ::west + ::up)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({right, top}).direction, glm::normalize(::north + ::east + ::up)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({left, bottom}).direction, glm::normalize(::north + ::west + ::down)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({right, bottom}).direction, glm::normalize(::north + ::east + ::down)); camera.forward = ::east; - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}), ::east); - BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}), glm::normalize(::north + ::east)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}), glm::normalize(::south + ::east)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}).direction, ::east); + BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}).direction, glm::normalize(::north + ::east)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}).direction, glm::normalize(::south + ::east)); camera.forward = glm::normalize(::north + ::down); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}), glm::normalize(::north + ::down)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}), glm::normalize(::north)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}).direction, glm::normalize(::north + ::down)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}).direction, glm::normalize(::north)); camera.forward = glm::normalize(::north + ::west + ::down); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}), glm::normalize(::north + ::west + ::down)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}), glm::normalize(::north + ::west + ::up * 0.2F)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}).direction, glm::normalize(::north + ::west + ::down)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}).direction, glm::normalize(::north + ::west + ::up * 0.2F)); camera.forward = glm::normalize(::north + ::west); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}), glm::normalize(::north + ::west)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}), glm::normalize(::north + ::west + ::up * 1.2F)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}), glm::normalize(::north)); - BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}), glm::normalize(::west)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, centre}).direction, glm::normalize(::north + ::west)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({centre, top}).direction, glm::normalize(::north + ::west + ::up * 1.2F)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({right, centre}).direction, glm::normalize(::north)); + BOOST_CHECK_CLOSE_VEC(camera.unProject({left, centre}).direction, glm::normalize(::west)); } diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index b904388..41bbb39 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -52,7 +52,7 @@ public: float eh; std::ignore = gameState->world.applyOne( - &Selectable::intersectRay, camera->pos, camera->unProject(mouse), &baryPos, &eh); + &Selectable::intersectRay, camera->unProject(mouse), &baryPos, &eh); } } return false; -- cgit v1.2.3