Index: color.frag
===================================================================
--- color.frag	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
+++ color.frag	(revision f7d35dac677240a84b5a5c21202fc406d3227a0a)
@@ -1,5 +1,5 @@
 #version 410
 
-in vec3 position_eye, normal_eye, color, light_position_eye;
+in vec3 position_eye, normal_eye, color, light_position_eye, light2_position_eye;
 
 out vec4 frag_color;
@@ -24,14 +24,26 @@
 
   // diffuse intensity
-  vec3 Id = Ls * color * dot_prod;
+  vec3 Id = Ld * color * dot_prod;
+
+  vec3 direction_to_light2_eye = normalize(light2_position_eye - position_eye);
+  float dot_prod2 = max(dot(direction_to_light2_eye, normal_eye), 0.0);
+
+  // diffuse intensity
+  vec3 Id2 = Ld * color * dot_prod2;
+
+  vec3 surface_to_viewer_eye = normalize(-position_eye);
 
   vec3 reflection_eye = reflect(-direction_to_light_eye, normal_eye);
-  vec3 surface_to_viewer_eye = normalize(-position_eye);
   float dot_prod_specular = max(dot(reflection_eye, surface_to_viewer_eye), 0.0);
   float specular_factor = pow(dot_prod_specular, specular_exponent);
 
+  vec3 reflection_eye2 = reflect(-direction_to_light2_eye, normal_eye);
+  float dot_prod_specular2 = max(dot(reflection_eye2, surface_to_viewer_eye), 0.0);
+  float specular_factor2 = pow(dot_prod_specular2, specular_exponent);
+
   // specular intensity
   vec3 Is = Ls * Ks * specular_factor;
+  vec3 Is2 = Ls * Ks * specular_factor2;
 
-  frag_color = vec4(Is + Id + Ia, 1.0);
+  frag_color = vec4(Is + Id + Ia + Is2 + Id2, 1.0);
 }
Index: color.vert
===================================================================
--- color.vert	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
+++ color.vert	(revision f7d35dac677240a84b5a5c21202fc406d3227a0a)
@@ -14,8 +14,9 @@
 layout(location = 3) in uint ubo_index;
 
-out vec3 position_eye, normal_eye, color, light_position_eye;
+out vec3 position_eye, normal_eye, color, light_position_eye, light2_position_eye;
 
 // fixed point light position
 vec3 light_position_world = vec3(0.0, 0.0, 2.0);
+vec3 light2_position_world = vec3(0.0, -3.0, -2.0);
 
 void main() {
@@ -24,4 +25,5 @@
   color = vertex_color;
   light_position_eye = vec3(view * vec4(light_position_world, 1.0));
+  light2_position_eye = vec3(view * vec4(light2_position_world, 1.0));
 
   gl_Position = proj * vec4(position_eye, 1.0);
Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
+++ new-game.cpp	(revision f7d35dac677240a84b5a5c21202fc406d3227a0a)
@@ -36,6 +36,4 @@
 using namespace std;
 using namespace glm;
-
-#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444
 
 struct SceneObject {
@@ -63,8 +61,15 @@
 };
 
+#define NUM_KEYS (512)
+#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444 (maybe make this a const instead)
+
+const int KEY_STATE_UNCHANGED = -1;
 const bool FULLSCREEN = false;
-const bool SHOW_FPS = true;
-const bool DISABLE_VSYNC = true; // disable vsync to see real framerate
-unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime
+const bool SHOW_FPS = false;
+const bool DISABLE_VSYNC = false; // disable vsync to see real framerate
+unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime, so it can't be const
+
+int key_state[NUM_KEYS];
+bool key_pressed[NUM_KEYS];
 
 int width = 640;
@@ -95,4 +100,5 @@
 
 void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
 
 bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point);
@@ -212,4 +218,5 @@
 
    glfwSetMouseButtonCallback(window, mouse_button_callback);
+   glfwSetKeyCallback(window, key_callback);
 
    const GLubyte* renderer = glGetString(GL_RENDERER);
@@ -388,5 +395,5 @@
       1.0f, 1.0f,
       0.0f, 0.0f,
-      1.0f, 0.0f
+      1.0f, 0.0f,
    };
    obj.selected_colors = {
@@ -399,7 +406,7 @@
    };
 
-   T_model = translate(mat4(), vec3(0.0f, -0.65f, 0.0f));
+   T_model = translate(mat4(), vec3(0.0f, -0.9f, 0.0f));
    R_model = rotate(mat4(), -1.0f, vec3(1.0f, 0.0f, 0.0f));
-   obj.model_mat = T_model * R_model;
+   obj.model_mat = T_model; //T_model * R_model;
 
    addObjectToScene(obj);
@@ -463,7 +470,4 @@
    glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
 
-   float speed = 1.0f;
-   float last_position = 0.0f;
-
    float cam_speed = 1.0f;
    float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
@@ -553,12 +557,13 @@
       }
 
-      if (fabs(last_position) > 1.0f) {
-         speed = -speed;
-      }
-
-      // Handle events (Ideally, move all event-handling code
-      // before the render code)
+      // Handle events
 
       clickedObject = NULL;
+
+      // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
+      // so that GLFW_PRESS and GLFW_RELEASE are only detected once
+      // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down continuously)
+      fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
+
       glfwPollEvents();
 
@@ -585,10 +590,19 @@
             selectedObject = &objects[1];
          }
-      }
-
-      /*
-      model[12] = last_position + speed*elapsed_seconds;
-      last_position = model[12];
-      */
+
+         /*
+         if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
+            //transformObject(objects[1], translate(mat4(), vec3(0.3f, 0.0f, 0.0f)), ubo);
+         }
+         if (key_pressed[GLFW_KEY_RIGHT]) {
+            transformObject(objects[2], translate(mat4(), vec3(0.01f, 0.0f, 0.0f)), ubo);
+         }
+         if (key_pressed[GLFW_KEY_LEFT]) {
+            transformObject(objects[2], translate(mat4(), vec3(-0.01f, 0.0f, 0.0f)), ubo);
+         }
+         */
+      }
+
+      // Render scene
 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -621,4 +635,5 @@
          cam_pos.x -= cos(cam_yaw)*dist;
          cam_pos.z += sin(cam_yaw)*dist;
+
          cam_moved = true;
       }
@@ -626,4 +641,5 @@
          cam_pos.x += cos(cam_yaw)*dist;
          cam_pos.z -= sin(cam_yaw)*dist;
+
          cam_moved = true;
       }
@@ -631,4 +647,5 @@
          cam_pos.x -= sin(cam_yaw)*dist;
          cam_pos.z -= cos(cam_yaw)*dist;
+
          cam_moved = true;
       }
@@ -636,4 +653,5 @@
          cam_pos.x += sin(cam_yaw)*dist;
          cam_pos.z += cos(cam_yaw)*dist;
+
          cam_moved = true;
       }
@@ -649,4 +667,5 @@
          T = translate(mat4(), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
          R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
+
          view_mat = R*T;
 
@@ -720,6 +739,5 @@
       if (closest_object == NULL) {
          cout << "No object was clicked" << endl;
-      }
-      else {
+      } else {
          clickedObject = closest_object;
          cout << "Clicked object: " << clickedObject->id << endl;
@@ -727,4 +745,12 @@
    }
 }
+
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+   key_state[key] = action;
+
+   // should be true for GLFW_PRESS and GLFW_REPEAT
+   key_pressed[key] = (action != GLFW_RELEASE);
+}
+
 
 GLuint loadShader(GLenum type, string file) {
@@ -819,6 +845,4 @@
    vec3 normal = vec3(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
 
-   print4DVector("Full world ray", world_ray);
-
    vec3 local_ray = (inverse(obj->model_mat) * world_ray).xyz();
    vec3 local_cam = (inverse(obj->model_mat) * cam).xyz();
@@ -827,11 +851,7 @@
 
    float d = -glm::dot(points[0], normal);
-   cout << "d: " << d << endl;
-
    float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
-   cout << "t: " << t << endl;
 
    vec3 intersection = local_cam + t*local_ray;
-   printVector("Intersection", intersection);
 
    if (insideTriangle(intersection, points)) {
@@ -842,4 +862,5 @@
    }
 }
+
 bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
    vec3 v21 = triangle_points[1] - triangle_points[0];
Index: texture.frag
===================================================================
--- texture.frag	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
+++ texture.frag	(revision f7d35dac677240a84b5a5c21202fc406d3227a0a)
@@ -29,5 +29,5 @@
 
   // diffuse intensity
-  vec3 Id = Ls * vec3(texel) * dot_prod;
+  vec3 Id = Ld * vec3(texel) * dot_prod;
 
   vec3 reflection_eye = reflect(-direction_to_light_eye, normal_eye);
