Index: TODO.txt
===================================================================
--- TODO.txt	(revision e3ca955539753579d1d53adbe352643c6127686e)
+++ TODO.txt	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
@@ -2,5 +2,4 @@
 ==========
 -Read the sections about shader debugging, starting from line 59
--Change the background to gray in case my square is being rendered in black
 
 TODO
@@ -15,4 +14,14 @@
 DONE
 ==========
--Print a warning if texture images don't sizes of 2^x
+-Print a warning if texture images don't have sizes of 2^x
 -Fix the texture-mapping code to not flip the texture upside down.
+
+NEW TODO
+==========
+-Unbind buffers (by binding to 0) once I'm done using them. This will help catch errors faster where I'm using a different buffer than I expect.
+-Show the fps in a gui component instead of printing it to the console
+
+New DONE
+==========
+-Move buffer memory allocation code into populateBuffers()
+-Go through the large design comment blocks and clean them up. Turn them into documentation for the code that's been written since I wrote the designs.
Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision e3ca955539753579d1d53adbe352643c6127686e)
+++ new-game.cpp	(revision 0d5c100c93d066c6ff7e51863a954be3a7465b43)
@@ -32,4 +32,5 @@
 #include <vector>
 #include <queue>
+#include <map>
 
 using namespace std;
@@ -63,6 +64,6 @@
 
 const bool FULLSCREEN = false;
-const bool SHOW_FPS = false;
-const bool DISABLE_VSYNC = true;
+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
 
@@ -81,5 +82,5 @@
 
 SceneObject* clickedObject = NULL;
-SceneObject* selectedObject;
+SceneObject* selectedObject = NULL;
 
 float NEAR_CLIP = 0.1f;
@@ -106,4 +107,14 @@
 
 void addObjectToScene(SceneObject& obj);
+void populateBuffers(vector<SceneObject>& objects,
+                     GLuint* points_vbo,
+                     GLuint* colors_vbo,
+                     GLuint* selected_colors_vbo,
+                     GLuint* texcoords_vbo,
+                     GLuint* normals_vbo,
+                     GLuint* ubo,
+                     GLuint* model_mat_idx_vbo,
+                     map<GLuint, unsigned int>& shaderCounts,
+                     map<GLuint, unsigned int>& curShaderBase);
 
 void renderMainMenu();
@@ -115,5 +126,7 @@
                   GLuint points_vbo, GLuint normals_vbo,
                   GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
-                  SceneObject* selectedObject);
+                  SceneObject* selectedObject,
+                  map<GLuint, unsigned int>& shaderCounts,
+                  map<GLuint, unsigned int>& curShaderBase);
 void renderSceneGui();
 
@@ -173,6 +186,6 @@
    * for every 1024 objects and then draws all those objects with one glDraw call.
    *
-   * Since I'm currently drawing all my objects dynamically (i.e switcing the shaders they use),
-   * I'll table the implementation of this algorithm until I have a reasonable number of objects always using the same shader
+   * Since I currently have very few objects, I'll wait to implement this  until I have
+   * a reasonable number of objects always using the same shader.
    */
 
@@ -232,29 +245,31 @@
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
-   // I can create a vbo to store all points for all models,
-   // and another vbo to store all colors for all models, but how do I allow alternating between
-   // using colors and textures for each model?
-   // Do I create a third vbo for texture coordinates and change which vertex attribute array I have bound
-   // when I want to draw a textured model?
-   // Or do I create one vao with vertices and colors and another with vertices and textures and switch between the two?
-   // Since I would have to switch shader programs to toggle between using colors or textures,
-   // I think I should use one vao for both cases and have a points vbo, a colors vbo, and a textures vbo
-   // One program will use the points and colors, and the other will use the points and texture coords
-   // Review how to bind vbos to vertex attributes in the shader.
-   //
-   // Binding vbos is done using glVertexAttribPointer(...) on a per-vao basis and is not tied to any specific shader.
-   // This means, I could create two vaos, one for each shader and have one use points+colors, while the other
-   // uses points+texxcoords.
-   //
-   // At some point, when I have lots of objects, I want to group them by shader when drawing them.
-   // I'd probably create some sort of set per shader and have each set contain the ids of all objects currently using that shader
-   // Most likely, I'd want to implement each set using a bit field. Makes it constant time for updates and iterating through them
-   // should not be much of an issue either.
-   // Assuming making lots of draw calls instead of one is not innefficient, I should be fine.
-   // I might also want to use one glDrawElements call per shader to draw multiple non-memory-adjacent models
-   //
-   // DECISION: Use a glDrawElements call per shader since I use a regular array to specify the elements to draw
-   // Actually, this will only work once I get UBOs working since each object will have a different model matrix
-   // For now, I could implement this with a glDrawElements call per object and update the model uniform for each object
+   /* RENDERING ALGORITHM
+    * 
+    * Create a separate vbo for each of the following things:
+    * - points
+    * - colors
+    * - texture coordinates
+    * - selected colors
+    * - normals
+    * - indices into a ubo that stores a model matrix for each object
+    *
+    * Also, make a model matrix ubo, the entirety of which will be passed to the vertex shader.
+    * The vbo containing the correct index into the ubo (mentioned above) will be used to select
+    * the right model matrix for each point. The index in the vbo will be the saem for all points
+    * of any given object.
+    *
+    * There will be two shader programs for now, one for draing colored objects, and another for
+    * drawing textured ones. The points, normals, and model mat ubo indices will be passed to both
+    * shaders, while the colors vbo will only be passed to the colors shader, and the texcoords vbo
+    * only to the texture shader.
+    *
+    * Right now, the currently selected object is drawn using one color (specified in the selected
+    * colors vbo) regardless of whether it is normally rendering using colors or a texture. The selected
+    * object is rendering by binding the selected colors vbo in place of the colors vbo and using the colors
+    * shader. Then, the selected object is redrawn along with all other objects, but the depth buffer test
+    * prevents the unselected version of the object from appearing on the screen. This lets me render all the
+    * objects that use a particular shader using one glDrawArrays() call.
+    */
 
    GLuint color_sp = loadShaderProgram("./color.vert", "./color.frag");
@@ -393,98 +408,19 @@
    GLsizeiptr offset;
 
-   GLsizeiptr points_buffer_size = 0;
-   GLsizeiptr textures_buffer_size = 0;
-   GLsizeiptr ubo_buffer_size = 0;
-   GLsizeiptr model_mat_idx_buffer_size = 0;
-
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      points_buffer_size += obj_it->points.size() * sizeof(GLfloat);
-      textures_buffer_size += obj_it->texcoords.size() * sizeof(GLfloat);
-      ubo_buffer_size += 16 * sizeof(GLfloat);
-      model_mat_idx_buffer_size += obj_it->num_points * sizeof(GLuint);
-   }
-
-   GLuint points_vbo = 0;
-   glGenBuffers(1, &points_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->points.size() * sizeof(GLfloat), &obj_it->points[0]);
-      offset += obj_it->points.size() * sizeof(GLfloat);
-   }
-
-   GLuint colors_vbo = 0;
-   glGenBuffers(1, &colors_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->colors.size() * sizeof(GLfloat), &obj_it->colors[0]);
-      offset += obj_it->colors.size() * sizeof(GLfloat);
-   }
-
-   GLuint selected_colors_vbo = 0;
-   glGenBuffers(1, &selected_colors_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->selected_colors.size() * sizeof(GLfloat), &obj_it->selected_colors[0]);
-      offset += obj_it->selected_colors.size() * sizeof(GLfloat);
-   }
-
-   GLuint texcoords_vbo = 0;
-   glGenBuffers(1, &texcoords_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
-   glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->texcoords.size() * sizeof(GLfloat), &obj_it->texcoords[0]);
-      offset += obj_it->texcoords.size() * sizeof(GLfloat);
-   }
-
-   GLuint normals_vbo = 0;
-   glGenBuffers(1, &normals_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->normals.size() * sizeof(GLfloat), &obj_it->normals[0]);
-      offset += obj_it->normals.size() * sizeof(GLfloat);
-   }
-   glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
-   GLuint ubo = 0;
-   glGenBuffers(1, &ubo);
-   glBindBuffer(GL_UNIFORM_BUFFER, ubo);
-   glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_UNIFORM_BUFFER, offset, sizeof(obj_it->model_mat), value_ptr(obj_it->model_mat));
-      offset += sizeof(obj_it->model_mat);
-   }
-   glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
-   GLuint model_mat_idx_vbo = 0;
-   glGenBuffers(1, &model_mat_idx_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
-   glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   unsigned int idx = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      for (int i = 0; i < obj_it->num_points; i++) {
-         glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(GLuint), &idx);
-         offset += sizeof(GLuint);
-      }
-      idx++;
-   }
+   GLuint points_vbo, colors_vbo, selected_colors_vbo, texcoords_vbo,
+      normals_vbo, ubo, model_mat_idx_vbo;
+
+   map<GLuint, unsigned int> shaderCounts, curShaderBase;
+
+   populateBuffers(objects,
+                  &points_vbo,
+                  &colors_vbo,
+                  &selected_colors_vbo,
+                  &texcoords_vbo,
+                  &normals_vbo,
+                  &ubo,
+                  &model_mat_idx_vbo,
+                  shaderCounts,
+                  curShaderBase);
 
    GLuint vao = 0;
@@ -593,5 +529,4 @@
    //glPolygonMode(GL_FRONT, GL_LINE);
 
-   // disable vsync to see real framerate
    if (DISABLE_VSYNC && SHOW_FPS) {
       glfwSwapInterval(0);
@@ -670,5 +605,6 @@
                points_vbo, normals_vbo,
                colors_vbo, texcoords_vbo, selected_colors_vbo,
-               selectedObject);
+               selectedObject,
+               shaderCounts, curShaderBase);
             renderSceneGui();
             break;
@@ -762,20 +698,19 @@
       SceneObject* closest_object = NULL;
 
-      SceneObject* obj;
       for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
-         obj = &*it;
-
          for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
-            if (faceClicked({
-               vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
-               vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
-               vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
+            if (faceClicked(
+               {
+                  vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
+                  vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
+                  vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
                },
-               obj, ray_world, cam_pos_temp, click_point)) {
+               &*it, ray_world, cam_pos_temp, click_point
+            )) {
                click_point = view_mat * click_point;
 
                if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
                   closest_point = click_point.xyz();
-                  closest_object = obj;
+                  closest_object = &*it;
                }
             }
@@ -926,25 +861,164 @@
 }
 
-// The easiest thing here seems to be to set all the colors we want in a CPU array once per frame,
-// them copy it over to the GPU and make one draw call
-// This method also easily allows us to use any colors we want for each shape.
-// Try to compare the frame times for the current method and the new one
-//
-// Alternatively, I have one large color buffer that has selected and unselected colors
-// Then, when I know which object is selected, I can use glVertexAttribPointer to decide
-// whether to use the selected or unselected color for it
-
-// I'll have to think of the best way to do something similar when using
-// one draw call. Probably, in that case, I'll use one draw call for all unselectable objects
-// and use the approach mentioned above for all selectable objects.
-// I can have one colors vbo for unselectable objects and another for selected+unselected colors
-// of selectable objects
-
-// For both colored and textured objects, using a single draw call will only work for objects
-// that don't change state (i.e. don't change colors or switch from colored to textured).
-
-// This means I'll probably have one call for static colored objects, one call for static textured objects,
-// a loop of calls for dynamic currently colored objects, and a loop of calls for dynamic currently textured objects.
-// This will increase if I add new shaders since I'll need either one new call or one new loop of calls per shader
+void addObjectToScene(SceneObject& obj) {
+   obj.id = objects.size(); // currently unused
+   obj.num_points = obj.points.size() / 3;
+
+   obj.normals.reserve(obj.points.size());
+   for (int i = 0; i < obj.points.size(); i += 9) {
+      vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
+      vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
+      vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
+
+      vec3 normal = normalize(cross(point2 - point1, point3 - point1));
+
+      // Add the same normal for all 3 points
+      for (int j = 0; j < 3; j++) {
+         obj.normals.push_back(normal.x);
+         obj.normals.push_back(normal.y);
+         obj.normals.push_back(normal.z);
+      }
+   }
+
+   objects.push_back(obj);
+}
+
+void populateBuffers(vector<SceneObject>& objects,
+                     GLuint* points_vbo,
+                     GLuint* colors_vbo,
+                     GLuint* selected_colors_vbo,
+                     GLuint* texcoords_vbo,
+                     GLuint* normals_vbo,
+                     GLuint* ubo,
+                     GLuint* model_mat_idx_vbo,
+                     map<GLuint, unsigned int>& shaderCounts,
+                     map<GLuint, unsigned int>& curShaderBase) {
+   GLsizeiptr points_buffer_size = 0;
+   GLsizeiptr textures_buffer_size = 0;
+   GLsizeiptr ubo_buffer_size = 0;
+   GLsizeiptr model_mat_idx_buffer_size = 0;
+
+   map<GLuint, unsigned int> curShaderOffset;
+
+   map<GLuint, unsigned int> shaderUboCounts;
+   map<GLuint, unsigned int> curShaderUboBase;
+   map<GLuint, unsigned int> curShaderUboOffset;
+
+   vector<SceneObject>::iterator it;
+
+   /* Find all shaders that need to be used and  the number of objects and
+    * number of points for each shader. Construct a map from shader id to count
+    * of points being drawn using that shader (for thw model matrix ubo, we
+    * need object counts instead). These will be used to get offsets into the
+    * vertex buffer for each shader.
+    */
+   for (it = objects.begin(); it != objects.end(); it++) {
+      points_buffer_size += it->points.size() * sizeof(GLfloat);
+      textures_buffer_size += it->texcoords.size() * sizeof(GLfloat);
+      ubo_buffer_size += 16 * sizeof(GLfloat);
+      model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
+
+      if (shaderCounts.count(it->shader_program) == 0) {
+         shaderCounts[it->shader_program] = it->num_points;
+         shaderUboCounts[it->shader_program] = 1;
+      } else {
+         shaderCounts[it->shader_program] += it->num_points;
+         shaderUboCounts[it->shader_program]++;
+      }
+   }
+
+   map<GLuint, unsigned int>::iterator shaderIt;
+   unsigned int lastShaderCount = 0;
+   unsigned int lastShaderUboCount = 0;
+
+   /*
+    * The counts calculated above can be used to get the starting offset of
+    * each shader in the vertex buffer. Create a map of base offsets to mark
+    * where the data for the first object using a given shader begins. Also,
+    * create a map of current offsets to mark where to copy data for the next
+    * object being added.
+    */
+   cout << "Shader counts:" << endl;
+   for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
+      curShaderOffset[shaderIt->first] = 0;
+      curShaderUboOffset[shaderIt->first] = 0;
+
+      curShaderBase[shaderIt->first] = lastShaderCount;
+      lastShaderCount += shaderCounts[shaderIt->first];
+
+      curShaderUboBase[shaderIt->first] = lastShaderUboCount;
+      lastShaderUboCount += shaderUboCounts[shaderIt->first];
+   }
+
+   // Initialize all the buffers using the counts calculated above
+
+   *points_vbo = 0;
+   glGenBuffers(1, points_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *colors_vbo = 0;
+   glGenBuffers(1, colors_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *selected_colors_vbo = 0;
+   glGenBuffers(1, selected_colors_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *texcoords_vbo = 0;
+   glGenBuffers(1, texcoords_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
+   glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *normals_vbo = 0;
+   glGenBuffers(1, normals_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *ubo = 0;
+   glGenBuffers(1, ubo);
+   glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
+   glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   *model_mat_idx_vbo = 0;
+   glGenBuffers(1, model_mat_idx_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
+   glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   GLint vertex_ubo_offset;
+   for (it = objects.begin(); it != objects.end(); it++) {
+      it->vertex_vbo_offset = curShaderBase[it->shader_program] + curShaderOffset[it->shader_program];
+      vertex_ubo_offset = curShaderUboBase[it->shader_program] + curShaderUboOffset[it->shader_program];
+
+      glBindBuffer(GL_ARRAY_BUFFER, *points_vbo);
+      glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->points.size() * sizeof(GLfloat), &it->points[0]);
+
+      glBindBuffer(GL_ARRAY_BUFFER, *colors_vbo);
+      glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->colors.size() * sizeof(GLfloat), &it->colors[0]);
+
+      glBindBuffer(GL_ARRAY_BUFFER, *selected_colors_vbo);
+      glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->selected_colors.size() * sizeof(GLfloat), &it->selected_colors[0]);
+
+      glBindBuffer(GL_ARRAY_BUFFER, *texcoords_vbo);
+      glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 2, it->texcoords.size() * sizeof(GLfloat), &it->texcoords[0]);
+
+      glBindBuffer(GL_ARRAY_BUFFER, *normals_vbo);
+      glBufferSubData(GL_ARRAY_BUFFER, it->vertex_vbo_offset * sizeof(GLfloat) * 3, it->normals.size() * sizeof(GLfloat), &it->normals[0]);
+
+      glBindBuffer(GL_ARRAY_BUFFER, *model_mat_idx_vbo);
+      for (int i = 0; i < it->num_points; i++) {
+         glBufferSubData(GL_ARRAY_BUFFER, (it->vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &vertex_ubo_offset);
+      }
+
+      curShaderOffset[it->shader_program] += it->num_points;
+
+      glBindBuffer(GL_UNIFORM_BUFFER, *ubo);
+      glBufferSubData(GL_UNIFORM_BUFFER, vertex_ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(it->model_mat));
+
+      curShaderUboOffset[it->shader_program]++;
+   }
+}
 
 void renderScene(vector<SceneObject>& objects,
@@ -953,30 +1027,16 @@
                   GLuint points_vbo, GLuint normals_vbo,
                   GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
-                  SceneObject* selectedObject) {
-
-   vector<int> colored_objs, selected_objs, textured_objs;
-
-   // group scene objects by shader and vbo
-   for (unsigned int i = 0; i < objects.size(); i++) {
-      if (selectedObject == &objects[i]) {
-         selected_objs.push_back(i);
-      }
-      if (objects[i].shader_program == color_sp) {
-         colored_objs.push_back(i);
-      } else if (objects[i].shader_program == texture_sp) {
-         textured_objs.push_back(i);
-      }
-   }
-
-   vector<int>::iterator it;
+                  SceneObject* selectedObject,
+                  map<GLuint, unsigned int>& shaderCounts,
+                  map<GLuint, unsigned int>& curShaderBase) {
 
    glUseProgram(color_sp);
    glBindVertexArray(vao1);
 
-   glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
-   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
-
-   for (it = selected_objs.begin(); it != selected_objs.end(); it++) {
-      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
+   if (selectedObject != NULL) {
+      glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
+      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+      glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
    }
 
@@ -984,14 +1044,10 @@
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
-   for (it = colored_objs.begin(); it != colored_objs.end(); it++) {
-      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
-   }
+   glDrawArrays(GL_TRIANGLES, curShaderBase[color_sp], shaderCounts[color_sp]);
 
    glUseProgram(texture_sp);
    glBindVertexArray(vao2);
 
-   for (it = textured_objs.begin(); it != textured_objs.end(); it++) {
-      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
-   }
+   glDrawArrays(GL_TRIANGLES, curShaderBase[texture_sp], shaderCounts[texture_sp]);
 }
 
@@ -1051,31 +1107,4 @@
 }
 
-void addObjectToScene(SceneObject& obj) {
-   obj.id = objects.size(); // currently unused
-   obj.num_points = obj.points.size() / 3;
-
-   static GLint vbo_offset = 0;
-   obj.vertex_vbo_offset = vbo_offset;
-   vbo_offset += obj.num_points;
-
-   obj.normals.reserve(obj.points.size());
-   for (int i = 0; i < obj.points.size(); i += 9) {
-      vec3 point1 = vec3(obj.points[i], obj.points[i+1], obj.points[i + 2]);
-      vec3 point2 = vec3(obj.points[i+3], obj.points[i + 4], obj.points[i + 5]);
-      vec3 point3 = vec3(obj.points[i+6], obj.points[i + 7], obj.points[i + 8]);
-
-      vec3 normal = normalize(cross(point2 - point1, point3 - point1));
-
-      // Add the same normal for all 3 points
-      for (int j = 0; j < 3; j++) {
-         obj.normals.push_back(normal.x);
-         obj.normals.push_back(normal.y);
-         obj.normals.push_back(normal.z);
-      }
-   }
-
-   objects.push_back(obj);
-}
-
 void renderMainMenu() {
 }
