#include "camera.h"
 #include <math.h>
 #include <stdlib.h>
+#include "input.h"
 
 static vec3_t worldSpaceVec;
 static float aspectRatio = 16.f/9.f;   // sane default for the aspect ratio
        }
 }
 
-void crpgCameraUpdate(crpgCamera *c, float dtms)
+void crpgCameraUpdate(crpgCamera *c)
+{
+       vec3_t panAxis = (vec3_t){0.f,0.f,0.f};
+
+       panAxis.x = crpgInputHeld(INPUT_CAMERA_PAN_RIGHT) ? 1 : 0;
+       panAxis.x = crpgInputHeld(INPUT_CAMERA_PAN_LEFT) ? -1 : panAxis.x;
+
+       panAxis.y = crpgInputHeld(INPUT_CAMERA_PAN_UP) ? 1 : 0;
+       panAxis.y = crpgInputHeld(INPUT_CAMERA_PAN_DOWN) ? -1 : panAxis.y;
+
+       panAxis.z = crpgInputHeld(INPUT_CAMERA_PAN_IN) ? 1 : 0;
+       panAxis.z = crpgInputHeld(INPUT_CAMERA_PAN_OUT) ? -1 : panAxis.z;
+
+       Camera_t *ct = (Camera_t *)c;
+       ct->pan = panAxis;
+}
+
+void crpgCameraRender(crpgCamera *c, float dtms)
 {
        Camera_t *ct = (Camera_t *)c;
        vec3_t *components[] = { &(ct->from), &(ct->to), &(ct->up) };
 
 void crpgCameraSetAR(float ar);
 mat4_t *crpgCameraGetMat(crpgCamera *c);
 void crpgCameraSetSpeed(crpgCamera *c, float speedPerSecond);
-void crpgCameraUpdate(crpgCamera *c, float dtms);
+void crpgCameraRender(crpgCamera *c, float dtms);
+void crpgCameraUpdate(crpgCamera *c);
 #endif//CAMERA_H
 
--- /dev/null
+#include "input.h"
+#include "err.h"
+#include <SDL2/SDL.h>
+
+typedef struct InputDevice{
+       Uint8 *state;
+       Uint8 *prevState;
+       Uint8 *binds;
+}InputDevice;
+
+static InputDevice kb = {NULL,NULL,NULL};
+
+bool devicesNotInitilised()
+{
+       if(kb.binds == NULL){
+               err_output("Error: Can't bind keys, kbBinds is NULL!");
+               return true;
+       }
+       return false;
+}
+
+void loadKeybinds()
+{
+       if(devicesNotInitilised()){
+               return;
+       }
+
+       //TODO: change from static keybinds to keybinds loaded from a file
+       kb.binds[INPUT_CAMERA_PAN_UP] = SDL_SCANCODE_W;
+       kb.binds[INPUT_CAMERA_PAN_DOWN] = SDL_SCANCODE_S;
+       kb.binds[INPUT_CAMERA_PAN_LEFT] = SDL_SCANCODE_A;
+       kb.binds[INPUT_CAMERA_PAN_RIGHT] = SDL_SCANCODE_D;
+       kb.binds[INPUT_CAMERA_PAN_IN] = SDL_SCANCODE_Q;
+       kb.binds[INPUT_CAMERA_PAN_OUT] = SDL_SCANCODE_E;
+}
+
+bool crpgInputPressed(int action)
+{
+       if(devicesNotInitilised()){
+               return false;
+       }
+       printf("binds is: %d, SDL is %d\n", kb.binds[action], SDL_SCANCODE_D);
+       printf("current state: %d, prev state: %d\n\n", kb.state[kb.binds[action]], kb.prevState[kb.binds[action]]);
+       return (kb.state[ kb.binds[action] ] && !kb.prevState[ kb.binds[action] ]);
+}
+
+bool crpgInputHeld(int action)
+{
+       if(devicesNotInitilised()){
+               return false;
+       }
+
+       return (kb.state[ kb.binds[action] ] || kb.prevState[ kb.binds[action] ]);
+}
+
+bool crpgInputReleased(int action)
+{
+       if(devicesNotInitilised()){
+               return false;
+       }
+
+       return (!kb.state[ kb.binds[action] ] && kb.prevState[ kb.binds[action] ]);
+}
+
+
+void crpgInputInit()
+{
+       kb.binds = malloc(sizeof(Uint8) * INPUT_LAST);
+       loadKeybinds();
+}
+
+void crpgInputCleanup()
+{
+       free(kb.binds);
+}
+
+void crpgInputUpdate()
+{
+       //SDL_PumpEvents();
+       kb.prevState = kb.state;
+       kb.state = SDL_GetKeyboardState(NULL);
+}
 
--- /dev/null
+#ifndef INPUT_H
+#define INPUT_H
+#include <stdbool.h>
+
+typedef enum crpgInputActions{
+       INPUT_CAMERA_PAN_DOWN = 0,
+       INPUT_CAMERA_PAN_UP,
+       INPUT_CAMERA_PAN_LEFT,
+       INPUT_CAMERA_PAN_RIGHT,
+       INPUT_CAMERA_PAN_IN,
+       INPUT_CAMERA_PAN_OUT,
+       INPUT_LAST
+}crpgInputActions;
+
+void crpgInputInit();
+void crpgInputUpdate();
+void crpgInputCleanup();
+
+bool crpgInputPressed(int action);
+bool crpgInputHeld(int action);
+bool crpgInputReleased(int action);
+#endif//INPUT_H
 
 #include "cube.h"
 #include "camera.h"
 #include "timestep.h"
+#include "input.h"
 
 static SDL_Window *window = NULL;
 static SDL_GLContext *context = NULL;
        /* syncing the buffer swap with the monitor's vertical refresh */
        SDL_GL_SetSwapInterval(1);
        glViewport(0, 0, screen_width, screen_height);
+       crpgInputInit();
 
        glewExperimental = GL_TRUE;
        glewInit();
                if(e.type == SDL_QUIT){
                        quit = true;
                }
-               if(e.type == SDL_KEYDOWN){
-                       switch(e.key.keysym.sym){
-                               case SDLK_k:
-                                       blendVal += .2f;
-                                       crpgShaderSetFloat(shader, "blendVal", blendVal);
-                                       break;
-                               case SDLK_j:
-                                       blendVal -= .2f;
-                                       crpgShaderSetFloat(shader, "blendVal", blendVal);
-                                       break;
-                               case SDLK_w:
-                                       crpgCameraPan(camera, vec3(0,0,-1));
-                                       crpgCubeSetCamera(cubes[0], crpgCameraGetMat(camera));
-                                       crpgCubeSetCamera(cubes[1], crpgCameraGetMat(camera));
-                                       break;
-                               case SDLK_s:
-                                       crpgCameraPan(camera, vec3(0,0,1));
-                                       crpgCubeSetCamera(cubes[0], crpgCameraGetMat(camera));
-                                       crpgCubeSetCamera(cubes[1], crpgCameraGetMat(camera));
-                                       break;
-                               case SDLK_d:
-                                       crpgCameraPan(camera, vec3(1,0,0));
-                                       crpgCubeSetCamera(cubes[0], crpgCameraGetMat(camera));
-                                       crpgCubeSetCamera(cubes[1], crpgCameraGetMat(camera));
-                                       break;
-                               case SDLK_a:
-                                       crpgCameraPan(camera, vec3(-1,0,0));
-                                       crpgCubeSetCamera(cubes[0], crpgCameraGetMat(camera));
-                                       crpgCubeSetCamera(cubes[1], crpgCameraGetMat(camera));
-                                       break;
-                       }
-               }
        }
+       crpgInputUpdate();
 
        // Updating physics as many times as we need to consume dt
-       while(crpgTimeStepPhysRequried(physUpdates)){
-               crpgCameraUpdate(camera, crpgTimeStepDelta());
-
+       while(crpgTimeStepPhysRequired(physUpdates)){
+               crpgCameraUpdate(camera);
+               crpgCubeSetCamera(cubes[0], crpgCameraGetMat(camera));
+               crpgCubeSetCamera(cubes[1], crpgCameraGetMat(camera));
                physUpdates++;
        }
 }
 
 static void render()
 {
+       crpgCameraRender(camera, crpgTimeStepDelta());
+
        glClearColor(0.2, 0.3, 0.3, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        }
 
        SDL_Quit();
+       crpgInputCleanup();
        crpgCubeFree(cubes[0]);
        crpgCubeFree(cubes[1]);
        return 0;
 
        totalDeltaTime = frameTime / desiredFrameTime;
 }
 
-bool crpgTimeStepPhysRequried(int updatesThisFrame)
+bool crpgTimeStepPhysRequired(int updatesThisFrame)
 {
        if(totalDeltaTime <= 0.f || updatesThisFrame >= MAX_PHYSICS_STEPS){
                return false;
-       } else {
-               deltaTime = fminf(totalDeltaTime, MAX_DELTA_TIME);
-               totalDeltaTime -= deltaTime;
        }
+
+       deltaTime = fminf(totalDeltaTime, MAX_DELTA_TIME);
+       totalDeltaTime -= deltaTime;
+       return true;
 }