source: opengl-game/new-game.cpp@ 6877ef3

feature/imgui-sdl points-test
Last change on this file since 6877ef3 was 6877ef3, checked in by Dmitry Portnoy <dmp1488@…>, 6 years ago

Finish integrating lasers into the object rendering pipeline and remove a bunch of code for creating and using laser-specific vbos.

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