Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision 612d1f6169693232d03c30388f8a5c8f88f1e010)
+++ new-game.cpp	(revision e9347b4781a33614fabee5ff0cae384ad1816004)
@@ -95,6 +95,6 @@
 unsigned char* loadImage(string file_name, int* x, int* y);
 
-void printVector(string label, vec3 v);
-void print4DVector(string label, vec4 v);
+void printVector(string label, vec3& v);
+void print4DVector(string label, vec4& v);
 
 void initObject(SceneObject& obj);
@@ -146,4 +146,6 @@
 
 void translateLaser(SceneObject& laser, const vec3& translation, GLuint ubo);
+void updateLaserTarget(SceneObject& laser, vector<SceneObject>& objects, GLuint points_vbo);
+bool getLaserAndAsteroidIntersection(vec3& start, vec3& end, SceneObject& asteroid, vec3& intersection);
 
 void renderMainMenu();
@@ -215,5 +217,6 @@
 
 /*
-* TODO: Asteroid movement currently depends on framerate, fix this in a generic/reusable way
+* TODO: Asteroid and ship movement currently depend on framerate, fix this in a generic/reusable way
+* Disabling vsync is a great way to test this
 */
 
@@ -1005,5 +1008,6 @@
          elapsed_seconds_spawn += elapsed_seconds;
          if (elapsed_seconds_spawn > 0.5f) {
-            spawnAsteroid(vec3(getRandomNum(-1.3f, 1.3f), getRandomNum(-3.0f, -1.0f), getRandomNum(-5.5f, -4.5f)), color_sp,
+            //spawnAsteroid(vec3(getRandomNum(-1.3f, 1.3f), getRandomNum(-3.0f, -1.0f), getRandomNum(-5.5f, -4.5f)), color_sp,
+            spawnAsteroid(vec3(getRandomNum(-1.3f, 1.3f), -1.2f, getRandomNum(-5.5f, -4.5f)), color_sp,
                shaderBufferInfo,
                points_vbo,
@@ -1042,8 +1046,8 @@
             transformObject(objects[0], translate(mat4(1.0f), vec3(0.01f, 0.0f, 0.0f)), ubo);
 
-            if (leftLaserIdx != -1) {
+            if (leftLaserIdx != -1 && !objects[leftLaserIdx].deleted) {
                translateLaser(objects[leftLaserIdx], vec3(0.01f, 0.0f, 0.0f), ubo);
             }
-            if (rightLaserIdx != -1) {
+            if (rightLaserIdx != -1 && !objects[rightLaserIdx].deleted) {
                translateLaser(objects[rightLaserIdx], vec3(0.01f, 0.0f, 0.0f), ubo);
             }
@@ -1052,8 +1056,8 @@
             transformObject(objects[0], translate(mat4(1.0f), vec3(-0.01f, 0.0f, 0.0f)), ubo);
 
-            if (leftLaserIdx != -1) {
+            if (leftLaserIdx != -1 && !objects[leftLaserIdx].deleted) {
                translateLaser(objects[leftLaserIdx], vec3(-0.01f, 0.0f, 0.0f), ubo);
             }
-            if (rightLaserIdx != -1) {
+            if (rightLaserIdx != -1 && !objects[rightLaserIdx].deleted) {
                translateLaser(objects[rightLaserIdx], vec3(-0.01f, 0.0f, 0.0f), ubo);
             }
@@ -1109,7 +1113,9 @@
          }
 
-         // TODO: Probablu remove this since it was only added to test that object removal owrks
-         if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
-            removeObjectFromScene(objects[0], ubo);
+         if (leftLaserIdx != -1 && !objects[leftLaserIdx].deleted) {
+            updateLaserTarget(objects[leftLaserIdx], objects, points_vbo);
+         }
+         if (rightLaserIdx != -1 && !objects[rightLaserIdx].deleted) {
+            updateLaserTarget(objects[rightLaserIdx], objects, points_vbo);
          }
       }
@@ -1400,9 +1406,9 @@
 }
 
-void printVector(string label, vec3 v) {
+void printVector(string label, vec3& v) {
    cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
 }
 
-void print4DVector(string label, vec4 v) {
+void print4DVector(string label, vec4& v) {
    cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
 }
@@ -1535,5 +1541,6 @@
    GLfloat radius_z = max_z - obj.bounding_center.z;
 
-   // This actually underestimates the radius. Might need to be fixed at some point.
+   // TODO: This actually underestimates the radius. Might need to be fixed at some point.
+   // TODO: Does not take into account any scaling in the model matrix
    obj.bounding_radius = radius_x;
    if (obj.bounding_radius < radius_y)
@@ -1857,7 +1864,5 @@
 
 void translateLaser(SceneObject& laser, const vec3& translation, GLuint ubo) {
-   if (laser.deleted) return;
-
-   // TODO: A lot of the values I calculate here can be calculated once and saved when the laser is created,
+   // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
    // and then re-used here
 
@@ -1865,5 +1870,5 @@
 
    vec3 start = vec3(laser.model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
-   vec3 end = vec3(laser.model_transform * vec4(0.0f, 0.0f, laser.points[2] + laser.points[20], 1.0f));
+   vec3 end = vec3(laser.model_transform * vec4(0.0f, 0.0f, laser.points[38], 1.0f));
 
    vec3 ray = end - start;
@@ -1887,4 +1892,91 @@
 
    transformObject(laser, translate(mat4(1.0f), translation), ubo);
+}
+
+void updateLaserTarget(SceneObject& laser, vector<SceneObject>& objects, GLuint points_vbo) {
+   // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
+   // and then re-used here
+
+   vec3 start = vec3(laser.model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
+   vec3 end = vec3(laser.model_transform * vec4(0.0f, 0.0f, laser.points[2] + laser.points[20], 1.0f));
+
+   vec3 intersection(0.0f), closestIntersection(0.0f);
+   SceneObject* closestAsteroid = NULL;
+
+   for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
+      if (it->type == TYPE_ASTEROID && !it->deleted && getLaserAndAsteroidIntersection(start, end, *it, intersection)) {
+         // TODO: Implement a more generic algorithm for testing the closest object by getting the distance between the points
+         if (closestAsteroid == NULL || intersection.z > closestIntersection.z) {
+            // TODO: At this point, find the real intersection of the laser with one of the asteroid's sides
+            closestAsteroid = &*it;
+            closestIntersection = intersection;
+         }
+      }
+   }
+
+   float width = laser.points[0] - laser.points[2];
+
+   float length = 5.24f;
+   if (closestAsteroid != NULL) {
+      length = glm::length(closestIntersection - start);
+   }
+
+   laser.points[20] = -length + width / 2;
+   laser.points[23] = -length + width / 2;
+   laser.points[29] = -length + width / 2;
+   laser.points[38] = -length;
+   laser.points[41] = -length;
+   laser.points[44] = -length + width / 2;
+   laser.points[47] = -length;
+   laser.points[50] = -length + width / 2;
+   laser.points[53] = -length + width / 2;
+
+   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
+   glBufferSubData(GL_ARRAY_BUFFER, laser.vertex_vbo_offset * sizeof(GLfloat) * 3, laser.points.size() * sizeof(GLfloat), &laser.points[0]);
+}
+
+bool getLaserAndAsteroidIntersection(vec3& start, vec3& end, SceneObject& asteroid, vec3& intersection) {
+   /*
+   ### LINE EQUATIONS ###
+   x = x1 + u * (x2 - x1)
+   y = y1 + u * (y2 - y1)
+   z = z1 + u * (z2 - z1)
+
+   ### SPHERE EQUATION ###
+   (x - x3)^2 + (y - y3)^2 + (z - z3)^2 = r^2
+
+   ### QUADRATIC EQUATION TO SOLVE ###
+   a*u^2 + b*u + c = 0
+   WHERE THE CONSTANTS ARE
+   a = (x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2
+   b = 2*( (x2 - x1)*(x1 - x3) + (y2 - y1)*(y1 - y3) + (z2 - z1)*(z1 - z3) )
+   c = x3^2 + y3^2 + z3^2 + x1^2 + y1^2 + z1^2 - 2(x3*x1 + y3*y1 + z3*z1) - r^2
+
+   u = (-b +- sqrt(b^2 - 4*a*c)) / 2a
+
+   If the value under the root is >= 0, we got an intersection
+   If the value > 0, there are two solutions. Take the one closer to 0, since that's the
+   one closer to the laser start point
+   */
+
+   vec3& center = asteroid.bounding_center;
+
+   float a = pow(end.x-start.x, 2) + pow(end.y-start.y, 2) + pow(end.z-start.z, 2);
+   float b = 2*((start.x-end.x)*(start.x-center.x) + (end.y-start.y)*(start.y-center.y) + (end.z-start.z)*(start.z-center.z));
+   float c = pow(center.x, 2) + pow(center.y, 2) + pow(center.z, 2) + pow(start.x, 2) + pow(start.y, 2) + pow(start.z, 2) - 2*(center.x*start.x + center.y*start.y + center.z*start.z) - pow(asteroid.bounding_radius, 2);
+   float discriminant = pow(b, 2) - 4*a*c;
+
+   if (discriminant >= 0.0f) {
+      // In this case, the negative root will always give the point closer to the laser start point
+      float u = (-b - sqrt(discriminant)) / (2 * a);
+
+      // Check that the intersection is within the line segment corresponding to the laser
+      if (0.0f <= u && u <= 1.0f) {
+         intersection = start + u * (end - start);
+         return true;
+      }
+   }
+
+   return false;
 }
 
@@ -2137,4 +2229,11 @@
 
    initObject(obj);
+   // This accounts for the scaling in model_base.
+   // Dividing by 8 instead of 10 since the bounding radius algorithm
+   // under-calculates the true value.
+   // TODO: Once the intersection check with the sides of the asteroid is done,
+   // this can be removed.
+   obj.bounding_radius /= 8.0f;
+
    addObjectToScene(obj, shaderBufferInfo,
                   points_vbo,
