source: opengl-game/new-game.cpp@ 42e642d

feature/imgui-sdl points-test
Last change on this file since 42e642d was 3effd81, checked in by Dmitry Portnoy <dmp1488@…>, 7 years ago

Change addLaserToScene() to position the laser between the correct endpoints and rotate it towards the camera so perceived width is constant.

  • Property mode set to 100644
File size: 64.4 KB
RevLine 
[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>
[93baa0e]26#include <cmath>
[1099b95]27#include <string>
[19c9338]28#include <array>
[df652d5]29#include <vector>
[93462c6]30#include <queue>
[0d5c100]31#include <map>
[22b2c37]32
[5272b6b]33using namespace std;
[7ee66ea]34using namespace glm;
35
[92b1e90]36enum State {
37 STATE_MAIN_MENU,
38 STATE_GAME,
39};
40
41enum Event {
42 EVENT_GO_TO_MAIN_MENU,
43 EVENT_GO_TO_GAME,
44 EVENT_QUIT,
45};
46
47enum ObjectType {
48 TYPE_SHIP,
49 TYPE_ASTEROID,
50 TYPE_LASER,
51};
52
[df652d5]53struct SceneObject {
[d9f99b2]54 unsigned int id;
[92b1e90]55 ObjectType type;
[95595de]56
57 // Currently, model_transform should only have translate, and rotation and scale need to be done in model_base since
58 // they need to be done when the object is at the origin. I should change this to have separate scale, rotate, and translate
59 // matrices for each object that can be updated independently and then applied to the object in that order.
[5c403fe]60 mat4 model_mat, model_base, model_transform;
[95595de]61 mat4 translate_mat; // beginning of doing what's mentioned above
[baa5848]62 GLuint shader_program;
[05e43cf]63 unsigned int num_points;
[c3c3158]64 GLuint vertex_vbo_offset;
65 GLuint ubo_offset;
[07ed460]66 vector<GLfloat> points;
67 vector<GLfloat> colors;
68 vector<GLfloat> texcoords;
[9dd2eb7]69 vector<GLfloat> normals;
[07ed460]70 vector<GLfloat> selected_colors;
[c3c3158]71 bool deleted;
[3d06b4e]72 vec3 bounding_center;
73 GLfloat bounding_radius;
[c3c3158]74};
75
76struct BufferInfo {
77 unsigned int vbo_base;
78 unsigned int vbo_offset;
79 unsigned int vbo_capacity;
80 unsigned int ubo_base;
81 unsigned int ubo_offset;
82 unsigned int ubo_capacity;
[df652d5]83};
84
[4f3262f]85void glfw_error_callback(int error, const char* description);
86
87void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
[f7d35da]88void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
[4f3262f]89
[d9f99b2]90bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point);
[5c9d193]91bool insideTriangle(vec3 p, array<vec3, 3> triangle_points);
[33a9664]92
[ec4456b]93GLuint loadShader(GLenum type, string file);
[485424b]94GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath);
95unsigned char* loadImage(string file_name, int* x, int* y);
[ec4456b]96
[d12d003]97void printVector(string label, vec3 v);
[b73cb3b]98void print4DVector(string label, vec4 v);
[d12d003]99
[c3c3158]100void addObjectToSceneDuringInit(SceneObject& obj);
101void addObjectToScene(SceneObject& obj, map<GLuint, BufferInfo>& shaderBufferInfo,
102 GLuint points_vbo,
103 GLuint colors_vbo,
104 GLuint selected_colors_vbo,
105 GLuint texcoords_vbo,
106 GLuint normals_vbo,
107 GLuint ubo,
[6877ef3]108 GLuint model_mat_idx_vbo);
[95595de]109void removeObjectFromScene(SceneObject& obj, GLuint ubo);
[c3c3158]110
[3d06b4e]111void calculateObjectBoundingBox(SceneObject& obj);
112
[fd6f465]113void addLaserToScene(vec3 start, vec3 end, vec3 color, GLfloat width, GLuint laser_sp);
[b155f13]114
[c3c3158]115void initializeBuffers(
116 GLuint* points_vbo,
117 GLuint* colors_vbo,
118 GLuint* selected_colors_vbo,
119 GLuint* texcoords_vbo,
120 GLuint* normals_vbo,
121 GLuint* ubo,
[6877ef3]122 GLuint* model_mat_idx_vbo);
[c3c3158]123
[0d5c100]124void populateBuffers(vector<SceneObject>& objects,
[c3c3158]125 map<GLuint, BufferInfo>& shaderBufferInfo,
126 GLuint points_vbo,
127 GLuint colors_vbo,
128 GLuint selected_colors_vbo,
129 GLuint texcoords_vbo,
130 GLuint normals_vbo,
131 GLuint ubo,
[6877ef3]132 GLuint model_mat_idx_vbo);
[c3c3158]133
134void copyObjectDataToBuffers(SceneObject& obj,
135 map<GLuint, BufferInfo>& shaderBufferInfo,
136 GLuint points_vbo,
137 GLuint colors_vbo,
138 GLuint selected_colors_vbo,
139 GLuint texcoords_vbo,
140 GLuint normals_vbo,
141 GLuint ubo,
[6877ef3]142 GLuint model_mat_idx_vbo);
[f9a242b]143
[5c403fe]144void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo);
145
[93462c6]146void renderMainMenu();
147void renderMainMenuGui();
148
[92b1e90]149void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
150 GLuint color_sp, GLuint texture_sp, GLuint laser_sp,
[fd6f465]151 GLuint color_vao, GLuint texture_vao, GLuint laser_vao,
[b155f13]152 GLuint colors_vbo, GLuint selected_colors_vbo,
[92b1e90]153 SceneObject* selectedObject);
[93462c6]154void renderSceneGui();
[d12d003]155
[c3c3158]156void spawnAsteroid(vec3 pos, GLuint shader,
157 map<GLuint, BufferInfo>& shaderBufferInfo,
158 GLuint points_vbo,
159 GLuint colors_vbo,
160 GLuint selected_colors_vbo,
161 GLuint texcoords_vbo,
162 GLuint normals_vbo,
163 GLuint ubo,
[6877ef3]164 GLuint model_mat_idx_vbo);
[cf2d1e5]165
[5527206]166float getRandomNum(float low, float high);
167
168#define NUM_KEYS (512)
169#define ONE_DEG_IN_RAD ((2.0f * M_PI) / 360.0f) // 0.017444444 (maybe make this a const instead)
170
171const int KEY_STATE_UNCHANGED = -1;
172const bool FULLSCREEN = false;
173const bool SHOW_FPS = false;
174const bool DISABLE_VSYNC = false; // disable vsync to see real framerate
175unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime, so it can't be const
176
177int key_state[NUM_KEYS];
178bool key_pressed[NUM_KEYS];
179
180int width = 640;
181int height = 480;
182
183double fps;
184
185vec3 cam_pos;
186
187mat4 view_mat;
188mat4 proj_mat;
189
190// TODO: Consider using a list instead since it will make element deletion more efficient
191vector<SceneObject> objects;
192queue<Event> events;
193
194SceneObject* clickedObject = NULL;
195SceneObject* selectedObject = NULL;
196
197float NEAR_CLIP = 0.1f;
198float FAR_CLIP = 100.0f;
199
[95595de]200// TODO: Should really have some array or struct of UI-related variables
[5527206]201bool isRunning = true;
202
203ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
204
[3effd81]205/*
206* TODO: Make lasers shoot from the ends of the ship's wings when the user presses a button and disappear after a second or so
207* TODO: Asteroid movement currently depends on framerate, fix this in a generic/reusable way
208*/
209
[c1ca5b5]210int main(int argc, char* argv[]) {
[5272b6b]211 cout << "New OpenGL Game" << endl;
212
[ec4456b]213 if (!restart_gl_log()) {}
214 gl_log("starting GLFW\n%s\n", glfwGetVersionString());
[22b2c37]215
[ec4456b]216 glfwSetErrorCallback(glfw_error_callback);
[5272b6b]217 if (!glfwInit()) {
218 fprintf(stderr, "ERROR: could not start GLFW3\n");
219 return 1;
[be246ad]220 }
221
222#ifdef __APPLE__
223 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
224 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
225 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
226 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
227#endif
[5272b6b]228
[9f9f9a7]229 glfwWindowHint(GLFW_SAMPLES, 16);
[ec4456b]230
231 GLFWwindow* window = NULL;
[e856d62]232 GLFWmonitor* mon = NULL;
[ec4456b]233
234 if (FULLSCREEN) {
[e856d62]235 mon = glfwGetPrimaryMonitor();
[ec4456b]236 const GLFWvidmode* vmode = glfwGetVideoMode(mon);
237
238 width = vmode->width;
239 height = vmode->height;
[e856d62]240 cout << "Fullscreen resolution " << vmode->width << "x" << vmode->height << endl;
[ec4456b]241 }
[e856d62]242 window = glfwCreateWindow(width, height, "New OpenGL Game", mon, NULL);
[ec4456b]243
[5272b6b]244 if (!window) {
245 fprintf(stderr, "ERROR: could not open window with GLFW3\n");
246 glfwTerminate();
247 return 1;
248 }
[c62eee6]249
[644a2e4]250 glfwMakeContextCurrent(window);
[5272b6b]251 glewExperimental = GL_TRUE;
252 glewInit();
253
[5527206]254 srand(time(0));
255
[14ff67c]256 /*
257 * RENDERING ALGORITHM NOTES:
258 *
259 * Basically, I need to split my objects into groups, so that each group fits into
260 * GL_MAX_UNIFORM_BLOCK_SIZE. I need to have an offset and a size for each group.
261 * Getting the offset is straitforward. The size may as well be GL_MAX_UNIFORM_BLOCK_SIZE
262 * for each group, since it seems that smaller sizes just round up to the nearest GL_MAX_UNIFORM_BLOCK_SIZE
263 *
264 * I'll need to have a loop inside my render loop that calls glBindBufferRange(GL_UNIFORM_BUFFER, ...
265 * for every 1024 objects and then draws all those objects with one glDraw call.
266 *
[0d5c100]267 * Since I currently have very few objects, I'll wait to implement this until I have
268 * a reasonable number of objects always using the same shader.
[14ff67c]269 */
270
271 GLint UNIFORM_BUFFER_OFFSET_ALIGNMENT, MAX_UNIFORM_BLOCK_SIZE;
272 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &UNIFORM_BUFFER_OFFSET_ALIGNMENT);
273 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &MAX_UNIFORM_BLOCK_SIZE);
274
275 MAX_UNIFORMS = MAX_UNIFORM_BLOCK_SIZE / sizeof(mat4);
276
277 cout << "UNIFORM_BUFFER_OFFSET_ALIGNMENT: " << UNIFORM_BUFFER_OFFSET_ALIGNMENT << endl;
278 cout << "MAX_UNIFORMS: " << MAX_UNIFORMS << endl;
279
[c1ca5b5]280 // Setup Dear ImGui binding
281 IMGUI_CHECKVERSION();
282 ImGui::CreateContext();
283 ImGuiIO& io = ImGui::GetIO(); (void)io;
284 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
285 //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
286 ImGui_ImplGlfwGL3_Init(window, true);
287
288 // Setup style
289 ImGui::StyleColorsDark();
290 //ImGui::StyleColorsClassic();
291
292 glfwSetMouseButtonCallback(window, mouse_button_callback);
[f7d35da]293 glfwSetKeyCallback(window, key_callback);
[c1ca5b5]294
[5272b6b]295 const GLubyte* renderer = glGetString(GL_RENDERER);
296 const GLubyte* version = glGetString(GL_VERSION);
297 printf("Renderer: %s\n", renderer);
298 printf("OpenGL version supported %s\n", version);
[93baa0e]299
[9f9f9a7]300 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
301
[5272b6b]302 glEnable(GL_DEPTH_TEST);
303 glDepthFunc(GL_LESS);
[516668e]304
[93baa0e]305 glEnable(GL_CULL_FACE);
306 // glCullFace(GL_BACK);
307 // glFrontFace(GL_CW);
308
[9f9f9a7]309 /*
[485424b]310 int x, y;
311 unsigned char* texImage = loadImage("test.png", &x, &y);
312 if (texImage) {
313 cout << "Yay, I loaded an image!" << endl;
314 cout << x << endl;
315 cout << y << endl;
[e856d62]316 printf("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
[485424b]317 }
318
[9f9f9a7]319 GLuint testTex = 0;
320 glGenTextures(1, &testTex);
321 glActiveTexture(GL_TEXTURE0);
322 glBindTexture(GL_TEXTURE_2D, testTex);
323 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
324
325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
327 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
328 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
329 */
330
331 int x, y;
332 unsigned char* texImage = loadImage("laser.png", &x, &y);
333 if (texImage) {
334 cout << "Laser texture loaded successfully!" << endl;
335 cout << x << endl;
336 cout << y << endl;
337 printf("first 4 bytes are: %i %i %i %i\n", texImage[0], texImage[1], texImage[2], texImage[3]);
338 }
339
340 GLuint laserTex = 0;
341 glGenTextures(1, &laserTex);
[485424b]342 glActiveTexture(GL_TEXTURE0);
[9f9f9a7]343 glBindTexture(GL_TEXTURE_2D, laserTex);
[485424b]344 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage);
345
346 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
348 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
349 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
350
[0d5c100]351 /* RENDERING ALGORITHM
352 *
353 * Create a separate vbo for each of the following things:
354 * - points
355 * - colors
356 * - texture coordinates
357 * - selected colors
358 * - normals
359 * - indices into a ubo that stores a model matrix for each object
360 *
361 * Also, make a model matrix ubo, the entirety of which will be passed to the vertex shader.
362 * The vbo containing the correct index into the ubo (mentioned above) will be used to select
363 * the right model matrix for each point. The index in the vbo will be the saem for all points
364 * of any given object.
365 *
366 * There will be two shader programs for now, one for draing colored objects, and another for
367 * drawing textured ones. The points, normals, and model mat ubo indices will be passed to both
368 * shaders, while the colors vbo will only be passed to the colors shader, and the texcoords vbo
369 * only to the texture shader.
370 *
371 * Right now, the currently selected object is drawn using one color (specified in the selected
372 * colors vbo) regardless of whether it is normally rendering using colors or a texture. The selected
373 * object is rendering by binding the selected colors vbo in place of the colors vbo and using the colors
374 * shader. Then, the selected object is redrawn along with all other objects, but the depth buffer test
375 * prevents the unselected version of the object from appearing on the screen. This lets me render all the
376 * objects that use a particular shader using one glDrawArrays() call.
377 */
[cffca4d]378
[c3c3158]379 map<GLuint, BufferInfo> shaderBufferInfo;
380
[cffca4d]381 GLuint color_sp = loadShaderProgram("./color.vert", "./color.frag");
382 GLuint texture_sp = loadShaderProgram("./texture.vert", "./texture.frag");
[b155f13]383 GLuint laser_sp = loadShaderProgram("./laser.vert", "./laser.frag");
[cffca4d]384
[c3c3158]385 shaderBufferInfo[color_sp] = BufferInfo();
386 shaderBufferInfo[texture_sp] = BufferInfo();
[b155f13]387 shaderBufferInfo[laser_sp] = BufferInfo();
[c3c3158]388
[3effd81]389 cam_pos = vec3(0.0f, 0.0f, 2.0f);
390 float cam_yaw = 0.0f * 2.0f * 3.14159f / 360.0f;
391 float cam_pitch = -50.0f * 2.0f * 3.14159f / 360.0f;
392
[f9a242b]393 SceneObject obj;
[07ed460]394 mat4 T_model, R_model;
395
[92b1e90]396 // TODO: Confirm there's nothing I need from the commented out models and delete them
397 // (Check to make sure the textured square is drawn correctly)
398
[cf2d1e5]399 /*
[07ed460]400 // triangle
[f9a242b]401 obj = SceneObject();
402 obj.shader_program = color_sp;
403 obj.points = {
[d12d003]404 0.0f, 0.5f, 0.0f,
405 -0.5f, -0.5f, 0.0f,
406 0.5f, -0.5f, 0.0f,
407 0.5f, -0.5f, 0.0f,
408 -0.5f, -0.5f, 0.0f,
409 0.0f, 0.5f, 0.0f,
[516668e]410 };
[f9a242b]411 obj.colors = {
[07ed460]412 1.0f, 0.0f, 0.0f,
413 0.0f, 0.0f, 1.0f,
414 0.0f, 1.0f, 0.0f,
415 0.0f, 1.0f, 0.0f,
416 0.0f, 0.0f, 1.0f,
417 1.0f, 0.0f, 0.0f,
[93baa0e]418 };
[c94a699]419 obj.texcoords = { 0.0f };
[f9a242b]420 obj.selected_colors = {
[07ed460]421 0.0f, 1.0f, 0.0f,
422 0.0f, 1.0f, 0.0f,
423 0.0f, 1.0f, 0.0f,
424 0.0f, 1.0f, 0.0f,
425 0.0f, 1.0f, 0.0f,
426 0.0f, 1.0f, 0.0f,
427 };
428
[dba67b2]429 T_model = translate(mat4(1.0f), vec3(0.45f, -1.5f, 0.0f));
430 R_model = rotate(mat4(1.0f), 0.0f, vec3(0.0f, 1.0f, 0.0f));
[5c403fe]431 obj.model_base = T_model*R_model;
[f9a242b]432
[c3c3158]433 addObjectToSceneDuringInit(obj);
[33a9664]434
[07ed460]435 // square
[f9a242b]436 obj = SceneObject();
437 obj.shader_program = texture_sp;
438 obj.points = {
[b73cb3b]439 0.5f, 0.5f, 0.0f,
[d12d003]440 -0.5f, 0.5f, 0.0f,
441 -0.5f, -0.5f, 0.0f,
[b73cb3b]442 0.5f, 0.5f, 0.0f,
[d12d003]443 -0.5f, -0.5f, 0.0f,
[b73cb3b]444 0.5f, -0.5f, 0.0f,
[64a70f4]445 };
[c94a699]446 obj.colors = { 0.0f };
[f9a242b]447 obj.texcoords = {
[64a70f4]448 1.0f, 1.0f,
449 0.0f, 1.0f,
[07ed460]450 0.0f, 0.0f,
451 1.0f, 1.0f,
452 0.0f, 0.0f,
453 1.0f, 0.0f
[485424b]454 };
[f9a242b]455 obj.selected_colors = {
[9f4986b]456 0.0f, 0.6f, 0.9f,
457 0.0f, 0.6f, 0.9f,
458 0.0f, 0.6f, 0.9f,
459 0.0f, 0.6f, 0.9f,
460 0.0f, 0.6f, 0.9f,
461 0.0f, 0.6f, 0.9f,
[19c9338]462 };
[df652d5]463
[dba67b2]464 T_model = translate(mat4(1.0f), vec3(-0.5f, -1.5f, -1.00f));
465 R_model = rotate(mat4(1.0f), 0.5f, vec3(0.0f, 1.0f, 0.0f));
[5c403fe]466 obj.model_base = T_model*R_model;
[f9a242b]467
[c3c3158]468 addObjectToSceneDuringInit(obj);
[cf2d1e5]469 */
[f9a242b]470
471 // player ship
472 obj = SceneObject();
[92b1e90]473 obj.type = TYPE_SHIP;
[f9a242b]474 obj.shader_program = color_sp;
475 obj.points = {
[81f28c0]476 //back
[3d06b4e]477 -0.5f, 0.3f, 0.0f,
478 -0.5f, 0.0f, 0.0f,
479 0.5f, 0.0f, 0.0f,
480 -0.5f, 0.3f, 0.0f,
481 0.5f, 0.0f, 0.0f,
482 0.5f, 0.3f, 0.0f,
[81f28c0]483
484 // left back
[3d06b4e]485 -0.5f, 0.3f, -2.0f,
486 -0.5f, 0.0f, -2.0f,
487 -0.5f, 0.0f, 0.0f,
488 -0.5f, 0.3f, -2.0f,
489 -0.5f, 0.0f, 0.0f,
490 -0.5f, 0.3f, 0.0f,
[81f28c0]491
492 // right back
[3d06b4e]493 0.5f, 0.3f, 0.0f,
494 0.5f, 0.0f, 0.0f,
495 0.5f, 0.0f, -2.0f,
496 0.5f, 0.3f, 0.0f,
497 0.5f, 0.0f, -2.0f,
498 0.5f, 0.3f, -2.0f,
[81f28c0]499
500 // left mid
[3d06b4e]501 -0.25f, 0.3f, -3.0f,
502 -0.25f, 0.0f, -3.0f,
503 -0.5f, 0.0f, -2.0f,
504 -0.25f, 0.3f, -3.0f,
505 -0.5f, 0.0f, -2.0f,
506 -0.5f, 0.3f, -2.0f,
[81f28c0]507
508 // right mid
[3d06b4e]509 0.5f, 0.3f, -2.0f,
510 0.5f, 0.0f, -2.0f,
511 0.25f, 0.0f, -3.0f,
512 0.5f, 0.3f, -2.0f,
513 0.25f, 0.0f, -3.0f,
514 0.25f, 0.3f, -3.0f,
[81f28c0]515
516 // left front
[3d06b4e]517 0.0f, 0.0f, -3.5f,
518 -0.25f, 0.0f, -3.0f,
519 -0.25f, 0.3f, -3.0f,
[81f28c0]520
521 // right front
[3d06b4e]522 0.25f, 0.3f, -3.0f,
523 0.25f, 0.0f, -3.0f,
524 0.0f, 0.0f, -3.5f,
[81f28c0]525
526 // top back
[3d06b4e]527 -0.5f, 0.3f, -2.0f,
528 -0.5f, 0.3f, 0.0f,
529 0.5f, 0.3f, 0.0f,
530 -0.5f, 0.3f, -2.0f,
531 0.5f, 0.3f, 0.0f,
532 0.5f, 0.3f, -2.0f,
[81f28c0]533
[20e0020]534 // bottom back
[3d06b4e]535 -0.5f, 0.0f, 0.0f,
536 -0.5f, 0.0f, -2.0f,
537 0.5f, 0.0f, 0.0f,
538 0.5f, 0.0f, 0.0f,
539 -0.5f, 0.0f, -2.0f,
540 0.5f, 0.0f, -2.0f,
[20e0020]541
542 // top mid
[3d06b4e]543 -0.25f, 0.3f, -3.0f,
544 -0.5f, 0.3f, -2.0f,
545 0.5f, 0.3f, -2.0f,
546 -0.25f, 0.3f, -3.0f,
547 0.5f, 0.3f, -2.0f,
548 0.25f, 0.3f, -3.0f,
[20e0020]549
550 // bottom mid
[3d06b4e]551 -0.5f, 0.0f, -2.0f,
552 -0.25f, 0.0f, -3.0f,
553 0.5f, 0.0f, -2.0f,
554 0.5f, 0.0f, -2.0f,
555 -0.25f, 0.0f, -3.0f,
556 0.25f, 0.0f, -3.0f,
[20e0020]557
558 // top front
[3d06b4e]559 -0.25f, 0.3f, -3.0f,
560 0.25f, 0.3f, -3.0f,
561 0.0f, 0.0f, -3.5f,
[20e0020]562
563 // bottom front
[3d06b4e]564 0.25f, 0.0f, -3.0f,
565 -0.25f, 0.0f, -3.0f,
566 0.0f, 0.0f, -3.5f,
[20e0020]567
568 // left wing start back
[3d06b4e]569 -1.5f, 0.3f, 0.0f,
570 -1.5f, 0.0f, 0.0f,
571 -0.5f, 0.0f, 0.0f,
572 -1.5f, 0.3f, 0.0f,
573 -0.5f, 0.0f, 0.0f,
574 -0.5f, 0.3f, 0.0f,
[20e0020]575
576 // left wing start top
[3d06b4e]577 -0.5f, 0.3f, -0.3f,
578 -1.3f, 0.3f, -0.3f,
579 -1.5f, 0.3f, 0.0f,
580 -0.5f, 0.3f, -0.3f,
581 -1.5f, 0.3f, 0.0f,
582 -0.5f, 0.3f, 0.0f,
[20e0020]583
584 // left wing start front
[3d06b4e]585 -0.5f, 0.3f, -0.3f,
586 -0.5f, 0.0f, -0.3f,
587 -1.3f, 0.0f, -0.3f,
588 -0.5f, 0.3f, -0.3f,
589 -1.3f, 0.0f, -0.3f,
590 -1.3f, 0.3f, -0.3f,
[20e0020]591
592 // left wing start bottom
[3d06b4e]593 -0.5f, 0.0f, 0.0f,
594 -1.5f, 0.0f, 0.0f,
595 -1.3f, 0.0f, -0.3f,
596 -0.5f, 0.0f, 0.0f,
597 -1.3f, 0.0f, -0.3f,
598 -0.5f, 0.0f, -0.3f,
[20e0020]599
600 // left wing end outside
[3d06b4e]601 -1.5f, 0.3f, 0.0f,
602 -2.2f, 0.15f, -0.8f,
603 -1.5f, 0.0f, 0.0f,
[20e0020]604
605 // left wing end top
[3d06b4e]606 -1.3f, 0.3f, -0.3f,
607 -2.2f, 0.15f, -0.8f,
608 -1.5f, 0.3f, 0.0f,
[20e0020]609
610 // left wing end front
[3d06b4e]611 -1.3f, 0.0f, -0.3f,
612 -2.2f, 0.15f, -0.8f,
613 -1.3f, 0.3f, -0.3f,
[20e0020]614
615 // left wing end bottom
[3d06b4e]616 -1.5f, 0.0f, 0.0f,
617 -2.2f, 0.15f, -0.8f,
618 -1.3f, 0.0f, -0.3f,
[20e0020]619
620 // right wing start back
[3d06b4e]621 1.5f, 0.0f, 0.0f,
622 1.5f, 0.3f, 0.0f,
623 0.5f, 0.0f, 0.0f,
624 0.5f, 0.0f, 0.0f,
625 1.5f, 0.3f, 0.0f,
626 0.5f, 0.3f, 0.0f,
[20e0020]627
628 // right wing start top
[3d06b4e]629 1.3f, 0.3f, -0.3f,
630 0.5f, 0.3f, -0.3f,
631 1.5f, 0.3f, 0.0f,
632 1.5f, 0.3f, 0.0f,
633 0.5f, 0.3f, -0.3f,
634 0.5f, 0.3f, 0.0f,
[20e0020]635
636 // right wing start front
[3d06b4e]637 0.5f, 0.0f, -0.3f,
638 0.5f, 0.3f, -0.3f,
639 1.3f, 0.0f, -0.3f,
640 1.3f, 0.0f, -0.3f,
641 0.5f, 0.3f, -0.3f,
642 1.3f, 0.3f, -0.3f,
[20e0020]643
644 // right wing start bottom
[3d06b4e]645 1.5f, 0.0f, 0.0f,
646 0.5f, 0.0f, 0.0f,
647 1.3f, 0.0f, -0.3f,
648 1.3f, 0.0f, -0.3f,
649 0.5f, 0.0f, 0.0f,
650 0.5f, 0.0f, -0.3f,
[20e0020]651
652 // right wing end outside
[3d06b4e]653 2.2f, 0.15f, -0.8f,
654 1.5f, 0.3f, 0.0f,
655 1.5f, 0.0f, 0.0f,
[20e0020]656
657 // right wing end top
[3d06b4e]658 2.2f, 0.15f, -0.8f,
659 1.3f, 0.3f, -0.3f,
660 1.5f, 0.3f, 0.0f,
[20e0020]661
662 // right wing end front
[3d06b4e]663 2.2f, 0.15f, -0.8f,
664 1.3f, 0.0f, -0.3f,
665 1.3f, 0.3f, -0.3f,
[20e0020]666
667 // right wing end bottom
[3d06b4e]668 2.2f, 0.15f, -0.8f,
669 1.5f, 0.0f, 0.0f,
670 1.3f, 0.0f, -0.3f,
[f9a242b]671 };
672 obj.colors = {
673 0.0f, 0.0f, 0.3f,
674 0.0f, 0.0f, 0.3f,
675 0.0f, 0.0f, 0.3f,
676 0.0f, 0.0f, 0.3f,
677 0.0f, 0.0f, 0.3f,
678 0.0f, 0.0f, 0.3f,
[81f28c0]679
680 0.0f, 0.0f, 0.3f,
681 0.0f, 0.0f, 0.3f,
682 0.0f, 0.0f, 0.3f,
683 0.0f, 0.0f, 0.3f,
684 0.0f, 0.0f, 0.3f,
685 0.0f, 0.0f, 0.3f,
686
687 0.0f, 0.0f, 0.3f,
688 0.0f, 0.0f, 0.3f,
689 0.0f, 0.0f, 0.3f,
690 0.0f, 0.0f, 0.3f,
691 0.0f, 0.0f, 0.3f,
692 0.0f, 0.0f, 0.3f,
693
694 0.0f, 0.0f, 0.3f,
695 0.0f, 0.0f, 0.3f,
696 0.0f, 0.0f, 0.3f,
697 0.0f, 0.0f, 0.3f,
698 0.0f, 0.0f, 0.3f,
699 0.0f, 0.0f, 0.3f,
700
701 0.0f, 0.0f, 0.3f,
702 0.0f, 0.0f, 0.3f,
703 0.0f, 0.0f, 0.3f,
704 0.0f, 0.0f, 0.3f,
705 0.0f, 0.0f, 0.3f,
706 0.0f, 0.0f, 0.3f,
707
[cf2d1e5]708 0.0f, 0.0f, 1.0f,
709 0.0f, 0.0f, 1.0f,
710 0.0f, 0.0f, 1.0f,
[81f28c0]711
[cf2d1e5]712 0.0f, 0.0f, 1.0f,
713 0.0f, 0.0f, 1.0f,
714 0.0f, 0.0f, 1.0f,
[81f28c0]715
[cf2d1e5]716 0.0f, 0.0f, 1.0f,
717 0.0f, 0.0f, 1.0f,
718 0.0f, 0.0f, 1.0f,
719 0.0f, 0.0f, 1.0f,
720 0.0f, 0.0f, 1.0f,
721 0.0f, 0.0f, 1.0f,
[81f28c0]722
[cf2d1e5]723 0.0f, 0.0f, 1.0f,
724 0.0f, 0.0f, 1.0f,
725 0.0f, 0.0f, 1.0f,
726 0.0f, 0.0f, 1.0f,
727 0.0f, 0.0f, 1.0f,
728 0.0f, 0.0f, 1.0f,
[81f28c0]729
[cf2d1e5]730 0.0f, 0.0f, 1.0f,
731 0.0f, 0.0f, 1.0f,
732 0.0f, 0.0f, 1.0f,
733 0.0f, 0.0f, 1.0f,
734 0.0f, 0.0f, 1.0f,
735 0.0f, 0.0f, 1.0f,
[81f28c0]736
[cf2d1e5]737 0.0f, 0.0f, 1.0f,
738 0.0f, 0.0f, 1.0f,
739 0.0f, 0.0f, 1.0f,
740 0.0f, 0.0f, 1.0f,
741 0.0f, 0.0f, 1.0f,
742 0.0f, 0.0f, 1.0f,
[81f28c0]743
744 0.0f, 0.0f, 0.3f,
745 0.0f, 0.0f, 0.3f,
746 0.0f, 0.0f, 0.3f,
[20e0020]747
[81f28c0]748 0.0f, 0.0f, 0.3f,
749 0.0f, 0.0f, 0.3f,
750 0.0f, 0.0f, 0.3f,
751
752 0.0f, 0.0f, 0.3f,
753 0.0f, 0.0f, 0.3f,
754 0.0f, 0.0f, 0.3f,
755 0.0f, 0.0f, 0.3f,
756 0.0f, 0.0f, 0.3f,
757 0.0f, 0.0f, 0.3f,
758
[20e0020]759 0.0f, 0.0f, 0.3f,
760 0.0f, 0.0f, 0.3f,
761 0.0f, 0.0f, 0.3f,
762 0.0f, 0.0f, 0.3f,
763 0.0f, 0.0f, 0.3f,
764 0.0f, 0.0f, 0.3f,
765
766 0.0f, 0.0f, 0.3f,
767 0.0f, 0.0f, 0.3f,
768 0.0f, 0.0f, 0.3f,
769 0.0f, 0.0f, 0.3f,
770 0.0f, 0.0f, 0.3f,
771 0.0f, 0.0f, 0.3f,
772
773 0.0f, 0.0f, 0.3f,
774 0.0f, 0.0f, 0.3f,
775 0.0f, 0.0f, 0.3f,
776 0.0f, 0.0f, 0.3f,
777 0.0f, 0.0f, 0.3f,
778 0.0f, 0.0f, 0.3f,
779
780 0.0f, 0.0f, 0.3f,
781 0.0f, 0.0f, 0.3f,
782 0.0f, 0.0f, 0.3f,
783
784 0.0f, 0.0f, 0.3f,
785 0.0f, 0.0f, 0.3f,
786 0.0f, 0.0f, 0.3f,
787
788 0.0f, 0.0f, 0.3f,
789 0.0f, 0.0f, 0.3f,
790 0.0f, 0.0f, 0.3f,
791
792 0.0f, 0.0f, 0.3f,
793 0.0f, 0.0f, 0.3f,
794 0.0f, 0.0f, 0.3f,
795
796 0.0f, 0.0f, 0.3f,
797 0.0f, 0.0f, 0.3f,
798 0.0f, 0.0f, 0.3f,
799 0.0f, 0.0f, 0.3f,
800 0.0f, 0.0f, 0.3f,
801 0.0f, 0.0f, 0.3f,
802
803 0.0f, 0.0f, 0.3f,
804 0.0f, 0.0f, 0.3f,
805 0.0f, 0.0f, 0.3f,
806 0.0f, 0.0f, 0.3f,
807 0.0f, 0.0f, 0.3f,
808 0.0f, 0.0f, 0.3f,
809
810 0.0f, 0.0f, 0.3f,
811 0.0f, 0.0f, 0.3f,
812 0.0f, 0.0f, 0.3f,
813 0.0f, 0.0f, 0.3f,
814 0.0f, 0.0f, 0.3f,
815 0.0f, 0.0f, 0.3f,
816
817 0.0f, 0.0f, 0.3f,
818 0.0f, 0.0f, 0.3f,
819 0.0f, 0.0f, 0.3f,
820 0.0f, 0.0f, 0.3f,
821 0.0f, 0.0f, 0.3f,
822 0.0f, 0.0f, 0.3f,
823
824 0.0f, 0.0f, 0.3f,
825 0.0f, 0.0f, 0.3f,
826 0.0f, 0.0f, 0.3f,
827
[81f28c0]828 0.0f, 0.0f, 0.3f,
829 0.0f, 0.0f, 0.3f,
830 0.0f, 0.0f, 0.3f,
831
832 0.0f, 0.0f, 0.3f,
833 0.0f, 0.0f, 0.3f,
834 0.0f, 0.0f, 0.3f,
835
836 0.0f, 0.0f, 0.3f,
837 0.0f, 0.0f, 0.3f,
838 0.0f, 0.0f, 0.3f,
[f9a242b]839 };
[cf2d1e5]840 obj.texcoords = { 0.0f };
841 obj.selected_colors = { 0.0f };
[f9a242b]842
[b155f13]843 T_model = translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f));
[dba67b2]844 R_model = rotate(mat4(1.0f), 20.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 0.0f, 0.0f));
845 R_model = mat4(1.0f);
846 obj.model_base = T_model * R_model * scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
[f9a242b]847
[95595de]848 obj.translate_mat = T_model;
849
[c3c3158]850 addObjectToSceneDuringInit(obj);
[cf2d1e5]851
[fd6f465]852 addLaserToScene(vec3(0.34f, -2.0f, 1.6f), vec3(0.34f, -2.0f, -3.0f), vec3(0.0f, 1.0f, 0.0f), 0.04f, laser_sp);
853 addLaserToScene(vec3(-0.34f, -2.0f, 1.6f), vec3(-0.34f, -2.0f, -3.0f), vec3(0.0f, 1.0f, 0.0f), 0.04f, laser_sp);
[92b1e90]854
[07ed460]855 vector<SceneObject>::iterator obj_it;
[19c9338]856
[0d5c100]857 GLuint points_vbo, colors_vbo, selected_colors_vbo, texcoords_vbo,
[6877ef3]858 normals_vbo, ubo, model_mat_idx_vbo;
[e165b85]859
[c3c3158]860 initializeBuffers(
861 &points_vbo,
862 &colors_vbo,
863 &selected_colors_vbo,
864 &texcoords_vbo,
865 &normals_vbo,
866 &ubo,
[6877ef3]867 &model_mat_idx_vbo);
[e165b85]868
[0d5c100]869 populateBuffers(objects,
[c3c3158]870 shaderBufferInfo,
871 points_vbo,
872 colors_vbo,
873 selected_colors_vbo,
874 texcoords_vbo,
875 normals_vbo,
876 ubo,
[6877ef3]877 model_mat_idx_vbo);
[b155f13]878
[92b1e90]879 GLuint color_vao = 0;
880 glGenVertexArrays(1, &color_vao);
881 glBindVertexArray(color_vao);
[516668e]882
[8b7cfcf]883 glEnableVertexAttribArray(0);
884 glEnableVertexAttribArray(1);
[9dd2eb7]885 glEnableVertexAttribArray(2);
[14ff67c]886 glEnableVertexAttribArray(3);
[644a2e4]887
[cffca4d]888 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
889 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
890
891 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
892 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
893
[14ff67c]894 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
895 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
896
[92b1e90]897 GLuint texture_vao = 0;
898 glGenVertexArrays(1, &texture_vao);
899 glBindVertexArray(texture_vao);
[644a2e4]900
[485424b]901 glEnableVertexAttribArray(0);
902 glEnableVertexAttribArray(1);
[9dd2eb7]903 glEnableVertexAttribArray(2);
[14ff67c]904 glEnableVertexAttribArray(3);
[8b7cfcf]905
[cffca4d]906 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
907 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
[1a530df]908
[cffca4d]909 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
910 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
911
912 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
913 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
[644a2e4]914
[14ff67c]915 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
916 glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
917
[fd6f465]918 GLuint laser_vao = 0;
919 glGenVertexArrays(1, &laser_vao);
920 glBindVertexArray(laser_vao);
921
922 glEnableVertexAttribArray(0);
923 glEnableVertexAttribArray(1);
924 glEnableVertexAttribArray(2);
925
926 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
927 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
928
929 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
930 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
931
932 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
933 glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, 0, 0);
934
[7ee66ea]935 float cam_speed = 1.0f;
[201e2f8]936 float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
[809ce16]937 float cam_pitch_speed = 60.0f*ONE_DEG_IN_RAD;
[7ee66ea]938
[b73cb3b]939 // glm::lookAt can create the view matrix
940 // glm::perspective can create the projection matrix
941
[dba67b2]942 mat4 T = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
943 mat4 yaw_mat = rotate(mat4(1.0f), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
944 mat4 pitch_mat = rotate(mat4(1.0f), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
[8d5e67b]945 mat4 R = pitch_mat * yaw_mat;
[c62eee6]946 view_mat = R*T;
[7ee66ea]947
[3effd81]948 // TODO: Create a function to construct the projection matrix
949 // (Maybe I should just use glm::perspective, after making sure it matches what I have now)
[7ee66ea]950 float fov = 67.0f * ONE_DEG_IN_RAD;
951 float aspect = (float)width / (float)height;
952
[d12d003]953 float range = tan(fov * 0.5f) * NEAR_CLIP;
954 float Sx = NEAR_CLIP / (range * aspect);
955 float Sy = NEAR_CLIP / range;
956 float Sz = -(FAR_CLIP + NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
957 float Pz = -(2.0f * FAR_CLIP * NEAR_CLIP) / (FAR_CLIP - NEAR_CLIP);
[7ee66ea]958
[c62eee6]959 float proj_arr[] = {
[7ee66ea]960 Sx, 0.0f, 0.0f, 0.0f,
961 0.0f, Sy, 0.0f, 0.0f,
962 0.0f, 0.0f, Sz, -1.0f,
963 0.0f, 0.0f, Pz, 0.0f,
964 };
[c62eee6]965 proj_mat = make_mat4(proj_arr);
[7ee66ea]966
[14ff67c]967 GLuint ub_binding_point = 0;
968
[fd6f465]969 // TODO: Replace test_loc and mat_loc with more descriptive names
[cffca4d]970 GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
971 GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
[14ff67c]972 GLuint color_sp_ub_index = glGetUniformBlockIndex(color_sp, "models");
[7ee66ea]973
[cffca4d]974 GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
975 GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
[14ff67c]976 GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
[19c9338]977
[b155f13]978 GLuint laser_view_mat_loc = glGetUniformLocation(laser_sp, "view");
979 GLuint laser_proj_mat_loc = glGetUniformLocation(laser_sp, "proj");
[9f9f9a7]980 GLuint laser_color_loc = glGetUniformLocation(laser_sp, "laser_color");
[fd6f465]981 GLuint laser_sp_ub_index = glGetUniformBlockIndex(laser_sp, "models");
982
[b155f13]983
[cffca4d]984 glUseProgram(color_sp);
[19c9338]985 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
[c62eee6]986 glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
[485424b]987
[14ff67c]988 glUniformBlockBinding(color_sp, color_sp_ub_index, ub_binding_point);
989 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
[e165b85]990
[fd6f465]991
[cffca4d]992 glUseProgram(texture_sp);
[19c9338]993 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
[c62eee6]994 glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
[7ee66ea]995
[14ff67c]996 glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
997 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
998
[9f9f9a7]999
[b155f13]1000 glUseProgram(laser_sp);
1001 glUniformMatrix4fv(laser_view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1002 glUniformMatrix4fv(laser_proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
[9f9f9a7]1003 glUniform3f(laser_color_loc, 0.2f, 1.0f, 0.2f);
[b155f13]1004
[fd6f465]1005 glUniformBlockBinding(laser_sp, laser_sp_ub_index, ub_binding_point);
1006 glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
1007
1008
[7ee66ea]1009 bool cam_moved = false;
1010
[046ce72]1011 int frame_count = 0;
[f70ab75]1012 double elapsed_seconds_fps = 0.0f;
[5527206]1013 double elapsed_seconds_spawn = 0.0f;
[93baa0e]1014 double previous_seconds = glfwGetTime();
[046ce72]1015
[9dd2eb7]1016 // This draws wireframes. Useful for seeing separate faces and occluded objects.
1017 //glPolygonMode(GL_FRONT, GL_LINE);
1018
[14ff67c]1019 if (DISABLE_VSYNC && SHOW_FPS) {
1020 glfwSwapInterval(0);
1021 }
[1c81bf0]1022
[93462c6]1023 State curState = STATE_MAIN_MENU;
1024
[5b3462b]1025 while (!glfwWindowShouldClose(window) && isRunning) {
[93baa0e]1026 double current_seconds = glfwGetTime();
1027 double elapsed_seconds = current_seconds - previous_seconds;
1028 previous_seconds = current_seconds;
1029
[14ff67c]1030 if (SHOW_FPS) {
1031 elapsed_seconds_fps += elapsed_seconds;
1032 if (elapsed_seconds_fps > 0.25f) {
1033 fps = (double)frame_count / elapsed_seconds_fps;
1034 cout << "FPS: " << fps << endl;
[046ce72]1035
[14ff67c]1036 frame_count = 0;
1037 elapsed_seconds_fps = 0.0f;
1038 }
[046ce72]1039
[14ff67c]1040 frame_count++;
1041 }
[046ce72]1042
[f7d35da]1043 // Handle events
[baa5848]1044
1045 clickedObject = NULL;
[f7d35da]1046
1047 // reset the all key states to KEY_STATE_UNCHANGED (something the GLFW key callback can never return)
1048 // so that GLFW_PRESS and GLFW_RELEASE are only detected once
[cf2d1e5]1049 // TODO: Change this if we ever need to act on GLFW_REPEAT (which is when a key is held down
1050 // continuously for a period of time)
[f7d35da]1051 fill(key_state, key_state + NUM_KEYS, KEY_STATE_UNCHANGED);
1052
[baa5848]1053 glfwPollEvents();
1054
[93462c6]1055 while (!events.empty()) {
1056 switch (events.front()) {
1057 case EVENT_GO_TO_MAIN_MENU:
1058 curState = STATE_MAIN_MENU;
1059 break;
1060 case EVENT_GO_TO_GAME:
1061 curState = STATE_GAME;
1062 break;
1063 case EVENT_QUIT:
1064 isRunning = false;
1065 break;
1066 }
1067 events.pop();
[147ac6d]1068 }
[93462c6]1069
1070 if (curState == STATE_GAME) {
[95595de]1071
1072 elapsed_seconds_spawn += elapsed_seconds;
1073 if (elapsed_seconds_spawn > 0.5f) {
1074 spawnAsteroid(vec3(getRandomNum(-1.3f, 1.3f), getRandomNum(-3.0f, -1.0f), getRandomNum(-5.5f, -4.5f)), color_sp,
1075 shaderBufferInfo,
1076 points_vbo,
1077 colors_vbo,
1078 selected_colors_vbo,
1079 texcoords_vbo,
1080 normals_vbo,
1081 ubo,
[6877ef3]1082 model_mat_idx_vbo);
[95595de]1083
1084 elapsed_seconds_spawn -= 0.5f;
1085 }
1086
[cf2d1e5]1087 /*
[93462c6]1088 if (clickedObject == &objects[0]) {
1089 selectedObject = &objects[0];
1090 }
1091 if (clickedObject == &objects[1]) {
1092 selectedObject = &objects[1];
1093 }
[cf2d1e5]1094 */
[f7d35da]1095
1096 /*
1097 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
[dba67b2]1098 transformObject(objects[1], translate(mat4(1.0f), vec3(0.3f, 0.0f, 0.0f)), ubo);
[f7d35da]1099 }
1100 if (key_pressed[GLFW_KEY_RIGHT]) {
[dba67b2]1101 transformObject(objects[2], translate(mat4(1.0f), vec3(0.01f, 0.0f, 0.0f)), ubo);
[f7d35da]1102 }
1103 if (key_pressed[GLFW_KEY_LEFT]) {
[dba67b2]1104 transformObject(objects[2], translate(mat4(1.0f), vec3(-0.01f, 0.0f, 0.0f)), ubo);
[f7d35da]1105 }
1106 */
[cf2d1e5]1107
1108 if (key_pressed[GLFW_KEY_RIGHT]) {
[dba67b2]1109 transformObject(objects[0], translate(mat4(1.0f), vec3(0.01f, 0.0f, 0.0f)), ubo);
[cf2d1e5]1110 }
1111 if (key_pressed[GLFW_KEY_LEFT]) {
[dba67b2]1112 transformObject(objects[0], translate(mat4(1.0f), vec3(-0.01f, 0.0f, 0.0f)), ubo);
[cf2d1e5]1113 }
1114
[92b1e90]1115 // this code moves the asteroids
1116 for (int i = 0; i < objects.size(); i++) {
1117 if (objects[i].type == TYPE_ASTEROID && !objects[i].deleted) {
[dba67b2]1118 transformObject(objects[i], translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.04f)), ubo);
[95595de]1119
[ebaa95c]1120 vec3 obj_center = vec3(view_mat * vec4(objects[i].bounding_center, 1.0f));
1121
1122 if ((obj_center.z - objects[i].bounding_radius) > -NEAR_CLIP) {
[95595de]1123 removeObjectFromScene(objects[i], ubo);
1124 }
[5527206]1125 }
[cf2d1e5]1126 }
[93baa0e]1127
[c3c3158]1128 if (key_state[GLFW_KEY_SPACE] == GLFW_PRESS) {
[95595de]1129 removeObjectFromScene(objects[0], ubo);
[c3c3158]1130 }
[baa5848]1131 }
[df652d5]1132
[c3c3158]1133 if (key_state[GLFW_KEY_ESCAPE] == GLFW_PRESS) {
[ec4456b]1134 glfwSetWindowShouldClose(window, 1);
1135 }
[7ee66ea]1136
1137 float dist = cam_speed * elapsed_seconds;
[c3c3158]1138 if (key_pressed[GLFW_KEY_A]) {
[dba67b2]1139 vec3 dir = vec3(inverse(R) * vec4(-1.0f, 0.0f, 0.0f, 1.0f));
[809ce16]1140 cam_pos += dir * dist;
[f7d35da]1141
[7ee66ea]1142 cam_moved = true;
1143 }
[c3c3158]1144 if (key_pressed[GLFW_KEY_D]) {
[dba67b2]1145 vec3 dir = vec3(inverse(R) * vec4(1.0f, 0.0f, 0.0f, 1.0f));
[809ce16]1146 cam_pos += dir * dist;
[f7d35da]1147
[7ee66ea]1148 cam_moved = true;
1149 }
[c3c3158]1150 if (key_pressed[GLFW_KEY_W]) {
[dba67b2]1151 vec3 dir = vec3(inverse(R) * vec4(0.0f, 0.0f, -1.0f, 1.0f));
[809ce16]1152 cam_pos += dir * dist;
[f7d35da]1153
[7ee66ea]1154 cam_moved = true;
1155 }
[c3c3158]1156 if (key_pressed[GLFW_KEY_S]) {
[dba67b2]1157 vec3 dir = vec3(inverse(R) * vec4(0.0f, 0.0f, 1.0f, 1.0f));
[809ce16]1158 cam_pos += dir * dist;
[f7d35da]1159
[7ee66ea]1160 cam_moved = true;
1161 }
[cf2d1e5]1162 /*
[c3c3158]1163 if (key_pressed[GLFW_KEY_LEFT]) {
1164 cam_yaw += cam_yaw_speed * elapsed_seconds;
1165 cam_moved = true;
[7ee66ea]1166 }
[c3c3158]1167 if (key_pressed[GLFW_KEY_RIGHT]) {
1168 cam_yaw -= cam_yaw_speed * elapsed_seconds;
1169 cam_moved = true;
[7ee66ea]1170 }
[c3c3158]1171 if (key_pressed[GLFW_KEY_UP]) {
1172 cam_pitch += cam_pitch_speed * elapsed_seconds;
1173 cam_moved = true;
[809ce16]1174 }
[c3c3158]1175 if (key_pressed[GLFW_KEY_DOWN]) {
1176 cam_pitch -= cam_pitch_speed * elapsed_seconds;
1177 cam_moved = true;
[809ce16]1178 }
[cf2d1e5]1179 */
[7ee66ea]1180 if (cam_moved) {
[dba67b2]1181 T = translate(mat4(1.0f), vec3(-cam_pos.x, -cam_pos.y, -cam_pos.z));
[809ce16]1182
[dba67b2]1183 mat4 yaw_mat = rotate(mat4(1.0f), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
1184 mat4 pitch_mat = rotate(mat4(1.0f), -cam_pitch, vec3(1.0f, 0.0f, 0.0f));
[809ce16]1185 R = pitch_mat * yaw_mat;
[f7d35da]1186
[c3c3158]1187 view_mat = R * T;
[7ee66ea]1188
[20e0020]1189 //printVector("cam pos", cam_pos);
[809ce16]1190
[cffca4d]1191 glUseProgram(color_sp);
[267c4c5]1192 glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
1193
[cffca4d]1194 glUseProgram(texture_sp);
[7ee66ea]1195 glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
[267c4c5]1196
[b155f13]1197 glUseProgram(laser_sp);
1198 glUniformMatrix4fv(laser_view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
1199
[7ee66ea]1200 cam_moved = false;
1201 }
[c3c3158]1202
1203 // Render scene
1204
1205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1206
1207 switch (curState) {
1208 case STATE_MAIN_MENU:
1209 renderMainMenu();
1210 renderMainMenuGui();
1211 break;
1212 case STATE_GAME:
[92b1e90]1213 renderScene(shaderBufferInfo,
1214 color_sp, texture_sp, laser_sp,
[fd6f465]1215 color_vao, texture_vao, laser_vao,
[b155f13]1216 colors_vbo, selected_colors_vbo,
[92b1e90]1217 selectedObject);
[c3c3158]1218 renderSceneGui();
1219 break;
1220 }
1221
1222 glfwSwapBuffers(window);
[644a2e4]1223 }
1224
[c1ca5b5]1225 ImGui_ImplGlfwGL3_Shutdown();
1226 ImGui::DestroyContext();
1227
1228 glfwDestroyWindow(window);
[5272b6b]1229 glfwTerminate();
[c1ca5b5]1230
[5272b6b]1231 return 0;
1232}
[ec4456b]1233
[4f3262f]1234void glfw_error_callback(int error, const char* description) {
1235 gl_log_err("GLFW ERROR: code %i msg: %s\n", error, description);
1236}
1237
1238void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
1239 double mouse_x, mouse_y;
1240 glfwGetCursorPos(window, &mouse_x, &mouse_y);
1241
1242 if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
1243 cout << "Mouse clicked (" << mouse_x << "," << mouse_y << ")" << endl;
1244 selectedObject = NULL;
1245
1246 float x = (2.0f*mouse_x) / width - 1.0f;
1247 float y = 1.0f - (2.0f*mouse_y) / height;
1248
1249 cout << "x: " << x << ", y: " << y << endl;
1250
1251 vec4 ray_clip = vec4(x, y, -1.0f, 1.0f);
1252 vec4 ray_eye = inverse(proj_mat) * ray_clip;
[dba67b2]1253 ray_eye = vec4(vec2(ray_eye), -1.0f, 1.0f);
[4f3262f]1254 vec4 ray_world = inverse(view_mat) * ray_eye;
1255
1256 vec4 click_point;
1257 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
1258 SceneObject* closest_object = NULL;
1259
1260 for (vector<SceneObject>::iterator it = objects.begin(); it != objects.end(); it++) {
[92b1e90]1261 if (it->type == TYPE_LASER) continue;
[4f3262f]1262 for (unsigned int p_idx = 0; p_idx < it->points.size(); p_idx += 9) {
[0d5c100]1263 if (faceClicked(
1264 {
1265 vec3(it->points[p_idx], it->points[p_idx + 1], it->points[p_idx + 2]),
1266 vec3(it->points[p_idx + 3], it->points[p_idx + 4], it->points[p_idx + 5]),
1267 vec3(it->points[p_idx + 6], it->points[p_idx + 7], it->points[p_idx + 8]),
[4f3262f]1268 },
[3effd81]1269 &*it, ray_world, vec4(cam_pos, 1.0f), click_point
[0d5c100]1270 )) {
[4f3262f]1271 click_point = view_mat * click_point;
1272
1273 if (-NEAR_CLIP >= click_point.z && click_point.z > -FAR_CLIP && click_point.z > closest_point.z) {
[dba67b2]1274 closest_point = vec3(click_point);
[0d5c100]1275 closest_object = &*it;
[4f3262f]1276 }
1277 }
1278 }
1279 }
1280
1281 if (closest_object == NULL) {
1282 cout << "No object was clicked" << endl;
[f7d35da]1283 } else {
[4f3262f]1284 clickedObject = closest_object;
1285 cout << "Clicked object: " << clickedObject->id << endl;
1286 }
1287 }
1288}
1289
[f7d35da]1290void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
1291 key_state[key] = action;
1292
1293 // should be true for GLFW_PRESS and GLFW_REPEAT
1294 key_pressed[key] = (action != GLFW_RELEASE);
1295}
1296
1297
[ec4456b]1298GLuint loadShader(GLenum type, string file) {
1299 cout << "Loading shader from file " << file << endl;
1300
1301 ifstream shaderFile(file);
1302 GLuint shaderId = 0;
1303
1304 if (shaderFile.is_open()) {
1305 string line, shaderString;
1306
1307 while(getline(shaderFile, line)) {
1308 shaderString += line + "\n";
1309 }
1310 shaderFile.close();
1311 const char* shaderCString = shaderString.c_str();
1312
1313 shaderId = glCreateShader(type);
1314 glShaderSource(shaderId, 1, &shaderCString, NULL);
1315 glCompileShader(shaderId);
1316
1317 cout << "Loaded successfully" << endl;
1318 } else {
[e856d62]1319 cout << "Failed to load the file" << endl;
[ec4456b]1320 }
1321
1322 return shaderId;
1323}
[485424b]1324
1325GLuint loadShaderProgram(string vertexShaderPath, string fragmentShaderPath) {
1326 GLuint vs = loadShader(GL_VERTEX_SHADER, vertexShaderPath);
1327 GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
1328
1329 GLuint shader_program = glCreateProgram();
1330 glAttachShader(shader_program, vs);
1331 glAttachShader(shader_program, fs);
1332
1333 glLinkProgram(shader_program);
1334
1335 return shader_program;
1336}
1337
1338unsigned char* loadImage(string file_name, int* x, int* y) {
1339 int n;
[e856d62]1340 int force_channels = 4; // This forces RGBA (4 bytes per pixel)
[485424b]1341 unsigned char* image_data = stbi_load(file_name.c_str(), x, y, &n, force_channels);
[e856d62]1342
1343 int width_in_bytes = *x * 4;
1344 unsigned char *top = NULL;
1345 unsigned char *bottom = NULL;
1346 unsigned char temp = 0;
1347 int half_height = *y / 2;
1348
1349 // flip image upside-down to account for OpenGL treating lower-left as (0, 0)
1350 for (int row = 0; row < half_height; row++) {
1351 top = image_data + row * width_in_bytes;
1352 bottom = image_data + (*y - row - 1) * width_in_bytes;
1353 for (int col = 0; col < width_in_bytes; col++) {
1354 temp = *top;
1355 *top = *bottom;
1356 *bottom = temp;
1357 top++;
1358 bottom++;
1359 }
1360 }
1361
[485424b]1362 if (!image_data) {
1363 fprintf(stderr, "ERROR: could not load %s\n", file_name.c_str());
1364 }
[e856d62]1365
1366 // Not Power-of-2 check
1367 if ((*x & (*x - 1)) != 0 || (*y & (*y - 1)) != 0) {
1368 fprintf(stderr, "WARNING: texture %s is not power-of-2 dimensions\n", file_name.c_str());
1369 }
1370
[485424b]1371 return image_data;
1372}
[33a9664]1373
[d9f99b2]1374bool faceClicked(array<vec3, 3> points, SceneObject* obj, vec4 world_ray, vec4 cam, vec4& click_point) {
[5c9d193]1375 // LINE EQUATION: P = O + Dt
[b73cb3b]1376 // O = cam
[5c9d193]1377 // D = ray_world
1378
[b73cb3b]1379 // PLANE EQUATION: P dot n + d = 0
1380 // n is the normal vector
1381 // d is the offset from the origin
[5c9d193]1382
1383 // Take the cross-product of two vectors on the plane to get the normal
[d9f99b2]1384 vec3 v1 = points[1] - points[0];
1385 vec3 v2 = points[2] - points[0];
[5c9d193]1386
1387 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);
[b73cb3b]1388
[dba67b2]1389 vec3 local_ray = vec3(inverse(obj->model_mat) * world_ray);
1390 vec3 local_cam = vec3(inverse(obj->model_mat) * cam);
[5c9d193]1391
[b73cb3b]1392 local_ray = local_ray - local_cam;
[5c9d193]1393
[d9f99b2]1394 float d = -glm::dot(points[0], normal);
[5c9d193]1395 float t = -(glm::dot(local_cam, normal) + d) / glm::dot(local_ray, normal);
1396
1397 vec3 intersection = local_cam + t*local_ray;
1398
[d9f99b2]1399 if (insideTriangle(intersection, points)) {
[e82692b]1400 click_point = obj->model_mat * vec4(intersection, 1.0f);
1401 return true;
1402 } else {
1403 return false;
1404 }
[5c9d193]1405}
[f7d35da]1406
[5c9d193]1407bool insideTriangle(vec3 p, array<vec3, 3> triangle_points) {
[d9f99b2]1408 vec3 v21 = triangle_points[1] - triangle_points[0];
1409 vec3 v31 = triangle_points[2] - triangle_points[0];
1410 vec3 pv1 = p - triangle_points[0];
[33a9664]1411
1412 float y = (pv1.y*v21.x - pv1.x*v21.y) / (v31.y*v21.x - v31.x*v21.y);
1413 float x = (pv1.x-y*v31.x) / v21.x;
1414
1415 return x > 0.0f && y > 0.0f && x+y < 1.0f;
1416}
[d12d003]1417
1418void printVector(string label, vec3 v) {
1419 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << ")" << endl;
1420}
[b73cb3b]1421
1422void print4DVector(string label, vec4 v) {
1423 cout << label << " -> (" << v.x << "," << v.y << "," << v.z << "," << v.w << ")" << endl;
1424}
[c1ca5b5]1425
[c3c3158]1426void addObjectToSceneDuringInit(SceneObject& obj) {
[3d06b4e]1427 // Each objects must have at least 3 points, so the size of
1428 // the points array must be a positive multiple of 9
1429 if (obj.points.size() == 0 || (obj.points.size() % 9) != 0) {
1430 return;
1431 }
1432
[0d5c100]1433 obj.id = objects.size(); // currently unused
1434 obj.num_points = obj.points.size() / 3;
[dba67b2]1435 obj.model_transform = mat4(1.0f);
[c3c3158]1436 obj.deleted = false;
[0d5c100]1437
1438 obj.normals.reserve(obj.points.size());
1439 for (int i = 0; i < obj.points.size(); i += 9) {
1440 vec3 point1 = vec3(obj.points[i], obj.points[i + 1], obj.points[i + 2]);
1441 vec3 point2 = vec3(obj.points[i + 3], obj.points[i + 4], obj.points[i + 5]);
1442 vec3 point3 = vec3(obj.points[i + 6], obj.points[i + 7], obj.points[i + 8]);
[cffca4d]1443
[0d5c100]1444 vec3 normal = normalize(cross(point2 - point1, point3 - point1));
[cffca4d]1445
[0d5c100]1446 // Add the same normal for all 3 points
1447 for (int j = 0; j < 3; j++) {
1448 obj.normals.push_back(normal.x);
1449 obj.normals.push_back(normal.y);
1450 obj.normals.push_back(normal.z);
1451 }
1452 }
[cffca4d]1453
[3d06b4e]1454 calculateObjectBoundingBox(obj);
1455
[95595de]1456 obj.bounding_center = vec3(obj.translate_mat * vec4(obj.bounding_center, 1.0f));
1457
[0d5c100]1458 objects.push_back(obj);
1459}
[cffca4d]1460
[c3c3158]1461void addObjectToScene(SceneObject& obj,
1462 map<GLuint, BufferInfo>& shaderBufferInfo,
1463 GLuint points_vbo,
1464 GLuint colors_vbo,
1465 GLuint selected_colors_vbo,
1466 GLuint texcoords_vbo,
1467 GLuint normals_vbo,
1468 GLuint ubo,
[6877ef3]1469 GLuint model_mat_idx_vbo) {
[c3c3158]1470 addObjectToSceneDuringInit(obj);
1471
1472 BufferInfo* bufferInfo = &shaderBufferInfo[obj.shader_program];
1473
[3d06b4e]1474 // Check if the buffers aren't large enough to fit the new object and, if so, call
1475 // populateBuffers() to resize and repopupulate them
[c3c3158]1476 if (bufferInfo->vbo_capacity < (bufferInfo->ubo_offset + obj.num_points) ||
1477 bufferInfo->ubo_capacity < (bufferInfo->ubo_offset + 1)) {
1478 populateBuffers(objects, shaderBufferInfo,
1479 points_vbo,
1480 colors_vbo,
1481 selected_colors_vbo,
1482 texcoords_vbo,
1483 normals_vbo,
1484 ubo,
[6877ef3]1485 model_mat_idx_vbo);
[c3c3158]1486 } else {
1487 copyObjectDataToBuffers(objects.back(), shaderBufferInfo,
1488 points_vbo,
1489 colors_vbo,
1490 selected_colors_vbo,
1491 texcoords_vbo,
1492 normals_vbo,
1493 ubo,
[6877ef3]1494 model_mat_idx_vbo);
[c3c3158]1495 }
1496}
1497
[95595de]1498void removeObjectFromScene(SceneObject& obj, GLuint ubo) {
[c3c3158]1499 if (!obj.deleted) {
1500 // Move the object outside the render bounds of the scene so it doesn't get rendered
1501 // TODO: Find a better way of hiding the object until the next time buffers are repopulated
[dba67b2]1502 transformObject(obj, translate(mat4(1.0f), vec3(0.0f, 0.0f, FAR_CLIP * 1000.0f)), ubo);
[c3c3158]1503 obj.deleted = true;
1504 }
1505}
1506
[3d06b4e]1507void calculateObjectBoundingBox(SceneObject& obj) {
1508 GLfloat min_x = obj.points[0];
1509 GLfloat max_x = obj.points[0];
1510 GLfloat min_y = obj.points[1];
1511 GLfloat max_y = obj.points[1];
1512 GLfloat min_z = obj.points[2];
1513 GLfloat max_z = obj.points[2];
1514
1515 // start from the second point
1516 for (int i = 3; i < obj.points.size(); i += 3) {
1517 if (min_x > obj.points[i]) {
1518 min_x = obj.points[i];
1519 }
1520 else if (max_x < obj.points[i]) {
1521 max_x = obj.points[i];
1522 }
1523
1524 if (min_y > obj.points[i + 1]) {
1525 min_y = obj.points[i + 1];
1526 }
1527 else if (max_y < obj.points[i + 1]) {
1528 max_y = obj.points[i + 1];
1529 }
1530
1531 if (min_z > obj.points[i + 2]) {
1532 min_z = obj.points[i + 2];
1533 }
1534 else if (max_z < obj.points[i + 2]) {
1535 max_z = obj.points[i + 2];
1536 }
1537 }
1538
1539 obj.bounding_center = vec3((min_x + max_x) / 2.0f, (min_y + max_y) / 2.0f, (min_z + max_z) / 2.0f);
1540
1541 GLfloat radius_x = max_x - obj.bounding_center.x;
1542 GLfloat radius_y = max_y - obj.bounding_center.y;
1543 GLfloat radius_z = max_z - obj.bounding_center.z;
1544
[95595de]1545 // This actually underestimates the radius. Might need to be fixed at some point.
[3d06b4e]1546 obj.bounding_radius = radius_x;
1547 if (obj.bounding_radius < radius_y)
1548 obj.bounding_radius = radius_y;
1549 if (obj.bounding_radius < radius_z)
1550 obj.bounding_radius = radius_z;
1551
1552 for (int i = 0; i < obj.points.size(); i += 3) {
1553 obj.points[i] -= obj.bounding_center.x;
1554 obj.points[i + 1] -= obj.bounding_center.y;
1555 obj.points[i + 2] -= obj.bounding_center.z;
1556 }
1557
1558 obj.bounding_center = vec3(0.0f, 0.0f, 0.0f);
1559}
1560
[3effd81]1561/* LASER RENDERING/POSITIONING ALGORITHM
1562 * -Draw a thin rectangle for the laser beam, using the specified width and endpoints
1563 * -Texture the beam with a grayscale partially transparent image
1564 * -In the shader, blend the image with a color to support lasers of different colors
1565 *
1566 * The flat part of the textured rectangle needs to always face the camera, so the laser's width is constant
1567 * This is done as follows:
1568* -Determine the length of the laser based on the start and end points
1569* -Draw a rectangle along the z-axis and rotated upwards along the y-axis, with the correct final length and width
1570* -Rotate the beam around the z-axis by the correct angle, sot that in its final position, the flat part faces the camera
1571* -Rotate the beam along the x-axis and then along the y-axis and then translate it to put it into its final position
1572*/
[fd6f465]1573void addLaserToScene(vec3 start, vec3 end, vec3 color, GLfloat width, GLuint laser_sp) {
1574 SceneObject obj = SceneObject();
[92b1e90]1575 obj.id = objects.size(); // currently unused
1576 obj.type = TYPE_LASER;
[fd6f465]1577 obj.shader_program = laser_sp;
[92b1e90]1578 obj.deleted = false;
[b155f13]1579
[3effd81]1580 vec3 ray = end - start;
1581 float length = glm::length(ray);
[b155f13]1582
[92b1e90]1583 obj.points = {
[fd6f465]1584 width / 2, 0.0f, -width / 2,
1585 -width / 2, 0.0f, -width / 2,
1586 -width / 2, 0.0f, 0.0f,
1587 width / 2, 0.0f, -width / 2,
1588 -width / 2, 0.0f, 0.0f,
1589 width / 2, 0.0f, 0.0f,
1590 width / 2, 0.0f, -length + width / 2,
1591 -width / 2, 0.0f, -length + width / 2,
1592 -width / 2, 0.0f, -width / 2,
1593 width / 2, 0.0f, -length + width / 2,
1594 -width / 2, 0.0f, -width / 2,
1595 width / 2, 0.0f, -width / 2,
1596 width / 2, 0.0f, -length,
1597 -width / 2, 0.0f, -length,
1598 -width / 2, 0.0f, -length + width / 2,
1599 width / 2, 0.0f, -length,
1600 -width / 2, 0.0f, -length + width / 2,
1601 width / 2, 0.0f, -length + width / 2,
[b155f13]1602 };
1603
[9f9f9a7]1604 obj.texcoords = {
1605 1.0f, 0.5f,
1606 0.0f, 0.5f,
1607 0.0f, 0.0f,
1608 1.0f, 0.5f,
1609 0.0f, 0.0f,
1610 1.0f, 0.0f,
1611 1.0f, 0.51f,
1612 0.0f, 0.51f,
1613 0.0f, 0.49f,
1614 1.0f, 0.51f,
1615 0.0f, 0.49f,
1616 1.0f, 0.49f,
1617 1.0f, 1.0f,
1618 0.0f, 1.0f,
1619 0.0f, 0.5f,
1620 1.0f, 1.0f,
1621 0.0f, 0.5f,
1622 1.0f, 0.5f,
1623 };
1624
[92b1e90]1625 obj.num_points = obj.points.size() / 3;
[3effd81]1626
1627 float xAxisRotation = asin(ray.y / length);
1628 float yAxisRotation = atan2(-ray.x, -ray.z);
1629
1630 vec3 normal(rotate(mat4(1.0f), yAxisRotation, vec3(0.0f, 1.0f, 0.0f)) *
1631 rotate(mat4(1.0f), xAxisRotation, vec3(1.0f, 0.0f, 0.0f)) *
1632 vec4(0.0f, 1.0f, 0.0f, 1.0f));
1633
1634 // To project point P onto line AB:
1635 // projection = A + dot(AP,AB) / dot(AB,AB) * AB
1636 vec3 projOnLaser = start + glm::dot(cam_pos-start, ray) / (length*length) * ray;
1637 vec3 laserToCam = cam_pos - projOnLaser;
1638
1639 float zAxisRotation = -atan2(glm::dot(glm::cross(normal, laserToCam), glm::normalize(ray)), glm::dot(normal, laserToCam));
1640
1641 obj.model_base = mat4(1.0f);
1642 obj.model_base = rotate(mat4(1.0f), zAxisRotation, vec3(0.0f, 0.0f, 1.0f)) * obj.model_base;
1643 obj.model_base = rotate(mat4(1.0f), xAxisRotation, vec3(1.0f, 0.0f, 0.0f)) * obj.model_base;
1644 obj.model_base = rotate(mat4(1.0f), yAxisRotation, vec3(0.0f, 1.0f, 0.0f)) * obj.model_base;
1645 obj.model_base = translate(mat4(1.0f), start) * obj.model_base;
[fd6f465]1646 obj.model_transform = mat4(1.0f);
[b155f13]1647
[92b1e90]1648 objects.push_back(obj);
[b155f13]1649}
1650
[c3c3158]1651void initializeBuffers(
1652 GLuint* points_vbo,
1653 GLuint* colors_vbo,
1654 GLuint* selected_colors_vbo,
1655 GLuint* texcoords_vbo,
1656 GLuint* normals_vbo,
1657 GLuint* ubo,
[6877ef3]1658 GLuint* model_mat_idx_vbo) {
[c3c3158]1659 *points_vbo = 0;
1660 glGenBuffers(1, points_vbo);
1661
1662 *colors_vbo = 0;
1663 glGenBuffers(1, colors_vbo);
1664
1665 *selected_colors_vbo = 0;
1666 glGenBuffers(1, selected_colors_vbo);
1667
1668 *texcoords_vbo = 0;
1669 glGenBuffers(1, texcoords_vbo);
1670
1671 *normals_vbo = 0;
1672 glGenBuffers(1, normals_vbo);
1673
1674 *ubo = 0;
1675 glGenBuffers(1, ubo);
1676
1677 *model_mat_idx_vbo = 0;
1678 glGenBuffers(1, model_mat_idx_vbo);
1679}
1680
[0d5c100]1681void populateBuffers(vector<SceneObject>& objects,
[c3c3158]1682 map<GLuint, BufferInfo>& shaderBufferInfo,
1683 GLuint points_vbo,
1684 GLuint colors_vbo,
1685 GLuint selected_colors_vbo,
1686 GLuint texcoords_vbo,
1687 GLuint normals_vbo,
1688 GLuint ubo,
[6877ef3]1689 GLuint model_mat_idx_vbo) {
[0d5c100]1690 GLsizeiptr points_buffer_size = 0;
1691 GLsizeiptr textures_buffer_size = 0;
1692 GLsizeiptr ubo_buffer_size = 0;
1693 GLsizeiptr model_mat_idx_buffer_size = 0;
1694
[c3c3158]1695 map<GLuint, unsigned int> shaderCounts;
[0d5c100]1696 map<GLuint, unsigned int> shaderUboCounts;
[93462c6]1697
[0d5c100]1698 vector<SceneObject>::iterator it;
1699
[92b1e90]1700 /* Find all shaders that need to be used and the number of objects and
[c3c3158]1701 * number of points for each shader. Construct a map from shader id to count
1702 * of points being drawn using that shader (for thw model matrix ubo, we
1703 * need object counts instead). These will be used to get offsets into the
1704 * vertex buffer for each shader.
1705 */
1706 for (it = objects.begin(); it != objects.end();) {
1707 if (it->deleted) {
1708 it = objects.erase(it);
[0d5c100]1709 } else {
[c94a699]1710 points_buffer_size += it->num_points * sizeof(GLfloat) * 3;
1711 textures_buffer_size += it->num_points * sizeof(GLfloat) * 2;
[c3c3158]1712 ubo_buffer_size += 16 * sizeof(GLfloat);
1713 model_mat_idx_buffer_size += it->num_points * sizeof(GLuint);
1714
1715 if (shaderCounts.count(it->shader_program) == 0) {
1716 shaderCounts[it->shader_program] = it->num_points;
1717 shaderUboCounts[it->shader_program] = 1;
1718 } else {
1719 shaderCounts[it->shader_program] += it->num_points;
1720 shaderUboCounts[it->shader_program]++;
1721 }
1722
1723 it++;
[e3ca955]1724 }
[0d5c100]1725 }
1726
[c3c3158]1727 // double the buffer sizes to leave room for new objects
1728 points_buffer_size *= 2;
1729 textures_buffer_size *= 2;
1730 ubo_buffer_size *= 2;
1731 model_mat_idx_buffer_size *= 2;
1732
[0d5c100]1733 map<GLuint, unsigned int>::iterator shaderIt;
1734 unsigned int lastShaderCount = 0;
1735 unsigned int lastShaderUboCount = 0;
1736
1737 /*
[c3c3158]1738 * The counts calculated above can be used to get the starting offset of
1739 * each shader in the vertex buffer. Create a map of base offsets to mark
1740 * where the data for the first object using a given shader begins. Also,
1741 * create a map of current offsets to mark where to copy data for the next
1742 * object being added.
1743 */
[0d5c100]1744 for (shaderIt = shaderCounts.begin(); shaderIt != shaderCounts.end(); shaderIt++) {
[c3c3158]1745 shaderBufferInfo[shaderIt->first].vbo_base = lastShaderCount * 2;
1746 shaderBufferInfo[shaderIt->first].ubo_base = lastShaderUboCount * 2;
[92b1e90]1747
[3effd81]1748 /*
[c3c3158]1749 cout << "shader: " << shaderIt->first << endl;
1750 cout << "point counts: " << shaderCounts[shaderIt->first] << endl;
1751 cout << "object counts: " << shaderUboCounts[shaderIt->first] << endl;
1752 cout << "vbo_base: " << shaderBufferInfo[shaderIt->first].vbo_base << endl;
1753 cout << "ubo_base: " << shaderBufferInfo[shaderIt->first].ubo_base << endl;
[3effd81]1754 */
[0d5c100]1755
[c3c3158]1756 shaderBufferInfo[shaderIt->first].vbo_offset = 0;
1757 shaderBufferInfo[shaderIt->first].ubo_offset = 0;
1758
1759 shaderBufferInfo[shaderIt->first].vbo_capacity = shaderCounts[shaderIt->first] * 2;
1760 shaderBufferInfo[shaderIt->first].ubo_capacity = shaderUboCounts[shaderIt->first] * 2;
[0d5c100]1761
[c3c3158]1762 lastShaderCount += shaderCounts[shaderIt->first];
[0d5c100]1763 lastShaderUboCount += shaderUboCounts[shaderIt->first];
1764 }
1765
[c3c3158]1766 // Allocate all the buffers using the counts calculated above
[0d5c100]1767
[c3c3158]1768 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
[0d5c100]1769 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1770
[c3c3158]1771 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
[0d5c100]1772 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1773
[c3c3158]1774 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
[0d5c100]1775 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1776
[c3c3158]1777 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
[0d5c100]1778 glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
1779
[c3c3158]1780 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
[0d5c100]1781 glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
1782
[c3c3158]1783 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
[0d5c100]1784 glBufferData(GL_UNIFORM_BUFFER, ubo_buffer_size, NULL, GL_DYNAMIC_DRAW);
1785
[c3c3158]1786 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
[0d5c100]1787 glBufferData(GL_ARRAY_BUFFER, model_mat_idx_buffer_size, NULL, GL_DYNAMIC_DRAW);
1788
1789 for (it = objects.begin(); it != objects.end(); it++) {
[c3c3158]1790 copyObjectDataToBuffers(*it, shaderBufferInfo,
1791 points_vbo,
1792 colors_vbo,
1793 selected_colors_vbo,
1794 texcoords_vbo,
1795 normals_vbo,
1796 ubo,
[6877ef3]1797 model_mat_idx_vbo);
[c3c3158]1798 }
1799}
[0d5c100]1800
[c3c3158]1801void copyObjectDataToBuffers(SceneObject& obj,
1802 map<GLuint, BufferInfo>& shaderBufferInfo,
1803 GLuint points_vbo,
1804 GLuint colors_vbo,
1805 GLuint selected_colors_vbo,
1806 GLuint texcoords_vbo,
1807 GLuint normals_vbo,
1808 GLuint ubo,
[6877ef3]1809 GLuint model_mat_idx_vbo) {
[c3c3158]1810 BufferInfo* bufferInfo = &shaderBufferInfo[obj.shader_program];
[0d5c100]1811
[c3c3158]1812 obj.vertex_vbo_offset = bufferInfo->vbo_base + bufferInfo->vbo_offset;
1813 obj.ubo_offset = bufferInfo->ubo_base + bufferInfo->ubo_offset;
[0d5c100]1814
[6877ef3]1815 glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
1816 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.points.size() * sizeof(GLfloat), &obj.points[0]);
[0d5c100]1817
[fd6f465]1818 glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
1819 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 2, obj.texcoords.size() * sizeof(GLfloat), &obj.texcoords[0]);
[0d5c100]1820
[fd6f465]1821 glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
1822 for (int i = 0; i < obj.num_points; i++) {
1823 glBufferSubData(GL_ARRAY_BUFFER, (obj.vertex_vbo_offset + i) * sizeof(GLuint), sizeof(GLuint), &obj.ubo_offset);
1824 }
[0d5c100]1825
[6877ef3]1826 if (obj.type != TYPE_LASER) {
[fd6f465]1827 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
1828 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.colors.size() * sizeof(GLfloat), &obj.colors[0]);
1829
[92b1e90]1830 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1831 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.selected_colors.size() * sizeof(GLfloat), &obj.selected_colors[0]);
[0d5c100]1832
[92b1e90]1833 glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
1834 glBufferSubData(GL_ARRAY_BUFFER, obj.vertex_vbo_offset * sizeof(GLfloat) * 3, obj.normals.size() * sizeof(GLfloat), &obj.normals[0]);
1835 }
[c3c3158]1836
[fd6f465]1837 obj.model_mat = obj.model_transform * obj.model_base;
1838 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1839 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1840
[c3c3158]1841 bufferInfo->vbo_offset += obj.num_points;
1842 bufferInfo->ubo_offset++;
[0d5c100]1843}
[93462c6]1844
[5c403fe]1845void transformObject(SceneObject& obj, const mat4& transform, GLuint ubo) {
[3d06b4e]1846 obj.model_transform = transform * obj.model_transform;
[5c403fe]1847 obj.model_mat = obj.model_transform * obj.model_base;
1848
[95595de]1849 obj.bounding_center = vec3(transform * vec4(obj.bounding_center, 1.0f));
1850
[5c403fe]1851 glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1852 glBufferSubData(GL_UNIFORM_BUFFER, obj.ubo_offset * sizeof(mat4), sizeof(mat4), value_ptr(obj.model_mat));
1853}
1854
[92b1e90]1855void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
1856 GLuint color_sp, GLuint texture_sp, GLuint laser_sp,
[fd6f465]1857 GLuint color_vao, GLuint texture_vao, GLuint laser_vao,
[b155f13]1858 GLuint colors_vbo, GLuint selected_colors_vbo,
[92b1e90]1859 SceneObject* selectedObject) {
[93462c6]1860
[cffca4d]1861 glUseProgram(color_sp);
[92b1e90]1862 glBindVertexArray(color_vao);
[93462c6]1863
[0d5c100]1864 if (selectedObject != NULL) {
1865 glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
1866 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
[cffca4d]1867
[0d5c100]1868 glDrawArrays(GL_TRIANGLES, selectedObject->vertex_vbo_offset, selectedObject->num_points);
[cffca4d]1869 }
[93462c6]1870
[e3ca955]1871 glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
[cffca4d]1872 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
[93462c6]1873
[c3c3158]1874 glDrawArrays(GL_TRIANGLES, shaderBufferInfo[color_sp].vbo_base, shaderBufferInfo[color_sp].vbo_offset);
[93462c6]1875
[cffca4d]1876 glUseProgram(texture_sp);
[92b1e90]1877 glBindVertexArray(texture_vao);
[93462c6]1878
[c3c3158]1879 glDrawArrays(GL_TRIANGLES, shaderBufferInfo[texture_sp].vbo_base, shaderBufferInfo[texture_sp].vbo_offset);
[93462c6]1880
[9f9f9a7]1881 glEnable(GL_BLEND);
1882
[92b1e90]1883 glUseProgram(laser_sp);
[fd6f465]1884 glBindVertexArray(laser_vao);
[b155f13]1885
[92b1e90]1886 glDrawArrays(GL_TRIANGLES, shaderBufferInfo[laser_sp].vbo_base, shaderBufferInfo[laser_sp].vbo_offset);
[9f9f9a7]1887
1888 glDisable(GL_BLEND);
[b155f13]1889}
1890
[93462c6]1891void renderSceneGui() {
[c1ca5b5]1892 ImGui_ImplGlfwGL3_NewFrame();
1893
1894 // 1. Show a simple window.
1895 // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
[5b3462b]1896 /*
[c1ca5b5]1897 {
1898 static float f = 0.0f;
1899 static int counter = 0;
1900 ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
1901 ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
1902 ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
1903
1904 ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
1905 ImGui::Checkbox("Another Window", &show_another_window);
1906
1907 if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
1908 counter++;
1909 ImGui::SameLine();
1910 ImGui::Text("counter = %d", counter);
1911
1912 ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
1913 }
[5b3462b]1914 */
[c1ca5b5]1915
[5b3462b]1916 {
1917 ImGui::SetNextWindowSize(ImVec2(85, 22), ImGuiCond_Once);
1918 ImGui::SetNextWindowPos(ImVec2(10, 50), ImGuiCond_Once);
[f0cc877]1919 ImGui::Begin("WndStats", NULL,
1920 ImGuiWindowFlags_NoTitleBar |
1921 ImGuiWindowFlags_NoResize |
1922 ImGuiWindowFlags_NoMove);
[5b3462b]1923 ImGui::Text("Score: ???");
[c1ca5b5]1924 ImGui::End();
1925 }
1926
[5b3462b]1927 {
1928 ImGui::SetNextWindowPos(ImVec2(380, 10), ImGuiCond_Once);
1929 ImGui::SetNextWindowSize(ImVec2(250, 35), ImGuiCond_Once);
[f0cc877]1930 ImGui::Begin("WndMenubar", NULL,
1931 ImGuiWindowFlags_NoTitleBar |
[5b3462b]1932 ImGuiWindowFlags_NoResize |
1933 ImGuiWindowFlags_NoMove);
[93462c6]1934 ImGui::InvisibleButton("", ImVec2(155, 18));
[5b3462b]1935 ImGui::SameLine();
[93462c6]1936 if (ImGui::Button("Main Menu")) {
1937 events.push(EVENT_GO_TO_MAIN_MENU);
[5b3462b]1938 }
1939 ImGui::End();
[c1ca5b5]1940 }
1941
[93462c6]1942 ImGui::Render();
1943 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1944}
1945
1946void renderMainMenu() {
1947}
1948
1949void renderMainMenuGui() {
1950 ImGui_ImplGlfwGL3_NewFrame();
1951
[f0cc877]1952 {
1953 int padding = 4;
1954 ImGui::SetNextWindowPos(ImVec2(-padding, -padding), ImGuiCond_Once);
[93462c6]1955 ImGui::SetNextWindowSize(ImVec2(width + 2 * padding, height + 2 * padding), ImGuiCond_Once);
[f0cc877]1956 ImGui::Begin("WndMain", NULL,
1957 ImGuiWindowFlags_NoTitleBar |
1958 ImGuiWindowFlags_NoResize |
1959 ImGuiWindowFlags_NoMove);
[93462c6]1960
1961 ImGui::InvisibleButton("", ImVec2(10, 80));
1962 ImGui::InvisibleButton("", ImVec2(285, 18));
1963 ImGui::SameLine();
1964 if (ImGui::Button("New Game")) {
1965 events.push(EVENT_GO_TO_GAME);
1966 }
1967
1968 ImGui::InvisibleButton("", ImVec2(10, 15));
1969 ImGui::InvisibleButton("", ImVec2(300, 18));
1970 ImGui::SameLine();
1971 if (ImGui::Button("Quit")) {
1972 events.push(EVENT_QUIT);
1973 }
1974
[f0cc877]1975 ImGui::End();
1976 }
1977
[c1ca5b5]1978 ImGui::Render();
1979 ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());
1980}
[cf2d1e5]1981
[c3c3158]1982void spawnAsteroid(vec3 pos, GLuint shader,
1983 map<GLuint, BufferInfo>& shaderBufferInfo,
1984 GLuint points_vbo,
1985 GLuint colors_vbo,
1986 GLuint selected_colors_vbo,
1987 GLuint texcoords_vbo,
1988 GLuint normals_vbo,
1989 GLuint ubo,
[6877ef3]1990 GLuint model_mat_idx_vbo) {
[cf2d1e5]1991 SceneObject obj = SceneObject();
[92b1e90]1992 obj.type = TYPE_ASTEROID;
[cf2d1e5]1993 obj.shader_program = shader;
1994
1995 obj.points = {
1996 // front
1997 1.0f, 1.0f, 1.0f,
1998 -1.0f, 1.0f, 1.0f,
1999 -1.0f, -1.0f, 1.0f,
2000 1.0f, 1.0f, 1.0f,
2001 -1.0f, -1.0f, 1.0f,
2002 1.0f, -1.0f, 1.0f,
2003
2004 // top
2005 1.0f, 1.0f, -1.0f,
2006 -1.0f, 1.0f, -1.0f,
2007 -1.0f, 1.0f, 1.0f,
2008 1.0f, 1.0f, -1.0f,
2009 -1.0f, 1.0f, 1.0f,
2010 1.0f, 1.0f, 1.0f,
2011
2012 // bottom
2013 1.0f, -1.0f, 1.0f,
2014 -1.0f, -1.0f, 1.0f,
2015 -1.0f, -1.0f, -1.0f,
2016 1.0f, -1.0f, 1.0f,
2017 -1.0f, -1.0f, -1.0f,
2018 1.0f, -1.0f, -1.0f,
2019
2020 // back
2021 1.0f, 1.0f, -1.0f,
2022 -1.0f, -1.0f, -1.0f,
2023 -1.0f, 1.0f, -1.0f,
2024 1.0f, 1.0f, -1.0f,
2025 1.0f, -1.0f, -1.0f,
2026 -1.0f, -1.0f, -1.0f,
2027
2028 // right
2029 1.0f, 1.0f, -1.0f,
2030 1.0f, 1.0f, 1.0f,
2031 1.0f, -1.0f, 1.0f,
2032 1.0f, 1.0f, -1.0f,
2033 1.0f, -1.0f, 1.0f,
2034 1.0f, -1.0f, -1.0f,
2035
2036 // left
2037 -1.0f, 1.0f, 1.0f,
2038 -1.0f, 1.0f, -1.0f,
2039 -1.0f, -1.0f, -1.0f,
2040 -1.0f, 1.0f, 1.0f,
2041 -1.0f, -1.0f, -1.0f,
2042 -1.0f, -1.0f, 1.0f,
2043 };
2044 obj.colors = {
2045 // front
2046 0.8f, 0.0f, 0.0f,
2047 0.8f, 0.0f, 0.0f,
2048 0.8f, 0.0f, 0.0f,
2049 0.8f, 0.0f, 0.0f,
2050 0.8f, 0.0f, 0.0f,
2051 0.8f, 0.0f, 0.0f,
2052
2053 // top
2054 0.8f, 0.0f, 0.0f,
2055 0.8f, 0.0f, 0.0f,
2056 0.8f, 0.0f, 0.0f,
2057 0.8f, 0.0f, 0.0f,
2058 0.8f, 0.0f, 0.0f,
2059 0.8f, 0.0f, 0.0f,
2060
2061 // bottom
2062 0.8f, 0.0f, 0.0f,
2063 0.8f, 0.0f, 0.0f,
2064 0.8f, 0.0f, 0.0f,
2065 0.8f, 0.0f, 0.0f,
2066 0.8f, 0.0f, 0.0f,
2067 0.8f, 0.0f, 0.0f,
2068
2069 // back
2070 0.8f, 0.0f, 0.0f,
2071 0.8f, 0.0f, 0.0f,
2072 0.8f, 0.0f, 0.0f,
2073 0.8f, 0.0f, 0.0f,
2074 0.8f, 0.0f, 0.0f,
2075 0.8f, 0.0f, 0.0f,
2076
2077 // right
2078 0.8f, 0.0f, 0.0f,
2079 0.8f, 0.0f, 0.0f,
2080 0.8f, 0.0f, 0.0f,
2081 0.8f, 0.0f, 0.0f,
2082 0.8f, 0.0f, 0.0f,
2083 0.8f, 0.0f, 0.0f,
2084
2085 // left
2086 0.8f, 0.0f, 0.0f,
2087 0.8f, 0.0f, 0.0f,
2088 0.8f, 0.0f, 0.0f,
2089 0.8f, 0.0f, 0.0f,
2090 0.8f, 0.0f, 0.0f,
2091 0.8f, 0.0f, 0.0f,
2092 };
2093 obj.texcoords = { 0.0f };
2094 obj.selected_colors = { 0.0f };
2095
[dba67b2]2096 mat4 T = translate(mat4(1.0f), pos);
2097 mat4 R = rotate(mat4(1.0f), 60.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 1.0f, -1.0f));
2098 obj.model_base = T * R * scale(mat4(1.0f), vec3(0.1f, 0.1f, 0.1f));
[cf2d1e5]2099
[95595de]2100 obj.translate_mat = T;
2101
[c3c3158]2102 addObjectToScene(obj, shaderBufferInfo,
2103 points_vbo,
2104 colors_vbo,
2105 selected_colors_vbo,
2106 texcoords_vbo,
2107 normals_vbo,
2108 ubo,
[6877ef3]2109 model_mat_idx_vbo);
[cf2d1e5]2110}
[5527206]2111
2112float getRandomNum(float low, float high) {
2113 return low + ((float)rand()/RAND_MAX) * (high-low);
2114}
Note: See TracBrowser for help on using the repository browser.