summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-01-28 18:51:30 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2021-01-28 18:51:30 +0000
commit235f128136c7c23a64fa5f0424edf05879b8ee9b (patch)
treef703d173de2e55fdbdf9723cc5993df63bcff200
parentGenerate some random terrain with a water layer (diff)
downloadilt-235f128136c7c23a64fa5f0424edf05879b8ee9b.tar.bz2
ilt-235f128136c7c23a64fa5f0424edf05879b8ee9b.tar.xz
ilt-235f128136c7c23a64fa5f0424edf05879b8ee9b.zip
Input stack and logical split of camera controller
-rw-r--r--application/inputHandler.h13
-rw-r--r--application/main.cpp118
-rw-r--r--application/manualCameraController.cpp65
-rw-r--r--application/manualCameraController.h25
-rw-r--r--gfx/camera_controller.h14
-rw-r--r--gfx/gl/camera.cpp4
-rw-r--r--gfx/gl/camera.h5
-rw-r--r--utility/collection.hpp37
8 files changed, 192 insertions, 89 deletions
diff --git a/application/inputHandler.h b/application/inputHandler.h
new file mode 100644
index 0000000..bcb900b
--- /dev/null
+++ b/application/inputHandler.h
@@ -0,0 +1,13 @@
+#ifndef INPUT_HANDLER_H
+#define INPUT_HANDLER_H
+
+union SDL_Event;
+
+class InputHandler {
+public:
+ virtual ~InputHandler() = default;
+
+ virtual bool handleInput(SDL_Event &) = 0;
+};
+
+#endif
diff --git a/application/main.cpp b/application/main.cpp
index 912fa4f..0685d5e 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -1,5 +1,7 @@
#include "game/terrain.h"
#include "gfx/window.h"
+#include "inputHandler.h"
+#include "manualCameraController.h"
#include <SDL2/SDL.h>
#include <chrono>
#include <cmath>
@@ -7,6 +9,7 @@
#include <game/physical.h>
#include <game/world.h>
#include <game/worldobject.h>
+#include <gfx/camera_controller.h>
#include <gfx/gl/camera.h>
#include <gfx/gl/shader.h>
#include <gfx/gl/transform.h>
@@ -15,6 +18,7 @@
#include <memory>
#include <numbers>
#include <special_members.hpp>
+#include <vector>
#include <worker.h>
static const int DISPLAY_WIDTH = 800;
@@ -36,7 +40,7 @@ private:
float counter {};
};
-class SDL_Application {
+class SDL_Application : public InputHandler, public std::enable_shared_from_this<SDL_Application> {
public:
SDL_Application()
{
@@ -50,13 +54,26 @@ public:
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
}
- ~SDL_Application()
+
+ ~SDL_Application() override
{
SDL_Quit();
}
+
NO_COPY(SDL_Application);
NO_MOVE(SDL_Application);
+ bool
+ handleInput(SDL_Event & e) override
+ {
+ switch (e.type) {
+ case SDL_QUIT:
+ isRunning = false;
+ return true;
+ }
+ return false;
+ }
+
void
run()
{
@@ -65,7 +82,6 @@ public:
Worker w;
- World world;
world.create<Monkey>();
world.create<Terrain>();
@@ -76,90 +92,19 @@ public:
shader.Bind();
shader.setView(camera.GetViewProjection());
- SDL_Event e;
- bool isRunning = true;
-
auto t_start = std::chrono::high_resolution_clock::now();
const auto framelen = std::chrono::milliseconds {1000} / 120;
- bool mrb {false}, ctrl {false};
- while (isRunning) {
- while (SDL_PollEvent(&e)) {
- switch (e.type) {
- case SDL_QUIT:
- isRunning = false;
- break;
- case SDL_KEYDOWN:
- switch (e.key.keysym.sym) {
- case SDLK_KP_8:
- camera.MoveForward(1);
- break;
- case SDLK_KP_2:
- camera.MoveForward(-1);
- break;
- case SDLK_KP_4:
- camera.MoveRight(1);
- break;
- case SDLK_KP_6:
- camera.MoveRight(-1);
- break;
- case SDLK_KP_7:
- camera.RotateY(0.04);
- break;
- case SDLK_KP_9:
- camera.RotateY(-0.04);
- break;
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- ctrl = true;
- break;
- }
- shader.setView(camera.GetViewProjection());
- break;
- case SDL_KEYUP:
- switch (e.key.keysym.sym) {
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- ctrl = false;
- break;
- }
- break;
- case SDL_MOUSEBUTTONDOWN:
- switch (e.button.button) {
- case SDL_BUTTON_RIGHT:
- SDL_SetRelativeMouseMode(SDL_TRUE);
- mrb = true;
- break;
- }
- break;
- case SDL_MOUSEBUTTONUP:
- switch (e.button.button) {
- case SDL_BUTTON_RIGHT:
- SDL_SetRelativeMouseMode(SDL_FALSE);
- mrb = false;
- break;
- }
- break;
- case SDL_MOUSEMOTION:
- if (mrb) {
- if (ctrl) {
- camera.RotateY(-0.01F * e.motion.xrel);
- camera.Pitch(-0.01F * e.motion.yrel);
- }
- else {
- camera.MoveRight(e.motion.xrel);
- camera.SlideForward(e.motion.yrel);
- }
- shader.setView(camera.GetViewProjection());
- }
- break;
- }
- }
+ inputStack.objects.push_back(shared_from_this());
+ inputStack.objects.insert(inputStack.objects.begin(), world.create<ManualCameraController>());
+ while (isRunning) {
+ processInputs();
const auto t_end = std::chrono::high_resolution_clock::now();
const auto t_passed = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start);
world.apply(&WorldObject::tick, t_passed);
+ world.apply<CameraController>(&CameraController::updateCamera, &camera, &shader);
windows.apply(&Window::Clear, 0.0F, 0.0F, 0.0F, 1.0F);
world.apply<Renderable>(&Renderable::render, shader);
windows.apply(&Window::SwapBuffers);
@@ -170,12 +115,25 @@ public:
t_start = t_end;
}
}
+
+private:
+ void
+ processInputs()
+ {
+ for (SDL_Event e; SDL_PollEvent(&e);) {
+ inputStack.applyOne(&InputHandler::handleInput, e);
+ }
+ }
+
+ bool isRunning {true};
+ Collection<InputHandler> inputStack;
+ World world;
};
int
main(int, char **)
{
- SDL_Application().run();
+ std::make_shared<SDL_Application>()->run();
return 0;
}
diff --git a/application/manualCameraController.cpp b/application/manualCameraController.cpp
new file mode 100644
index 0000000..36f3312
--- /dev/null
+++ b/application/manualCameraController.cpp
@@ -0,0 +1,65 @@
+#include "manualCameraController.h"
+#include <gfx/gl/camera.h>
+#include <gfx/gl/shader.h>
+
+bool
+ManualCameraController::handleInput(SDL_Event & e)
+{
+ switch (e.type) {
+ case SDL_KEYDOWN:
+ switch (e.key.keysym.sym) {
+ case SDLK_LCTRL:
+ case SDLK_RCTRL:
+ ctrl = true;
+ return true;
+ }
+ break;
+ case SDL_KEYUP:
+ switch (e.key.keysym.sym) {
+ case SDLK_LCTRL:
+ case SDLK_RCTRL:
+ ctrl = false;
+ return true;
+ }
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ switch (e.button.button) {
+ case SDL_BUTTON_RIGHT:
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+ mrb = true;
+ return true;
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ switch (e.button.button) {
+ case SDL_BUTTON_RIGHT:
+ SDL_SetRelativeMouseMode(SDL_FALSE);
+ mrb = false;
+ return true;
+ }
+ break;
+ case SDL_MOUSEMOTION:
+ if (mrb) {
+ motion = e.motion;
+ }
+ return true;
+ }
+ return false;
+}
+
+void
+ManualCameraController::updateCamera(Camera * camera, Shader * shader) const
+{
+ if (motion) {
+ if (ctrl) {
+ camera->RotateY(-0.01F * motion->xrel);
+ camera->Pitch(-0.01F * motion->yrel);
+ }
+ else {
+ camera->MoveRight(motion->xrel);
+ camera->SlideForward(motion->yrel);
+ }
+ shader->setView(camera->GetViewProjection());
+ motion.reset();
+ }
+}
diff --git a/application/manualCameraController.h b/application/manualCameraController.h
new file mode 100644
index 0000000..112ec5c
--- /dev/null
+++ b/application/manualCameraController.h
@@ -0,0 +1,25 @@
+#ifndef MANUAL_CAMERA_CONTROLLER_H
+#define MANUAL_CAMERA_CONTROLLER_H
+
+#include "game/worldobject.h"
+#include "inputHandler.h"
+#include <SDL2/SDL.h>
+#include <gfx/camera_controller.h>
+#include <optional>
+
+class Camera;
+class Shader;
+
+class ManualCameraController : public CameraController, public InputHandler {
+public:
+ bool handleInput(SDL_Event & e) override;
+
+ void tick(TickDuration) override { }
+
+ void updateCamera(Camera * camera, Shader * shader) const override;
+
+private:
+ bool ctrl {false}, mrb {false};
+ mutable std::optional<SDL_MouseMotionEvent> motion;
+};
+#endif
diff --git a/gfx/camera_controller.h b/gfx/camera_controller.h
new file mode 100644
index 0000000..cdc70d2
--- /dev/null
+++ b/gfx/camera_controller.h
@@ -0,0 +1,14 @@
+#ifndef CAMERA_CONTROLLER_H
+#define CAMERA_CONTROLLER_H
+
+#include <game/worldobject.h>
+
+class Camera;
+class Shader;
+
+class CameraController : public WorldObject {
+public:
+ virtual void updateCamera(Camera *, Shader *) const = 0;
+};
+
+#endif
diff --git a/gfx/gl/camera.cpp b/gfx/gl/camera.cpp
index 2f48ca5..c98ff70 100644
--- a/gfx/gl/camera.cpp
+++ b/gfx/gl/camera.cpp
@@ -2,8 +2,8 @@
#include <glm/gtx/transform.hpp>
Camera::Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar) :
- projection {glm::perspective(fov, aspect, zNear, zFar)}, pos {pos}, forward {0.0F, 0.0F, 1.0F}, up {0.0F, 1.0F,
- 0.0F}
+ pos {pos}, forward {0.0F, 0.0F, 1.0F}, up {0.0F, 1.0F, 0.0F}, projection {
+ glm::perspective(fov, aspect, zNear, zFar)}
{
}
diff --git a/gfx/gl/camera.h b/gfx/gl/camera.h
index 90d88a3..3d8ece4 100644
--- a/gfx/gl/camera.h
+++ b/gfx/gl/camera.h
@@ -15,11 +15,12 @@ public:
void Pitch(float angle);
void RotateY(float angle);
-private:
- glm::mat4 projection;
glm::vec3 pos;
glm::vec3 forward;
glm::vec3 up;
+
+private:
+ glm::mat4 projection;
};
#endif
diff --git a/utility/collection.hpp b/utility/collection.hpp
index 1422a84..a9ddb78 100644
--- a/utility/collection.hpp
+++ b/utility/collection.hpp
@@ -6,26 +6,53 @@
template<typename Object> class Collection {
public:
- using Ptr = std::unique_ptr<Object>;
+ using Ptr = std::shared_ptr<Object>;
std::vector<Ptr> objects;
template<typename T = Object, typename... Params>
- const auto &
+ auto
create(Params &&... params)
{
- return objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...));
+ auto obj = std::make_shared<T>(std::forward<Params>(params)...);
+ objects.emplace_back(obj);
+ return obj;
}
template<typename T = Object, typename M = void, typename... Params>
- void
+ auto
apply(const M & m, Params &&... params) const
{
- std::for_each(objects.cbegin(), objects.cend(), [&m, &params...](auto && op) {
+ return std::count_if(objects.begin(), objects.end(), [&m, &params...](auto && op) {
if (auto o = dynamic_cast<T *>(op.get())) {
std::invoke(m, o, std::forward<Params>(params)...);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ template<typename T = Object, typename M = void, typename... Params>
+ auto
+ applyOne(const M & m, Params &&... params) const
+ {
+ return std::find_if(objects.begin(), objects.end(), [&m, &params...](auto && op) {
+ if (auto o = dynamic_cast<T *>(op.get())) {
+ return std::invoke(m, o, std::forward<Params>(params)...);
}
+ return false;
});
}
+
+ template<typename T = Object>
+ void
+ removeAll()
+ {
+ objects.erase(std::remove_if(objects.begin(), objects.end(),
+ [](auto && op) {
+ return dynamic_cast<T *>(op.get());
+ }),
+ objects.end());
+ }
};
#endif