| [22b2c37] | 1 | #include "logger.h"
 | 
|---|
| [5272b6b] | 2 | 
 | 
|---|
| [485424b] | 3 | #include "stb_image.h"
 | 
|---|
 | 4 | 
 | 
|---|
| [4e0b82b] | 5 | // I think this was for the OpenGL 4 book font file tutorial
 | 
|---|
 | 6 | //#define STB_IMAGE_WRITE_IMPLEMENTATION
 | 
|---|
 | 7 | //#include "stb_image_write.h"
 | 
|---|
 | 8 | 
 | 
|---|
| [1099b95] | 9 | #define _USE_MATH_DEFINES
 | 
|---|
| [5c9d193] | 10 | 
 | 
|---|
| [c62eee6] | 11 | #include <glm/mat4x4.hpp>
 | 
|---|
| [7ee66ea] | 12 | #include <glm/gtc/matrix_transform.hpp>
 | 
|---|
 | 13 | #include <glm/gtc/type_ptr.hpp>
 | 
|---|
 | 14 | 
 | 
|---|
| [c1ca5b5] | 15 | #include "IMGUI/imgui.h"
 | 
|---|
 | 16 | #include "imgui_impl_glfw_gl3.h"
 | 
|---|
 | 17 | 
 | 
|---|
| [5272b6b] | 18 | #include <GL/glew.h>
 | 
|---|
 | 19 | #include <GLFW/glfw3.h>
 | 
|---|
 | 20 | 
 | 
|---|
| [22b2c37] | 21 | #include <cstdio>
 | 
|---|
| [5527206] | 22 | #include <cstdlib>
 | 
|---|
 | 23 | #include <ctime>
 | 
|---|
| [22b2c37] | 24 | #include <iostream>
 | 
|---|
| [ec4456b] | 25 | #include <fstream>
 | 
|---|
| [1f3d32b] | 26 | #include <sstream>
 | 
|---|
| [93baa0e] | 27 | #include <cmath>
 | 
|---|
| [1099b95] | 28 | #include <string>
 | 
|---|
| [19c9338] | 29 | #include <array>
 | 
|---|
| [df652d5] | 30 | #include <vector>
 | 
|---|
| [93462c6] | 31 | #include <queue>
 | 
|---|
| [0d5c100] | 32 | #include <map>
 | 
|---|
| [22b2c37] | 33 | 
 | 
|---|
| [5272b6b] | 34 | using namespace std;
 | 
|---|
| [7ee66ea] | 35 | using namespace glm;
 | 
|---|
 | 36 | 
 | 
|---|
| [92b1e90] | 37 | enum State {
 | 
|---|
 | 38 |    STATE_MAIN_MENU,
 | 
|---|
 | 39 |    STATE_GAME,
 | 
|---|
 | 40 | };
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | enum Event {
 | 
|---|
 | 43 |    EVENT_GO_TO_MAIN_MENU,
 | 
|---|
 | 44 |    EVENT_GO_TO_GAME,
 | 
|---|
 | 45 |    EVENT_QUIT,
 | 
|---|
 | 46 | };
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | enum ObjectType {
 | 
|---|
 | 49 |    TYPE_SHIP,
 | 
|---|
 | 50 |    TYPE_ASTEROID,
 | 
|---|
 | 51 |    TYPE_LASER,
 | 
|---|
| [646f3f2] | 52 |    TYPE_EXPLOSION,
 | 
|---|
| [92b1e90] | 53 | };
 | 
|---|
 | 54 | 
 | 
|---|
| [a0eb547] | 55 | enum AttribType {
 | 
|---|
 | 56 |    ATTRIB_UNIFORM,
 | 
|---|
 | 57 |    ATTRIB_OBJECT_VARYING,
 | 
|---|
 | 58 |    ATTRIB_POINT_VARYING,
 | 
|---|
 | 59 | };
 | 
|---|
 | 60 | 
 | 
|---|
| [49db5fc] | 61 | // Add more types as I need them
 | 
|---|
 | 62 | enum UniformType {
 | 
|---|
 | 63 |    UNIFORM_NONE,
 | 
|---|
 | 64 |    UNIFORM_MATRIX_4F,
 | 
|---|
 | 65 |    UNIFORM_1F,
 | 
|---|
 | 66 |    UNIFORM_3F,
 | 
|---|
 | 67 | };
 | 
|---|
 | 68 | 
 | 
|---|
| [df652d5] | 69 | struct SceneObject {
 | 
|---|
| [d9f99b2] | 70 |    unsigned int id;
 | 
|---|
| [92b1e90] | 71 |    ObjectType type;
 | 
|---|
| [95595de] | 72 | 
 | 
|---|
 | 73 |    // Currently, model_transform should only have translate, and rotation and scale need to be done in model_base since
 | 
|---|
 | 74 |    // they need to be done when the object is at the origin. I should change this to have separate scale, rotate, and translate
 | 
|---|
 | 75 |    // matrices for each object that can be updated independently and then applied to the object in that order.
 | 
|---|
| [4c7cd57] | 76 |    // TODO: Actually, to make this as generic as possible, each object should have a matrix stack to support,
 | 
|---|
 | 77 |    // for instance, applying a rotate, then a translate, then another rotate. Think about and implement the best approach.
 | 
|---|
| [5c403fe] | 78 |    mat4 model_mat, model_base, model_transform;
 | 
|---|
| [95595de] | 79 |    mat4 translate_mat; // beginning of doing what's mentioned above
 | 
|---|
| [05e43cf] | 80 |    unsigned int num_points;
 | 
|---|
| [c3c3158] | 81 |    GLuint vertex_vbo_offset;
 | 
|---|
 | 82 |    GLuint ubo_offset;
 | 
|---|
| [07ed460] | 83 |    vector<GLfloat> points;
 | 
|---|
 | 84 |    vector<GLfloat> colors;
 | 
|---|
 | 85 |    vector<GLfloat> texcoords;
 | 
|---|
| [9dd2eb7] | 86 |    vector<GLfloat> normals;
 | 
|---|
| [c3c3158] | 87 |    bool deleted;
 | 
|---|
| [3d06b4e] | 88 |    vec3 bounding_center;
 | 
|---|
 | 89 |    GLfloat bounding_radius;
 | 
|---|
| [c3c3158] | 90 | };
 | 
|---|
 | 91 | 
 | 
|---|
| [1f3d32b] | 92 | struct Asteroid : SceneObject {
 | 
|---|
| [0e0f851] | 93 |    float hp;
 | 
|---|
| [1f3d32b] | 94 | };
 | 
|---|
 | 95 | 
 | 
|---|
 | 96 | struct Laser : SceneObject {
 | 
|---|
 | 97 |    Asteroid* targetAsteroid;
 | 
|---|
 | 98 | };
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 | struct EffectOverTime {
 | 
|---|
| [0e0f851] | 101 |    float& effectedValue;
 | 
|---|
 | 102 |    float startValue;
 | 
|---|
| [1f3d32b] | 103 |    double startTime;
 | 
|---|
| [0e0f851] | 104 |    float changePerSecond;
 | 
|---|
| [1f3d32b] | 105 |    bool deleted;
 | 
|---|
 | 106 |    SceneObject* effectedObject;
 | 
|---|
 | 107 | 
 | 
|---|
| [39ac76d] | 108 |    // TODO: Why not just use an initializer list for all the instance variables
 | 
|---|
| [b220f78] | 109 |    // TODO: Maybe pass in startTime instead of calling glfwGetTime() here
 | 
|---|
| [0e0f851] | 110 |    EffectOverTime(float& effectedValue, float changePerSecond, SceneObject* object)
 | 
|---|
 | 111 |       : effectedValue(effectedValue), changePerSecond(changePerSecond), effectedObject(object) {
 | 
|---|
| [1f3d32b] | 112 |       startValue = effectedValue;
 | 
|---|
 | 113 |       startTime = glfwGetTime();
 | 
|---|
 | 114 |       deleted = false;
 | 
|---|
 | 115 |    }
 | 
|---|
 | 116 | };
 | 
|---|
 | 117 | 
 | 
|---|
| [c3c3158] | 118 | struct BufferInfo {
 | 
|---|
 | 119 |    unsigned int vbo_base;
 | 
|---|
 | 120 |    unsigned int ubo_base;
 | 
|---|
 | 121 |    unsigned int ubo_offset;
 | 
|---|
 | 122 |    unsigned int ubo_capacity;
 | 
|---|
| [df652d5] | 123 | };
 | 
|---|
 | 124 | 
 | 
|---|
| [a0eb547] | 125 | struct AttribInfo {
 | 
|---|
 | 126 |    AttribType attribType;
 | 
|---|
 | 127 |    GLuint index;
 | 
|---|
 | 128 |    GLint size;
 | 
|---|
 | 129 |    GLenum type;
 | 
|---|
| [49db5fc] | 130 |    UniformType uniType;
 | 
|---|
 | 131 |    GLuint buffer; // For uniforms, this is the uniform location
 | 
|---|
| [a0eb547] | 132 |    size_t fieldOffset;
 | 
|---|
| [49db5fc] | 133 |    GLfloat* data; // pointer to data source for uniform attributes
 | 
|---|
| [a0eb547] | 134 | };
 | 
|---|
 | 135 | 
 | 
|---|
| [7a55b49] | 136 | struct ShaderModelGroup {
 | 
|---|
 | 137 |    GLuint shaderProgram;
 | 
|---|
 | 138 |    GLuint vao;
 | 
|---|
| [a0eb547] | 139 |    map<string, AttribInfo> attribs;
 | 
|---|
| [7a55b49] | 140 |    unsigned int numPoints;
 | 
|---|
| [a0eb547] | 141 |    unsigned int vboCapacity;
 | 
|---|
| [7a55b49] | 142 | };
 | 
|---|
 | 143 | 
 | 
|---|
| [4f3262f] | 144 | void glfw_error_callback(int error, const char* description);
 | 
|---|
 | 145 | 
 | 
|---|
 | 146 | void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
 | 
|---|
| [f7d35da] | 147 | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
 | 
|---|
| [4f3262f] | 148 | 
 | 
|---|
| [0e0f851] | 149 | void APIENTRY debugGlCallback(
 | 
|---|
 | 150 |    GLenum source,
 | 
|---|
 | 151 |    GLenum type,
 | 
|---|
 | 152 |    GLuint id,
 | 
|---|
 | 153 |    GLenum severity,
 | 
|---|
 | 154 |    GLsizei length,
 | 
|---|
 | 155 |    const GLchar* message,
 | 
|---|
 | 156 |    const void* userParam
 | 
|---|
 | 157 | );
 | 
|---|
 | 158 | 
 | 
|---|
| [d9f99b2] | 159 | bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point);
 | 
|---|
| [5c9d193] | 160 | bool insideTriangle(vec3 p, array<vec3, 3> triangle_points);
 | 
|---|
| [33a9664] | 161 | 
 | 
|---|
| [ec4456b] | 162 | GLuint loadShader(GLenum type, string file);
 | 
|---|
| [485424b] | 163 | GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath);
 | 
|---|
 | 164 | unsigned char* loadImage(string file_name, int* x, int* y);
 | 
|---|
| [ec4456b] | 165 | 
 | 
|---|
| [e9347b4] | 166 | void printVector(string label, vec3& v);
 | 
|---|
 | 167 | void print4DVector(string label, vec4& v);
 | 
|---|
| [d12d003] | 168 | 
 | 
|---|
| [1f3d32b] | 169 | void initObject(SceneObject* obj);
 | 
|---|
 | 170 | void addObjectToScene(SceneObject* obj,
 | 
|---|
| [8316333] | 171 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 172 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [c3c3158] | 173 |                   GLuint points_vbo,
 | 
|---|
 | 174 |                   GLuint colors_vbo,
 | 
|---|
 | 175 |                   GLuint texcoords_vbo,
 | 
|---|
 | 176 |                   GLuint normals_vbo,
 | 
|---|
 | 177 |                   GLuint ubo,
 | 
|---|
| [0414306] | 178 |                   GLuint model_mat_idx_vbo);
 | 
|---|
| [95595de] | 179 | void removeObjectFromScene(SceneObject& obj, GLuint ubo);
 | 
|---|
| [c3c3158] | 180 | 
 | 
|---|
| [7a55b49] | 181 | ShaderModelGroup createModelGroup(GLuint shaderProgram);
 | 
|---|
 | 182 | void removeModelFromGroup(ShaderModelGroup& modelGroup, SceneObject& model);
 | 
|---|
 | 183 | void addModelToGroup(ShaderModelGroup& modelGroup, SceneObject& model);
 | 
|---|
 | 184 | 
 | 
|---|
| [a0eb547] | 185 | void defineModelGroupAttrib(ShaderModelGroup& modelGroup, string name, AttribType attribType, GLint size, GLenum type, size_t fieldOffset);
 | 
|---|
| [49db5fc] | 186 | void defineModelGroupUniform(ShaderModelGroup& modelGroup, string name, AttribType attribType, GLint size, UniformType type, GLfloat* data);
 | 
|---|
| [a0eb547] | 187 | void initModelGroupAttribs(ShaderModelGroup& modelGroup);
 | 
|---|
| [49db5fc] | 188 | void bindUniformData(AttribInfo& attrib);
 | 
|---|
| [b220f78] | 189 | void bindUniformData(AttribInfo& attrib, GLfloat* data);
 | 
|---|
| [a0eb547] | 190 | 
 | 
|---|
 | 191 | size_t GLsizeof(GLenum);
 | 
|---|
 | 192 | GLvoid* getVectorAttribPtr(SceneObject& obj, size_t attribOffset);
 | 
|---|
 | 193 | GLvoid* getScalarAttribPtr(SceneObject& obj, size_t attribOffset);
 | 
|---|
 | 194 | 
 | 
|---|
| [1f3d32b] | 195 | void calculateObjectBoundingBox(SceneObject* obj);
 | 
|---|
| [b155f13] | 196 | 
 | 
|---|
| [c3c3158] | 197 | void initializeBuffers(
 | 
|---|
 | 198 |                   GLuint* points_vbo,
 | 
|---|
 | 199 |                   GLuint* colors_vbo,
 | 
|---|
 | 200 |                   GLuint* texcoords_vbo,
 | 
|---|
 | 201 |                   GLuint* normals_vbo,
 | 
|---|
 | 202 |                   GLuint* ubo,
 | 
|---|
| [6877ef3] | 203 |                   GLuint* model_mat_idx_vbo);
 | 
|---|
| [c3c3158] | 204 | 
 | 
|---|
| [b220f78] | 205 | void initializeParticleEffectBuffers(vec3 origin,
 | 
|---|
| [646f3f2] | 206 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 207 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [646f3f2] | 208 |                   GLuint points_vbo,
 | 
|---|
 | 209 |                   GLuint colors_vbo,
 | 
|---|
 | 210 |                   GLuint texcoords_vbo,
 | 
|---|
 | 211 |                   GLuint normals_vbo,
 | 
|---|
 | 212 |                   GLuint ubo,
 | 
|---|
 | 213 |                   GLuint model_mat_idx_vbo);
 | 
|---|
| [db06984] | 214 | 
 | 
|---|
| [1f3d32b] | 215 | void populateBuffers(vector<SceneObject*>& objects,
 | 
|---|
| [c3c3158] | 216 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 217 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [c3c3158] | 218 |                   GLuint points_vbo,
 | 
|---|
 | 219 |                   GLuint colors_vbo,
 | 
|---|
 | 220 |                   GLuint texcoords_vbo,
 | 
|---|
 | 221 |                   GLuint normals_vbo,
 | 
|---|
 | 222 |                   GLuint ubo,
 | 
|---|
| [0414306] | 223 |                   GLuint model_mat_idx_vbo);
 | 
|---|
| [c3c3158] | 224 | 
 | 
|---|
 | 225 | void copyObjectDataToBuffers(SceneObject& obj,
 | 
|---|
 | 226 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 227 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [49db5fc] | 228 |                   GLuint ubo);
 | 
|---|
| [f9a242b] | 229 | 
 | 
|---|
| [5c403fe] | 230 | void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo);
 | 
|---|
 | 231 | 
 | 
|---|
| [646f3f2] | 232 | // TODO: instead of using these methods, create constructors for these
 | 
|---|
| [dd9771c] | 233 | SceneObject* createShip();
 | 
|---|
 | 234 | Asteroid* createAsteroid(vec3 pos);
 | 
|---|
 | 235 | Laser* createLaser(vec3 start, vec3 end, vec3 color, GLfloat width);
 | 
|---|
 | 236 | SceneObject* createExplosion();
 | 
|---|
| [1f3d32b] | 237 | 
 | 
|---|
 | 238 | void translateLaser(Laser* laser, const vec3& translation, GLuint ubo);
 | 
|---|
| [a0eb547] | 239 | void updateLaserTarget(Laser* laser, vector<SceneObject*>& objects, ShaderModelGroup& laserSmg, GLuint asteroid_sp);
 | 
|---|
| [e9347b4] | 240 | bool getLaserAndAsteroidIntersection(vec3& start, vec3& end, SceneObject& asteroid, vec3& intersection);
 | 
|---|
| [612d1f6] | 241 | 
 | 
|---|
| [93462c6] | 242 | void renderMainMenu();
 | 
|---|
 | 243 | void renderMainMenuGui();
 | 
|---|
 | 244 | 
 | 
|---|
| [0414306] | 245 | void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [b62c109] | 246 |                   map<ObjectType, ShaderModelGroup>& modelGroups, GLuint ubo);
 | 
|---|
| [db06984] | 247 | 
 | 
|---|
| [93462c6] | 248 | void renderSceneGui();
 | 
|---|
| [d12d003] | 249 | 
 | 
|---|
| [5527206] | 250 | float getRandomNum(float low, float high);
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | #define NUM_KEYS (512)
 | 
|---|
 | 253 | #define ONE_DEG_IN_RAD ((2.0f * M_PI) / 360.0f) // 0.017444444 (maybe make this a const instead)
 | 
|---|
| [8fbd34f] | 254 | #define TARGET_FPS 60.0f
 | 
|---|
| [5527206] | 255 | 
 | 
|---|
 | 256 | const int KEY_STATE_UNCHANGED = -1;
 | 
|---|
 | 257 | const bool FULLSCREEN = false;
 | 
|---|
| [db06984] | 258 | const int EXPLOSION_PARTICLE_COUNT = 300;
 | 
|---|
| [5527206] | 259 | unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime, so it can't be const
 | 
|---|
 | 260 | 
 | 
|---|
 | 261 | int key_state[NUM_KEYS];
 | 
|---|
| [fabed35] | 262 | bool key_down[NUM_KEYS];
 | 
|---|
| [5527206] | 263 | 
 | 
|---|
 | 264 | int width = 640;
 | 
|---|
 | 265 | int height = 480;
 | 
|---|
 | 266 | 
 | 
|---|
 | 267 | double fps;
 | 
|---|
| [1e3dddf] | 268 | unsigned int score = 0;
 | 
|---|
| [5527206] | 269 | 
 | 
|---|
 | 270 | vec3 cam_pos;
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 | mat4 view_mat;
 | 
|---|
 | 273 | mat4 proj_mat;
 | 
|---|
 | 274 | 
 | 
|---|
| [1f3d32b] | 275 | vector<SceneObject*> objects;
 | 
|---|
| [5527206] | 276 | queue<Event> events;
 | 
|---|
| [1f3d32b] | 277 | vector<EffectOverTime*> effects;
 | 
|---|
| [5527206] | 278 | 
 | 
|---|
 | 279 | SceneObject* clickedObject = NULL;
 | 
|---|
 | 280 | SceneObject* selectedObject = NULL;
 | 
|---|
 | 281 | 
 | 
|---|
 | 282 | float NEAR_CLIP = 0.1f;
 | 
|---|
 | 283 | float FAR_CLIP = 100.0f;
 | 
|---|
 | 284 | 
 | 
|---|
| [95595de] | 285 | // TODO: Should really have some array or struct of UI-related variables
 | 
|---|
| [5527206] | 286 | bool isRunning = true;
 | 
|---|
 | 287 | 
 | 
|---|
 | 288 | ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
 | 
|---|
 | 289 | 
 | 
|---|
| [1f3d32b] | 290 | Laser* leftLaser = NULL;
 | 
|---|
 | 291 | EffectOverTime* leftLaserEffect = NULL;
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 | Laser* rightLaser = NULL;
 | 
|---|
 | 294 | EffectOverTime* rightLaserEffect = NULL;
 | 
|---|
| [fabed35] | 295 | 
 | 
|---|
| [646f3f2] | 296 | SceneObject* objExplosion;
 | 
|---|
 | 297 | SceneObject* objFirst;
 | 
|---|
 | 298 | 
 | 
|---|
| [3effd81] | 299 | /*
 | 
|---|
| [e9347b4] | 300 | * TODO: Asteroid and ship movement currently depend on framerate, fix this in a generic/reusable way
 | 
|---|
 | 301 | * Disabling vsync is a great way to test this
 | 
|---|
| [3effd81] | 302 | */
 | 
|---|
 | 303 | 
 | 
|---|
| [c1ca5b5] | 304 | int main(int argc, char* argv[]) {
 | 
|---|
| [5272b6b] | 305 |    cout << "New OpenGL Game" << endl;
 | 
|---|
 | 306 | 
 | 
|---|
| [ec4456b] | 307 |    if (!restart_gl_log()) {}
 | 
|---|
 | 308 |    gl_log("starting GLFW\n%s\n", glfwGetVersionString());
 | 
|---|
| [22b2c37] | 309 | 
 | 
|---|
| [ec4456b] | 310 |    glfwSetErrorCallback(glfw_error_callback);
 | 
|---|
| [5272b6b] | 311 |    if (!glfwInit()) {
 | 
|---|
 | 312 |       fprintf(stderr, "ERROR: could not start GLFW3\n");
 | 
|---|
 | 313 |       return 1;
 | 
|---|
| [be246ad] | 314 |    }
 | 
|---|
 | 315 | 
 | 
|---|
 | 316 | #ifdef __APPLE__
 | 
|---|
 | 317 |    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
 | 
|---|
 | 318 |    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 | 
|---|
 | 319 |    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
 | 
|---|
 | 320 |    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 | 
|---|
| [446e55d] | 321 | #else
 | 
|---|
 | 322 |    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
 | 
|---|
 | 323 |    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 | 
|---|
| [be246ad] | 324 | #endif
 | 
|---|
| [5272b6b] | 325 | 
 | 
|---|
| [ec4456b] | 326 |    GLFWwindow* window = NULL;
 | 
|---|
| [e856d62] | 327 |    GLFWmonitor* mon = NULL;
 | 
|---|
| [ec4456b] | 328 | 
 | 
|---|
| [0e0f851] | 329 |    glfwWindowHint(GLFW_SAMPLES, 16);
 | 
|---|
 | 330 |    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
 | 
|---|
 | 331 | 
 | 
|---|
| [ec4456b] | 332 |    if (FULLSCREEN) {
 | 
|---|
| [e856d62] | 333 |       mon = glfwGetPrimaryMonitor();
 | 
|---|
| [ec4456b] | 334 |       const GLFWvidmode* vmode = glfwGetVideoMode(mon);
 | 
|---|
 | 335 | 
 | 
|---|
 | 336 |       width = vmode->width;
 | 
|---|
 | 337 |       height = vmode->height;
 | 
|---|
| [e856d62] | 338 |       cout << "Fullscreen resolution " << vmode->width << "x" << vmode->height << endl;
 | 
|---|
| [ec4456b] | 339 |    }
 | 
|---|
| [e856d62] | 340 |    window = glfwCreateWindow(width, height, "New OpenGL Game", mon, NULL);
 | 
|---|
| [ec4456b] | 341 | 
 | 
|---|
| [5272b6b] | 342 |    if (!window) {
 | 
|---|
 | 343 |       fprintf(stderr, "ERROR: could not open window with GLFW3\n");
 | 
|---|
 | 344 |       glfwTerminate();
 | 
|---|
 | 345 |       return 1;
 | 
|---|
 | 346 |    }
 | 
|---|
| [c62eee6] | 347 | 
 | 
|---|
| [644a2e4] | 348 |    glfwMakeContextCurrent(window);
 | 
|---|
| [5272b6b] | 349 |    glewExperimental = GL_TRUE;
 | 
|---|
 | 350 |    glewInit();
 | 
|---|
 | 351 | 
 | 
|---|
| [0e0f851] | 352 |    if (GLEW_KHR_debug) {
 | 
|---|
 | 353 |       cout << "FOUND GLEW debug extension" << endl;
 | 
|---|
 | 354 |       glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
 | 
|---|
 | 355 |       glDebugMessageCallback((GLDEBUGPROC)debugGlCallback, nullptr);
 | 
|---|
 | 356 |       cout << "Bound debug callback" << endl;
 | 
|---|
| [446e55d] | 357 |    } else {
 | 
|---|
 | 358 |      cout << "OpenGL debugg message callback is not supported" << endl;
 | 
|---|
| [0e0f851] | 359 |    }
 | 
|---|
 | 360 | 
 | 
|---|
| [5527206] | 361 |    srand(time(0));
 | 
|---|
 | 362 | 
 | 
|---|
| [14ff67c] | 363 |    /*
 | 
|---|
 | 364 |    * RENDERING ALGORITHM NOTES:
 | 
|---|
 | 365 |    *
 | 
|---|
 | 366 |    * Basically, I need to split my objects into groups, so that each group fits into
 | 
|---|
 | 367 |    * GL_MAX_UNIFORM_BLOCK_SIZE. I need to have an offset and a size for each group.
 | 
|---|
 | 368 |    * Getting the offset is straitforward. The size may as well be GL_MAX_UNIFORM_BLOCK_SIZE
 | 
|---|
 | 369 |    * for each group, since it seems that smaller sizes just round up to the nearest GL_MAX_UNIFORM_BLOCK_SIZE
 | 
|---|
 | 370 |    *
 | 
|---|
 | 371 |    * I'll need to have a loop inside my render loop that calls glBindBufferRange(GL_UNIFORM_BUFFER, ...
 | 
|---|
 | 372 |    * for every 1024 objects and then draws all those objects with one glDraw call.
 | 
|---|
 | 373 |    *
 | 
|---|
| [0d5c100] | 374 |    * Since I currently have very few objects, I'll wait to implement this  until I have
 | 
|---|
 | 375 |    * a reasonable number of objects always using the same shader.
 | 
|---|
| [14ff67c] | 376 |    */
 | 
|---|
 | 377 | 
 | 
|---|
 | 378 |    GLint UNIFORM_BUFFER_OFFSET_ALIGNMENT, MAX_UNIFORM_BLOCK_SIZE;
 | 
|---|
 | 379 |    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &UNIFORM_BUFFER_OFFSET_ALIGNMENT);
 | 
|---|
 | 380 |    glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &MAX_UNIFORM_BLOCK_SIZE);
 | 
|---|
 | 381 | 
 | 
|---|
 | 382 |    MAX_UNIFORMS = MAX_UNIFORM_BLOCK_SIZE / sizeof(mat4);
 | 
|---|
 | 383 | 
 | 
|---|
 | 384 |    cout << "UNIFORM_BUFFER_OFFSET_ALIGNMENT: " << UNIFORM_BUFFER_OFFSET_ALIGNMENT << endl;
 | 
|---|
 | 385 |    cout << "MAX_UNIFORMS: " << MAX_UNIFORMS << endl;
 | 
|---|
 | 386 | 
 | 
|---|
| [c1ca5b5] | 387 |    // Setup Dear ImGui binding
 | 
|---|
 | 388 |    IMGUI_CHECKVERSION();
 | 
|---|
 | 389 |    ImGui::CreateContext();
 | 
|---|
 | 390 |    ImGuiIO& io = ImGui::GetIO(); (void)io;
 | 
|---|
 | 391 |    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Enable Keyboard Controls
 | 
|---|
 | 392 |    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;   // Enable Gamepad Controls
 | 
|---|
 | 393 |    ImGui_ImplGlfwGL3_Init(window, true);
 | 
|---|
 | 394 | 
 | 
|---|
 | 395 |    // Setup style
 | 
|---|
 | 396 |    ImGui::StyleColorsDark();
 | 
|---|
 | 397 |    //ImGui::StyleColorsClassic();
 | 
|---|
 | 398 | 
 | 
|---|
 | 399 |    glfwSetMouseButtonCallback(window, mouse_button_callback);
 | 
|---|
| [f7d35da] | 400 |    glfwSetKeyCallback(window, key_callback);
 | 
|---|
| [c1ca5b5] | 401 | 
 | 
|---|
| [5272b6b] | 402 |    const GLubyte* renderer = glGetString(GL_RENDERER);
 | 
|---|
 | 403 |    const GLubyte* version = glGetString(GL_VERSION);
 | 
|---|
| [0e0f851] | 404 |    cout << "Renderer: " << renderer << endl;
 | 
|---|
 | 405 |    cout << "OpenGL version supported " << version << endl;
 | 
|---|
| [93baa0e] | 406 | 
 | 
|---|
| [9f9f9a7] | 407 |    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | 
|---|
 | 408 | 
 | 
|---|
| [5272b6b] | 409 |    glEnable(GL_DEPTH_TEST);
 | 
|---|
 | 410 |    glDepthFunc(GL_LESS);
 | 
|---|
| [516668e] | 411 | 
 | 
|---|
| [93baa0e] | 412 |    glEnable(GL_CULL_FACE);
 | 
|---|
 | 413 |    // glCullFace(GL_BACK);
 | 
|---|
 | 414 |    // glFrontFace(GL_CW);
 | 
|---|
 | 415 | 
 | 
|---|
| [9f9f9a7] | 416 |    /*
 | 
|---|
| [485424b] | 417 |    int x, y;
 | 
|---|
 | 418 |    unsigned char* texImage = loadImage("test.png", &x, &y);
 | 
|---|
 | 419 |    if (texImage) {
 | 
|---|
 | 420 |      cout << "Yay, I loaded an image!" << endl;
 | 
|---|
 | 421 |      cout << x << endl;
 | 
|---|
 | 422 |      cout << y << endl;
 | 
|---|
| [e856d62] | 423 |      printf("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
 | 
|---|
| [485424b] | 424 |    }
 | 
|---|
 | 425 | 
 | 
|---|
| [9f9f9a7] | 426 |    GLuint testTex = 0;
 | 
|---|
 | 427 |    glGenTextures(1, &testTex);
 | 
|---|
 | 428 |    glActiveTexture(GL_TEXTURE0);
 | 
|---|
 | 429 |    glBindTexture(GL_TEXTURE_2D, testTex);
 | 
|---|
 | 430 |    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
 | 
|---|
 | 431 | 
 | 
|---|
 | 432 |    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
|---|
 | 433 |    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
|---|
 | 434 |    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
|---|
 | 435 |    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
|---|
 | 436 |    */
 | 
|---|
 | 437 | 
 | 
|---|
 | 438 |    int x, y;
 | 
|---|
 | 439 |    unsigned char* texImage = loadImage("laser.png", &x, &y);
 | 
|---|
 | 440 |    if (texImage) {
 | 
|---|
 | 441 |       cout << "Laser texture loaded successfully!" << endl;
 | 
|---|
 | 442 |       cout << x << endl;
 | 
|---|
 | 443 |       cout << y << endl;
 | 
|---|
 | 444 |       printf("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
 | 
|---|
 | 445 |    }
 | 
|---|
 | 446 | 
 | 
|---|
 | 447 |    GLuint laserTex = 0;
 | 
|---|
 | 448 |    glGenTextures(1, &laserTex);
 | 
|---|
| [485424b] | 449 |    glActiveTexture(GL_TEXTURE0);
 | 
|---|
| [9f9f9a7] | 450 |    glBindTexture(GL_TEXTURE_2D, laserTex);
 | 
|---|
| [485424b] | 451 |    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
 | 
|---|
 | 452 | 
 | 
|---|
 | 453 |    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
|---|
 | 454 |    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
|---|
 | 455 |    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
|---|
 | 456 |    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
|---|
 | 457 | 
 | 
|---|
| [0d5c100] | 458 |    /* RENDERING ALGORITHM
 | 
|---|
 | 459 |     * 
 | 
|---|
 | 460 |     * Create a separate vbo for each of the following things:
 | 
|---|
 | 461 |     * - points
 | 
|---|
 | 462 |     * - colors
 | 
|---|
 | 463 |     * - texture coordinates
 | 
|---|
 | 464 |     * - selected colors
 | 
|---|
 | 465 |     * - normals
 | 
|---|
 | 466 |     * - indices into a ubo that stores a model matrix for each object
 | 
|---|
 | 467 |     *
 | 
|---|
 | 468 |     * Also, make a model matrix ubo, the entirety of which will be passed to the vertex shader.
 | 
|---|
 | 469 |     * The vbo containing the correct index into the ubo (mentioned above) will be used to select
 | 
|---|
 | 470 |     * the right model matrix for each point. The index in the vbo will be the saem for all points
 | 
|---|
 | 471 |     * of any given object.
 | 
|---|
 | 472 |     *
 | 
|---|
 | 473 |     * Right now, the currently selected object is drawn using one color (specified in the selected
 | 
|---|
 | 474 |     * colors vbo) regardless of whether it is normally rendering using colors or a texture. The selected
 | 
|---|
 | 475 |     * object is rendering by binding the selected colors vbo in place of the colors vbo and using the colors
 | 
|---|
 | 476 |     * shader. Then, the selected object is redrawn along with all other objects, but the depth buffer test
 | 
|---|
 | 477 |     * prevents the unselected version of the object from appearing on the screen. This lets me render all the
 | 
|---|
 | 478 |     * objects that use a particular shader using one glDrawArrays() call.
 | 
|---|
 | 479 |     */
 | 
|---|
| [cffca4d] | 480 | 
 | 
|---|
| [49db5fc] | 481 |    GLfloat laserColor[3] = {0.2f, 1.0f, 0.2f};
 | 
|---|
| [b220f78] | 482 |    GLfloat curTime, prevTime, elapsedTime;
 | 
|---|
| [49db5fc] | 483 | 
 | 
|---|
| [de53394] | 484 |    GLuint
 | 
|---|
 | 485 |     points_vbo,
 | 
|---|
 | 486 |     colors_vbo,
 | 
|---|
 | 487 |     texcoords_vbo,
 | 
|---|
 | 488 |     normals_vbo,
 | 
|---|
 | 489 |     ubo,
 | 
|---|
 | 490 |     model_mat_idx_vbo;
 | 
|---|
| [81f28c0] | 491 | 
 | 
|---|
| [1f3d32b] | 492 |    initializeBuffers(
 | 
|---|
 | 493 |       &points_vbo,
 | 
|---|
 | 494 |       &colors_vbo,
 | 
|---|
 | 495 |       &texcoords_vbo,
 | 
|---|
 | 496 |       &normals_vbo,
 | 
|---|
 | 497 |       &ubo,
 | 
|---|
 | 498 |       &model_mat_idx_vbo);
 | 
|---|
| [81f28c0] | 499 | 
 | 
|---|
| [a0eb547] | 500 |    map<GLuint, BufferInfo> shaderBufferInfo;
 | 
|---|
 | 501 |    map<ObjectType, ShaderModelGroup> modelGroups;
 | 
|---|
 | 502 | 
 | 
|---|
 | 503 |    modelGroups[TYPE_SHIP] = createModelGroup(
 | 
|---|
 | 504 |       loadShaderProgram("./ship.vert", "./ship.frag"));
 | 
|---|
 | 505 |    shaderBufferInfo[modelGroups[TYPE_SHIP].shaderProgram] = BufferInfo(); // temporary
 | 
|---|
| [0e0f851] | 506 | 
 | 
|---|
| [a0eb547] | 507 |    defineModelGroupAttrib(modelGroups[TYPE_SHIP], "vertex_position", ATTRIB_POINT_VARYING,
 | 
|---|
 | 508 |       3, GL_FLOAT, offsetof(SceneObject, points));
 | 
|---|
 | 509 |    defineModelGroupAttrib(modelGroups[TYPE_SHIP], "vertex_color", ATTRIB_POINT_VARYING,
 | 
|---|
 | 510 |       3, GL_FLOAT, offsetof(SceneObject, colors));
 | 
|---|
 | 511 |    defineModelGroupAttrib(modelGroups[TYPE_SHIP], "vertex_normal", ATTRIB_POINT_VARYING,
 | 
|---|
 | 512 |       3, GL_FLOAT, offsetof(SceneObject, normals));
 | 
|---|
 | 513 |    defineModelGroupAttrib(modelGroups[TYPE_SHIP], "ubo_index", ATTRIB_OBJECT_VARYING,
 | 
|---|
 | 514 |       1, GL_UNSIGNED_INT, offsetof(SceneObject, ubo_offset));
 | 
|---|
| [81f28c0] | 515 | 
 | 
|---|
| [49db5fc] | 516 |    defineModelGroupUniform(modelGroups[TYPE_SHIP], "view", ATTRIB_UNIFORM,
 | 
|---|
 | 517 |       1, UNIFORM_MATRIX_4F, value_ptr(view_mat));
 | 
|---|
 | 518 |    defineModelGroupUniform(modelGroups[TYPE_SHIP], "proj", ATTRIB_UNIFORM,
 | 
|---|
 | 519 |       1, UNIFORM_MATRIX_4F, value_ptr(proj_mat));
 | 
|---|
 | 520 | 
 | 
|---|
| [a0eb547] | 521 |    initModelGroupAttribs(modelGroups[TYPE_SHIP]);
 | 
|---|
| [20e0020] | 522 | 
 | 
|---|
| [1f3d32b] | 523 |    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
 | 
|---|
| [646f3f2] | 524 |    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 525 |    modelGroups[TYPE_SHIP].attribs["vertex_position"].buffer = points_vbo;
 | 
|---|
| [20e0020] | 526 | 
 | 
|---|
| [2b0214c] | 527 |    glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
 | 
|---|
| [646f3f2] | 528 |    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 529 |    modelGroups[TYPE_SHIP].attribs["vertex_color"].buffer = colors_vbo;
 | 
|---|
| [2b0214c] | 530 | 
 | 
|---|
| [1f3d32b] | 531 |    glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
 | 
|---|
| [646f3f2] | 532 |    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 533 |    modelGroups[TYPE_SHIP].attribs["vertex_normal"].buffer = normals_vbo;
 | 
|---|
| [20e0020] | 534 | 
 | 
|---|
| [1f3d32b] | 535 |    glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
 | 
|---|
| [646f3f2] | 536 |    glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, NULL);
 | 
|---|
| [a0eb547] | 537 |    modelGroups[TYPE_SHIP].attribs["ubo_index"].buffer = model_mat_idx_vbo;
 | 
|---|
| [20e0020] | 538 | 
 | 
|---|
| [a0eb547] | 539 |    modelGroups[TYPE_ASTEROID] = createModelGroup(
 | 
|---|
 | 540 |       loadShaderProgram("./asteroid.vert", "./asteroid.frag"));
 | 
|---|
 | 541 |    shaderBufferInfo[modelGroups[TYPE_ASTEROID].shaderProgram] = BufferInfo(); // temporary
 | 
|---|
| [0e0f851] | 542 | 
 | 
|---|
| [a0eb547] | 543 |    defineModelGroupAttrib(modelGroups[TYPE_ASTEROID], "vertex_position", ATTRIB_POINT_VARYING,
 | 
|---|
 | 544 |       3, GL_FLOAT, offsetof(SceneObject, points));
 | 
|---|
 | 545 |    defineModelGroupAttrib(modelGroups[TYPE_ASTEROID], "vertex_color", ATTRIB_POINT_VARYING,
 | 
|---|
 | 546 |       3, GL_FLOAT, offsetof(SceneObject, colors));
 | 
|---|
 | 547 |    defineModelGroupAttrib(modelGroups[TYPE_ASTEROID], "vertex_normal", ATTRIB_POINT_VARYING,
 | 
|---|
 | 548 |       3, GL_FLOAT, offsetof(SceneObject, normals));
 | 
|---|
 | 549 |    defineModelGroupAttrib(modelGroups[TYPE_ASTEROID], "ubo_index", ATTRIB_OBJECT_VARYING,
 | 
|---|
 | 550 |       1, GL_UNSIGNED_INT, offsetof(SceneObject, ubo_offset));
 | 
|---|
 | 551 | 
 | 
|---|
| [49db5fc] | 552 |    defineModelGroupUniform(modelGroups[TYPE_ASTEROID], "view", ATTRIB_UNIFORM,
 | 
|---|
 | 553 |       1, UNIFORM_MATRIX_4F, value_ptr(view_mat));
 | 
|---|
 | 554 |    defineModelGroupUniform(modelGroups[TYPE_ASTEROID], "proj", ATTRIB_UNIFORM,
 | 
|---|
 | 555 |       1, UNIFORM_MATRIX_4F, value_ptr(proj_mat));
 | 
|---|
 | 556 | 
 | 
|---|
| [a0eb547] | 557 |    initModelGroupAttribs(modelGroups[TYPE_ASTEROID]);
 | 
|---|
| [0e0f851] | 558 | 
 | 
|---|
 | 559 |    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
 | 
|---|
| [646f3f2] | 560 |    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 561 |    modelGroups[TYPE_ASTEROID].attribs["vertex_position"].buffer = points_vbo;
 | 
|---|
| [0e0f851] | 562 | 
 | 
|---|
 | 563 |    glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
 | 
|---|
| [646f3f2] | 564 |    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 565 |    modelGroups[TYPE_ASTEROID].attribs["vertex_color"].buffer = colors_vbo;
 | 
|---|
| [0e0f851] | 566 | 
 | 
|---|
 | 567 |    glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
 | 
|---|
| [646f3f2] | 568 |    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 569 |    modelGroups[TYPE_ASTEROID].attribs["vertex_normal"].buffer = normals_vbo;
 | 
|---|
| [0e0f851] | 570 | 
 | 
|---|
 | 571 |    glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
 | 
|---|
| [646f3f2] | 572 |    glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, NULL);
 | 
|---|
| [a0eb547] | 573 |    modelGroups[TYPE_ASTEROID].attribs["ubo_index"].buffer = model_mat_idx_vbo;
 | 
|---|
 | 574 | 
 | 
|---|
 | 575 |    modelGroups[TYPE_LASER] = createModelGroup(
 | 
|---|
 | 576 |       loadShaderProgram("./laser.vert", "./laser.frag"));
 | 
|---|
 | 577 |    shaderBufferInfo[modelGroups[TYPE_LASER].shaderProgram] = BufferInfo(); // temporary
 | 
|---|
| [0e0f851] | 578 | 
 | 
|---|
| [a0eb547] | 579 |    defineModelGroupAttrib(modelGroups[TYPE_LASER], "vertex_position", ATTRIB_POINT_VARYING,
 | 
|---|
 | 580 |       3, GL_FLOAT, offsetof(SceneObject, points));
 | 
|---|
 | 581 |    defineModelGroupAttrib(modelGroups[TYPE_LASER], "vt", ATTRIB_POINT_VARYING,
 | 
|---|
 | 582 |       2, GL_FLOAT, offsetof(SceneObject, texcoords));
 | 
|---|
 | 583 |    defineModelGroupAttrib(modelGroups[TYPE_LASER], "ubo_index", ATTRIB_OBJECT_VARYING,
 | 
|---|
 | 584 |       1, GL_UNSIGNED_INT, offsetof(SceneObject, ubo_offset));
 | 
|---|
| [20e0020] | 585 | 
 | 
|---|
| [49db5fc] | 586 |    defineModelGroupUniform(modelGroups[TYPE_LASER], "view", ATTRIB_UNIFORM,
 | 
|---|
 | 587 |       1, UNIFORM_MATRIX_4F, value_ptr(view_mat));
 | 
|---|
 | 588 |    defineModelGroupUniform(modelGroups[TYPE_LASER], "proj", ATTRIB_UNIFORM,
 | 
|---|
 | 589 |       1, UNIFORM_MATRIX_4F, value_ptr(proj_mat));
 | 
|---|
 | 590 |     defineModelGroupUniform(modelGroups[TYPE_LASER], "laser_color", ATTRIB_UNIFORM,
 | 
|---|
 | 591 |       1, UNIFORM_3F, laserColor);
 | 
|---|
 | 592 | 
 | 
|---|
| [a0eb547] | 593 |    initModelGroupAttribs(modelGroups[TYPE_LASER]);
 | 
|---|
| [20e0020] | 594 | 
 | 
|---|
| [1f3d32b] | 595 |    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
 | 
|---|
| [646f3f2] | 596 |    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 597 |    modelGroups[TYPE_LASER].attribs["vertex_position"].buffer = points_vbo;
 | 
|---|
| [20e0020] | 598 | 
 | 
|---|
| [1f3d32b] | 599 |    glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
 | 
|---|
| [646f3f2] | 600 |    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
 | 
|---|
| [a0eb547] | 601 |    modelGroups[TYPE_LASER].attribs["vt"].buffer = texcoords_vbo;
 | 
|---|
| [20e0020] | 602 | 
 | 
|---|
| [1f3d32b] | 603 |    glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
 | 
|---|
| [646f3f2] | 604 |    glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, 0, NULL);
 | 
|---|
| [a0eb547] | 605 |    modelGroups[TYPE_LASER].attribs["ubo_index"].buffer = model_mat_idx_vbo;
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 |    modelGroups[TYPE_EXPLOSION] = createModelGroup(
 | 
|---|
 | 608 |       loadShaderProgram("./explosion.vert", "./explosion.frag"));
 | 
|---|
 | 609 |    shaderBufferInfo[modelGroups[TYPE_EXPLOSION].shaderProgram] = BufferInfo(); // temporary
 | 
|---|
 | 610 | 
 | 
|---|
| [b220f78] | 611 |    // The last parameter (offset) is only used for populating the buffers since the distance
 | 
|---|
 | 612 |    // between each item is needed there. However, that code isn't run for explosions right now anyway,
 | 
|---|
 | 613 |    // so I may as well pass in 0 here.
 | 
|---|
 | 614 |    defineModelGroupAttrib(modelGroups[TYPE_EXPLOSION], "v_i", ATTRIB_POINT_VARYING,
 | 
|---|
 | 615 |       3, GL_FLOAT, 0);
 | 
|---|
 | 616 |    defineModelGroupAttrib(modelGroups[TYPE_EXPLOSION], "start_time", ATTRIB_POINT_VARYING,
 | 
|---|
 | 617 |       1, GL_FLOAT, 0);
 | 
|---|
 | 618 | 
 | 
|---|
 | 619 |    defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "explosion_start_time", ATTRIB_UNIFORM,
 | 
|---|
 | 620 |       1, UNIFORM_1F, &curTime);
 | 
|---|
 | 621 |    defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "cur_time", ATTRIB_UNIFORM,
 | 
|---|
 | 622 |       1, UNIFORM_1F, &curTime);
 | 
|---|
 | 623 |    defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "model_mat", ATTRIB_UNIFORM,
 | 
|---|
 | 624 |       1, UNIFORM_MATRIX_4F, NULL);
 | 
|---|
 | 625 |    defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "view", ATTRIB_UNIFORM,
 | 
|---|
 | 626 |       1, UNIFORM_MATRIX_4F, value_ptr(view_mat));
 | 
|---|
 | 627 |    defineModelGroupUniform(modelGroups[TYPE_EXPLOSION], "proj", ATTRIB_UNIFORM,
 | 
|---|
 | 628 |       1, UNIFORM_MATRIX_4F, value_ptr(proj_mat));
 | 
|---|
 | 629 | 
 | 
|---|
| [b05e2b5] | 630 |    initModelGroupAttribs(modelGroups[TYPE_EXPLOSION]);
 | 
|---|
| [de53394] | 631 | 
 | 
|---|
| [a0eb547] | 632 |    cam_pos = vec3(0.0f, 0.0f, 2.0f);
 | 
|---|
 | 633 |    float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
 | 
|---|
 | 634 |    float cam_pitch = -50.0f * 2.0f * 3.14159f / 360.0f;
 | 
|---|
 | 635 | 
 | 
|---|
 | 636 |    // player ship
 | 
|---|
 | 637 |    SceneObject* ship = createShip();
 | 
|---|
 | 638 |    objects.push_back(ship);
 | 
|---|
 | 639 | 
 | 
|---|
 | 640 |    vector<SceneObject>::iterator obj_it;
 | 
|---|
 | 641 | 
 | 
|---|
 | 642 |    populateBuffers(objects,
 | 
|---|
 | 643 |       shaderBufferInfo, modelGroups,
 | 
|---|
 | 644 |       points_vbo,
 | 
|---|
 | 645 |       colors_vbo,
 | 
|---|
 | 646 |       texcoords_vbo,
 | 
|---|
 | 647 |       normals_vbo,
 | 
|---|
 | 648 |       ubo,
 | 
|---|
 | 649 |       model_mat_idx_vbo);
 | 
|---|
| [20e0020] | 650 | 
 | 
|---|
| [1f3d32b] | 651 |    float cam_speed = 1.0f;
 | 
|---|
 | 652 |    float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
 | 
|---|
 | 653 |    float cam_pitch_speed = 60.0f*ONE_DEG_IN_RAD;
 | 
|---|
| [20e0020] | 654 | 
 | 
|---|
| [1f3d32b] | 655 |    // glm::lookAt can create the view matrix
 | 
|---|
 | 656 |    // glm::perspective can create the projection matrix
 | 
|---|
| [20e0020] | 657 | 
 | 
|---|
| [1f3d32b] | 658 |    mat4 T = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
 | 
|---|
 | 659 |    mat4 yaw_mat = rotate(mat4(1.0f), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
 | 
|---|
 | 660 |    mat4 pitch_mat = rotate(mat4(1.0f), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
 | 
|---|
 | 661 |    mat4 R = pitch_mat * yaw_mat;
 | 
|---|
 | 662 |    view_mat = R*T;
 | 
|---|
| [20e0020] | 663 | 
 | 
|---|
| [1f3d32b] | 664 |    // TODO: Create a function to construct the projection matrix
 | 
|---|
 | 665 |    // (Maybe I should just use glm::perspective, after making sure it matches what I have now)
 | 
|---|
 | 666 |    float fov = 67.0f * ONE_DEG_IN_RAD;
 | 
|---|
 | 667 |    float aspect = (float)width / (float)height;
 | 
|---|
| [20e0020] | 668 | 
 | 
|---|
| [1f3d32b] | 669 |    float range = tan(fov * 0.5f) * NEAR_CLIP;
 | 
|---|
 | 670 |    float Sx = NEAR_CLIP / (range * aspect);
 | 
|---|
 | 671 |    float Sy = NEAR_CLIP / range;
 | 
|---|
 | 672 |    float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
 | 
|---|
 | 673 |    float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
 | 
|---|
| [20e0020] | 674 | 
 | 
|---|
| [1f3d32b] | 675 |    float proj_arr[] = {
 | 
|---|
 | 676 |      Sx, 0.0f, 0.0f, 0.0f,
 | 
|---|
 | 677 |      0.0f, Sy, 0.0f, 0.0f,
 | 
|---|
 | 678 |      0.0f, 0.0f, Sz, -1.0f,
 | 
|---|
 | 679 |      0.0f, 0.0f, Pz, 0.0f,
 | 
|---|
| [f9a242b] | 680 |    };
 | 
|---|
| [1f3d32b] | 681 |    proj_mat = make_mat4(proj_arr);
 | 
|---|
| [81f28c0] | 682 | 
 | 
|---|
| [b220f78] | 683 |    initializeParticleEffectBuffers(vec3(0.0f, -1.2f, 0.65f),
 | 
|---|
| [646f3f2] | 684 |       shaderBufferInfo,
 | 
|---|
| [0414306] | 685 |       modelGroups,
 | 
|---|
| [646f3f2] | 686 |       points_vbo,
 | 
|---|
 | 687 |       colors_vbo,
 | 
|---|
 | 688 |       texcoords_vbo,
 | 
|---|
 | 689 |       normals_vbo,
 | 
|---|
 | 690 |       ubo,
 | 
|---|
 | 691 |       model_mat_idx_vbo);
 | 
|---|
| [fe5e3ca] | 692 | 
 | 
|---|
| [c5fb958] | 693 |    /* TODO: Fix the UBO binding code based on the following forum post (in order to support multiple ubos):
 | 
|---|
 | 694 | 
 | 
|---|
 | 695 |       No, you're misunderstanding how this works. UBO binding works exactly like texture object binding.
 | 
|---|
 | 696 | 
 | 
|---|
 | 697 |       The OpenGL context has a number of slots for binding UBOs. There are GL_MAX_UNIFORM_BUFFER_BINDINGS number of
 | 
|---|
 | 698 |       slots for UBO binding.
 | 
|---|
 | 699 | 
 | 
|---|
 | 700 |       Uniform Blocks in a program can be set to use one of the slots in the context. You do this by first querying
 | 
|---|
 | 701 |       the block index using the block name (glGetUniformBlockIndex). This is similar to how you need to use
 | 
|---|
 | 702 |       glGetUniformLocation in order to set a uniform's value with glUniform. Block indices, like uniform locations,
 | 
|---|
 | 703 |       are specific to a program.
 | 
|---|
 | 704 | 
 | 
|---|
 | 705 |       Once you have the block index, you use glUniformBlockBinding to set that specific program to use a particular
 | 
|---|
 | 706 |       uniform buffer slot in the context.
 | 
|---|
 | 707 | 
 | 
|---|
 | 708 |       Let's say you have a global UBO that you want to use for every program. To make using it easier, you want to
 | 
|---|
 | 709 |       bind it just once.
 | 
|---|
 | 710 | 
 | 
|---|
 | 711 |       So first, you pick a uniform buffer slot in the context, one that always will refer to this UBO. Let's say
 | 
|---|
 | 712 |       you pick slot 8.
 | 
|---|
 | 713 | 
 | 
|---|
 | 714 |       When you build a program object that may use this global uniform buffer, what you do is quite simple. First,
 | 
|---|
 | 715 |       after linking the program, call glGetUniformBlockIndex(program, "NameOfGlobalUniformBlock"). If you get back
 | 
|---|
 | 716 |       GL_INVALID_INDEX, then you know that the global uniform block isn't used in that program. Otherwise you get
 | 
|---|
 | 717 |       back a block index.
 | 
|---|
 | 718 | 
 | 
|---|
 | 719 |       If you got a valid block index, then you call glUniformBlockBinding(program, uniformBlockIndex, 8). Remember
 | 
|---|
 | 720 |       that 8 is the uniform buffer context slot that we selected earlier. This causes this particular program to
 | 
|---|
 | 721 |       use uniform buffer slot #8 to find the buffer for "NameOfGlobalUniformBlock".
 | 
|---|
 | 722 | 
 | 
|---|
 | 723 |       Finally, to set the actual buffer in the context, call glBindBufferRange(GL_UNIFORM_BUFFER, 8,
 | 
|---|
 | 724 |       bufferObjectName, offset, size);
 | 
|---|
 | 725 |    */
 | 
|---|
| [fe5e3ca] | 726 | 
 | 
|---|
| [1f3d32b] | 727 |    GLuint ub_binding_point = 0;
 | 
|---|
| [81f28c0] | 728 | 
 | 
|---|
| [4c7cd57] | 729 |    GLuint ship_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_SHIP].shaderProgram, "models");
 | 
|---|
| [0e0f851] | 730 | 
 | 
|---|
| [0414306] | 731 |    GLuint asteroid_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_ASTEROID].shaderProgram, "models");
 | 
|---|
| [81f28c0] | 732 | 
 | 
|---|
| [b62c109] | 733 |    GLuint laser_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_LASER].shaderProgram, "models");
 | 
|---|
| [81f28c0] | 734 | 
 | 
|---|
| [0414306] | 735 |    GLuint explosion_sp_models_ub_index = glGetUniformBlockIndex(modelGroups[TYPE_EXPLOSION].shaderProgram, "models");
 | 
|---|
| [db06984] | 736 | 
 | 
|---|
| [81f28c0] | 737 | 
 | 
|---|
| [4c7cd57] | 738 |    glUseProgram(modelGroups[TYPE_SHIP].shaderProgram);
 | 
|---|
| [49db5fc] | 739 |    bindUniformData(modelGroups[TYPE_SHIP].attribs["view"]);
 | 
|---|
 | 740 |    bindUniformData(modelGroups[TYPE_SHIP].attribs["proj"]);
 | 
|---|
| [485424b] | 741 | 
 | 
|---|
| [4c7cd57] | 742 |    glUniformBlockBinding(modelGroups[TYPE_SHIP].shaderProgram, ship_sp_models_ub_index, ub_binding_point);
 | 
|---|
| [14ff67c] | 743 |    glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
 | 
|---|
| [e165b85] | 744 | 
 | 
|---|
| [fd6f465] | 745 | 
 | 
|---|
| [0414306] | 746 |    glUseProgram(modelGroups[TYPE_ASTEROID].shaderProgram);
 | 
|---|
| [49db5fc] | 747 |    bindUniformData(modelGroups[TYPE_ASTEROID].attribs["view"]);
 | 
|---|
 | 748 |    bindUniformData(modelGroups[TYPE_ASTEROID].attribs["proj"]);
 | 
|---|
| [0e0f851] | 749 | 
 | 
|---|
| [0414306] | 750 |    glUniformBlockBinding(modelGroups[TYPE_ASTEROID].shaderProgram, asteroid_sp_models_ub_index, ub_binding_point);
 | 
|---|
| [0e0f851] | 751 |    glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
 | 
|---|
 | 752 | 
 | 
|---|
 | 753 | 
 | 
|---|
| [49db5fc] | 754 |    // may want to do initialization for basic_texture uniform here too
 | 
|---|
 | 755 |    // Right now, I think I'm getting away without getting that uniform location because I'm only
 | 
|---|
 | 756 |    // using one texture, so setting it to GL_TEXTURE0 once works
 | 
|---|
| [b62c109] | 757 |    glUseProgram(modelGroups[TYPE_LASER].shaderProgram);
 | 
|---|
| [49db5fc] | 758 |    bindUniformData(modelGroups[TYPE_LASER].attribs["view"]);
 | 
|---|
 | 759 |    bindUniformData(modelGroups[TYPE_LASER].attribs["proj"]);
 | 
|---|
 | 760 |    bindUniformData(modelGroups[TYPE_LASER].attribs["laser_color"]);
 | 
|---|
| [b155f13] | 761 | 
 | 
|---|
| [b62c109] | 762 |    glUniformBlockBinding(modelGroups[TYPE_LASER].shaderProgram, laser_sp_models_ub_index, ub_binding_point);
 | 
|---|
| [fd6f465] | 763 |    glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
 | 
|---|
 | 764 | 
 | 
|---|
 | 765 | 
 | 
|---|
| [0414306] | 766 |    glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 | 
|---|
 | 767 |    glUniformBlockBinding(modelGroups[TYPE_EXPLOSION].shaderProgram, explosion_sp_models_ub_index, ub_binding_point);
 | 
|---|
| [646f3f2] | 768 |    glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
 | 
|---|
 | 769 | 
 | 
|---|
 | 770 | 
 | 
|---|
| [7ee66ea] | 771 |    bool cam_moved = false;
 | 
|---|
 | 772 | 
 | 
|---|
| [046ce72] | 773 |    int frame_count = 0;
 | 
|---|
| [f70ab75] | 774 |    double elapsed_seconds_fps = 0.0f;
 | 
|---|
| [5527206] | 775 |    double elapsed_seconds_spawn = 0.0f;
 | 
|---|
| [b220f78] | 776 | 
 | 
|---|
 | 777 |    prevTime = glfwGetTime();
 | 
|---|
| [046ce72] | 778 | 
 | 
|---|
| [9dd2eb7] | 779 |    // This draws wireframes. Useful for seeing separate faces and occluded objects.
 | 
|---|
 | 780 |    //glPolygonMode(GL_FRONT, GL_LINE);
 | 
|---|
 | 781 | 
 | 
|---|
| [1f3d32b] | 782 |    // disable vsync to see real framerate
 | 
|---|
 | 783 |    //glfwSwapInterval(0);
 | 
|---|
| [1c81bf0] | 784 | 
 | 
|---|
| [93462c6] | 785 |    State curState = STATE_MAIN_MENU;
 | 
|---|
 | 786 | 
 | 
|---|
| [5b3462b] | 787 |    while (!glfwWindowShouldClose(window) && isRunning) {
 | 
|---|
| [b220f78] | 788 |       curTime = glfwGetTime();
 | 
|---|
 | 789 |       elapsedTime = curTime - prevTime;
 | 
|---|
| [8fbd34f] | 790 | 
 | 
|---|
 | 791 |       // temporary code to get around vsync issue in OSX Sierra
 | 
|---|
| [b220f78] | 792 |       if (elapsedTime < (1.0f / TARGET_FPS)) {
 | 
|---|
| [8fbd34f] | 793 |         continue;
 | 
|---|
 | 794 |       }
 | 
|---|
 | 795 | 
 | 
|---|
| [b220f78] | 796 |       prevTime = curTime;
 | 
|---|
| [93baa0e] | 797 | 
 | 
|---|
| [b220f78] | 798 |       elapsed_seconds_fps += elapsedTime;
 | 
|---|
| [1f3d32b] | 799 |       if (elapsed_seconds_fps > 0.25f) {
 | 
|---|
 | 800 |          fps = (double)frame_count / elapsed_seconds_fps;
 | 
|---|
| [046ce72] | 801 | 
 | 
|---|
| [1f3d32b] | 802 |          frame_count = 0;
 | 
|---|
 | 803 |          elapsed_seconds_fps = 0.0f;
 | 
|---|
| [14ff67c] | 804 |       }
 | 
|---|
| [046ce72] | 805 | 
 | 
|---|
| [1f3d32b] | 806 |       frame_count++;
 | 
|---|
 | 807 | 
 | 
|---|
| [f7d35da] | 808 |       // Handle events
 | 
|---|
| [baa5848] | 809 | 
 | 
|---|
 | 810 |       clickedObject = NULL;
 | 
|---|
| [f7d35da] | 811 | 
 | 
|---|
 | 812 |       // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
 | 
|---|
 | 813 |       // so that GLFW_PRESS and GLFW_RELEASE are only detected once
 | 
|---|
| [cf2d1e5] | 814 |       // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down
 | 
|---|
 | 815 |       //  continuously for a period of time)
 | 
|---|
| [f7d35da] | 816 |       fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
 | 
|---|
 | 817 | 
 | 
|---|
| [baa5848] | 818 |       glfwPollEvents();
 | 
|---|
 | 819 | 
 | 
|---|
| [93462c6] | 820 |       while (!events.empty()) {
 | 
|---|
 | 821 |          switch (events.front()) {
 | 
|---|
 | 822 |             case EVENT_GO_TO_MAIN_MENU:
 | 
|---|
 | 823 |                curState = STATE_MAIN_MENU;
 | 
|---|
 | 824 |                break;
 | 
|---|
 | 825 |             case EVENT_GO_TO_GAME:
 | 
|---|
 | 826 |                curState = STATE_GAME;
 | 
|---|
 | 827 |                break;
 | 
|---|
 | 828 |             case EVENT_QUIT:
 | 
|---|
 | 829 |                isRunning = false;
 | 
|---|
 | 830 |                break;
 | 
|---|
 | 831 |          }
 | 
|---|
 | 832 |          events.pop();
 | 
|---|
| [147ac6d] | 833 |       }
 | 
|---|
| [93462c6] | 834 | 
 | 
|---|
 | 835 |       if (curState == STATE_GAME) {
 | 
|---|
| [95595de] | 836 | 
 | 
|---|
| [b220f78] | 837 |          elapsed_seconds_spawn += elapsedTime;
 | 
|---|
| [95595de] | 838 |          if (elapsed_seconds_spawn > 0.5f) {
 | 
|---|
| [dd9771c] | 839 |             SceneObject* obj = createAsteroid(vec3(getRandomNum(-1.3f, 1.3f), -1.2f, getRandomNum(-5.5f, -4.5f)));
 | 
|---|
| [0414306] | 840 |             addObjectToScene(obj, shaderBufferInfo, modelGroups,
 | 
|---|
| [95595de] | 841 |                points_vbo,
 | 
|---|
 | 842 |                colors_vbo,
 | 
|---|
 | 843 |                texcoords_vbo,
 | 
|---|
 | 844 |                normals_vbo,
 | 
|---|
 | 845 |                ubo,
 | 
|---|
| [0414306] | 846 |                model_mat_idx_vbo);
 | 
|---|
| [95595de] | 847 | 
 | 
|---|
 | 848 |             elapsed_seconds_spawn -= 0.5f;
 | 
|---|
 | 849 |          }
 | 
|---|
 | 850 | 
 | 
|---|
| [cf2d1e5] | 851 |          /*
 | 
|---|
| [93462c6] | 852 |          if (clickedObject == &objects[0]) {
 | 
|---|
 | 853 |             selectedObject = &objects[0];
 | 
|---|
 | 854 |          }
 | 
|---|
 | 855 |          if (clickedObject == &objects[1]) {
 | 
|---|
 | 856 |             selectedObject = &objects[1];
 | 
|---|
 | 857 |          }
 | 
|---|
| [cf2d1e5] | 858 |          */
 | 
|---|
| [f7d35da] | 859 | 
 | 
|---|
 | 860 |          /*
 | 
|---|
 | 861 |          if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
 | 
|---|
| [dba67b2] | 862 |             transformObject(objects[1], translate(mat4(1.0f), vec3(0.3f, 0.0f, 0.0f)), ubo);
 | 
|---|
| [f7d35da] | 863 |          }
 | 
|---|
| [fabed35] | 864 |          if (key_down[GLFW_KEY_RIGHT]) {
 | 
|---|
| [dba67b2] | 865 |             transformObject(objects[2], translate(mat4(1.0f), vec3(0.01f, 0.0f, 0.0f)), ubo);
 | 
|---|
| [f7d35da] | 866 |          }
 | 
|---|
| [fabed35] | 867 |          if (key_down[GLFW_KEY_LEFT]) {
 | 
|---|
| [dba67b2] | 868 |             transformObject(objects[2], translate(mat4(1.0f), vec3(-0.01f, 0.0f, 0.0f)), ubo);
 | 
|---|
| [f7d35da] | 869 |          }
 | 
|---|
 | 870 |          */
 | 
|---|
| [cf2d1e5] | 871 | 
 | 
|---|
| [fabed35] | 872 |          if (key_down[GLFW_KEY_RIGHT]) {
 | 
|---|
| [1f3d32b] | 873 |             transformObject(*objects[0], translate(mat4(1.0f), vec3(0.01f, 0.0f, 0.0f)), ubo);
 | 
|---|
| [fabed35] | 874 | 
 | 
|---|
| [1f3d32b] | 875 |             if (leftLaser != NULL && !leftLaser->deleted) {
 | 
|---|
 | 876 |                translateLaser(leftLaser, vec3(0.01f, 0.0f, 0.0f), ubo);
 | 
|---|
| [fabed35] | 877 |             }
 | 
|---|
| [1f3d32b] | 878 |             if (rightLaser != NULL && !rightLaser->deleted) {
 | 
|---|
 | 879 |                translateLaser(rightLaser, vec3(0.01f, 0.0f, 0.0f), ubo);
 | 
|---|
| [fabed35] | 880 |             }
 | 
|---|
| [cf2d1e5] | 881 |          }
 | 
|---|
| [fabed35] | 882 |          if (key_down[GLFW_KEY_LEFT]) {
 | 
|---|
| [1f3d32b] | 883 |             transformObject(*objects[0], translate(mat4(1.0f), vec3(-0.01f, 0.0f, 0.0f)), ubo);
 | 
|---|
| [fabed35] | 884 | 
 | 
|---|
| [1f3d32b] | 885 |             if (leftLaser != NULL && !leftLaser->deleted) {
 | 
|---|
 | 886 |                translateLaser(leftLaser, vec3(-0.01f, 0.0f, 0.0f), ubo);
 | 
|---|
| [fabed35] | 887 |             }
 | 
|---|
| [1f3d32b] | 888 |             if (rightLaser != NULL && !rightLaser->deleted) {
 | 
|---|
 | 889 |                translateLaser(rightLaser, vec3(-0.01f, 0.0f, 0.0f), ubo);
 | 
|---|
| [fabed35] | 890 |             }
 | 
|---|
| [8316333] | 891 |          }
 | 
|---|
| [fabed35] | 892 | 
 | 
|---|
 | 893 |          if (key_state[GLFW_KEY_Z] == GLFW_PRESS) {
 | 
|---|
| [1f3d32b] | 894 |             vec3 offset(objects[0]->model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
| [8316333] | 895 | 
 | 
|---|
| [dd9771c] | 896 |             leftLaser = createLaser(
 | 
|---|
 | 897 |                vec3(-0.21f, -1.19f, 1.76f)+offset,
 | 
|---|
 | 898 |                vec3(-0.21f, -1.19f, -3.0f)+offset,
 | 
|---|
 | 899 |                vec3(0.0f, 1.0f, 0.0f), 0.03f);
 | 
|---|
| [0414306] | 900 |             addObjectToScene(leftLaser, shaderBufferInfo, modelGroups,
 | 
|---|
| [8316333] | 901 |                points_vbo,
 | 
|---|
 | 902 |                colors_vbo,
 | 
|---|
 | 903 |                texcoords_vbo,
 | 
|---|
 | 904 |                normals_vbo,
 | 
|---|
 | 905 |                ubo,
 | 
|---|
| [0414306] | 906 |                model_mat_idx_vbo);
 | 
|---|
| [fabed35] | 907 |          } else if (key_state[GLFW_KEY_Z] == GLFW_RELEASE) {
 | 
|---|
| [1f3d32b] | 908 |             removeObjectFromScene(*leftLaser, ubo);
 | 
|---|
| [8316333] | 909 |          }
 | 
|---|
| [fabed35] | 910 | 
 | 
|---|
 | 911 |          if (key_state[GLFW_KEY_X] == GLFW_PRESS) {
 | 
|---|
| [1f3d32b] | 912 |             vec3 offset(objects[0]->model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
| [8316333] | 913 | 
 | 
|---|
| [dd9771c] | 914 |             rightLaser = createLaser(
 | 
|---|
 | 915 |                vec3(0.21f, -1.19f, 1.76f) + offset,
 | 
|---|
 | 916 |                vec3(0.21f, -1.19f, -3.0f) + offset,
 | 
|---|
 | 917 |                vec3(0.0f, 1.0f, 0.0f), 0.03f);
 | 
|---|
| [0414306] | 918 |             addObjectToScene(rightLaser, shaderBufferInfo, modelGroups,
 | 
|---|
| [8316333] | 919 |                points_vbo,
 | 
|---|
 | 920 |                colors_vbo,
 | 
|---|
 | 921 |                texcoords_vbo,
 | 
|---|
 | 922 |                normals_vbo,
 | 
|---|
 | 923 |                ubo,
 | 
|---|
| [0414306] | 924 |                model_mat_idx_vbo);
 | 
|---|
| [fabed35] | 925 |          } else if (key_state[GLFW_KEY_X] == GLFW_RELEASE) {
 | 
|---|
| [1f3d32b] | 926 |             removeObjectFromScene(*rightLaser, ubo);
 | 
|---|
| [cf2d1e5] | 927 |          }
 | 
|---|
 | 928 | 
 | 
|---|
| [92b1e90] | 929 |          // this code moves the asteroids
 | 
|---|
| [8e8aed6] | 930 |          for (unsigned int i = 0; i < objects.size(); i++) {
 | 
|---|
| [1f3d32b] | 931 |             if (objects[i]->type == TYPE_ASTEROID && !objects[i]->deleted) {
 | 
|---|
 | 932 |                transformObject(*objects[i], translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.04f)), ubo);
 | 
|---|
| [95595de] | 933 | 
 | 
|---|
| [1f3d32b] | 934 |                vec3 obj_center = vec3(view_mat * vec4(objects[i]->bounding_center, 1.0f));
 | 
|---|
| [ebaa95c] | 935 | 
 | 
|---|
| [1f3d32b] | 936 |                if ((obj_center.z - objects[i]->bounding_radius) > -NEAR_CLIP) {
 | 
|---|
 | 937 |                   removeObjectFromScene(*objects[i], ubo);
 | 
|---|
| [95595de] | 938 |                }
 | 
|---|
| [2b0214c] | 939 |                if (((Asteroid*)objects[i])->hp <= 0) {
 | 
|---|
| [646f3f2] | 940 |                   // TODO: Optimize this so I don't recalculate the camera rotation every time
 | 
|---|
 | 941 |                   float cam_pitch = -50.0f * 2.0f * 3.14159f / 360.0f;
 | 
|---|
 | 942 |                   mat4 pitch_mat = rotate(mat4(1.0f), cam_pitch, vec3(1.0f, 0.0f, 0.0f));
 | 
|---|
 | 943 |                   mat4 model_mat = translate(mat4(1.0f), objects[i]->bounding_center + vec3(0.0f, 0.0f, 0.0f)) * pitch_mat;
 | 
|---|
 | 944 | 
 | 
|---|
| [2b0214c] | 945 |                   removeObjectFromScene(*objects[i], ubo);
 | 
|---|
| [1e3dddf] | 946 |                   score++;
 | 
|---|
| [adb104f] | 947 | 
 | 
|---|
| [646f3f2] | 948 |                   objExplosion->model_mat = model_mat;
 | 
|---|
 | 949 | 
 | 
|---|
 | 950 |                   // initiate an explosion
 | 
|---|
| [0414306] | 951 |                   glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 | 
|---|
| [646f3f2] | 952 | 
 | 
|---|
| [b220f78] | 953 |                   bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["explosion_start_time"]);
 | 
|---|
 | 954 |                   bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["model_mat"], value_ptr(objExplosion->model_mat));
 | 
|---|
| [2b0214c] | 955 |                }
 | 
|---|
| [5527206] | 956 |             }
 | 
|---|
| [cf2d1e5] | 957 |          }
 | 
|---|
| [93baa0e] | 958 | 
 | 
|---|
| [1f3d32b] | 959 |          if (leftLaser != NULL && !leftLaser->deleted) {
 | 
|---|
| [a0eb547] | 960 |             updateLaserTarget(leftLaser, objects, modelGroups[TYPE_LASER], modelGroups[TYPE_ASTEROID].shaderProgram);
 | 
|---|
| [1f3d32b] | 961 |          }
 | 
|---|
 | 962 |          if (rightLaser != NULL && !rightLaser->deleted) {
 | 
|---|
| [a0eb547] | 963 |             updateLaserTarget(rightLaser, objects, modelGroups[TYPE_LASER], modelGroups[TYPE_ASTEROID].shaderProgram);
 | 
|---|
| [1f3d32b] | 964 |          }
 | 
|---|
 | 965 |       }
 | 
|---|
 | 966 | 
 | 
|---|
 | 967 |       for (vector<EffectOverTime*>::iterator it = effects.begin(); it != effects.end(); ) {
 | 
|---|
 | 968 |          if ((*it)->deleted || (*it)->effectedObject->deleted) {
 | 
|---|
 | 969 |             delete *it;
 | 
|---|
 | 970 |             it = effects.erase(it);
 | 
|---|
 | 971 |          } else {
 | 
|---|
 | 972 |             EffectOverTime* eot = *it;
 | 
|---|
| [b220f78] | 973 |             eot->effectedValue = eot->startValue + (curTime - eot->startTime) * eot->changePerSecond;
 | 
|---|
| [1f3d32b] | 974 | 
 | 
|---|
 | 975 |             it++;
 | 
|---|
| [c3c3158] | 976 |          }
 | 
|---|
| [baa5848] | 977 |       }
 | 
|---|
| [df652d5] | 978 | 
 | 
|---|
| [c3c3158] | 979 |       if (key_state[GLFW_KEY_ESCAPE] == GLFW_PRESS) {
 | 
|---|
| [ec4456b] | 980 |          glfwSetWindowShouldClose(window, 1);
 | 
|---|
 | 981 |       }
 | 
|---|
| [7ee66ea] | 982 | 
 | 
|---|
| [b220f78] | 983 |       float dist = cam_speed * elapsedTime;
 | 
|---|
| [fabed35] | 984 |       if (key_down[GLFW_KEY_A]) {
 | 
|---|
| [dba67b2] | 985 |          vec3 dir = vec3(inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
| [809ce16] | 986 |          cam_pos += dir * dist;
 | 
|---|
| [f7d35da] | 987 | 
 | 
|---|
| [7ee66ea] | 988 |          cam_moved = true;
 | 
|---|
 | 989 |       }
 | 
|---|
| [fabed35] | 990 |       if (key_down[GLFW_KEY_D]) {
 | 
|---|
| [dba67b2] | 991 |          vec3 dir = vec3(inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
| [809ce16] | 992 |          cam_pos += dir * dist;
 | 
|---|
| [f7d35da] | 993 | 
 | 
|---|
| [7ee66ea] | 994 |          cam_moved = true;
 | 
|---|
 | 995 |       }
 | 
|---|
| [fabed35] | 996 |       if (key_down[GLFW_KEY_W]) {
 | 
|---|
| [dba67b2] | 997 |          vec3 dir = vec3(inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f));
 | 
|---|
| [809ce16] | 998 |          cam_pos += dir * dist;
 | 
|---|
| [f7d35da] | 999 | 
 | 
|---|
| [7ee66ea] | 1000 |          cam_moved = true;
 | 
|---|
 | 1001 |       }
 | 
|---|
| [fabed35] | 1002 |       if (key_down[GLFW_KEY_S]) {
 | 
|---|
| [dba67b2] | 1003 |          vec3 dir = vec3(inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f));
 | 
|---|
| [809ce16] | 1004 |          cam_pos += dir * dist;
 | 
|---|
| [f7d35da] | 1005 | 
 | 
|---|
| [7ee66ea] | 1006 |          cam_moved = true;
 | 
|---|
 | 1007 |       }
 | 
|---|
| [cf2d1e5] | 1008 |       /*
 | 
|---|
| [fabed35] | 1009 |       if (key_down[GLFW_KEY_LEFT]) {
 | 
|---|
| [b220f78] | 1010 |       cam_yaw += cam_yaw_speed * elapsedTime;
 | 
|---|
| [c3c3158] | 1011 |       cam_moved = true;
 | 
|---|
| [7ee66ea] | 1012 |       }
 | 
|---|
| [fabed35] | 1013 |       if (key_down[GLFW_KEY_RIGHT]) {
 | 
|---|
| [b220f78] | 1014 |       cam_yaw -= cam_yaw_speed * elapsedTime;
 | 
|---|
| [c3c3158] | 1015 |       cam_moved = true;
 | 
|---|
| [7ee66ea] | 1016 |       }
 | 
|---|
| [fabed35] | 1017 |       if (key_down[GLFW_KEY_UP]) {
 | 
|---|
| [b220f78] | 1018 |       cam_pitch += cam_pitch_speed * elapsedTime;
 | 
|---|
| [c3c3158] | 1019 |       cam_moved = true;
 | 
|---|
| [809ce16] | 1020 |       }
 | 
|---|
| [fabed35] | 1021 |       if (key_down[GLFW_KEY_DOWN]) {
 | 
|---|
| [b220f78] | 1022 |       cam_pitch -= cam_pitch_speed * elapsedTime;
 | 
|---|
| [c3c3158] | 1023 |       cam_moved = true;
 | 
|---|
| [809ce16] | 1024 |       }
 | 
|---|
| [cf2d1e5] | 1025 |       */
 | 
|---|
| [1f3d32b] | 1026 |       if (cam_moved && false) { // disable camera movement
 | 
|---|
| [dba67b2] | 1027 |          T = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
 | 
|---|
| [809ce16] | 1028 | 
 | 
|---|
| [dba67b2] | 1029 |          mat4 yaw_mat = rotate(mat4(1.0f), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
 | 
|---|
 | 1030 |          mat4 pitch_mat = rotate(mat4(1.0f), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
 | 
|---|
| [809ce16] | 1031 |          R = pitch_mat * yaw_mat;
 | 
|---|
| [f7d35da] | 1032 | 
 | 
|---|
| [c3c3158] | 1033 |          view_mat = R * T;
 | 
|---|
| [7ee66ea] | 1034 | 
 | 
|---|
| [4c7cd57] | 1035 |          glUseProgram(modelGroups[TYPE_SHIP].shaderProgram);
 | 
|---|
| [49db5fc] | 1036 |          bindUniformData(modelGroups[TYPE_SHIP].attribs["view"]);
 | 
|---|
| [267c4c5] | 1037 | 
 | 
|---|
| [b62c109] | 1038 |          glUseProgram(modelGroups[TYPE_LASER].shaderProgram);
 | 
|---|
| [49db5fc] | 1039 |          bindUniformData(modelGroups[TYPE_LASER].attribs["view"]);
 | 
|---|
| [b155f13] | 1040 | 
 | 
|---|
| [7ee66ea] | 1041 |          cam_moved = false;
 | 
|---|
 | 1042 |       }
 | 
|---|
| [c3c3158] | 1043 | 
 | 
|---|
| [0414306] | 1044 |       glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 | 
|---|
| [b220f78] | 1045 |       bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["cur_time"]);
 | 
|---|
| [db06984] | 1046 | 
 | 
|---|
| [c3c3158] | 1047 |       // Render scene
 | 
|---|
 | 1048 | 
 | 
|---|
 | 1049 |       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
|---|
 | 1050 | 
 | 
|---|
 | 1051 |       switch (curState) {
 | 
|---|
 | 1052 |          case STATE_MAIN_MENU:
 | 
|---|
 | 1053 |             renderMainMenu();
 | 
|---|
 | 1054 |             renderMainMenuGui();
 | 
|---|
 | 1055 |             break;
 | 
|---|
 | 1056 |          case STATE_GAME:
 | 
|---|
| [b62c109] | 1057 |             renderScene(shaderBufferInfo, modelGroups, ubo);
 | 
|---|
| [c3c3158] | 1058 |             renderSceneGui();
 | 
|---|
 | 1059 |             break;
 | 
|---|
 | 1060 |       }
 | 
|---|
 | 1061 | 
 | 
|---|
 | 1062 |       glfwSwapBuffers(window);
 | 
|---|
| [644a2e4] | 1063 |    }
 | 
|---|
 | 1064 | 
 | 
|---|
| [c1ca5b5] | 1065 |    ImGui_ImplGlfwGL3_Shutdown();
 | 
|---|
 | 1066 |    ImGui::DestroyContext();
 | 
|---|
 | 1067 | 
 | 
|---|
 | 1068 |    glfwDestroyWindow(window);
 | 
|---|
| [5272b6b] | 1069 |    glfwTerminate();
 | 
|---|
| [c1ca5b5] | 1070 | 
 | 
|---|
| [1f3d32b] | 1071 |    // free memory
 | 
|---|
 | 1072 | 
 | 
|---|
 | 1073 |    for (vector<SceneObject*>::iterator it = objects.begin(); it != objects.end(); it++) {
 | 
|---|
 | 1074 |       delete *it;
 | 
|---|
 | 1075 |    }
 | 
|---|
 | 1076 | 
 | 
|---|
| [5272b6b] | 1077 |    return 0;
 | 
|---|
 | 1078 | }
 | 
|---|
| [ec4456b] | 1079 | 
 | 
|---|
| [4f3262f] | 1080 | void glfw_error_callback(int error, const char* description) {
 | 
|---|
 | 1081 |    gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
 | 
|---|
 | 1082 | }
 | 
|---|
 | 1083 | 
 | 
|---|
 | 1084 | void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
 | 
|---|
 | 1085 |    double mouse_x, mouse_y;
 | 
|---|
 | 1086 |    glfwGetCursorPos(window, &mouse_x, &mouse_y);
 | 
|---|
 | 1087 | 
 | 
|---|
 | 1088 |    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
 | 
|---|
 | 1089 |       cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
 | 
|---|
 | 1090 |       selectedObject = NULL;
 | 
|---|
 | 1091 | 
 | 
|---|
 | 1092 |       float x = (2.0f*mouse_x) / width - 1.0f;
 | 
|---|
 | 1093 |       float y = 1.0f - (2.0f*mouse_y) / height;
 | 
|---|
 | 1094 | 
 | 
|---|
 | 1095 |       cout << "x: " << x << ", y: " << y << endl;
 | 
|---|
 | 1096 | 
 | 
|---|
 | 1097 |       vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
 | 
|---|
 | 1098 |       vec4 ray_eye = inverse(proj_mat) * ray_clip;
 | 
|---|
| [dba67b2] | 1099 |       ray_eye = vec4(vec2(ray_eye), -1.0f, 1.0f);
 | 
|---|
| [4f3262f] | 1100 |       vec4 ray_world = inverse(view_mat) * ray_eye;
 | 
|---|
 | 1101 | 
 | 
|---|
 | 1102 |       vec4 click_point;
 | 
|---|
 | 1103 |       vec3 closest_point = vec3(0.0f, 0.0f, -FAR_CLIP); // Any valid point will be closer than the far clipping plane, so initial value to that
 | 
|---|
 | 1104 |       SceneObject* closest_object = NULL;
 | 
|---|
 | 1105 | 
 | 
|---|
| [1f3d32b] | 1106 |       for (vector<SceneObject*>::iterator it = objects.begin(); it != objects.end(); it++) {
 | 
|---|
 | 1107 |          if ((*it)->type == TYPE_LASER) continue;
 | 
|---|
 | 1108 |          for (unsigned int p_idx = 0; p_idx < (*it)->points.size(); p_idx += 9) {
 | 
|---|
| [0d5c100] | 1109 |             if (faceClicked(
 | 
|---|
 | 1110 |                {
 | 
|---|
| [1f3d32b] | 1111 |                   vec3((*it)->points[p_idx], (*it)->points[p_idx + 1], (*it)->points[p_idx + 2]),
 | 
|---|
 | 1112 |                   vec3((*it)->points[p_idx + 3], (*it)->points[p_idx + 4], (*it)->points[p_idx + 5]),
 | 
|---|
 | 1113 |                   vec3((*it)->points[p_idx + 6], (*it)->points[p_idx + 7], (*it)->points[p_idx + 8]),
 | 
|---|
| [4f3262f] | 1114 |                },
 | 
|---|
| [1f3d32b] | 1115 |                *it, ray_world, vec4(cam_pos, 1.0f), click_point
 | 
|---|
| [0d5c100] | 1116 |             )) {
 | 
|---|
| [4f3262f] | 1117 |                click_point = view_mat * click_point;
 | 
|---|
 | 1118 | 
 | 
|---|
 | 1119 |                if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
 | 
|---|
| [dba67b2] | 1120 |                   closest_point = vec3(click_point);
 | 
|---|
| [1f3d32b] | 1121 |                   closest_object = *it;
 | 
|---|
| [4f3262f] | 1122 |                }
 | 
|---|
 | 1123 |             }
 | 
|---|
 | 1124 |          }
 | 
|---|
 | 1125 |       }
 | 
|---|
 | 1126 | 
 | 
|---|
 | 1127 |       if (closest_object == NULL) {
 | 
|---|
 | 1128 |          cout << "No object was clicked" << endl;
 | 
|---|
| [f7d35da] | 1129 |       } else {
 | 
|---|
| [4f3262f] | 1130 |          clickedObject = closest_object;
 | 
|---|
 | 1131 |          cout << "Clicked object: " << clickedObject->id << endl;
 | 
|---|
 | 1132 |       }
 | 
|---|
 | 1133 |    }
 | 
|---|
 | 1134 | }
 | 
|---|
 | 1135 | 
 | 
|---|
| [f7d35da] | 1136 | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
 | 
|---|
 | 1137 |    key_state[key] = action;
 | 
|---|
 | 1138 | 
 | 
|---|
 | 1139 |    // should be true for GLFW_PRESS and GLFW_REPEAT
 | 
|---|
| [fabed35] | 1140 |    key_down[key] = (action != GLFW_RELEASE);
 | 
|---|
| [f7d35da] | 1141 | }
 | 
|---|
 | 1142 | 
 | 
|---|
| [0e0f851] | 1143 | void APIENTRY debugGlCallback(
 | 
|---|
 | 1144 |    GLenum source,
 | 
|---|
 | 1145 |    GLenum type,
 | 
|---|
 | 1146 |    GLuint id,
 | 
|---|
 | 1147 |    GLenum severity,
 | 
|---|
 | 1148 |    GLsizei length,
 | 
|---|
 | 1149 |    const GLchar* message,
 | 
|---|
 | 1150 |    const void* userParam
 | 
|---|
 | 1151 | ) {
 | 
|---|
 | 1152 |    string strMessage(message);
 | 
|---|
 | 1153 | 
 | 
|---|
 | 1154 |    // TODO: Use C++ strings directly
 | 
|---|
 | 1155 |    char source_str[2048];
 | 
|---|
 | 1156 |    char type_str[2048];
 | 
|---|
 | 1157 |    char severity_str[2048];
 | 
|---|
 | 1158 | 
 | 
|---|
 | 1159 |    switch (source) {
 | 
|---|
| [a0eb547] | 1160 |       case 0x8246:
 | 
|---|
 | 1161 |          strcpy(source_str, "API");
 | 
|---|
 | 1162 |          break;
 | 
|---|
 | 1163 |       case 0x8247:
 | 
|---|
 | 1164 |          strcpy(source_str, "WINDOW_SYSTEM");
 | 
|---|
 | 1165 |          break;
 | 
|---|
 | 1166 |       case 0x8248:
 | 
|---|
 | 1167 |          strcpy(source_str, "SHADER_COMPILER");
 | 
|---|
 | 1168 |          break;
 | 
|---|
 | 1169 |       case 0x8249:
 | 
|---|
 | 1170 |          strcpy(source_str, "THIRD_PARTY");
 | 
|---|
 | 1171 |          break;
 | 
|---|
 | 1172 |       case 0x824A:
 | 
|---|
 | 1173 |          strcpy(source_str, "APPLICATION");
 | 
|---|
 | 1174 |          break;
 | 
|---|
 | 1175 |       case 0x824B:
 | 
|---|
 | 1176 |          strcpy(source_str, "OTHER");
 | 
|---|
 | 1177 |          break;
 | 
|---|
 | 1178 |       default:
 | 
|---|
 | 1179 |          strcpy(source_str, "undefined");
 | 
|---|
 | 1180 |          break;
 | 
|---|
| [0e0f851] | 1181 |    }
 | 
|---|
 | 1182 | 
 | 
|---|
 | 1183 |    switch (type) {
 | 
|---|
| [a0eb547] | 1184 |       case 0x824C:
 | 
|---|
 | 1185 |          strcpy(type_str, "ERROR");
 | 
|---|
 | 1186 |          break;
 | 
|---|
 | 1187 |       case 0x824D:
 | 
|---|
 | 1188 |          strcpy(type_str, "DEPRECATED_BEHAVIOR");
 | 
|---|
 | 1189 |          break;
 | 
|---|
 | 1190 |       case 0x824E:
 | 
|---|
 | 1191 |          strcpy(type_str, "UNDEFINED_BEHAVIOR");
 | 
|---|
 | 1192 |          break;
 | 
|---|
 | 1193 |       case 0x824F:
 | 
|---|
 | 1194 |          strcpy(type_str, "PORTABILITY");
 | 
|---|
 | 1195 |          break;
 | 
|---|
 | 1196 |       case 0x8250:
 | 
|---|
 | 1197 |          strcpy(type_str, "PERFORMANCE");
 | 
|---|
 | 1198 |          break;
 | 
|---|
 | 1199 |       case 0x8251:
 | 
|---|
 | 1200 |          strcpy(type_str, "OTHER");
 | 
|---|
 | 1201 |          break;
 | 
|---|
 | 1202 |       case 0x8268:
 | 
|---|
 | 1203 |          strcpy(type_str, "MARKER");
 | 
|---|
 | 1204 |          break;
 | 
|---|
 | 1205 |       case 0x8269:
 | 
|---|
 | 1206 |          strcpy(type_str, "PUSH_GROUP");
 | 
|---|
 | 1207 |          break;
 | 
|---|
 | 1208 |       case 0x826A:
 | 
|---|
 | 1209 |          strcpy(type_str, "POP_GROUP");
 | 
|---|
 | 1210 |          break;
 | 
|---|
 | 1211 |       default:
 | 
|---|
 | 1212 |          strcpy(type_str, "undefined");
 | 
|---|
 | 1213 |          break;
 | 
|---|
| [0e0f851] | 1214 |    }
 | 
|---|
 | 1215 |    switch (severity) {
 | 
|---|
| [a0eb547] | 1216 |       case 0x9146:
 | 
|---|
 | 1217 |          strcpy(severity_str, "HIGH");
 | 
|---|
 | 1218 |          break;
 | 
|---|
 | 1219 |       case 0x9147:
 | 
|---|
 | 1220 |          strcpy(severity_str, "MEDIUM");
 | 
|---|
 | 1221 |          break;
 | 
|---|
 | 1222 |       case 0x9148:
 | 
|---|
 | 1223 |          strcpy(severity_str, "LOW");
 | 
|---|
 | 1224 |          break;
 | 
|---|
 | 1225 |       case 0x826B:
 | 
|---|
 | 1226 |          strcpy(severity_str, "NOTIFICATION");
 | 
|---|
 | 1227 |          break;
 | 
|---|
 | 1228 |       default:
 | 
|---|
 | 1229 |          strcpy(severity_str, "undefined");
 | 
|---|
 | 1230 |          break;
 | 
|---|
| [0e0f851] | 1231 |    }
 | 
|---|
 | 1232 | 
 | 
|---|
 | 1233 |    if (string(severity_str) != "NOTIFICATION") {
 | 
|---|
 | 1234 |       cout << "OpenGL Error!!!" << endl;
 | 
|---|
 | 1235 |       cout << "Source: " << string(source_str) << endl;
 | 
|---|
 | 1236 |       cout << "Type: " << string(type_str) << endl;
 | 
|---|
 | 1237 |       cout << "Severity: " << string(severity_str) << endl;
 | 
|---|
 | 1238 |       cout << strMessage << endl;
 | 
|---|
 | 1239 |    }
 | 
|---|
 | 1240 | }
 | 
|---|
 | 1241 | 
 | 
|---|
| [f7d35da] | 1242 | 
 | 
|---|
| [ec4456b] | 1243 | GLuint loadShader(GLenum type, string file) {
 | 
|---|
 | 1244 |   cout << "Loading shader from file " << file << endl;
 | 
|---|
 | 1245 | 
 | 
|---|
 | 1246 |   ifstream shaderFile(file);
 | 
|---|
 | 1247 |   GLuint shaderId = 0;
 | 
|---|
 | 1248 | 
 | 
|---|
 | 1249 |   if (shaderFile.is_open()) {
 | 
|---|
 | 1250 |     string line, shaderString;
 | 
|---|
 | 1251 | 
 | 
|---|
 | 1252 |     while(getline(shaderFile, line)) {
 | 
|---|
 | 1253 |       shaderString += line + "\n";
 | 
|---|
 | 1254 |     }
 | 
|---|
 | 1255 |     shaderFile.close();
 | 
|---|
 | 1256 |     const char* shaderCString = shaderString.c_str();
 | 
|---|
 | 1257 | 
 | 
|---|
 | 1258 |     shaderId = glCreateShader(type);
 | 
|---|
 | 1259 |     glShaderSource(shaderId, 1, &shaderCString, NULL);
 | 
|---|
 | 1260 |     glCompileShader(shaderId);
 | 
|---|
 | 1261 | 
 | 
|---|
 | 1262 |     cout << "Loaded successfully" << endl;
 | 
|---|
 | 1263 |   } else {
 | 
|---|
| [e856d62] | 1264 |     cout << "Failed to load the file" << endl;
 | 
|---|
| [ec4456b] | 1265 |   }
 | 
|---|
 | 1266 | 
 | 
|---|
 | 1267 |   return shaderId;
 | 
|---|
 | 1268 | }
 | 
|---|
| [485424b] | 1269 | 
 | 
|---|
 | 1270 | GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
 | 
|---|
 | 1271 |    GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
 | 
|---|
 | 1272 |    GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
 | 
|---|
 | 1273 | 
 | 
|---|
 | 1274 |    GLuint shader_program = glCreateProgram();
 | 
|---|
 | 1275 |    glAttachShader(shader_program, vs);
 | 
|---|
 | 1276 |    glAttachShader(shader_program, fs);
 | 
|---|
 | 1277 | 
 | 
|---|
 | 1278 |    glLinkProgram(shader_program);
 | 
|---|
 | 1279 | 
 | 
|---|
 | 1280 |    return shader_program;
 | 
|---|
 | 1281 | }
 | 
|---|
 | 1282 | 
 | 
|---|
 | 1283 | unsigned char* loadImage(string file_name, int* x, int* y) {
 | 
|---|
 | 1284 |   int n;
 | 
|---|
| [e856d62] | 1285 |   int force_channels = 4; // This forces RGBA (4 bytes per pixel)
 | 
|---|
| [485424b] | 1286 |   unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
 | 
|---|
| [e856d62] | 1287 | 
 | 
|---|
 | 1288 |   int width_in_bytes = *x * 4;
 | 
|---|
 | 1289 |   unsigned char *top = NULL;
 | 
|---|
 | 1290 |   unsigned char *bottom = NULL;
 | 
|---|
 | 1291 |   unsigned char temp = 0;
 | 
|---|
 | 1292 |   int half_height = *y / 2;
 | 
|---|
 | 1293 | 
 | 
|---|
 | 1294 |   // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
 | 
|---|
 | 1295 |   for (int row = 0; row < half_height; row++) {
 | 
|---|
 | 1296 |      top = image_data + row * width_in_bytes;
 | 
|---|
 | 1297 |      bottom = image_data + (*y - row - 1) * width_in_bytes;
 | 
|---|
 | 1298 |      for (int col = 0; col < width_in_bytes; col++) {
 | 
|---|
 | 1299 |         temp = *top;
 | 
|---|
 | 1300 |         *top = *bottom;
 | 
|---|
 | 1301 |         *bottom = temp;
 | 
|---|
 | 1302 |         top++;
 | 
|---|
 | 1303 |         bottom++;
 | 
|---|
 | 1304 |      }
 | 
|---|
 | 1305 |   }
 | 
|---|
 | 1306 | 
 | 
|---|
| [485424b] | 1307 |   if (!image_data) {
 | 
|---|
 | 1308 |     fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
 | 
|---|
 | 1309 |   }
 | 
|---|
| [e856d62] | 1310 | 
 | 
|---|
 | 1311 |   // Not Power-of-2 check
 | 
|---|
 | 1312 |   if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
 | 
|---|
 | 1313 |      fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
 | 
|---|
 | 1314 |   }
 | 
|---|
 | 1315 | 
 | 
|---|
| [485424b] | 1316 |   return image_data;
 | 
|---|
 | 1317 | }
 | 
|---|
| [33a9664] | 1318 | 
 | 
|---|
| [d9f99b2] | 1319 | bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
 | 
|---|
| [5c9d193] | 1320 |    // LINE EQUATION:            P = O + Dt
 | 
|---|
| [b73cb3b] | 1321 |    // O = cam
 | 
|---|
| [5c9d193] | 1322 |    // D = ray_world
 | 
|---|
 | 1323 | 
 | 
|---|
| [b73cb3b] | 1324 |    // PLANE EQUATION:   P dot n + d = 0
 | 
|---|
 | 1325 |    // n is the normal vector
 | 
|---|
 | 1326 |    // d is the offset from the origin
 | 
|---|
| [5c9d193] | 1327 | 
 | 
|---|
 | 1328 |    // Take the cross-product of two vectors on the plane to get the normal
 | 
|---|
| [d9f99b2] | 1329 |    vec3 v1 = points[1] - points[0];
 | 
|---|
 | 1330 |    vec3 v2 = points[2] - points[0];
 | 
|---|
| [5c9d193] | 1331 | 
 | 
|---|
| [1f3d32b] | 1332 |    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);
 | 
|---|
 | 1333 | 
 | 
|---|
 | 1334 |    vec3 local_ray = vec3(inverse(obj->model_mat) * world_ray);
 | 
|---|
 | 1335 |    vec3 local_cam = vec3(inverse(obj->model_mat) * cam);
 | 
|---|
 | 1336 | 
 | 
|---|
 | 1337 |    local_ray = local_ray - local_cam;
 | 
|---|
 | 1338 | 
 | 
|---|
 | 1339 |    float d = -glm::dot(points[0], normal);
 | 
|---|
 | 1340 |    float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
 | 
|---|
 | 1341 | 
 | 
|---|
 | 1342 |    vec3 intersection = local_cam + t*local_ray;
 | 
|---|
 | 1343 | 
 | 
|---|
 | 1344 |    if (insideTriangle(intersection, points)) {
 | 
|---|
 | 1345 |       click_point = obj->model_mat * vec4(intersection, 1.0f);
 | 
|---|
 | 1346 |       return true;
 | 
|---|
 | 1347 |    } else {
 | 
|---|
 | 1348 |       return false;
 | 
|---|
 | 1349 |    }
 | 
|---|
 | 1350 | }
 | 
|---|
 | 1351 | 
 | 
|---|
 | 1352 | bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
 | 
|---|
 | 1353 |    vec3 v21 = triangle_points[1] - triangle_points[0];
 | 
|---|
 | 1354 |    vec3 v31 = triangle_points[2] - triangle_points[0];
 | 
|---|
 | 1355 |    vec3 pv1 = p - triangle_points[0];
 | 
|---|
 | 1356 | 
 | 
|---|
 | 1357 |    float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
 | 
|---|
 | 1358 |    float x = (pv1.x-y*v31.x) / v21.x;
 | 
|---|
 | 1359 | 
 | 
|---|
 | 1360 |    return x > 0.0f && y > 0.0f && x+y < 1.0f;
 | 
|---|
 | 1361 | }
 | 
|---|
 | 1362 | 
 | 
|---|
 | 1363 | void printVector(string label, vec3& v) {
 | 
|---|
 | 1364 |    cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
 | 
|---|
 | 1365 | }
 | 
|---|
 | 1366 | 
 | 
|---|
 | 1367 | void print4DVector(string label, vec4& v) {
 | 
|---|
 | 1368 |    cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
 | 
|---|
 | 1369 | }
 | 
|---|
 | 1370 | 
 | 
|---|
 | 1371 | void initObject(SceneObject* obj) {
 | 
|---|
 | 1372 |    // Each objects must have at least 3 points, so the size of
 | 
|---|
 | 1373 |    // the points array must be a positive multiple of 9
 | 
|---|
 | 1374 |    if (obj->points.size() == 0 || (obj->points.size() % 9) != 0) {
 | 
|---|
 | 1375 |       // TODO: Maybe throw some kind of error here instead
 | 
|---|
 | 1376 |       return;
 | 
|---|
 | 1377 |    }
 | 
|---|
 | 1378 | 
 | 
|---|
 | 1379 |    obj->id = objects.size(); // currently unused
 | 
|---|
 | 1380 |    obj->num_points = obj->points.size() / 3;
 | 
|---|
 | 1381 |    obj->model_transform = mat4(1.0f);
 | 
|---|
 | 1382 |    obj->deleted = false;
 | 
|---|
 | 1383 | 
 | 
|---|
 | 1384 |    obj->normals.reserve(obj->points.size());
 | 
|---|
| [8e8aed6] | 1385 |    for (unsigned int i = 0; i < obj->points.size(); i += 9) {
 | 
|---|
| [1f3d32b] | 1386 |       vec3 point1 = vec3(obj->points[i], obj->points[i + 1], obj->points[i + 2]);
 | 
|---|
 | 1387 |       vec3 point2 = vec3(obj->points[i + 3], obj->points[i + 4], obj->points[i + 5]);
 | 
|---|
 | 1388 |       vec3 point3 = vec3(obj->points[i + 6], obj->points[i + 7], obj->points[i + 8]);
 | 
|---|
 | 1389 | 
 | 
|---|
 | 1390 |       vec3 normal = normalize(cross(point2 - point1, point3 - point1));
 | 
|---|
 | 1391 | 
 | 
|---|
 | 1392 |       // Add the same normal for all 3 points
 | 
|---|
 | 1393 |       for (int j = 0; j < 3; j++) {
 | 
|---|
 | 1394 |          obj->normals.push_back(normal.x);
 | 
|---|
 | 1395 |          obj->normals.push_back(normal.y);
 | 
|---|
 | 1396 |          obj->normals.push_back(normal.z);
 | 
|---|
 | 1397 |       }
 | 
|---|
 | 1398 |    }
 | 
|---|
 | 1399 | 
 | 
|---|
| [646f3f2] | 1400 |    if (obj->type == TYPE_SHIP || obj->type == TYPE_ASTEROID) {
 | 
|---|
| [1f3d32b] | 1401 |       calculateObjectBoundingBox(obj);
 | 
|---|
 | 1402 | 
 | 
|---|
 | 1403 |       obj->bounding_center = vec3(obj->translate_mat * vec4(obj->bounding_center, 1.0f));
 | 
|---|
 | 1404 |    }
 | 
|---|
 | 1405 | }
 | 
|---|
 | 1406 | 
 | 
|---|
 | 1407 | void addObjectToScene(SceneObject* obj,
 | 
|---|
 | 1408 |    map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 1409 |    map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [1f3d32b] | 1410 |    GLuint points_vbo,
 | 
|---|
 | 1411 |    GLuint colors_vbo,
 | 
|---|
 | 1412 |    GLuint texcoords_vbo,
 | 
|---|
 | 1413 |    GLuint normals_vbo,
 | 
|---|
 | 1414 |    GLuint ubo,
 | 
|---|
| [0414306] | 1415 |    GLuint model_mat_idx_vbo) {
 | 
|---|
| [1f3d32b] | 1416 |    objects.push_back(obj);
 | 
|---|
 | 1417 | 
 | 
|---|
| [dd9771c] | 1418 |    BufferInfo* bufferInfo = &shaderBufferInfo[modelGroups[obj->type].shaderProgram];
 | 
|---|
| [1f3d32b] | 1419 | 
 | 
|---|
 | 1420 |    // Check if the buffers aren't large enough to fit the new object and, if so, call
 | 
|---|
 | 1421 |    // populateBuffers() to resize and repopupulate them
 | 
|---|
| [a0eb547] | 1422 |    if (modelGroups[obj->type].vboCapacity < (modelGroups[obj->type].numPoints + obj->num_points) ||
 | 
|---|
| [1f3d32b] | 1423 |       bufferInfo->ubo_capacity < (bufferInfo->ubo_offset + 1)) {
 | 
|---|
 | 1424 | 
 | 
|---|
 | 1425 |       if (leftLaser != NULL && leftLaser->deleted) {
 | 
|---|
 | 1426 |          leftLaser = NULL;
 | 
|---|
 | 1427 |       }
 | 
|---|
 | 1428 |       if (rightLaser != NULL && rightLaser->deleted) {
 | 
|---|
 | 1429 |          rightLaser = NULL;
 | 
|---|
 | 1430 |       }
 | 
|---|
 | 1431 | 
 | 
|---|
| [0414306] | 1432 |       populateBuffers(objects, shaderBufferInfo, modelGroups,
 | 
|---|
| [1f3d32b] | 1433 |          points_vbo,
 | 
|---|
 | 1434 |          colors_vbo,
 | 
|---|
 | 1435 |          texcoords_vbo,
 | 
|---|
 | 1436 |          normals_vbo,
 | 
|---|
 | 1437 |          ubo,
 | 
|---|
| [0414306] | 1438 |          model_mat_idx_vbo);
 | 
|---|
| [1f3d32b] | 1439 |    } else {
 | 
|---|
| [49db5fc] | 1440 |       copyObjectDataToBuffers(*objects.back(), shaderBufferInfo, modelGroups, ubo);
 | 
|---|
| [1f3d32b] | 1441 |    }
 | 
|---|
 | 1442 | }
 | 
|---|
 | 1443 | 
 | 
|---|
 | 1444 | void removeObjectFromScene(SceneObject& obj, GLuint ubo) {
 | 
|---|
 | 1445 |    if (!obj.deleted) {
 | 
|---|
 | 1446 |       // Move the object outside the render bounds of the scene so it doesn't get rendered
 | 
|---|
 | 1447 |       // TODO: Find a better way of hiding the object until the next time buffers are repopulated
 | 
|---|
 | 1448 |       transformObject(obj, translate(mat4(1.0f), vec3(0.0f, 0.0f, FAR_CLIP * 1000.0f)), ubo);
 | 
|---|
 | 1449 |       obj.deleted = true;
 | 
|---|
 | 1450 |    }
 | 
|---|
 | 1451 | }
 | 
|---|
 | 1452 | 
 | 
|---|
 | 1453 | void calculateObjectBoundingBox(SceneObject* obj) {
 | 
|---|
 | 1454 |    GLfloat min_x = obj->points[0];
 | 
|---|
 | 1455 |    GLfloat max_x = obj->points[0];
 | 
|---|
 | 1456 |    GLfloat min_y = obj->points[1];
 | 
|---|
 | 1457 |    GLfloat max_y = obj->points[1];
 | 
|---|
 | 1458 |    GLfloat min_z = obj->points[2];
 | 
|---|
 | 1459 |    GLfloat max_z = obj->points[2];
 | 
|---|
 | 1460 | 
 | 
|---|
 | 1461 |    // start from the second point
 | 
|---|
| [8e8aed6] | 1462 |    for (unsigned int i = 3; i < obj->points.size(); i += 3) {
 | 
|---|
| [1f3d32b] | 1463 |       if (min_x > obj->points[i]) {
 | 
|---|
 | 1464 |          min_x = obj->points[i];
 | 
|---|
 | 1465 |       }
 | 
|---|
 | 1466 |       else if (max_x < obj->points[i]) {
 | 
|---|
 | 1467 |          max_x = obj->points[i];
 | 
|---|
 | 1468 |       }
 | 
|---|
 | 1469 | 
 | 
|---|
 | 1470 |       if (min_y > obj->points[i + 1]) {
 | 
|---|
 | 1471 |          min_y = obj->points[i + 1];
 | 
|---|
 | 1472 |       }
 | 
|---|
 | 1473 |       else if (max_y < obj->points[i + 1]) {
 | 
|---|
 | 1474 |          max_y = obj->points[i + 1];
 | 
|---|
 | 1475 |       }
 | 
|---|
 | 1476 | 
 | 
|---|
 | 1477 |       if (min_z > obj->points[i + 2]) {
 | 
|---|
 | 1478 |          min_z = obj->points[i + 2];
 | 
|---|
 | 1479 |       }
 | 
|---|
 | 1480 |       else if (max_z < obj->points[i + 2]) {
 | 
|---|
 | 1481 |          max_z = obj->points[i + 2];
 | 
|---|
 | 1482 |       }
 | 
|---|
 | 1483 |    }
 | 
|---|
 | 1484 | 
 | 
|---|
 | 1485 |    obj->bounding_center = vec3((min_x + max_x) / 2.0f, (min_y + max_y) / 2.0f, (min_z + max_z) / 2.0f);
 | 
|---|
 | 1486 | 
 | 
|---|
 | 1487 |    GLfloat radius_x = max_x - obj->bounding_center.x;
 | 
|---|
 | 1488 |    GLfloat radius_y = max_y - obj->bounding_center.y;
 | 
|---|
 | 1489 |    GLfloat radius_z = max_z - obj->bounding_center.z;
 | 
|---|
 | 1490 | 
 | 
|---|
 | 1491 |    // TODO: This actually underestimates the radius. Might need to be fixed at some point.
 | 
|---|
 | 1492 |    // TODO: Does not take into account any scaling in the model matrix
 | 
|---|
 | 1493 |    obj->bounding_radius = radius_x;
 | 
|---|
 | 1494 |    if (obj->bounding_radius < radius_y)
 | 
|---|
 | 1495 |       obj->bounding_radius = radius_y;
 | 
|---|
 | 1496 |    if (obj->bounding_radius < radius_z)
 | 
|---|
 | 1497 |       obj->bounding_radius = radius_z;
 | 
|---|
 | 1498 | 
 | 
|---|
| [8e8aed6] | 1499 |    for (unsigned int i = 0; i < obj->points.size(); i += 3) {
 | 
|---|
| [1f3d32b] | 1500 |       obj->points[i] -= obj->bounding_center.x;
 | 
|---|
 | 1501 |       obj->points[i + 1] -= obj->bounding_center.y;
 | 
|---|
 | 1502 |       obj->points[i + 2] -= obj->bounding_center.z;
 | 
|---|
 | 1503 |    }
 | 
|---|
 | 1504 | 
 | 
|---|
 | 1505 |    obj->bounding_center = vec3(0.0f, 0.0f, 0.0f);
 | 
|---|
 | 1506 | }
 | 
|---|
 | 1507 | 
 | 
|---|
| [dd9771c] | 1508 | SceneObject* createShip() {
 | 
|---|
| [1f3d32b] | 1509 |    SceneObject* ship = new SceneObject();
 | 
|---|
 | 1510 | 
 | 
|---|
 | 1511 |    ship->type = TYPE_SHIP;
 | 
|---|
 | 1512 | 
 | 
|---|
 | 1513 |    ship->points = {
 | 
|---|
 | 1514 |       //back
 | 
|---|
 | 1515 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1516 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1517 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1518 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1519 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1520 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1521 | 
 | 
|---|
 | 1522 |       // left back
 | 
|---|
 | 1523 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1524 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1525 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1526 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1527 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1528 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1529 | 
 | 
|---|
 | 1530 |       // right back
 | 
|---|
 | 1531 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1532 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1533 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1534 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1535 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1536 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1537 | 
 | 
|---|
 | 1538 |       // left mid
 | 
|---|
 | 1539 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1540 |       -0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1541 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1542 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1543 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1544 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1545 | 
 | 
|---|
 | 1546 |       // right mid
 | 
|---|
 | 1547 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1548 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1549 |       0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1550 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1551 |       0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1552 |       0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1553 | 
 | 
|---|
 | 1554 |       // left front
 | 
|---|
 | 1555 |       0.0f,    0.0f,   -3.5f,
 | 
|---|
 | 1556 |       -0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1557 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1558 | 
 | 
|---|
 | 1559 |       // right front
 | 
|---|
 | 1560 |       0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1561 |       0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1562 |       0.0f,    0.0f,   -3.5f,
 | 
|---|
 | 1563 | 
 | 
|---|
 | 1564 |       // top back
 | 
|---|
 | 1565 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1566 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1567 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1568 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1569 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1570 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1571 | 
 | 
|---|
 | 1572 |       // bottom back
 | 
|---|
 | 1573 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1574 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1575 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1576 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1577 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1578 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1579 | 
 | 
|---|
 | 1580 |       // top mid
 | 
|---|
 | 1581 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1582 |       -0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1583 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1584 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1585 |       0.5f,    0.3f,   -2.0f,
 | 
|---|
 | 1586 |       0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1587 | 
 | 
|---|
 | 1588 |       // bottom mid
 | 
|---|
 | 1589 |       -0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1590 |       -0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1591 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1592 |       0.5f,    0.0f,   -2.0f,
 | 
|---|
 | 1593 |       -0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1594 |       0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1595 | 
 | 
|---|
 | 1596 |       // top front
 | 
|---|
 | 1597 |       -0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1598 |       0.25f,   0.3f,   -3.0f,
 | 
|---|
 | 1599 |       0.0f,    0.0f,   -3.5f,
 | 
|---|
 | 1600 | 
 | 
|---|
 | 1601 |       // bottom front
 | 
|---|
 | 1602 |       0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1603 |       -0.25f,   0.0f,   -3.0f,
 | 
|---|
 | 1604 |       0.0f,    0.0f,   -3.5f,
 | 
|---|
 | 1605 | 
 | 
|---|
 | 1606 |       // left wing start back
 | 
|---|
 | 1607 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1608 |       -1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1609 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1610 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1611 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1612 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1613 | 
 | 
|---|
 | 1614 |       // left wing start top
 | 
|---|
 | 1615 |       -0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1616 |       -1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1617 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1618 |       -0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1619 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1620 |       -0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1621 | 
 | 
|---|
 | 1622 |       // left wing start front
 | 
|---|
 | 1623 |       -0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1624 |       -0.5f,    0.0f,   -0.3f,
 | 
|---|
 | 1625 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1626 |       -0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1627 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1628 |       -1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1629 | 
 | 
|---|
 | 1630 |       // left wing start bottom
 | 
|---|
 | 1631 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1632 |       -1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1633 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1634 |       -0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1635 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1636 |       -0.5f,    0.0f,   -0.3f,
 | 
|---|
 | 1637 | 
 | 
|---|
 | 1638 |       // left wing end outside
 | 
|---|
 | 1639 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1640 |       -2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1641 |       -1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1642 | 
 | 
|---|
 | 1643 |       // left wing end top
 | 
|---|
 | 1644 |       -1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1645 |       -2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1646 |       -1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1647 | 
 | 
|---|
 | 1648 |       // left wing end front
 | 
|---|
 | 1649 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1650 |       -2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1651 |       -1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1652 | 
 | 
|---|
 | 1653 |       // left wing end bottom
 | 
|---|
 | 1654 |       -1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1655 |       -2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1656 |       -1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1657 | 
 | 
|---|
 | 1658 |       // right wing start back
 | 
|---|
 | 1659 |       1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1660 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1661 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1662 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1663 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1664 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1665 | 
 | 
|---|
 | 1666 |       // right wing start top
 | 
|---|
 | 1667 |       1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1668 |       0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1669 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1670 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1671 |       0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1672 |       0.5f,    0.3f,    0.0f,
 | 
|---|
 | 1673 | 
 | 
|---|
 | 1674 |       // right wing start front
 | 
|---|
 | 1675 |       0.5f,    0.0f,   -0.3f,
 | 
|---|
 | 1676 |       0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1677 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1678 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1679 |       0.5f,    0.3f,   -0.3f,
 | 
|---|
 | 1680 |       1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1681 | 
 | 
|---|
 | 1682 |       // right wing start bottom
 | 
|---|
 | 1683 |       1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1684 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1685 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1686 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1687 |       0.5f,    0.0f,    0.0f,
 | 
|---|
 | 1688 |       0.5f,    0.0f,   -0.3f,
 | 
|---|
 | 1689 | 
 | 
|---|
 | 1690 |       // right wing end outside
 | 
|---|
 | 1691 |       2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1692 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1693 |       1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1694 | 
 | 
|---|
 | 1695 |       // right wing end top
 | 
|---|
 | 1696 |       2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1697 |       1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1698 |       1.5f,    0.3f,    0.0f,
 | 
|---|
 | 1699 | 
 | 
|---|
 | 1700 |       // right wing end front
 | 
|---|
 | 1701 |       2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1702 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1703 |       1.3f,    0.3f,   -0.3f,
 | 
|---|
 | 1704 | 
 | 
|---|
 | 1705 |       // right wing end bottom
 | 
|---|
 | 1706 |       2.2f,    0.15f,  -0.8f,
 | 
|---|
 | 1707 |       1.5f,    0.0f,    0.0f,
 | 
|---|
 | 1708 |       1.3f,    0.0f,   -0.3f,
 | 
|---|
 | 1709 |    };
 | 
|---|
 | 1710 |    ship->colors = {
 | 
|---|
 | 1711 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1712 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1713 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1714 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1715 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1716 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1717 | 
 | 
|---|
 | 1718 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1719 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1720 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1721 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1722 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1723 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [b73cb3b] | 1724 | 
 | 
|---|
| [1f3d32b] | 1725 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1726 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1727 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1728 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1729 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1730 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [5c9d193] | 1731 | 
 | 
|---|
| [1f3d32b] | 1732 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1733 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1734 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1735 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1736 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1737 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [5c9d193] | 1738 | 
 | 
|---|
| [1f3d32b] | 1739 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1740 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1741 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1742 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1743 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1744 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [5c9d193] | 1745 | 
 | 
|---|
| [1f3d32b] | 1746 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1747 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1748 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [5c9d193] | 1749 | 
 | 
|---|
| [1f3d32b] | 1750 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1751 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1752 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [f7d35da] | 1753 | 
 | 
|---|
| [1f3d32b] | 1754 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1755 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1756 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1757 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1758 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1759 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [33a9664] | 1760 | 
 | 
|---|
| [1f3d32b] | 1761 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1762 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1763 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1764 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1765 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1766 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [33a9664] | 1767 | 
 | 
|---|
| [1f3d32b] | 1768 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1769 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1770 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1771 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1772 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1773 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [d12d003] | 1774 | 
 | 
|---|
| [1f3d32b] | 1775 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1776 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1777 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1778 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1779 |       0.0f, 0.0f, 1.0f,
 | 
|---|
 | 1780 |       0.0f, 0.0f, 1.0f,
 | 
|---|
| [b73cb3b] | 1781 | 
 | 
|---|
| [1f3d32b] | 1782 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1783 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1784 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [c1ca5b5] | 1785 | 
 | 
|---|
| [1f3d32b] | 1786 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1787 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1788 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [3d06b4e] | 1789 | 
 | 
|---|
| [1f3d32b] | 1790 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1791 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1792 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1793 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1794 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1795 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [0d5c100] | 1796 | 
 | 
|---|
| [1f3d32b] | 1797 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1798 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1799 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1800 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1801 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1802 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [cffca4d] | 1803 | 
 | 
|---|
| [1f3d32b] | 1804 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1805 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1806 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1807 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1808 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1809 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [cffca4d] | 1810 | 
 | 
|---|
| [1f3d32b] | 1811 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1812 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1813 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1814 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1815 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1816 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [cffca4d] | 1817 | 
 | 
|---|
| [1f3d32b] | 1818 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1819 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1820 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [95595de] | 1821 | 
 | 
|---|
| [1f3d32b] | 1822 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1823 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1824 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [cffca4d] | 1825 | 
 | 
|---|
| [1f3d32b] | 1826 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1827 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1828 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [c3c3158] | 1829 | 
 | 
|---|
| [1f3d32b] | 1830 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1831 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1832 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [c3c3158] | 1833 | 
 | 
|---|
| [1f3d32b] | 1834 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1835 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1836 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1837 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1838 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1839 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [fabed35] | 1840 | 
 | 
|---|
| [1f3d32b] | 1841 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1842 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1843 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1844 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1845 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1846 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [fabed35] | 1847 | 
 | 
|---|
| [1f3d32b] | 1848 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1849 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1850 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1851 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1852 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1853 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [c3c3158] | 1854 | 
 | 
|---|
| [1f3d32b] | 1855 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1856 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1857 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1858 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1859 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1860 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [c3c3158] | 1861 | 
 | 
|---|
| [1f3d32b] | 1862 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1863 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1864 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [3d06b4e] | 1865 | 
 | 
|---|
| [1f3d32b] | 1866 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1867 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1868 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [3d06b4e] | 1869 | 
 | 
|---|
| [1f3d32b] | 1870 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1871 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1872 |       0.0f, 0.0f, 0.3f,
 | 
|---|
| [3d06b4e] | 1873 | 
 | 
|---|
| [1f3d32b] | 1874 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1875 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1876 |       0.0f, 0.0f, 0.3f,
 | 
|---|
 | 1877 |    };
 | 
|---|
 | 1878 |    ship->texcoords = { 0.0f };
 | 
|---|
| [3d06b4e] | 1879 | 
 | 
|---|
| [1f3d32b] | 1880 |    mat4 T_model = translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f));
 | 
|---|
 | 1881 |    mat4 R_model(1.0f);
 | 
|---|
 | 1882 |    ship->model_base = T_model * R_model * scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
 | 
|---|
| [3d06b4e] | 1883 | 
 | 
|---|
| [1f3d32b] | 1884 |    ship->translate_mat = T_model;
 | 
|---|
| [3d06b4e] | 1885 | 
 | 
|---|
| [1f3d32b] | 1886 |    initObject(ship);
 | 
|---|
| [3d06b4e] | 1887 | 
 | 
|---|
| [1f3d32b] | 1888 |    return ship;
 | 
|---|
| [3d06b4e] | 1889 | }
 | 
|---|
 | 1890 | 
 | 
|---|
| [3effd81] | 1891 | /* LASER RENDERING/POSITIONING ALGORITHM
 | 
|---|
 | 1892 |  * -Draw a thin rectangle for the laser beam, using the specified width and endpoints
 | 
|---|
 | 1893 |  * -Texture the beam with a grayscale partially transparent image
 | 
|---|
 | 1894 |  * -In the shader, blend the image with a color to support lasers of different colors
 | 
|---|
 | 1895 |  *
 | 
|---|
 | 1896 |  * The flat part of the textured rectangle needs to always face the camera, so the laser's width is constant
 | 
|---|
 | 1897 |  * This is done as follows:
 | 
|---|
 | 1898 | * -Determine the length of the laser based on the start and end points
 | 
|---|
 | 1899 | * -Draw a rectangle along the z-axis and rotated upwards along the y-axis, with the correct final length and width
 | 
|---|
 | 1900 | * -Rotate the beam around the z-axis by the correct angle, sot that in its final position, the flat part faces the camera
 | 
|---|
 | 1901 | * -Rotate the beam along the x-axis and then along the y-axis and then translate it to put it into its final position
 | 
|---|
 | 1902 | */
 | 
|---|
| [8316333] | 1903 | // TODO: Make the color parameter have an effect
 | 
|---|
| [dd9771c] | 1904 | Laser* createLaser(vec3 start, vec3 end, vec3 color, GLfloat width) {
 | 
|---|
| [1f3d32b] | 1905 |    Laser* obj = new Laser();
 | 
|---|
 | 1906 |    obj->type = TYPE_LASER;
 | 
|---|
 | 1907 |    obj->targetAsteroid = NULL;
 | 
|---|
| [b155f13] | 1908 | 
 | 
|---|
| [3effd81] | 1909 |    vec3 ray = end - start;
 | 
|---|
 | 1910 |    float length = glm::length(ray);
 | 
|---|
| [b155f13] | 1911 | 
 | 
|---|
| [1f3d32b] | 1912 |    obj->points = {
 | 
|---|
| [fd6f465] | 1913 |        width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1914 |       -width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1915 |       -width / 2, 0.0f, 0.0f,
 | 
|---|
 | 1916 |        width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1917 |       -width / 2, 0.0f, 0.0f,
 | 
|---|
 | 1918 |        width / 2, 0.0f, 0.0f,
 | 
|---|
 | 1919 |        width / 2, 0.0f, -length + width / 2,
 | 
|---|
 | 1920 |       -width / 2, 0.0f, -length + width / 2,
 | 
|---|
 | 1921 |       -width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1922 |        width / 2, 0.0f, -length + width / 2,
 | 
|---|
 | 1923 |       -width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1924 |        width / 2, 0.0f, -width / 2,
 | 
|---|
 | 1925 |        width / 2, 0.0f, -length,
 | 
|---|
 | 1926 |       -width / 2, 0.0f, -length,
 | 
|---|
 | 1927 |       -width / 2, 0.0f, -length + width / 2,
 | 
|---|
 | 1928 |        width / 2, 0.0f, -length,
 | 
|---|
 | 1929 |       -width / 2, 0.0f, -length + width / 2,
 | 
|---|
 | 1930 |        width / 2, 0.0f, -length + width / 2,
 | 
|---|
| [b155f13] | 1931 |    };
 | 
|---|
 | 1932 | 
 | 
|---|
| [1f3d32b] | 1933 |    obj->texcoords = {
 | 
|---|
| [9f9f9a7] | 1934 |       1.0f, 0.5f,
 | 
|---|
 | 1935 |       0.0f, 0.5f,
 | 
|---|
 | 1936 |       0.0f, 0.0f,
 | 
|---|
 | 1937 |       1.0f, 0.5f,
 | 
|---|
 | 1938 |       0.0f, 0.0f,
 | 
|---|
 | 1939 |       1.0f, 0.0f,
 | 
|---|
 | 1940 |       1.0f, 0.51f,
 | 
|---|
 | 1941 |       0.0f, 0.51f,
 | 
|---|
 | 1942 |       0.0f, 0.49f,
 | 
|---|
 | 1943 |       1.0f, 0.51f,
 | 
|---|
 | 1944 |       0.0f, 0.49f,
 | 
|---|
 | 1945 |       1.0f, 0.49f,
 | 
|---|
 | 1946 |       1.0f, 1.0f,
 | 
|---|
 | 1947 |       0.0f, 1.0f,
 | 
|---|
 | 1948 |       0.0f, 0.5f,
 | 
|---|
 | 1949 |       1.0f, 1.0f,
 | 
|---|
 | 1950 |       0.0f, 0.5f,
 | 
|---|
 | 1951 |       1.0f, 0.5f,
 | 
|---|
 | 1952 |    };
 | 
|---|
 | 1953 | 
 | 
|---|
| [3effd81] | 1954 |    float xAxisRotation = asin(ray.y / length);
 | 
|---|
 | 1955 |    float yAxisRotation = atan2(-ray.x, -ray.z);
 | 
|---|
 | 1956 | 
 | 
|---|
 | 1957 |    vec3 normal(rotate(mat4(1.0f), yAxisRotation, vec3(0.0f, 1.0f, 0.0f)) *
 | 
|---|
 | 1958 |                rotate(mat4(1.0f), xAxisRotation, vec3(1.0f, 0.0f, 0.0f)) *
 | 
|---|
 | 1959 |                vec4(0.0f, 1.0f, 0.0f, 1.0f));
 | 
|---|
 | 1960 | 
 | 
|---|
 | 1961 |    // To project point P onto line AB:
 | 
|---|
 | 1962 |    // projection = A + dot(AP,AB) / dot(AB,AB) * AB
 | 
|---|
 | 1963 |    vec3 projOnLaser = start + glm::dot(cam_pos-start, ray) / (length*length) * ray;
 | 
|---|
 | 1964 |    vec3 laserToCam = cam_pos - projOnLaser;
 | 
|---|
 | 1965 | 
 | 
|---|
 | 1966 |    float zAxisRotation = -atan2(glm::dot(glm::cross(normal, laserToCam), glm::normalize(ray)), glm::dot(normal, laserToCam));
 | 
|---|
 | 1967 | 
 | 
|---|
| [1f3d32b] | 1968 |    obj->model_base = rotate(mat4(1.0f), zAxisRotation, vec3(0.0f, 0.0f, 1.0f));
 | 
|---|
| [b155f13] | 1969 | 
 | 
|---|
| [8316333] | 1970 |    initObject(obj);
 | 
|---|
 | 1971 | 
 | 
|---|
| [1f3d32b] | 1972 |    obj->model_transform = rotate(mat4(1.0f), xAxisRotation, vec3(1.0f, 0.0f, 0.0f)) * obj->model_transform;
 | 
|---|
 | 1973 |    obj->model_transform = rotate(mat4(1.0f), yAxisRotation, vec3(0.0f, 1.0f, 0.0f)) * obj->model_transform;
 | 
|---|
 | 1974 |    obj->model_transform = translate(mat4(1.0f), start) * obj->model_transform;
 | 
|---|
| [612d1f6] | 1975 | 
 | 
|---|
| [8316333] | 1976 |    return obj;
 | 
|---|
| [b155f13] | 1977 | }
 | 
|---|
 | 1978 | 
 | 
|---|
| [7a55b49] | 1979 | ShaderModelGroup createModelGroup(GLuint shaderProgram) {
 | 
|---|
 | 1980 |    ShaderModelGroup smg;
 | 
|---|
 | 1981 | 
 | 
|---|
 | 1982 |    smg.shaderProgram = shaderProgram;
 | 
|---|
| [0414306] | 1983 |    glGenVertexArrays(1, &smg.vao);
 | 
|---|
 | 1984 |    smg.numPoints = 0;
 | 
|---|
| [7a55b49] | 1985 | 
 | 
|---|
 | 1986 |    return smg;
 | 
|---|
 | 1987 | }
 | 
|---|
 | 1988 | 
 | 
|---|
 | 1989 | void removeModelFromGroup(ShaderModelGroup& modelGroup, SceneObject& model) {
 | 
|---|
 | 1990 |    // TODO: Implement
 | 
|---|
 | 1991 | }
 | 
|---|
 | 1992 | 
 | 
|---|
 | 1993 | void addModelToGroup(ShaderModelGroup& modelGroup, SceneObject& model) {
 | 
|---|
 | 1994 |    // TODO: Implement
 | 
|---|
 | 1995 | }
 | 
|---|
 | 1996 | 
 | 
|---|
| [a0eb547] | 1997 | void defineModelGroupAttrib(ShaderModelGroup& modelGroup, string name, AttribType attribType,
 | 
|---|
 | 1998 |                   GLint size, GLenum type, size_t fieldOffset) {
 | 
|---|
 | 1999 |    if (type != GL_FLOAT && type != GL_UNSIGNED_INT) {
 | 
|---|
 | 2000 |       cout << "Unknown shader program attribute type: " << type << endl;
 | 
|---|
 | 2001 |       return;
 | 
|---|
 | 2002 |    }
 | 
|---|
 | 2003 | 
 | 
|---|
 | 2004 |    AttribInfo attribInfo;
 | 
|---|
 | 2005 | 
 | 
|---|
 | 2006 |    attribInfo.attribType = attribType;
 | 
|---|
 | 2007 |    attribInfo.index = modelGroup.attribs.size();
 | 
|---|
 | 2008 |    attribInfo.size = size;
 | 
|---|
 | 2009 |    attribInfo.type = type;
 | 
|---|
 | 2010 |    attribInfo.fieldOffset = fieldOffset;
 | 
|---|
 | 2011 | 
 | 
|---|
 | 2012 |    modelGroup.attribs[name] = attribInfo;
 | 
|---|
 | 2013 | }
 | 
|---|
 | 2014 | 
 | 
|---|
| [49db5fc] | 2015 | void defineModelGroupUniform(ShaderModelGroup& modelGroup, string name, AttribType attribType,
 | 
|---|
 | 2016 |                   GLint size, UniformType type, GLfloat* data) {
 | 
|---|
 | 2017 |    AttribInfo attribInfo;
 | 
|---|
 | 2018 | 
 | 
|---|
 | 2019 |    attribInfo.attribType = attribType;
 | 
|---|
 | 2020 |    attribInfo.size = size;
 | 
|---|
 | 2021 |    attribInfo.uniType = type;
 | 
|---|
 | 2022 |    attribInfo.data = data;
 | 
|---|
 | 2023 | 
 | 
|---|
 | 2024 |    modelGroup.attribs[name] = attribInfo;
 | 
|---|
 | 2025 | }
 | 
|---|
 | 2026 | 
 | 
|---|
| [a0eb547] | 2027 | void initModelGroupAttribs(ShaderModelGroup& modelGroup) {
 | 
|---|
 | 2028 |    glBindVertexArray(modelGroup.vao);
 | 
|---|
 | 2029 | 
 | 
|---|
 | 2030 |    map<string, AttribInfo>::iterator it;
 | 
|---|
 | 2031 |    for (it = modelGroup.attribs.begin(); it != modelGroup.attribs.end(); it++) {
 | 
|---|
| [49db5fc] | 2032 |       if (it->second.attribType == ATTRIB_UNIFORM) {
 | 
|---|
 | 2033 |          it->second.buffer = glGetUniformLocation(modelGroup.shaderProgram, it->first.c_str());
 | 
|---|
 | 2034 |       } else {
 | 
|---|
 | 2035 |          glEnableVertexAttribArray(it->second.index);
 | 
|---|
| [a0eb547] | 2036 | 
 | 
|---|
| [49db5fc] | 2037 |          glGenBuffers(1, &it->second.buffer);
 | 
|---|
 | 2038 |          glBindBuffer(GL_ARRAY_BUFFER, it->second.buffer);
 | 
|---|
| [a0eb547] | 2039 | 
 | 
|---|
| [49db5fc] | 2040 |          switch (it->second.type) {
 | 
|---|
 | 2041 |             case GL_FLOAT: {
 | 
|---|
 | 2042 |                glVertexAttribPointer(it->second.index, it->second.size, it->second.type, GL_FALSE, 0, NULL);
 | 
|---|
 | 2043 |                break;
 | 
|---|
 | 2044 |             }
 | 
|---|
 | 2045 |             case GL_UNSIGNED_INT: {
 | 
|---|
 | 2046 |                glVertexAttribIPointer(it->second.index, it->second.size, it->second.type, 0, NULL);
 | 
|---|
 | 2047 |                break;
 | 
|---|
 | 2048 |             }
 | 
|---|
| [a0eb547] | 2049 |          }
 | 
|---|
 | 2050 |       }
 | 
|---|
 | 2051 |    }
 | 
|---|
 | 2052 | }
 | 
|---|
 | 2053 | 
 | 
|---|
| [49db5fc] | 2054 | void bindUniformData(AttribInfo& attrib) {
 | 
|---|
 | 2055 |    switch(attrib.uniType) {
 | 
|---|
 | 2056 |       case UNIFORM_MATRIX_4F:
 | 
|---|
 | 2057 |          glUniformMatrix4fv(attrib.buffer, attrib.size, GL_FALSE, attrib.data);
 | 
|---|
 | 2058 |          break;
 | 
|---|
 | 2059 |       case UNIFORM_1F:
 | 
|---|
| [b220f78] | 2060 |          glUniform1fv(attrib.buffer, attrib.size, attrib.data);
 | 
|---|
| [49db5fc] | 2061 |          break;
 | 
|---|
 | 2062 |       case UNIFORM_3F:
 | 
|---|
 | 2063 |          glUniform3fv(attrib.buffer, attrib.size, attrib.data);
 | 
|---|
 | 2064 |          break;
 | 
|---|
| [b220f78] | 2065 |       case UNIFORM_NONE:
 | 
|---|
 | 2066 |          break;
 | 
|---|
 | 2067 |    }
 | 
|---|
 | 2068 | }
 | 
|---|
 | 2069 | 
 | 
|---|
 | 2070 | void bindUniformData(AttribInfo& attrib, GLfloat *data) {
 | 
|---|
 | 2071 |    switch(attrib.uniType) {
 | 
|---|
 | 2072 |       case UNIFORM_MATRIX_4F:
 | 
|---|
 | 2073 |          glUniformMatrix4fv(attrib.buffer, attrib.size, GL_FALSE, data);
 | 
|---|
 | 2074 |          break;
 | 
|---|
 | 2075 |       case UNIFORM_1F:
 | 
|---|
 | 2076 |          glUniform1fv(attrib.buffer, attrib.size, data);
 | 
|---|
 | 2077 |          break;
 | 
|---|
 | 2078 |       case UNIFORM_3F:
 | 
|---|
 | 2079 |          glUniform3fv(attrib.buffer, attrib.size, data);
 | 
|---|
 | 2080 |          break;
 | 
|---|
 | 2081 |       case UNIFORM_NONE:
 | 
|---|
 | 2082 |          break;
 | 
|---|
| [49db5fc] | 2083 |    }
 | 
|---|
 | 2084 | }
 | 
|---|
 | 2085 | 
 | 
|---|
| [a0eb547] | 2086 | /* The purpose of this function is to replace the use of sizeof() when calling
 | 
|---|
 | 2087 |  * function like glBufferSubData and using AttribInfo to get offsets and types
 | 
|---|
 | 2088 |  * I need instead of hardcoding them. I can't save a type like GLfloat, but I cam
 | 
|---|
 | 2089 |  * save GL_FLOAT and use this function to return sizeof(GLfloat) when GL_FLOAT is
 | 
|---|
 | 2090 |  * passed.
 | 
|---|
 | 2091 |  */
 | 
|---|
 | 2092 | size_t GLsizeof(GLenum type) {
 | 
|---|
 | 2093 |    switch (type) {
 | 
|---|
 | 2094 |       case GL_FLOAT:
 | 
|---|
 | 2095 |          return sizeof(GLfloat);
 | 
|---|
 | 2096 |       case GL_UNSIGNED_INT:
 | 
|---|
 | 2097 |          return sizeof(GLuint);
 | 
|---|
 | 2098 |       default:
 | 
|---|
 | 2099 |          cout << "Uknown GL type passed to GLsizeof: " << type << endl;
 | 
|---|
 | 2100 |          return 0;
 | 
|---|
 | 2101 |    }
 | 
|---|
 | 2102 | }
 | 
|---|
 | 2103 | 
 | 
|---|
 | 2104 | /* This function returns a reference to the first element of a given vector
 | 
|---|
 | 2105 |  * attribute in obj. The vector is assumed to hold GLfloats. If the same thing
 | 
|---|
 | 2106 |  * needs to be done later for vectors of other types, we could pass in a GLenum,
 | 
|---|
 | 2107 |  * and do something similar to GLsizeof
 | 
|---|
 | 2108 |  */
 | 
|---|
 | 2109 | GLvoid* getVectorAttribPtr(SceneObject& obj, size_t attribOffset) {
 | 
|---|
 | 2110 |    return (GLvoid*)(&(*(vector<GLfloat>*)((size_t)&obj + attribOffset))[0]);
 | 
|---|
 | 2111 | }
 | 
|---|
 | 2112 | 
 | 
|---|
 | 2113 | GLvoid* getScalarAttribPtr(SceneObject& obj, size_t attribOffset) {
 | 
|---|
 | 2114 |    return (GLvoid*)((size_t)&obj + attribOffset);
 | 
|---|
 | 2115 | }
 | 
|---|
 | 2116 | 
 | 
|---|
| [c3c3158] | 2117 | void initializeBuffers(
 | 
|---|
 | 2118 |                   GLuint* points_vbo,
 | 
|---|
 | 2119 |                   GLuint* colors_vbo,
 | 
|---|
 | 2120 |                   GLuint* texcoords_vbo,
 | 
|---|
 | 2121 |                   GLuint* normals_vbo,
 | 
|---|
 | 2122 |                   GLuint* ubo,
 | 
|---|
| [6877ef3] | 2123 |                   GLuint* model_mat_idx_vbo) {
 | 
|---|
| [c3c3158] | 2124 |    *points_vbo = 0;
 | 
|---|
 | 2125 |    glGenBuffers(1, points_vbo);
 | 
|---|
 | 2126 | 
 | 
|---|
 | 2127 |    *colors_vbo = 0;
 | 
|---|
 | 2128 |    glGenBuffers(1, colors_vbo);
 | 
|---|
 | 2129 | 
 | 
|---|
 | 2130 |    *texcoords_vbo = 0;
 | 
|---|
 | 2131 |    glGenBuffers(1, texcoords_vbo);
 | 
|---|
 | 2132 | 
 | 
|---|
 | 2133 |    *normals_vbo = 0;
 | 
|---|
 | 2134 |    glGenBuffers(1, normals_vbo);
 | 
|---|
 | 2135 | 
 | 
|---|
 | 2136 |    *ubo = 0;
 | 
|---|
 | 2137 |    glGenBuffers(1, ubo);
 | 
|---|
 | 2138 | 
 | 
|---|
 | 2139 |    *model_mat_idx_vbo = 0;
 | 
|---|
 | 2140 |    glGenBuffers(1, model_mat_idx_vbo);
 | 
|---|
 | 2141 | }
 | 
|---|
 | 2142 | 
 | 
|---|
| [b220f78] | 2143 | void initializeParticleEffectBuffers(vec3 origin,
 | 
|---|
| [646f3f2] | 2144 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 2145 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [646f3f2] | 2146 |                   GLuint points_vbo,
 | 
|---|
 | 2147 |                   GLuint colors_vbo,
 | 
|---|
 | 2148 |                   GLuint texcoords_vbo,
 | 
|---|
 | 2149 |                   GLuint normals_vbo,
 | 
|---|
 | 2150 |                   GLuint ubo,
 | 
|---|
 | 2151 |                   GLuint model_mat_idx_vbo) {
 | 
|---|
| [db06984] | 2152 |    float vv[EXPLOSION_PARTICLE_COUNT * 3]; // initial velocities vec3
 | 
|---|
 | 2153 |    float vt[EXPLOSION_PARTICLE_COUNT]; // initial times
 | 
|---|
 | 2154 |    float t_accum = 0.0f; // start time
 | 
|---|
 | 2155 | 
 | 
|---|
 | 2156 |    for (int i = 0; i < EXPLOSION_PARTICLE_COUNT; i++) {
 | 
|---|
 | 2157 |       vt[i] = t_accum;
 | 
|---|
 | 2158 |       t_accum += 0.01f;
 | 
|---|
 | 2159 | 
 | 
|---|
| [adb104f] | 2160 |       float randx = ((float)rand() / (float)RAND_MAX) - 0.5f;
 | 
|---|
 | 2161 |       float randy = ((float)rand() / (float)RAND_MAX) - 0.5f;
 | 
|---|
| [db06984] | 2162 |       vv[i*3] = randx;
 | 
|---|
| [adb104f] | 2163 |       vv[i*3 + 1] = randy;
 | 
|---|
 | 2164 |       vv[i*3 + 2] = 0.0f;
 | 
|---|
| [db06984] | 2165 |    }
 | 
|---|
 | 2166 | 
 | 
|---|
| [fe5e3ca] | 2167 |    mat4 model_mat = translate(mat4(1.0f), origin);
 | 
|---|
 | 2168 | 
 | 
|---|
| [0414306] | 2169 |    glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 | 
|---|
| [7a55b49] | 2170 | 
 | 
|---|
| [b220f78] | 2171 |    bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["proj"]);
 | 
|---|
 | 2172 |    bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["view"]);
 | 
|---|
 | 2173 |    bindUniformData(modelGroups[TYPE_EXPLOSION].attribs["model_mat"], value_ptr(model_mat));
 | 
|---|
| [fe5e3ca] | 2174 | 
 | 
|---|
| [de53394] | 2175 |    // the glBufferData calls need to stay here while the corresponding arrays
 | 
|---|
| [b220f78] | 2176 |    // are local to this function. Once they're made part of the explosion object, I might be able
 | 
|---|
 | 2177 |    // to move this code out of here
 | 
|---|
| [646f3f2] | 2178 | 
 | 
|---|
| [b05e2b5] | 2179 |    glBindBuffer(GL_ARRAY_BUFFER, modelGroups[TYPE_EXPLOSION].attribs["v_i"].buffer);
 | 
|---|
| [b220f78] | 2180 |    glBufferData(GL_ARRAY_BUFFER, sizeof(vv), vv, GL_STATIC_DRAW);
 | 
|---|
| [db06984] | 2181 | 
 | 
|---|
| [b05e2b5] | 2182 |    glBindBuffer(GL_ARRAY_BUFFER, modelGroups[TYPE_EXPLOSION].attribs["start_time"].buffer);
 | 
|---|
| [b220f78] | 2183 |    glBufferData(GL_ARRAY_BUFFER, sizeof(vt), vt, GL_STATIC_DRAW);
 | 
|---|
| [db06984] | 2184 | 
 | 
|---|
| [dd9771c] | 2185 |    objExplosion = createExplosion();
 | 
|---|
| [0414306] | 2186 |    addObjectToScene(objExplosion, shaderBufferInfo, modelGroups,
 | 
|---|
| [646f3f2] | 2187 |       points_vbo,
 | 
|---|
 | 2188 |       colors_vbo,
 | 
|---|
 | 2189 |       texcoords_vbo,
 | 
|---|
 | 2190 |       normals_vbo,
 | 
|---|
 | 2191 |       ubo,
 | 
|---|
| [0414306] | 2192 |       model_mat_idx_vbo);
 | 
|---|
| [db06984] | 2193 | }
 | 
|---|
 | 2194 | 
 | 
|---|
| [1f3d32b] | 2195 | void populateBuffers(vector<SceneObject*>& objects,
 | 
|---|
| [c3c3158] | 2196 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 2197 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [c3c3158] | 2198 |                   GLuint points_vbo,
 | 
|---|
 | 2199 |                   GLuint colors_vbo,
 | 
|---|
 | 2200 |                   GLuint texcoords_vbo,
 | 
|---|
 | 2201 |                   GLuint normals_vbo,
 | 
|---|
 | 2202 |                   GLuint ubo,
 | 
|---|
| [0414306] | 2203 |                   GLuint ubo_idx_vbo) {
 | 
|---|
| [0e0f851] | 2204 |    GLsizeiptr num_points = 0;
 | 
|---|
 | 2205 |    GLsizeiptr num_objects = 0;
 | 
|---|
| [0d5c100] | 2206 | 
 | 
|---|
| [c3c3158] | 2207 |    map<GLuint, unsigned int> shaderCounts;
 | 
|---|
| [0d5c100] | 2208 |    map<GLuint, unsigned int> shaderUboCounts;
 | 
|---|
| [93462c6] | 2209 | 
 | 
|---|
| [646f3f2] | 2210 |    map<GLuint, BufferInfo>::iterator shaderIt;
 | 
|---|
 | 2211 | 
 | 
|---|
 | 2212 |    for (shaderIt = shaderBufferInfo.begin(); shaderIt != shaderBufferInfo.end(); shaderIt++) {
 | 
|---|
 | 2213 |       shaderCounts[shaderIt->first] = 0;
 | 
|---|
 | 2214 |       shaderUboCounts[shaderIt->first] = 0;
 | 
|---|
 | 2215 |    }
 | 
|---|
 | 2216 | 
 | 
|---|
| [1f3d32b] | 2217 |    vector<SceneObject*>::iterator it;
 | 
|---|
| [0d5c100] | 2218 | 
 | 
|---|
| [92b1e90] | 2219 |    /* Find all shaders that need to be used and the number of objects and
 | 
|---|
| [c3c3158] | 2220 |    * number of points for each shader. Construct a map from shader id to count
 | 
|---|
 | 2221 |    * of points being drawn using that shader (for thw model matrix ubo, we
 | 
|---|
 | 2222 |    * need object counts instead). These will be used to get offsets into the
 | 
|---|
 | 2223 |    * vertex buffer for each shader.
 | 
|---|
 | 2224 |    */
 | 
|---|
| [1f3d32b] | 2225 |    for (it = objects.begin(); it != objects.end(); ) {
 | 
|---|
 | 2226 |       if ((*it)->deleted) {
 | 
|---|
 | 2227 |          delete *it;
 | 
|---|
| [c3c3158] | 2228 |          it = objects.erase(it);
 | 
|---|
| [0d5c100] | 2229 |       } else {
 | 
|---|
| [0e0f851] | 2230 |          num_points += (*it)->num_points;
 | 
|---|
 | 2231 |          num_objects++;
 | 
|---|
| [c3c3158] | 2232 | 
 | 
|---|
| [dd9771c] | 2233 |          shaderCounts[modelGroups[(*it)->type].shaderProgram] += (*it)->num_points;
 | 
|---|
 | 2234 |          shaderUboCounts[modelGroups[(*it)->type].shaderProgram]++;
 | 
|---|
| [c3c3158] | 2235 | 
 | 
|---|
 | 2236 |          it++;
 | 
|---|
| [e3ca955] | 2237 |       }
 | 
|---|
| [0d5c100] | 2238 |    }
 | 
|---|
 | 2239 | 
 | 
|---|
| [c3c3158] | 2240 |    // double the buffer sizes to leave room for new objects
 | 
|---|
| [0e0f851] | 2241 |    num_points *= 2;
 | 
|---|
 | 2242 |    num_objects *= 2;
 | 
|---|
| [c3c3158] | 2243 | 
 | 
|---|
| [646f3f2] | 2244 |    map<GLuint, unsigned int>::iterator shaderCountIt;
 | 
|---|
| [0d5c100] | 2245 |    unsigned int lastShaderCount = 0;
 | 
|---|
 | 2246 |    unsigned int lastShaderUboCount = 0;
 | 
|---|
 | 2247 | 
 | 
|---|
 | 2248 |    /*
 | 
|---|
| [c3c3158] | 2249 |    * The counts calculated above can be used to get the starting offset of
 | 
|---|
 | 2250 |    * each shader in the vertex buffer. Create a map of base offsets to mark
 | 
|---|
 | 2251 |    * where the data for the first object using a given shader begins. Also,
 | 
|---|
 | 2252 |    * create a map of current offsets to mark where to copy data for the next
 | 
|---|
 | 2253 |    * object being added.
 | 
|---|
 | 2254 |    */
 | 
|---|
| [646f3f2] | 2255 |    for (shaderCountIt = shaderCounts.begin(); shaderCountIt != shaderCounts.end(); shaderCountIt++) {
 | 
|---|
| [0e0f851] | 2256 |       // When populating the buffers, leave as much empty space as space taken up by existing objects
 | 
|---|
 | 2257 |       // to allow new objects to be added without immediately having to resize the buffers
 | 
|---|
| [646f3f2] | 2258 |       shaderBufferInfo[shaderCountIt->first].vbo_base = lastShaderCount * 2;
 | 
|---|
 | 2259 |       shaderBufferInfo[shaderCountIt->first].ubo_base = lastShaderUboCount * 2;
 | 
|---|
| [0d5c100] | 2260 | 
 | 
|---|
| [646f3f2] | 2261 |       shaderBufferInfo[shaderCountIt->first].ubo_offset = 0;
 | 
|---|
| [c3c3158] | 2262 | 
 | 
|---|
| [646f3f2] | 2263 |       shaderBufferInfo[shaderCountIt->first].ubo_capacity = shaderUboCounts[shaderCountIt->first] * 2;
 | 
|---|
| [0d5c100] | 2264 | 
 | 
|---|
| [646f3f2] | 2265 |       lastShaderCount += shaderCounts[shaderCountIt->first];
 | 
|---|
 | 2266 |       lastShaderUboCount += shaderUboCounts[shaderCountIt->first];
 | 
|---|
| [0d5c100] | 2267 |    }
 | 
|---|
 | 2268 | 
 | 
|---|
| [a0eb547] | 2269 |    /* Since we just want to start with lasers, make a loop that goes through all the laser model group attributes
 | 
|---|
 | 2270 |     * and allocates data for them. Determine how to go from GLenum (e.g. GL_FLOAT) to typedef (e.g. GLfloat)
 | 
|---|
 | 2271 |     */
 | 
|---|
| [4c7cd57] | 2272 |    map<ObjectType, ShaderModelGroup>::iterator modelGroupIt;
 | 
|---|
| [a0eb547] | 2273 |    ShaderModelGroup* smg;
 | 
|---|
| [4c7cd57] | 2274 |    for (modelGroupIt = modelGroups.begin(); modelGroupIt != modelGroups.end(); modelGroupIt++) {
 | 
|---|
| [a0eb547] | 2275 |       smg = &modelGroups[modelGroupIt->first];
 | 
|---|
 | 2276 | 
 | 
|---|
 | 2277 |       smg->numPoints = 0;
 | 
|---|
 | 2278 |       smg->vboCapacity = shaderCounts[smg->shaderProgram] * 2;
 | 
|---|
 | 2279 |       /*
 | 
|---|
 | 2280 |       if (modelGroupIt->first == TYPE_LASER) {
 | 
|---|
 | 2281 |          smg = &modelGroups[modelGroupIt->first];
 | 
|---|
 | 2282 |          smg->numPoints = shaderCounts[smg->shaderProgram];
 | 
|---|
 | 2283 | 
 | 
|---|
 | 2284 |          // Here, I could add glBufferData calls to allocate space for laser buffers
 | 
|---|
 | 2285 |          if (modelGroupIt->first == TYPE_LASER) {
 | 
|---|
 | 2286 |             glBindBuffer(GL_ARRAY_BUFFER, smg->attribs["vertex_position"].buffer);
 | 
|---|
 | 2287 |             glBufferData(GL_ARRAY_BUFFER, smg->numPoints * sizeof(GLfloat) * smg->attribs["vertex_position"].size, NULL, GL_DYNAMIC_DRAW);
 | 
|---|
 | 2288 |          }
 | 
|---|
 | 2289 |       }
 | 
|---|
 | 2290 |       */
 | 
|---|
| [4c7cd57] | 2291 |    }
 | 
|---|
| [0414306] | 2292 | 
 | 
|---|
| [c3c3158] | 2293 |    // Allocate all the buffers using the counts calculated above
 | 
|---|
| [0d5c100] | 2294 | 
 | 
|---|
| [c3c3158] | 2295 |    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
 | 
|---|
| [0e0f851] | 2296 |    glBufferData(GL_ARRAY_BUFFER, num_points * sizeof(GLfloat) * 3, NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2297 | 
 | 
|---|
| [c3c3158] | 2298 |    glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
 | 
|---|
| [0e0f851] | 2299 |    glBufferData(GL_ARRAY_BUFFER, num_points * sizeof(GLfloat) * 3, NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2300 | 
 | 
|---|
| [c3c3158] | 2301 |    glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
 | 
|---|
| [0e0f851] | 2302 |    glBufferData(GL_ARRAY_BUFFER, num_points * sizeof(GLfloat) * 2, NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2303 | 
 | 
|---|
| [c3c3158] | 2304 |    glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
 | 
|---|
| [0e0f851] | 2305 |    glBufferData(GL_ARRAY_BUFFER, num_points * sizeof(GLfloat) * 3, NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2306 | 
 | 
|---|
| [c3c3158] | 2307 |    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
 | 
|---|
| [0e0f851] | 2308 |    glBufferData(GL_UNIFORM_BUFFER, num_objects * sizeof(mat4), NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2309 | 
 | 
|---|
| [0e0f851] | 2310 |    glBindBuffer(GL_ARRAY_BUFFER, ubo_idx_vbo);
 | 
|---|
 | 2311 |    glBufferData(GL_ARRAY_BUFFER, num_points * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
 | 
|---|
| [0d5c100] | 2312 | 
 | 
|---|
 | 2313 |    for (it = objects.begin(); it != objects.end(); it++) {
 | 
|---|
| [49db5fc] | 2314 |       copyObjectDataToBuffers(**it, shaderBufferInfo, modelGroups, ubo);
 | 
|---|
| [c3c3158] | 2315 |    }
 | 
|---|
 | 2316 | }
 | 
|---|
| [0d5c100] | 2317 | 
 | 
|---|
| [c3c3158] | 2318 | void copyObjectDataToBuffers(SceneObject& obj,
 | 
|---|
 | 2319 |                   map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [0414306] | 2320 |                   map<ObjectType, ShaderModelGroup>& modelGroups,
 | 
|---|
| [49db5fc] | 2321 |                   GLuint ubo) {
 | 
|---|
| [dd9771c] | 2322 |    BufferInfo* bufferInfo = &shaderBufferInfo[modelGroups[obj.type].shaderProgram];
 | 
|---|
| [0d5c100] | 2323 | 
 | 
|---|
| [b62c109] | 2324 |    obj.vertex_vbo_offset = bufferInfo->vbo_base + modelGroups[obj.type].numPoints;
 | 
|---|
| [c3c3158] | 2325 |    obj.ubo_offset = bufferInfo->ubo_base + bufferInfo->ubo_offset;
 | 
|---|
| [0d5c100] | 2326 | 
 | 
|---|
| [646f3f2] | 2327 |    if (obj.ubo_offset == 0) {
 | 
|---|
 | 2328 |       objFirst = &obj;
 | 
|---|
 | 2329 |    }
 | 
|---|
| [0d5c100] | 2330 | 
 | 
|---|
| [646f3f2] | 2331 |    if (obj.type != TYPE_EXPLOSION) {
 | 
|---|
| [a0eb547] | 2332 |       ShaderModelGroup& smg = modelGroups[obj.type];
 | 
|---|
| [0d5c100] | 2333 | 
 | 
|---|
| [a0eb547] | 2334 |       for (map<string, AttribInfo>::iterator it = smg.attribs.begin(); it != smg.attribs.end(); it++) {
 | 
|---|
 | 2335 |          glBindBuffer(GL_ARRAY_BUFFER, it->second.buffer);
 | 
|---|
| [fd6f465] | 2336 | 
 | 
|---|
| [a0eb547] | 2337 |          switch (it->second.attribType) {
 | 
|---|
 | 2338 |             case ATTRIB_POINT_VARYING:
 | 
|---|
 | 2339 |                glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * GLsizeof(it->second.type) * it->second.size,
 | 
|---|
 | 2340 |                   obj.num_points * GLsizeof(it->second.type) * it->second.size, getVectorAttribPtr(obj, it->second.fieldOffset));
 | 
|---|
 | 2341 |                break;
 | 
|---|
 | 2342 |             case ATTRIB_OBJECT_VARYING:
 | 
|---|
 | 2343 |                for (unsigned int i = 0; i < obj.num_points; i++) {
 | 
|---|
 | 2344 |                   glBufferSubData(GL_ARRAY_BUFFER, (obj.vertex_vbo_offset + i) * GLsizeof(it->second.type) * it->second.size,
 | 
|---|
 | 2345 |                      GLsizeof(it->second.type) * it->second.size, getScalarAttribPtr(obj, it->second.fieldOffset));
 | 
|---|
 | 2346 |                }
 | 
|---|
 | 2347 |                break;
 | 
|---|
 | 2348 |             case ATTRIB_UNIFORM:
 | 
|---|
 | 2349 |               break;
 | 
|---|
 | 2350 |          }
 | 
|---|
| [646f3f2] | 2351 |       }
 | 
|---|
| [fd6f465] | 2352 | 
 | 
|---|
| [646f3f2] | 2353 |       obj.model_mat = obj.model_transform * obj.model_base;
 | 
|---|
 | 2354 |       glBindBuffer(GL_UNIFORM_BUFFER, ubo);
 | 
|---|
 | 2355 |       glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
 | 
|---|
| [25b47d7] | 2356 | 
 | 
|---|
| [646f3f2] | 2357 |       if (obj.type == TYPE_ASTEROID) {
 | 
|---|
| [0414306] | 2358 |          glUseProgram(modelGroups[TYPE_ASTEROID].shaderProgram);
 | 
|---|
| [646f3f2] | 2359 | 
 | 
|---|
 | 2360 |          ostringstream oss;
 | 
|---|
 | 2361 |          oss << "hp[" << obj.ubo_offset << "]";
 | 
|---|
| [0414306] | 2362 |          glUniform1f(glGetUniformLocation(modelGroups[TYPE_ASTEROID].shaderProgram, oss.str().c_str()), ((Asteroid*)&obj)->hp);
 | 
|---|
| [646f3f2] | 2363 |       }
 | 
|---|
| [25b47d7] | 2364 |    }
 | 
|---|
| [0e0f851] | 2365 | 
 | 
|---|
| [b62c109] | 2366 |    modelGroups[obj.type].numPoints += obj.num_points;
 | 
|---|
| [c3c3158] | 2367 |    bufferInfo->ubo_offset++;
 | 
|---|
| [0d5c100] | 2368 | }
 | 
|---|
| [93462c6] | 2369 | 
 | 
|---|
| [5c403fe] | 2370 | void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
 | 
|---|
| [fabed35] | 2371 |    if (obj.deleted) return;
 | 
|---|
 | 2372 | 
 | 
|---|
| [3d06b4e] | 2373 |    obj.model_transform = transform * obj.model_transform;
 | 
|---|
| [5c403fe] | 2374 |    obj.model_mat = obj.model_transform * obj.model_base;
 | 
|---|
 | 2375 | 
 | 
|---|
| [95595de] | 2376 |    obj.bounding_center = vec3(transform * vec4(obj.bounding_center, 1.0f));
 | 
|---|
 | 2377 | 
 | 
|---|
| [5c403fe] | 2378 |    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
 | 
|---|
 | 2379 |    glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
 | 
|---|
 | 2380 | }
 | 
|---|
 | 2381 | 
 | 
|---|
| [1f3d32b] | 2382 | void translateLaser(Laser* laser, const vec3& translation, GLuint ubo) {
 | 
|---|
| [e9347b4] | 2383 |    // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
 | 
|---|
| [612d1f6] | 2384 |    // and then re-used here
 | 
|---|
 | 2385 | 
 | 
|---|
| [1f3d32b] | 2386 |    vec3 start = vec3(laser->model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
 | 2387 |    vec3 end = vec3(laser->model_transform * vec4(0.0f, 0.0f, laser->points[38], 1.0f));
 | 
|---|
| [612d1f6] | 2388 | 
 | 
|---|
 | 2389 |    vec3 ray = end - start;
 | 
|---|
 | 2390 |    float length = glm::length(ray);
 | 
|---|
 | 2391 | 
 | 
|---|
 | 2392 |    float xAxisRotation = asin(ray.y / length);
 | 
|---|
 | 2393 |    float yAxisRotation = atan2(-ray.x, -ray.z);
 | 
|---|
 | 2394 | 
 | 
|---|
 | 2395 |    vec3 normal(rotate(mat4(1.0f), yAxisRotation, vec3(0.0f, 1.0f, 0.0f)) *
 | 
|---|
 | 2396 |       rotate(mat4(1.0f), xAxisRotation, vec3(1.0f, 0.0f, 0.0f)) *
 | 
|---|
 | 2397 |       vec4(0.0f, 1.0f, 0.0f, 1.0f));
 | 
|---|
 | 2398 | 
 | 
|---|
 | 2399 |    // To project point P onto line AB:
 | 
|---|
 | 2400 |    // projection = A + dot(AP,AB) / dot(AB,AB) * AB
 | 
|---|
 | 2401 |    vec3 projOnLaser = start + glm::dot(cam_pos - start, ray) / (length*length) * ray;
 | 
|---|
 | 2402 |    vec3 laserToCam = cam_pos - projOnLaser;
 | 
|---|
 | 2403 | 
 | 
|---|
 | 2404 |    float zAxisRotation = -atan2(glm::dot(glm::cross(normal, laserToCam), glm::normalize(ray)), glm::dot(normal, laserToCam));
 | 
|---|
 | 2405 | 
 | 
|---|
| [1f3d32b] | 2406 |    laser->model_base = rotate(mat4(1.0f), zAxisRotation, vec3(0.0f, 0.0f, 1.0f));
 | 
|---|
| [612d1f6] | 2407 | 
 | 
|---|
| [1f3d32b] | 2408 |    transformObject(*laser, translate(mat4(1.0f), translation), ubo);
 | 
|---|
| [612d1f6] | 2409 | }
 | 
|---|
 | 2410 | 
 | 
|---|
| [a0eb547] | 2411 | void updateLaserTarget(Laser* laser, vector<SceneObject*>& objects, ShaderModelGroup& laserSmg, GLuint asteroid_sp) {
 | 
|---|
| [e9347b4] | 2412 |    // TODO: A lot of the values calculated here can be calculated once and saved when the laser is created,
 | 
|---|
 | 2413 |    // and then re-used here
 | 
|---|
 | 2414 | 
 | 
|---|
| [1f3d32b] | 2415 |    vec3 start = vec3(laser->model_transform * vec4(0.0f, 0.0f, 0.0f, 1.0f));
 | 
|---|
 | 2416 |    vec3 end = vec3(laser->model_transform * vec4(0.0f, 0.0f, laser->points[2] + laser->points[20], 1.0f));
 | 
|---|
| [e9347b4] | 2417 | 
 | 
|---|
 | 2418 |    vec3 intersection(0.0f), closestIntersection(0.0f);
 | 
|---|
| [1f3d32b] | 2419 |    Asteroid* closestAsteroid = NULL;
 | 
|---|
| [e9347b4] | 2420 | 
 | 
|---|
| [1f3d32b] | 2421 |    for (vector<SceneObject*>::iterator it = objects.begin(); it != objects.end(); it++) {
 | 
|---|
 | 2422 |       if ((*it)->type == TYPE_ASTEROID && !(*it)->deleted && getLaserAndAsteroidIntersection(start, end, **it, intersection)) {
 | 
|---|
| [e9347b4] | 2423 |          // TODO: Implement a more generic algorithm for testing the closest object by getting the distance between the points
 | 
|---|
 | 2424 |          if (closestAsteroid == NULL || intersection.z > closestIntersection.z) {
 | 
|---|
 | 2425 |             // TODO: At this point, find the real intersection of the laser with one of the asteroid's sides
 | 
|---|
| [1f3d32b] | 2426 |             closestAsteroid = (Asteroid*)*it;
 | 
|---|
| [e9347b4] | 2427 |             closestIntersection = intersection;
 | 
|---|
 | 2428 |          }
 | 
|---|
 | 2429 |       }
 | 
|---|
 | 2430 |    }
 | 
|---|
 | 2431 | 
 | 
|---|
| [1f3d32b] | 2432 |    float width = laser->points[0] - laser->points[2];
 | 
|---|
 | 2433 | 
 | 
|---|
 | 2434 |    if (laser->targetAsteroid != closestAsteroid) {
 | 
|---|
 | 2435 |       if (laser->targetAsteroid != NULL) {
 | 
|---|
 | 2436 |          if (laser == leftLaser) {
 | 
|---|
 | 2437 |             leftLaserEffect->deleted = true;
 | 
|---|
 | 2438 |          } else if (laser == rightLaser) {
 | 
|---|
 | 2439 |             rightLaserEffect->deleted = true;
 | 
|---|
 | 2440 |          }
 | 
|---|
 | 2441 |       }
 | 
|---|
 | 2442 | 
 | 
|---|
 | 2443 |       EffectOverTime* eot = NULL;
 | 
|---|
| [e9347b4] | 2444 | 
 | 
|---|
| [1f3d32b] | 2445 |       if (closestAsteroid != NULL) {
 | 
|---|
| [25b47d7] | 2446 |          eot = new EffectOverTime(closestAsteroid->hp, -20.0f, closestAsteroid);
 | 
|---|
| [1f3d32b] | 2447 |          effects.push_back(eot);
 | 
|---|
 | 2448 |       }
 | 
|---|
 | 2449 | 
 | 
|---|
 | 2450 |       if (laser == leftLaser) {
 | 
|---|
 | 2451 |          leftLaserEffect = eot;
 | 
|---|
 | 2452 |       } else if (laser == rightLaser) {
 | 
|---|
 | 2453 |          rightLaserEffect = eot;
 | 
|---|
 | 2454 |       }
 | 
|---|
 | 2455 |    }
 | 
|---|
 | 2456 |    laser->targetAsteroid = closestAsteroid;
 | 
|---|
 | 2457 | 
 | 
|---|
 | 2458 |    float length = 5.24f; // I think this was to make sure the laser went past the end of the screen
 | 
|---|
| [e9347b4] | 2459 |    if (closestAsteroid != NULL) {
 | 
|---|
 | 2460 |       length = glm::length(closestIntersection - start);
 | 
|---|
| [0e0f851] | 2461 | 
 | 
|---|
| [a0eb547] | 2462 |       // TODO: Find a more generic way of updating the asteroid hp than in updateLaserTarget
 | 
|---|
| [0e0f851] | 2463 | 
 | 
|---|
 | 2464 |       glUseProgram(asteroid_sp);
 | 
|---|
| [25b47d7] | 2465 | 
 | 
|---|
 | 2466 |       ostringstream oss;
 | 
|---|
 | 2467 |       oss << "hp[" << closestAsteroid->ubo_offset << "]";
 | 
|---|
 | 2468 |       glUniform1f(glGetUniformLocation(asteroid_sp, oss.str().c_str()), closestAsteroid->hp);
 | 
|---|
| [e9347b4] | 2469 |    }
 | 
|---|
 | 2470 | 
 | 
|---|
| [1f3d32b] | 2471 |    laser->points[20] = -length + width / 2;
 | 
|---|
 | 2472 |    laser->points[23] = -length + width / 2;
 | 
|---|
 | 2473 |    laser->points[29] = -length + width / 2;
 | 
|---|
 | 2474 |    laser->points[38] = -length;
 | 
|---|
 | 2475 |    laser->points[41] = -length;
 | 
|---|
 | 2476 |    laser->points[44] = -length + width / 2;
 | 
|---|
 | 2477 |    laser->points[47] = -length;
 | 
|---|
 | 2478 |    laser->points[50] = -length + width / 2;
 | 
|---|
 | 2479 |    laser->points[53] = -length + width / 2;
 | 
|---|
| [e9347b4] | 2480 | 
 | 
|---|
| [a0eb547] | 2481 |    AttribInfo* attrib = &laserSmg.attribs["vertex_position"];
 | 
|---|
 | 2482 |    glBindBuffer(GL_ARRAY_BUFFER, attrib->buffer);
 | 
|---|
 | 2483 |    glBufferSubData(GL_ARRAY_BUFFER, laser->vertex_vbo_offset * GLsizeof(attrib->type) * attrib->size,
 | 
|---|
 | 2484 |       laser->num_points * GLsizeof(attrib->type) * attrib->size, getVectorAttribPtr(*laser, attrib->fieldOffset));
 | 
|---|
| [e9347b4] | 2485 | }
 | 
|---|
 | 2486 | 
 | 
|---|
 | 2487 | bool getLaserAndAsteroidIntersection(vec3& start, vec3& end, SceneObject& asteroid, vec3& intersection) {
 | 
|---|
 | 2488 |    /*
 | 
|---|
 | 2489 |    ### LINE EQUATIONS ###
 | 
|---|
 | 2490 |    x = x1 + u * (x2 - x1)
 | 
|---|
 | 2491 |    y = y1 + u * (y2 - y1)
 | 
|---|
 | 2492 |    z = z1 + u * (z2 - z1)
 | 
|---|
 | 2493 | 
 | 
|---|
 | 2494 |    ### SPHERE EQUATION ###
 | 
|---|
 | 2495 |    (x - x3)^2 + (y - y3)^2 + (z - z3)^2 = r^2
 | 
|---|
 | 2496 | 
 | 
|---|
 | 2497 |    ### QUADRATIC EQUATION TO SOLVE ###
 | 
|---|
 | 2498 |    a*u^2 + b*u + c = 0
 | 
|---|
 | 2499 |    WHERE THE CONSTANTS ARE
 | 
|---|
 | 2500 |    a = (x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2
 | 
|---|
 | 2501 |    b = 2*( (x2 - x1)*(x1 - x3) + (y2 - y1)*(y1 - y3) + (z2 - z1)*(z1 - z3) )
 | 
|---|
 | 2502 |    c = x3^2 + y3^2 + z3^2 + x1^2 + y1^2 + z1^2 - 2(x3*x1 + y3*y1 + z3*z1) - r^2
 | 
|---|
 | 2503 | 
 | 
|---|
 | 2504 |    u = (-b +- sqrt(b^2 - 4*a*c)) / 2a
 | 
|---|
 | 2505 | 
 | 
|---|
 | 2506 |    If the value under the root is >= 0, we got an intersection
 | 
|---|
 | 2507 |    If the value > 0, there are two solutions. Take the one closer to 0, since that's the
 | 
|---|
 | 2508 |    one closer to the laser start point
 | 
|---|
 | 2509 |    */
 | 
|---|
 | 2510 | 
 | 
|---|
 | 2511 |    vec3& center = asteroid.bounding_center;
 | 
|---|
 | 2512 | 
 | 
|---|
 | 2513 |    float a = pow(end.x-start.x, 2) + pow(end.y-start.y, 2) + pow(end.z-start.z, 2);
 | 
|---|
 | 2514 |    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));
 | 
|---|
 | 2515 |    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);
 | 
|---|
 | 2516 |    float discriminant = pow(b, 2) - 4*a*c;
 | 
|---|
 | 2517 | 
 | 
|---|
 | 2518 |    if (discriminant >= 0.0f) {
 | 
|---|
 | 2519 |       // In this case, the negative root will always give the point closer to the laser start point
 | 
|---|
 | 2520 |       float u = (-b - sqrt(discriminant)) / (2 * a);
 | 
|---|
 | 2521 | 
 | 
|---|
 | 2522 |       // Check that the intersection is within the line segment corresponding to the laser
 | 
|---|
 | 2523 |       if (0.0f <= u && u <= 1.0f) {
 | 
|---|
 | 2524 |          intersection = start + u * (end - start);
 | 
|---|
 | 2525 |          return true;
 | 
|---|
 | 2526 |       }
 | 
|---|
 | 2527 |    }
 | 
|---|
 | 2528 | 
 | 
|---|
 | 2529 |    return false;
 | 
|---|
 | 2530 | }
 | 
|---|
 | 2531 | 
 | 
|---|
| [0414306] | 2532 | void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
 | 
|---|
| [b62c109] | 2533 |                   map<ObjectType, ShaderModelGroup>& modelGroups, GLuint ubo) {
 | 
|---|
| [93462c6] | 2534 | 
 | 
|---|
| [4c7cd57] | 2535 |    glUseProgram(modelGroups[TYPE_SHIP].shaderProgram);
 | 
|---|
 | 2536 |    glBindVertexArray(modelGroups[TYPE_SHIP].vao);
 | 
|---|
| [93462c6] | 2537 | 
 | 
|---|
| [4c7cd57] | 2538 |    glDrawArrays(GL_TRIANGLES, shaderBufferInfo[modelGroups[TYPE_SHIP].shaderProgram].vbo_base, modelGroups[TYPE_SHIP].numPoints);
 | 
|---|
| [93462c6] | 2539 | 
 | 
|---|
| [0414306] | 2540 |    glUseProgram(modelGroups[TYPE_ASTEROID].shaderProgram);
 | 
|---|
 | 2541 |    glBindVertexArray(modelGroups[TYPE_ASTEROID].vao);
 | 
|---|
| [0e0f851] | 2542 | 
 | 
|---|
| [0414306] | 2543 |    glDrawArrays(GL_TRIANGLES, shaderBufferInfo[modelGroups[TYPE_ASTEROID].shaderProgram].vbo_base, modelGroups[TYPE_ASTEROID].numPoints);
 | 
|---|
| [0e0f851] | 2544 | 
 | 
|---|
| [9f9f9a7] | 2545 |    glEnable(GL_BLEND);
 | 
|---|
 | 2546 | 
 | 
|---|
| [b62c109] | 2547 |    glUseProgram(modelGroups[TYPE_LASER].shaderProgram);
 | 
|---|
 | 2548 |    glBindVertexArray(modelGroups[TYPE_LASER].vao);
 | 
|---|
| [b155f13] | 2549 | 
 | 
|---|
| [b62c109] | 2550 |    glDrawArrays(GL_TRIANGLES, shaderBufferInfo[modelGroups[TYPE_LASER].shaderProgram].vbo_base, modelGroups[TYPE_LASER].numPoints);
 | 
|---|
| [9f9f9a7] | 2551 | 
 | 
|---|
| [0414306] | 2552 |    glUseProgram(modelGroups[TYPE_EXPLOSION].shaderProgram);
 | 
|---|
 | 2553 |    glBindVertexArray(modelGroups[TYPE_EXPLOSION].vao);
 | 
|---|
| [db06984] | 2554 | 
 | 
|---|
 | 2555 |    glEnable(GL_PROGRAM_POINT_SIZE);
 | 
|---|
 | 2556 | 
 | 
|---|
| [646f3f2] | 2557 |    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
 | 
|---|
 | 2558 |    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(mat4), value_ptr(objExplosion->model_mat));
 | 
|---|
| [db06984] | 2559 | 
 | 
|---|
| [0414306] | 2560 |    glDrawArrays(GL_POINTS, 0, modelGroups[TYPE_EXPLOSION].numPoints);
 | 
|---|
| [db06984] | 2561 | 
 | 
|---|
| [646f3f2] | 2562 |    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
 | 
|---|
 | 2563 |    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(mat4), value_ptr(objFirst->model_mat));
 | 
|---|
| [db06984] | 2564 | 
 | 
|---|
 | 2565 |    glDisable(GL_PROGRAM_POINT_SIZE);
 | 
|---|
 | 2566 |    glDisable(GL_BLEND);
 | 
|---|
| [b155f13] | 2567 | }
 | 
|---|
 | 2568 | 
 | 
|---|
| [93462c6] | 2569 | void renderSceneGui() {
 | 
|---|
| [c1ca5b5] | 2570 |    ImGui_ImplGlfwGL3_NewFrame();
 | 
|---|
 | 2571 | 
 | 
|---|
 | 2572 |    // 1. Show a simple window.
 | 
|---|
 | 2573 |    // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
 | 
|---|
| [5b3462b] | 2574 |    /*
 | 
|---|
| [c1ca5b5] | 2575 |    {
 | 
|---|
 | 2576 |       static float f = 0.0f;
 | 
|---|
 | 2577 |       static int counter = 0;
 | 
|---|
 | 2578 |       ImGui::Text("Hello, world!");                           // Display some text (you can use a format string too)
 | 
|---|
 | 2579 |       ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f    
 | 
|---|
 | 2580 |       ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
 | 
|---|
 | 2581 | 
 | 
|---|
 | 2582 |       ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our windows open/close state
 | 
|---|
 | 2583 |       ImGui::Checkbox("Another Window", &show_another_window);
 | 
|---|
 | 2584 | 
 | 
|---|
 | 2585 |       if (ImGui::Button("Button"))                            // Buttons return true when clicked (NB: most widgets return true when edited/activated)
 | 
|---|
 | 2586 |          counter++;
 | 
|---|
 | 2587 |       ImGui::SameLine();
 | 
|---|
 | 2588 |       ImGui::Text("counter = %d", counter);
 | 
|---|
 | 2589 | 
 | 
|---|
 | 2590 |       ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
 | 
|---|
 | 2591 |    }
 | 
|---|
| [5b3462b] | 2592 |    */
 | 
|---|
| [c1ca5b5] | 2593 | 
 | 
|---|
| [1e3dddf] | 2594 |    stringstream ssScore, ssFps;
 | 
|---|
 | 2595 |    ssScore << "Score: " << score;
 | 
|---|
 | 2596 |    ssFps << "FPS:   " << fps;
 | 
|---|
| [1f3d32b] | 2597 | 
 | 
|---|
| [5b3462b] | 2598 |    {
 | 
|---|
| [1f3d32b] | 2599 |       ImGui::SetNextWindowSize(ImVec2(95, 46), ImGuiCond_Once);
 | 
|---|
| [5b3462b] | 2600 |       ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
 | 
|---|
| [f0cc877] | 2601 |       ImGui::Begin("WndStats", NULL,
 | 
|---|
 | 2602 |          ImGuiWindowFlags_NoTitleBar |
 | 
|---|
 | 2603 |          ImGuiWindowFlags_NoResize |
 | 
|---|
 | 2604 |          ImGuiWindowFlags_NoMove);
 | 
|---|
| [1e3dddf] | 2605 |       ImGui::Text(ssScore.str().c_str());
 | 
|---|
 | 2606 |       ImGui::Text(ssFps.str().c_str());
 | 
|---|
| [c1ca5b5] | 2607 |       ImGui::End();
 | 
|---|
 | 2608 |    }
 | 
|---|
 | 2609 | 
 | 
|---|
| [5b3462b] | 2610 |    {
 | 
|---|
 | 2611 |       ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
 | 
|---|
 | 2612 |       ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
 | 
|---|
| [f0cc877] | 2613 |       ImGui::Begin("WndMenubar", NULL,
 | 
|---|
 | 2614 |          ImGuiWindowFlags_NoTitleBar |
 | 
|---|
| [5b3462b] | 2615 |          ImGuiWindowFlags_NoResize |
 | 
|---|
 | 2616 |          ImGuiWindowFlags_NoMove);
 | 
|---|
| [93462c6] | 2617 |       ImGui::InvisibleButton("", ImVec2(155, 18));
 | 
|---|
| [5b3462b] | 2618 |       ImGui::SameLine();
 | 
|---|
| [93462c6] | 2619 |       if (ImGui::Button("Main Menu")) {
 | 
|---|
 | 2620 |          events.push(EVENT_GO_TO_MAIN_MENU);
 | 
|---|
| [5b3462b] | 2621 |       }
 | 
|---|
 | 2622 |       ImGui::End();
 | 
|---|
| [c1ca5b5] | 2623 |    }
 | 
|---|
 | 2624 | 
 | 
|---|
| [93462c6] | 2625 |    ImGui::Render();
 | 
|---|
 | 2626 |    ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
 | 
|---|
 | 2627 | }
 | 
|---|
 | 2628 | 
 | 
|---|
 | 2629 | void renderMainMenu() {
 | 
|---|
 | 2630 | }
 | 
|---|
 | 2631 | 
 | 
|---|
 | 2632 | void renderMainMenuGui() {
 | 
|---|
 | 2633 |    ImGui_ImplGlfwGL3_NewFrame();
 | 
|---|
 | 2634 | 
 | 
|---|
| [f0cc877] | 2635 |    {
 | 
|---|
 | 2636 |       int padding = 4;
 | 
|---|
 | 2637 |       ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
 | 
|---|
| [93462c6] | 2638 |       ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
 | 
|---|
| [f0cc877] | 2639 |       ImGui::Begin("WndMain", NULL,
 | 
|---|
 | 2640 |          ImGuiWindowFlags_NoTitleBar |
 | 
|---|
 | 2641 |          ImGuiWindowFlags_NoResize |
 | 
|---|
 | 2642 |          ImGuiWindowFlags_NoMove);
 | 
|---|
| [93462c6] | 2643 | 
 | 
|---|
 | 2644 |       ImGui::InvisibleButton("", ImVec2(10, 80));
 | 
|---|
 | 2645 |       ImGui::InvisibleButton("", ImVec2(285, 18));
 | 
|---|
 | 2646 |       ImGui::SameLine();
 | 
|---|
 | 2647 |       if (ImGui::Button("New Game")) {
 | 
|---|
 | 2648 |          events.push(EVENT_GO_TO_GAME);
 | 
|---|
 | 2649 |       }
 | 
|---|
 | 2650 | 
 | 
|---|
 | 2651 |       ImGui::InvisibleButton("", ImVec2(10, 15));
 | 
|---|
 | 2652 |       ImGui::InvisibleButton("", ImVec2(300, 18));
 | 
|---|
 | 2653 |       ImGui::SameLine();
 | 
|---|
 | 2654 |       if (ImGui::Button("Quit")) {
 | 
|---|
 | 2655 |          events.push(EVENT_QUIT);
 | 
|---|
 | 2656 |       }
 | 
|---|
 | 2657 | 
 | 
|---|
| [f0cc877] | 2658 |       ImGui::End();
 | 
|---|
 | 2659 |    }
 | 
|---|
 | 2660 | 
 | 
|---|
| [c1ca5b5] | 2661 |    ImGui::Render();
 | 
|---|
 | 2662 |    ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
 | 
|---|
 | 2663 | }
 | 
|---|
| [cf2d1e5] | 2664 | 
 | 
|---|
| [dd9771c] | 2665 | Asteroid* createAsteroid(vec3 pos) {
 | 
|---|
| [1f3d32b] | 2666 |    Asteroid* obj = new Asteroid();
 | 
|---|
 | 2667 |    obj->type = TYPE_ASTEROID;
 | 
|---|
| [646f3f2] | 2668 |    obj->hp = 10.0f;
 | 
|---|
| [cf2d1e5] | 2669 | 
 | 
|---|
| [1f3d32b] | 2670 |    obj->points = {
 | 
|---|
| [cf2d1e5] | 2671 |       // front
 | 
|---|
 | 2672 |       1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2673 |       -1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2674 |       -1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2675 |       1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2676 |       -1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2677 |       1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2678 | 
 | 
|---|
 | 2679 |       // top
 | 
|---|
 | 2680 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2681 |       -1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2682 |       -1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2683 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2684 |       -1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2685 |       1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2686 | 
 | 
|---|
 | 2687 |       // bottom
 | 
|---|
 | 2688 |       1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2689 |       -1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2690 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2691 |       1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2692 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2693 |       1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2694 | 
 | 
|---|
 | 2695 |       // back
 | 
|---|
 | 2696 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2697 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2698 |       -1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2699 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2700 |       1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2701 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2702 | 
 | 
|---|
 | 2703 |       // right
 | 
|---|
 | 2704 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2705 |       1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2706 |       1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2707 |       1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2708 |       1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2709 |       1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2710 | 
 | 
|---|
 | 2711 |       // left
 | 
|---|
 | 2712 |       -1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2713 |       -1.0f,  1.0f, -1.0f,
 | 
|---|
 | 2714 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2715 |       -1.0f,  1.0f,  1.0f,
 | 
|---|
 | 2716 |       -1.0f, -1.0f, -1.0f,
 | 
|---|
 | 2717 |       -1.0f, -1.0f,  1.0f,
 | 
|---|
 | 2718 |    };
 | 
|---|
| [1f3d32b] | 2719 |    obj->colors = {
 | 
|---|
| [cf2d1e5] | 2720 |       // front
 | 
|---|
| [25b47d7] | 2721 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2722 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2723 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2724 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2725 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2726 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2727 | 
 | 
|---|
 | 2728 |       // top
 | 
|---|
| [25b47d7] | 2729 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2730 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2731 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2732 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2733 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2734 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2735 | 
 | 
|---|
 | 2736 |       // bottom
 | 
|---|
| [25b47d7] | 2737 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2738 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2739 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2740 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2741 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2742 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2743 | 
 | 
|---|
 | 2744 |       // back
 | 
|---|
| [25b47d7] | 2745 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2746 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2747 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2748 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2749 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2750 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2751 | 
 | 
|---|
 | 2752 |       // right
 | 
|---|
| [25b47d7] | 2753 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2754 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2755 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2756 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2757 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2758 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2759 | 
 | 
|---|
 | 2760 |       // left
 | 
|---|
| [25b47d7] | 2761 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2762 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2763 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2764 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2765 |       0.4f, 0.4f, 0.4f,
 | 
|---|
 | 2766 |       0.4f, 0.4f, 0.4f,
 | 
|---|
| [cf2d1e5] | 2767 |    };
 | 
|---|
| [1f3d32b] | 2768 |    obj->texcoords = { 0.0f };
 | 
|---|
| [cf2d1e5] | 2769 | 
 | 
|---|
| [dba67b2] | 2770 |    mat4 T = translate(mat4(1.0f), pos);
 | 
|---|
 | 2771 |    mat4 R = rotate(mat4(1.0f), 60.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 1.0f, -1.0f));
 | 
|---|
| [1f3d32b] | 2772 |    obj->model_base = T * R * scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
 | 
|---|
| [cf2d1e5] | 2773 | 
 | 
|---|
| [1f3d32b] | 2774 |    obj->translate_mat = T;
 | 
|---|
| [95595de] | 2775 | 
 | 
|---|
| [8316333] | 2776 |    initObject(obj);
 | 
|---|
| [e9347b4] | 2777 |    // This accounts for the scaling in model_base.
 | 
|---|
 | 2778 |    // Dividing by 8 instead of 10 since the bounding radius algorithm
 | 
|---|
 | 2779 |    // under-calculates the true value.
 | 
|---|
 | 2780 |    // TODO: Once the intersection check with the sides of the asteroid is done,
 | 
|---|
 | 2781 |    // this can be removed.
 | 
|---|
| [1f3d32b] | 2782 |    obj->bounding_radius /= 8.0f;
 | 
|---|
 | 2783 | 
 | 
|---|
 | 2784 |    return obj;
 | 
|---|
| [cf2d1e5] | 2785 | }
 | 
|---|
| [5527206] | 2786 | 
 | 
|---|
| [dd9771c] | 2787 | SceneObject* createExplosion() {
 | 
|---|
| [646f3f2] | 2788 |    SceneObject* obj = new SceneObject();
 | 
|---|
 | 2789 |    obj->type = TYPE_EXPLOSION;
 | 
|---|
 | 2790 | 
 | 
|---|
 | 2791 |    obj->points = {};
 | 
|---|
 | 2792 |    obj->colors = {};
 | 
|---|
 | 2793 | 
 | 
|---|
 | 2794 |    initObject(obj);
 | 
|---|
 | 2795 |    obj->num_points = EXPLOSION_PARTICLE_COUNT;
 | 
|---|
 | 2796 | 
 | 
|---|
 | 2797 |    return obj;
 | 
|---|
 | 2798 | }
 | 
|---|
 | 2799 | 
 | 
|---|
| [5527206] | 2800 | float getRandomNum(float low, float high) {
 | 
|---|
| [b220f78] | 2801 |    return low + ((float)rand() / RAND_MAX) * (high-low);
 | 
|---|
| [8e8aed6] | 2802 | }
 | 
|---|