Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision 49db5fc3bf58103571921feba975a9450206b5bf)
+++ new-game.cpp	(revision b220f7851c4ed247babdc756bef7299c365b7e40)
@@ -107,4 +107,5 @@
 
    // TODO: Why not just use an initializer list for all the instance variables
+   // TODO: Maybe pass in startTime instead of calling glfwGetTime() here
    EffectOverTime(float& effectedValue, float changePerSecond, SceneObject* object)
       : effectedValue(effectedValue), changePerSecond(changePerSecond), effectedObject(object) {
@@ -186,4 +187,5 @@
 void initModelGroupAttribs(ShaderModelGroup& modelGroup);
 void bindUniformData(AttribInfo& attrib);
+void bindUniformData(AttribInfo& attrib, GLfloat* data);
 
 size_t GLsizeof(GLenum);
@@ -201,5 +203,5 @@
                   GLuint* model_mat_idx_vbo);
 
-void initializeParticleEffectBuffers(vec3 origin, mat4 proj, mat4 view,
+void initializeParticleEffectBuffers(vec3 origin,
                   map<GLuint, BufferInfo>& shaderBufferInfo,
                   map<ObjectType, ShaderModelGroup>& modelGroups,
@@ -478,4 +480,5 @@
 
    GLfloat laserColor[3] = {0.2f, 1.0f, 0.2f};
+   GLfloat curTime, prevTime, elapsedTime;
 
    GLuint points_vbo, colors_vbo, texcoords_vbo, normals_vbo, ubo, model_mat_idx_vbo;
@@ -600,4 +603,26 @@
    shaderBufferInfo[modelGroups[TYPE_EXPLOSION].shaderProgram] = BufferInfo(); // temporary
 
+   // The last parameter (offset) is only used for populating the buffers since the distance
+   // between each item is needed there. However, that code isn't run for explosions right now anyway,
+   // so I may as well pass in 0 here.
+   defineModelGroupAttrib(modelGroups[TYPE_EXPLOSION], "v_i", ATTRIB_POINT_VARYING,
+      3, GL_FLOAT, 0);
+   defineModelGroupAttrib(modelGroups[TYPE_EXPLOSION], "start_time", ATTRIB_POINT_VARYING,
+      1, GL_FLOAT, 0);
+
+   defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "explosion_start_time", ATTRIB_UNIFORM,
+      1, UNIFORM_1F, &curTime);
+   defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "cur_time", ATTRIB_UNIFORM,
+      1, UNIFORM_1F, &curTime);
+   defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "model_mat", ATTRIB_UNIFORM,
+      1, UNIFORM_MATRIX_4F, NULL);
+   defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "view", ATTRIB_UNIFORM,
+      1, UNIFORM_MATRIX_4F, value_ptr(view_mat));
+   defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "proj", ATTRIB_UNIFORM,
+      1, UNIFORM_MATRIX_4F, value_ptr(proj_mat));
+   // Still need to do the model mat
+
+  initModelGroupAttribs(modelGroups[TYPE_EXPLOSION]);
+
    cam_pos = vec3(0.0f, 0.0f, 2.0f);
    float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
@@ -651,5 +676,5 @@
    proj_mat = make_mat4(proj_arr);
 
-   initializeParticleEffectBuffers(vec3(0.0f, -1.2f, 0.65f), proj_mat, view_mat,
+   initializeParticleEffectBuffers(vec3(0.0f, -1.2f, 0.65f),
       shaderBufferInfo,
       modelGroups,
@@ -703,6 +728,4 @@
    GLuint laser_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_LASER].shaderProgram, "models");
 
-   GLuint explosion_start_time_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "explosion_start_time");
-   GLuint cur_time_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "cur_time");
    GLuint explosion_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_EXPLOSION].shaderProgram, "models");
 
@@ -746,5 +769,6 @@
    double elapsed_seconds_fps = 0.0f;
    double elapsed_seconds_spawn = 0.0f;
-   double previous_seconds = glfwGetTime();
+
+   prevTime = glfwGetTime();
 
    // This draws wireframes. Useful for seeing separate faces and occluded objects.
@@ -757,15 +781,15 @@
 
    while (!glfwWindowShouldClose(window) && isRunning) {
-      double current_seconds = glfwGetTime();
-      double elapsed_seconds = current_seconds - previous_seconds;
+      curTime = glfwGetTime();
+      elapsedTime = curTime - prevTime;
 
       // temporary code to get around vsync issue in OSX Sierra
-      if (elapsed_seconds < (1.0f / TARGET_FPS)) {
+      if (elapsedTime < (1.0f / TARGET_FPS)) {
         continue;
       }
 
-      previous_seconds = current_seconds;
-
-      elapsed_seconds_fps += elapsed_seconds;
+      prevTime = curTime;
+
+      elapsed_seconds_fps += elapsedTime;
       if (elapsed_seconds_fps > 0.25f) {
          fps = (double)frame_count / elapsed_seconds_fps;
@@ -806,5 +830,5 @@
       if (curState == STATE_GAME) {
 
-         elapsed_seconds_spawn += elapsed_seconds;
+         elapsed_seconds_spawn += elapsedTime;
          if (elapsed_seconds_spawn > 0.5f) {
             SceneObject* obj = createAsteroid(vec3(getRandomNum(-1.3f, 1.3f), -1.2f, getRandomNum(-5.5f, -4.5f)));
@@ -918,13 +942,10 @@
 
                   objExplosion->model_mat = model_mat;
-                  GLfloat curTime = glfwGetTime();
 
                   // initiate an explosion
                   glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 
-                  GLuint model_mat_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "model_mat");
-                  glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, value_ptr(objExplosion->model_mat));
-
-                  glUniform1f(explosion_start_time_loc, (GLfloat)glfwGetTime());
+                  bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["explosion_start_time"]);
+                  bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["model_mat"], value_ptr(objExplosion->model_mat));
                }
             }
@@ -945,5 +966,5 @@
          } else {
             EffectOverTime* eot = *it;
-            eot->effectedValue = eot->startValue + (current_seconds - eot->startTime) * eot->changePerSecond;
+            eot->effectedValue = eot->startValue + (curTime - eot->startTime) * eot->changePerSecond;
 
             it++;
@@ -955,5 +976,5 @@
       }
 
-      float dist = cam_speed * elapsed_seconds;
+      float dist = cam_speed * elapsedTime;
       if (key_down[GLFW_KEY_A]) {
          vec3 dir = vec3(inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f));
@@ -982,17 +1003,17 @@
       /*
       if (key_down[GLFW_KEY_LEFT]) {
-      cam_yaw += cam_yaw_speed * elapsed_seconds;
+      cam_yaw += cam_yaw_speed * elapsedTime;
       cam_moved = true;
       }
       if (key_down[GLFW_KEY_RIGHT]) {
-      cam_yaw -= cam_yaw_speed * elapsed_seconds;
+      cam_yaw -= cam_yaw_speed * elapsedTime;
       cam_moved = true;
       }
       if (key_down[GLFW_KEY_UP]) {
-      cam_pitch += cam_pitch_speed * elapsed_seconds;
+      cam_pitch += cam_pitch_speed * elapsedTime;
       cam_moved = true;
       }
       if (key_down[GLFW_KEY_DOWN]) {
-      cam_pitch -= cam_pitch_speed * elapsed_seconds;
+      cam_pitch -= cam_pitch_speed * elapsedTime;
       cam_moved = true;
       }
@@ -1017,5 +1038,5 @@
 
       glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
-      glUniform1f(cur_time_loc, (GLfloat)current_seconds);
+      bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["cur_time"]);
 
       // Render scene
@@ -2032,8 +2053,26 @@
          break;
       case UNIFORM_1F:
-         glUniform3fv(attrib.buffer, attrib.size, attrib.data);
+         glUniform1fv(attrib.buffer, attrib.size, attrib.data);
          break;
       case UNIFORM_3F:
          glUniform3fv(attrib.buffer, attrib.size, attrib.data);
+         break;
+      case UNIFORM_NONE:
+         break;
+   }
+}
+
+void bindUniformData(AttribInfo& attrib, GLfloat *data) {
+   switch(attrib.uniType) {
+      case UNIFORM_MATRIX_4F:
+         glUniformMatrix4fv(attrib.buffer, attrib.size, GL_FALSE, data);
+         break;
+      case UNIFORM_1F:
+         glUniform1fv(attrib.buffer, attrib.size, data);
+         break;
+      case UNIFORM_3F:
+         glUniform3fv(attrib.buffer, attrib.size, data);
+         break;
+      case UNIFORM_NONE:
          break;
    }
@@ -2097,5 +2136,5 @@
 }
 
-void initializeParticleEffectBuffers(vec3 origin, mat4 proj, mat4 view,
+void initializeParticleEffectBuffers(vec3 origin,
                   map<GLuint, BufferInfo>& shaderBufferInfo,
                   map<ObjectType, ShaderModelGroup>& modelGroups,
@@ -2125,33 +2164,26 @@
    glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 
-   GLuint proj_mat_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "proj");
-   GLuint view_mat_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "view");
-
-   glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj));
-   glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view));
-
-   GLuint model_mat_loc = glGetUniformLocation(modelGroups[TYPE_EXPLOSION].shaderProgram, "model_mat");
-
-   glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, value_ptr(model_mat));
+   bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["proj"]);
+   bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["view"]);
+   bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["model_mat"], value_ptr(model_mat));
 
    GLuint velocity_vbo;
    glGenBuffers(1, &velocity_vbo);
+
+   GLuint time_vbo;
+   glGenBuffers(1, &time_vbo);
+
+   glBindVertexArray(modelGroups[TYPE_EXPLOSION].vao);
+
+   // the glBufferData and glVertexAttribPointer need to stay here while the corresponding arrays
+   // are local to this function. Once they're made part of the explosion object, I might be able
+   // to move this code out of here
+
    glBindBuffer(GL_ARRAY_BUFFER, velocity_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vv), vv, GL_STATIC_DRAW);
-
-   GLuint time_vbo;
-   glGenBuffers(1, &time_vbo);
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
+
    glBindBuffer(GL_ARRAY_BUFFER, time_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vt), vt, GL_STATIC_DRAW);
-
-   glBindVertexArray(modelGroups[TYPE_EXPLOSION].vao);
-
-   glEnableVertexAttribArray(0);
-   glEnableVertexAttribArray(1);
-
-   glBindBuffer(GL_ARRAY_BUFFER, velocity_vbo);
-   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
-
-   glBindBuffer(GL_ARRAY_BUFFER, time_vbo);
    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, NULL);
 
@@ -2772,4 +2804,4 @@
 
 float getRandomNum(float low, float high) {
-   return low + ((float)rand()/RAND_MAX) * (high-low);
-}
+   return low + ((float)rand() / RAND_MAX) * (high-low);
+}
