diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b4c7e3e7e520b7f478367294ac86c176b5c3a32..e93fc58bc90944b2506e4361b432e92fde1e60ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,8 @@ add_executable(${PROJECT_NAME}
         src/sph/sph_particle.cpp
         src/sph/sph_system.h
         src/sph/sph_system.cpp
+        src/utility/InputHandler.h
+        src/utility/InputHandler.cpp
         )
 
 
diff --git a/src/application.cpp b/src/application.cpp
index b29ba1d4d26230c7e0ce5bb647641a66c8bcf233..52c1ce1268f8e16d80d8e7617fe2ea3f4442dfea 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -1,5 +1,6 @@
 #include "application.h"
 
+InputHandler* Application::inputHandler = InputHandler::GetInstance();
 bool Application::dragging = false;
 
 Application::Application() {
@@ -48,9 +49,15 @@ void Application::key_callback(   GLFWwindow *window,
                                         int scancode,
                                         int action, 
                                         int mods) {
-    std::cout << key << " was pressed" << std::endl;
+//    std::cout << key << " was pressed" << std::endl;
     if(key == GLFW_KEY_ESCAPE)
         glfwSetWindowShouldClose(window, GLFW_TRUE);
+    if(action == GLFW_RELEASE)
+        InputHandler::KeyRelease(key);
+    else
+        InputHandler::KeyPress(key);
+
+    InputHandler::SetModifiers(mods);
 }
 
 
@@ -105,6 +112,8 @@ void Application::run() {
     // TODO think about rendering only in 24 FPS
     // TODO guarantee delta_time to be infinitesimal
     scene->update(delta_time);
+    camera->control(delta_time);
+
     //clear color and depth buffer
     glClearColor(0,0,0,1);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -114,4 +123,3 @@ void Application::run() {
 }
 
 
-
diff --git a/src/application.h b/src/application.h
index ea2e272f3232028b511ceafd87c58cf8ce089a5a..b1a3ec339260f3bf6fb2dbf592cf69f05cbab77b 100644
--- a/src/application.h
+++ b/src/application.h
@@ -10,10 +10,12 @@
 #include "constants.h"
 #include "scene.h"
 #include "rendering/camera.h"
+#include "utility/InputHandler.h"
 
 // TODO make this class a singleton
 class Application {
-    int keyArr[350];
+
+
     int width = WIDTH;
     int height = HEIGHT;
 
@@ -21,7 +23,7 @@ class Application {
     // Callback functions
     static void error_callback(int error, const char* description);
     static void resize_callback(GLFWwindow *window, int w, int h);
-    static void key_callback(GLFWwindow *window, int key, int scancode, 
+    static void key_callback(GLFWwindow *window, int key, int scancode,
             int action, int mods);
     static void mouse_click_callback(GLFWwindow *window, int button, int action,
             int mods);
@@ -29,6 +31,8 @@ class Application {
 
     std::shared_ptr<Scene> scene = std::make_shared<Scene>();
 
+    static InputHandler *inputHandler;
+
     void run();
     double time_since_last_frame;
 
diff --git a/src/rendering/camera.cpp b/src/rendering/camera.cpp
index 429007c3d1ecefdb8dea7940817a1ef333fe7bd7..1685c5c9396acb96e3b30cfd0b8ca2c7ba350f2a 100644
--- a/src/rendering/camera.cpp
+++ b/src/rendering/camera.cpp
@@ -1,33 +1,42 @@
+#include <iostream>
 #include "camera.h"
 
 Camera::Camera():
     aspect_ratio(1),
-    pos(0, 25, -50),
+    pos(1, 1, -3),
     forward(0,0,1),
     right(-1,0,0),
     speed(10) 
 {
+    inputHandler = InputHandler::GetInstance();
 }
 
 Camera::~Camera() {
 }
 
 
-void Camera::control(float delta_time, const bool* inputs) {
+void Camera::control(float delta_time) {
     // process camera keys
-    for(int i = 0; i < 256; i++) {
-        if(!inputs[i]) continue;
-        switch(i)
-        {
-            case 'w': pos += forward * speed * delta_time; break;
-            case 's': pos -= forward * speed * delta_time; break;
-            case 'a': pos -= right * speed * delta_time; break;
-            case 'd': pos += right * speed * delta_time; break;
-            case 'q': pos += glm::vec3(0,-1,0) * speed * delta_time; break;
-            case 'e': pos += glm::vec3(0,1,0) * speed * delta_time; break;
-            default: break;
-        }
-    }
+    if(InputHandler::IsPressed(GLFW_KEY_W))
+        pos += forward * speed * delta_time;
+
+
+    if(InputHandler::IsPressed(GLFW_KEY_S))
+        pos -= forward * speed * delta_time;
+
+    if(InputHandler::IsPressed(GLFW_KEY_A))
+        pos -= right * speed * delta_time;
+
+    if(InputHandler::IsPressed(GLFW_KEY_D))
+        pos += right * speed * delta_time;
+
+    if(InputHandler::IsPressed(GLFW_KEY_Q))
+        pos += glm::vec3(0,-1,0) * speed * delta_time;
+
+    if(InputHandler::IsPressed(GLFW_KEY_E))
+        pos += glm::vec3(0,1,0) * speed * delta_time;
+
+    std::cout << pos.x << pos.y << pos.z << std::endl;
 }
 
 void Camera::startDrag(int x, int y) {
diff --git a/src/rendering/camera.h b/src/rendering/camera.h
index 8c8ab523559e51343be40d7cc43caa2bc4f5a3eb..185641506f16690eb3b187c67e795c17adb72bcf 100644
--- a/src/rendering/camera.h
+++ b/src/rendering/camera.h
@@ -3,6 +3,7 @@
 
 #include <glm/glm.hpp>
 #include "../utility/gl.h"
+#include "../utility/InputHandler.h"
 
 class Camera {
     float aspect_ratio;
@@ -11,13 +12,15 @@ class Camera {
     glm::vec3 right;
     float speed;
 
+    InputHandler* inputHandler;
+
     glm::vec2 drag_start = glm::vec2(0,0);
 public:
     void setAspectRatio(float ar) {
         aspect_ratio = ar;
     }
 
-    void control(float delta_time, const bool* inputs);
+    void control(float delta_time);
     void startDrag(int x, int y);
     void drag(int x, int y);
 
diff --git a/src/sph/sph_system.cpp b/src/sph/sph_system.cpp
index ce0ef4cae119f121d7416e87f3c42bef0054be4f..597456a61a2a3fd85ae24a5126022d490ed3bed7 100644
--- a/src/sph/sph_system.cpp
+++ b/src/sph/sph_system.cpp
@@ -1,15 +1,14 @@
 #include "sph_system.h"
 
-
 namespace sph {
 
     System::System() {
         std::cout << "Initializing sph particle system with " << N <<
             " particles." << std::endl;
 
-        for(float y = 0; y < HEIGHT/3; y += H)         
-            for(float z = 0; z < 400; z += H)
-                for (float x = 0; x < WIDTH/4; x += H)
+        for(float y = 1; y < 5; y += 0.5f)
+            for(float z = 0; z < 2; z += 0.2f)
+                for (float x = 0; x < 2; x += 0.2f)
                     if (particles.size() < N)
                     {
                         float x_off = glm::linearRand(.0f, 1.f);
@@ -21,8 +20,9 @@ namespace sph {
     }
 
     System::~System() {
-        for(int i = 0; i < particles.size(); i++)
-            delete particles[i];
+        for(auto & particle : particles)
+            delete particle;
+
     }
 
     void System::compute_density_and_pressure() {
@@ -77,36 +77,35 @@ namespace sph {
             p->pos += DT * p->v;
 
             //boundary conditions
-            if (p->pos.x - EPS < 0) {
+            if (p->pos.x - EPS <= 0) {
                 p->v.x *= BOUND_DAMPING;
-                p->pos.x = 0.0f;
-                std::cout << "bottom: " << p->pos.x << std::endl;
+                p->pos.x = EPS;
             }
 
-            if(p->pos.x + EPS > WIDTH) {
+            if(p->pos.x + EPS > 2) {
                 p->v.x *= BOUND_DAMPING;
-                p->pos.x = WIDTH - EPS;
+                p->pos.x = 2 - EPS;
             }
 
-            if(p->pos.y - EPS > HEIGHT) {
+            if(p->pos.y - EPS <= 0) {
                 p->v.y *= BOUND_DAMPING;
-                p->pos.y = HEIGHT - EPS;
+                p->pos.y = EPS;
             }
 
-            if(p->pos.y + EPS > HEIGHT) {
+            if(p->pos.y + EPS >= 51) {
                 p->v.y *= BOUND_DAMPING;
-                p->pos.y = HEIGHT - EPS;
+                p->pos.y = 51 - EPS;
             }
 
             //TODO DEPTH CONSTANT VALUE
-            if(p->pos.z - EPS < 0) {
+            if(p->pos.z - EPS <= 0) {
                 p->v.z *= BOUND_DAMPING;
                 p->pos.z = EPS;
             }
 
-            if(p->pos.z + EPS > 400) {
+            if(p->pos.z + EPS >= 2) {
                 p->v.z *= BOUND_DAMPING;
-                p->pos.z = 400 - EPS;
+                p->pos.z = 2 - EPS;
             }
         }
     }
@@ -123,12 +122,12 @@ namespace sph {
     }
 
     void System::render() {
-
         // TODO MODERN OPENGL!!!!
         glEnable(GL_POINT_SMOOTH);
         glPointSize(H / 2.f);
 
         glColor4f(0.5f, 0.5f, 0.8f, 1.f);
+
         glBegin(GL_POINTS);
         for(auto &p : particles)
             glVertex3f(p->pos.x, p->pos.y, p->pos.z);
diff --git a/src/sph/sph_system.h b/src/sph/sph_system.h
index b52b6817def228489443b9f6939f6ba11e581d03..caab4f39068c59924948b1e071da2ba9f7348538 100644
--- a/src/sph/sph_system.h
+++ b/src/sph/sph_system.h
@@ -20,25 +20,25 @@ namespace sph {
     // const for equation of state
     const static float GAS_CONST = 2000.0f;
     // kernel radius
-    const static float H = 16.f;
+    const static float H = 4.f;
     // (kernel radius)^2 for optimization
     const static float H2 = H * H;
     // mass of particles
-    const static float M = 65.f;
+    const static float M = 60.f;
     // viscosity constant
-    const static float MU = 250.f; 
+    const static float MU = 42.f;
     // TODO decide the place for this
     // integration timestep
     const static float DT = 0.0005f; 
 
     // epsilon (e.g. at boundary check)
-    const static float EPS = H;
+    const static float EPS = 0.0001f;
     // damping when colliding with the boundary
     const static float BOUND_DAMPING = -0.5f;
 
     [[maybe_unused]] const static float PI = glm::pi<float>();
     // smoothing kernel as described in the Müller paper
-    const static float POLY6 = 315.f / (64 * glm::pi<float>() * glm::pow(H, 9));
+    const static float POLY6 = 315.f / (64.f * glm::pi<float>() * glm::pow(H, 9));
     const static float POLY6_GRAD_PRESS = -45.f / (glm::pi<float>()
             * glm::pow(H, 6));
     const static float POLY6_GRAD_VISC = 45.f / (glm::pi<float>() * glm::pow(H,
@@ -46,7 +46,7 @@ namespace sph {
 
     // PARTICLES
     // number of particles
-    const static int N = 500;
+    const static int N = 400;
 }
 
 namespace sph {
diff --git a/src/utility/InputHandler.cpp b/src/utility/InputHandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..92a2edf01d99b998e2c92b51e9ee2886e97c1489
--- /dev/null
+++ b/src/utility/InputHandler.cpp
@@ -0,0 +1,53 @@
+#include "InputHandler.h"
+
+InputHandler *InputHandler::singleton_ = nullptr;
+bool InputHandler::keyPressed[348];
+int InputHandler::modifiers = 0;
+
+InputHandler *InputHandler::GetInstance() {
+    if (singleton_ == nullptr) 
+        singleton_ = new InputHandler();
+
+    return singleton_;
+}
+
+void InputHandler::KeyPress(int key) {
+    keyPressed[key] = true;
+}
+
+void InputHandler::SetModifiers(int m) {
+    modifiers = m;
+}
+
+void InputHandler::KeyRelease(int key) {
+    keyPressed[key] = false;
+}
+
+bool InputHandler::IsPressed(int key) {
+    return keyPressed[key];
+}
+
+bool InputHandler::IsShiftPressed() {
+    return modifiers & GLFW_MOD_SHIFT;
+}
+
+bool InputHandler::IsControlPressed()  {
+    return modifiers & GLFW_MOD_CONTROL;
+}
+
+bool InputHandler::IsAltPressed() {
+    return modifiers & GLFW_MOD_ALT;
+}
+
+bool InputHandler::IsSuperPressed() {
+    return modifiers & GLFW_MOD_SUPER;
+}
+
+bool InputHandler::IsCapsLock() {
+    return modifiers & GLFW_MOD_CAPS_LOCK;
+}
+
+bool InputHandler::IsNumLock() {
+    return modifiers & GLFW_MOD_NUM_LOCK;
+}
+
diff --git a/src/utility/InputHandler.h b/src/utility/InputHandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..12e892f2a462d7a563b5388b25466fee9bbdf921
--- /dev/null
+++ b/src/utility/InputHandler.h
@@ -0,0 +1,67 @@
+#ifndef MADID_INPUTHANDLER_H
+#define MADID_INPUTHANDLER_H
+
+#include "gl.h"
+
+/**
+ * The inputHandler class defines the `GetInstance` method that serves as an
+ * alternative to constructor and lets clients access the same instance of this
+ * class over and over. (Singleton pattern)
+ */
+class InputHandler {
+    // Input handling
+    bool aKeyWasPressed;
+    static bool keyPressed[348];
+    static int modifiers;
+
+    /**
+     * The inputHandler's constructor should always be private to prevent direct
+     * construction calls with the `new` operator.
+     */
+    InputHandler() {
+        aKeyWasPressed = false;
+        modifiers = 0;
+        for (bool &k : keyPressed)
+            k = false;
+
+    }
+
+    static InputHandler *singleton_;
+
+public:
+
+    /**
+     * Singletons should not be cloneable.
+     */
+    InputHandler(InputHandler &other) = delete;
+
+    /**
+     * Singletons should not be assignable.
+     */
+    void operator=(const InputHandler &) = delete;
+
+    static InputHandler *GetInstance();
+
+    static void KeyPress(int key);
+
+    static void SetModifiers(int m);
+
+    static void KeyRelease(int key);
+
+    static bool IsPressed(int key);
+
+    static bool IsShiftPressed() ;
+
+    static bool IsControlPressed();
+
+    static bool IsAltPressed();
+
+    static bool IsSuperPressed();
+
+    static bool IsCapsLock();
+
+    static bool IsNumLock();
+
+};
+
+#endif //MADID_INPUTHANDLER_H