diff --git a/src/gooey.h b/src/gooey.h index f5a41ce..f371abe 100644 --- a/src/gooey.h +++ b/src/gooey.h @@ -15,9 +15,6 @@ void shutdownGooey(); bool gooeyProcessEvent(SDL_Event &event); void renderGooey(SDL_Handles &handles, HexDrawMode &mode); -// TODO: replace with game state -bool is_debug_render = true; - bool initGooey(SDL_Handles &handles, v2i vp_dims /*TODO: pass in game state*/) { @@ -45,7 +42,7 @@ gooeyProcessEvent(SDL_Event &event) } void -renderGooey(SDL_Handles &handles, HexDrawMode &mode) +renderGooey(SDL_Handles &handles, HexDrawMode &mode, bool &is_debug) { ImGui_ImplSdlGL3_NewFrame(handles.window); @@ -74,8 +71,8 @@ renderGooey(SDL_Handles &handles, HexDrawMode &mode) if (ImGui::Button("Cone Fill")) mode = CONE_FILL; - ImGui::Checkbox("Debug Render", &is_debug_render); - ImGui::SameLine(); ImGui::TextUnformatted(is_debug_render ? "true" : "false"); + ImGui::Checkbox("Debug Render", &is_debug); + ImGui::SameLine(); ImGui::TextUnformatted(is_debug ? "true" : "false"); ImGui::Render(); } diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 4f77757..5db03c8 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -331,65 +331,52 @@ handleMouseUp(SDL_MouseButtonEvent &e) } } -// TODO: use timer in render loop, and call SDL event handler -// per frame with event pump bool -enterLoop(SDL_Handles &handles) +processSDLEvents(SDL_Handles &handles) { SDL_Event e; - bool quit = false; - while(!quit) + bool run = true; + + while (SDL_PollEvent(&e)) { - // TODO: remove hack to not peg CPU. replace with an actual frame timer - SDL_Delay(16); // ~60hz + // let gooey have event + // TODO: need to check for both io.WantCaptureKeyboard and io.WantCaptureMouse + // to fix bug with 'ESC' not passing through while in imgui + bool gooey_wants = gooeyProcessEvent(e); - while (SDL_PollEvent(&e)) + switch (e.type) { - // let gooey have event - // TODO: need to check for both io.WantCaptureKeyboard and io.WantCaptureMouse - // to fix bug with 'ESC' not passing through while in imgui - bool gooey_wants = gooeyProcessEvent(e); - - switch (e.type) - { - case SDL_QUIT: - quit = true; - break; - case SDL_KEYDOWN: - if ( e.key.keysym.sym == SDLK_ESCAPE) - quit = true; - break; - case SDL_MOUSEBUTTONDOWN: - if (!gooey_wants) - { - g_game_state->is_selecting = true; - handleMouseDown(e.button); - } - break; - case SDL_MOUSEBUTTONUP: - if (!gooey_wants) - { - g_game_state->is_selecting = false; - handleMouseUp(e.button); - } - break; - case SDL_MOUSEMOTION: - if (!gooey_wants) - handleMouseMove(e.motion); - break; - default: - break; - } + case SDL_QUIT: + run = false; + break; + case SDL_KEYDOWN: + if ( e.key.keysym.sym == SDLK_ESCAPE) + run = false; + break; + case SDL_MOUSEBUTTONDOWN: + if (!gooey_wants) + { + g_game_state->is_selecting = true; + handleMouseDown(e.button); + } + break; + case SDL_MOUSEBUTTONUP: + if (!gooey_wants) + { + g_game_state->is_selecting = false; + handleMouseUp(e.button); + } + break; + case SDL_MOUSEMOTION: + if (!gooey_wants) + handleMouseMove(e.motion); + break; + default: + break; } - - // TODO: move loop to main() and condense all these SDL event functions? - // something like a large processSDLEvents() - renderFrame(g_game_state->hex_array /* TODO: pass in game state*/); - renderGooey(handles, g_game_state->draw_mode); - SDL_GL_SwapWindow(handles.window); } - - return true; + + return run; } bool @@ -466,9 +453,19 @@ int main(int argc, char* argv[]) LOG(ERROR) << "Fooey, No Gooey!\n"; return 1; } + + // main loop + while (processSDLEvents(handles)) + { + // TODO: remove hack to not peg CPU. replace with an actual frame timer + SDL_Delay(16); // ~60hz + renderFrame(g_game_state->hex_array); + if (g_render_state->is_debug_draw && g_game_state->draw_mode == CONE_FILL) + renderDebug(g_game_state->start_hex, g_game_state->current_hex); + renderGooey(handles, g_game_state->draw_mode, g_render_state->is_debug_draw); + SDL_GL_SwapWindow(handles.window); + } - // TODO: condense main loop - enterLoop(handles); cleanUp(handles); return 0; } diff --git a/src/renderer.h b/src/renderer.h index d4afc40..d64a2fa 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -3,12 +3,13 @@ #define RENDERER_H #include +#include // trig functions +#include // calloc // TODO: decide on extension library //#include #include - #include #include #include @@ -17,16 +18,6 @@ #include "hexgame.h" -// Interface - -bool initRenderer(SDL_Handles &handles, v2i vpDims); -bool createScene(std::vector* hexes); -// TODO: re-implement debug renderer -void debugRender(HexDrawMode mode, hex_info *startHex, hex_info *currentHex); -void renderFrame(const std::vector *hexes); -void freeBuffers(); - - const char * VERTEX_SHADER_CODE = "#version 330 core\n" "in vec3 vertexPosition_modelspace;\n" @@ -56,6 +47,13 @@ const char * LINE_FRAGMENT_SHADER_CODE = " color = vec3(0,0,0);\n" "}"; +const char * DEBUG_FRAGMENT_SHADER_CODE = + "#version 330 core\n" + "out vec3 color;\n" + "void main()\n" + "{\n" + " color = vec3(1,0,0);\n" + "}"; typedef struct clear_col { @@ -91,22 +89,30 @@ typedef struct gl_render_group GLuint vertex_array_id; } gl_render_group; - gl_matrix_info g_scene_matrices; gl_render_group g_filled_hex_render_group; gl_render_group g_hex_line_render_group; +gl_render_group g_debug_render_group; + +// Interface + +bool initRenderer(SDL_Handles &handles, v2i vpDims); +bool createScene(std::vector* hexes); +void renderFrame(const std::vector *hexes); +void renderDebug(hex_info *start_hex, hex_info * current_hex); +void freeBuffers(); // forward declarations -bool initShaders(GLuint &programID1, GLuint &programID2); bool initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id); // enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); -void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex); -bool fillColorBuffer(GLfloat buf[], int len, std::vector *hexes); +void fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex); +void fillColorBuffer(GLfloat buf[], int len, std::vector *hexes); +void fillHexLineBuffer(GLfloat buf[], int len, std::vector* hexes); bool checkGLBufferSize(GLenum buf_type, int expected_size, int line_num); - +bool initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]); bool initRenderer(SDL_Handles &handles, v2i vpDims) @@ -132,11 +138,13 @@ initRenderer(SDL_Handles &handles, v2i vpDims) handles.glContext = SDL_GL_CreateContext(handles.window); + // TODO: decide on extension library + gl3wInit(); +#if 0 // Initialize GLEW // glewExperimental is only needed in GLEW <= 1.13.0 // we can require version 2.0.0+ //glewExperimental = true; // Needed for core profile -#if 0 GLenum err = glewInit(); if (err != GLEW_OK) { LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n"; @@ -144,11 +152,6 @@ initRenderer(SDL_Handles &handles, v2i vpDims) } #endif -// TODO: remove for glew? -#if 1 - gl3wInit(); -#endif - LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n"; LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n"; LOG(INFO) << "opengl version: " << glGetString(GL_VERSION) << "\n"; @@ -169,8 +172,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims) // hide VRAM debug messages glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); + // TODO: check for errors when compiling shaders initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP"); initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP"); + initShaderProgram(g_debug_render_group, VERTEX_SHADER_CODE, DEBUG_FRAGMENT_SHADER_CODE, "MVP"); return true; } @@ -201,13 +206,13 @@ initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * fr glDeleteShader(vertex_shader_id); glDeleteShader(fragment_shader_id); + // TODO: check for errors when compiling shaders return true; } bool createScene(std::vector* hexes) { - //////////////////// // Model, View, Projection Matrices // left, right, bottom, top, zNear, zFar @@ -222,46 +227,26 @@ createScene(std::vector* hexes) g_scene_matrices.model = glm::mat4(1.0f); g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model; - - //////////////////// // Vertex Data // TODO: index duplicate vertices // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ int hex_count = (int) hexes->size(); - - gl_buffer *vertex_buffer = &g_filled_hex_render_group.vertex_buffer; - vertex_buffer->buffer_len = hex_count * 6 * 3 * 3; - vertex_buffer->buffer = (GLfloat*) std::calloc(vertex_buffer->buffer_len, sizeof(GLfloat)); - // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 - int buf_index = 54; + int vbuf_len = hex_count * 6 * 3 * 3; + GLfloat vbuf[vbuf_len]; for (int i = 0; i < hex_count; i++) - { - parseHexToGLBuffer(vertex_buffer->buffer, buf_index * i, (*hexes)[i]); - } - - glGenBuffers(1, &g_filled_hex_render_group.vertex_buffer.buffer_id); - glBindBuffer(GL_ARRAY_BUFFER, g_filled_hex_render_group.vertex_buffer.buffer_id); - glBufferData(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), vertex_buffer->buffer, GL_DYNAMIC_DRAW); - - if (!checkGLBufferSize(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__)) + fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]); + + if (!initGLBufferObject(&g_filled_hex_render_group.vertex_buffer, vbuf_len, GL_DYNAMIC_DRAW, vbuf)) return false; // color data for hex vertices - gl_buffer *color_buffer = &g_filled_hex_render_group.color_buffer; - color_buffer->buffer_len = vertex_buffer->buffer_len; - color_buffer->buffer = (GLfloat*) std::calloc(color_buffer->buffer_len, sizeof(GLfloat)); - - if (!fillColorBuffer(color_buffer->buffer, color_buffer->buffer_len, hexes)) - return false; + GLfloat cbuf[vbuf_len]; + fillColorBuffer(cbuf, vbuf_len, hexes); - glGenBuffers(1, &color_buffer->buffer_id); - glBindBuffer(GL_ARRAY_BUFFER, color_buffer->buffer_id); - glBufferData(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), color_buffer->buffer, GL_DYNAMIC_DRAW); - - if (!checkGLBufferSize(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), __LINE__)) + if (!initGLBufferObject(&g_filled_hex_render_group.color_buffer, vbuf_len, GL_DYNAMIC_DRAW, cbuf)) return false; // hex line vertex data @@ -270,51 +255,25 @@ createScene(std::vector* hexes) // and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements? // https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm - gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer; - line_vertex_buffer->buffer_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex - line_vertex_buffer->buffer = (GLfloat*) std::calloc(line_vertex_buffer->buffer_len, sizeof(GLfloat)); - - Point p1, p2; - int line_buf_idx = 0; - for (int i = 0; i < (int) hexes->size(); i++) - { - hex_info hxi = (*hexes)[i]; - for (int j = 0; j < 6; j ++) - { - if (j == 5) // wrap - { - p1 = hxi.vertices[j]; - p2 = hxi.vertices[0]; - } - else - { - p1 = hxi.vertices[j]; - p2 = hxi.vertices[j + 1]; - } - - line_vertex_buffer->buffer[line_buf_idx + 0] = p1.x; - line_vertex_buffer->buffer[line_buf_idx + 1] = p1.y; - line_vertex_buffer->buffer[line_buf_idx + 2] = 0.f; - line_vertex_buffer->buffer[line_buf_idx + 3] = p2.x; - line_vertex_buffer->buffer[line_buf_idx + 4] = p2.y; - line_vertex_buffer->buffer[line_buf_idx + 5] = 0.f; - - line_buf_idx += 6; - } - } - - glGenBuffers(1, &line_vertex_buffer->buffer_id); - glBindBuffer(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_id); - glBufferData(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), line_vertex_buffer->buffer, GL_STATIC_DRAW); + //gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer; + int line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex + GLfloat line_buf[line_buf_len]; + fillHexLineBuffer(line_buf, line_buf_len, hexes); + if (!initGLBufferObject(&g_hex_line_render_group.vertex_buffer, line_buf_len, GL_STATIC_DRAW, line_buf)) + return false; - if (!checkGLBufferSize(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__)) + // debug draw vertexes + + // 4 vertices, 3 floats per vertex + int len = 4 * 3; + if (!initGLBufferObject(&g_debug_render_group.vertex_buffer, len, GL_DYNAMIC_DRAW, 0)) return false; return true; } void -parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) +fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex) { // triangles for (int i = 0; i < 6; i++) @@ -359,28 +318,9 @@ parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) } } -bool -fillColorBuffer(GLfloat buf[], int len, std::vector *hexes) +void +fillColorBuffer(GLfloat buf[], int len, std::vector* hexes) { - if (!buf || len < 1) - { - LOG(ERROR) << "buffer length mismatch\n"; - return false; - } - - if (!hexes || hexes->size() == 0) - { - LOG(ERROR) << "hex_info input error\n"; - return false; - } - - // 3 floats per vertex, 3 vertexes per triangle, 6 triangles per hex - if (len != (int) hexes->size() * 3 * 3 * 6) - { - LOG(ERROR) << "hex_info input error\n"; - return false; - } - int buf_idx; int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6 for (int i = 0; i < (int) hexes->size(); i++) @@ -390,12 +330,40 @@ fillColorBuffer(GLfloat buf[], int len, std::vector *hexes) GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX; for (int j = 0; j < buf_len_per_hex; j++) - { buf[buf_idx + j] = color; - } } +} - return true; +void +fillHexLineBuffer(GLfloat buf[], int len, std::vector* hexes) +{ + Point p1, p2; + int idx = 0; + for (int i = 0; i < (int) hexes->size(); i++) + { + hex_info hxi = (*hexes)[i]; + for (int j = 0; j < 6; j ++) + { + if (j == 5) // wrap + { + p1 = hxi.vertices[j]; + p2 = hxi.vertices[0]; + } + else + { + p1 = hxi.vertices[j]; + p2 = hxi.vertices[j + 1]; + } + + buf[idx + 0] = p1.x; + buf[idx + 1] = p1.y; + buf[idx + 2] = 0.f; + buf[idx + 3] = p2.x; + buf[idx + 4] = p2.y; + buf[idx + 5] = 0.f; + idx += 6; + } + } } // NOTE: this will only work after a call to glBindBuffer @@ -414,6 +382,28 @@ checkGLBufferSize(GLenum buf_type, int expected_size, int line_num) return true; } +bool +initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]) +{ + buf_obj->buffer_len = (size_t) len; + buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); + + if (data) + { + for (int i = 0; i < len; i++) + buf_obj->buffer[i] = data[i]; + } + + glGenBuffers(1, &buf_obj->buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, buf_obj->buffer_id); + glBufferData(GL_ARRAY_BUFFER, len * sizeof(GLfloat), buf_obj->buffer, usage); + + if (!checkGLBufferSize(GL_ARRAY_BUFFER, len * sizeof(GLfloat), __LINE__)) + return false; + + return true; +} + void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) @@ -431,99 +421,117 @@ renderFrame(std::vector *hexes) glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - - // TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer - // https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object - gl_render_group* rg = &g_filled_hex_render_group; - glUseProgram(rg->program_id); - // Send our transformation to the currently bound shader, in the "g_MVP" uniform - glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - // 2nd attribute buffer : colors - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - // get new colors every frame - fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); - glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), rg->color_buffer.buffer); - - // draw - glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3); - - // cleanup - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - + // filled hexes + { + // TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer + // https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object + gl_render_group* rg = &g_filled_hex_render_group; + glUseProgram(rg->program_id); + // Send our transformation to the currently bound shader, in the "g_MVP" uniform + glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + // 2nd attribute buffer : colors + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + // get new colors every frame + fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); + glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), + rg->color_buffer.buffer); + // draw + glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3); + + // cleanup + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + } // hex lines + // TODO: conpress these calls into helper function + { + gl_render_group* rg = &g_hex_line_render_group; + glUseProgram(rg->program_id); + // Send our transformation to the currently bound shader, in the "g_MVP" uniform + glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); + + // 1st attribute buffer : vertices + GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0 + glEnableVertexAttribArray(attrib_index); + glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); + glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3); + glDisableVertexAttribArray(0); + } +} - rg = &g_hex_line_render_group; +void +renderDebug(hex_info *start_hex, hex_info *current_hex) +{ + if (!start_hex || !current_hex) + return; + + // fill vertex buffer + Point p1(start_hex->XPos, start_hex->YPos); + Point p2(current_hex->XPos, current_hex->YPos); + real64 angle = std::atan2(p2.y - p1.y, p2.x - p1.x); + real64 len = std::hypot(p2.y - p1.y, p2.x - p1.x); + real64 coneAngle = 24.5f * M_PI / 180; // M_PI is non-standard and may not be portable + + // TODO: add matrix math library for rotation transform? + // |x| | cos(a + b) -sin(a + b) 0 | + // |y| * | sin(a + b) cos(a + b) 0 | + // |0| | 0 0 1 | + // + real64 x1 = len * std::cos(angle); + real64 y1 = len * std::sin(angle); + // top of cone + real64 topX = x1 * std::cos(coneAngle) - y1 * std::sin(coneAngle) + p1.x; + real64 topY = x1 * std::sin(coneAngle) + y1 * std::cos(coneAngle) + p1.y; + // bottom of cone + real64 botX = x1 * std::cos(coneAngle) + y1 * std::sin(coneAngle) + p1.x; + real64 botY = x1 * std::sin(-1 * coneAngle) + y1 * std::cos(coneAngle) + p1.y; + // TODO: indexed line drawing + real64 buf[4 * 3] = { + p1.x, p1.y, 0, + botX, botY, 0, + p2.x, p2.y, 0, + topX, topY, 0, + }; + + // copy vertexes to render group + gl_render_group* rg = &g_debug_render_group; + for (int i = 0; i < 12; i++) + rg->vertex_buffer.buffer[i] = buf[i]; + + // TODO: conpress these calls into helper function glUseProgram(rg->program_id); // Send our transformation to the currently bound shader, in the "g_MVP" uniform glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); - // 1st attribute buffer : vertices - GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0 - glEnableVertexAttribArray(attrib_index); + glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); - glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3); -} - -#if 0 -// TODO: many globals used here -void -debugRender() -{ - if (globalDrawMode == CONE_FILL) - { - if (startHex && currentHex) - { - Point p1 = hex_to_pixel(global_layout, startHex->hex); - Point p2 = hex_to_pixel(global_layout, currentHex->hex); - - // NOTE: some cone drawing shenanigans - real32 angle = (real32) atan2(p2.y - p1.y, p2.x - p1.x); - real32 len = (real32) hypot(p2.y - p1.y, p2.x - p1.x); - real32 coneAngle = 24.5f * (real32) M_PI / 180; - - - // TODO: add matrix math library for rotation transform? - // |x| | cos(a + b) -sin(a + b) 0 | - // |y| * | sin(a + b) cos(a + b) 0 | - // |0| | 0 0 1 | - // - real32 x1 = len * cosf(angle); - real32 y1 = len * sinf(angle); - // top of cone - real32 topX = x1 * cosf(coneAngle) - y1 * sinf(coneAngle) + (real32) p1.x; - real32 topY = x1 * sinf(coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y; - // bottom of cone - real32 botX = x1 * cosf(coneAngle) + y1 * sinf(coneAngle) + (real32) p1.x; - real32 botY = x1 * sinf(-1 * coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y; - - glColor4f(1.0f, 1.0f, 0.5f, 1.0f); - glLineWidth(1.0f); - glBegin(GL_LINE_LOOP); - glVertex3d(p1.x, p1.y, 0); - glVertex3f(botX, botY, 0); - glVertex3d(p2.x, p2.y, 0); - glVertex3f(topX, topY, 0); - glEnd(); - } - } + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + // send new vertex data + glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat), + rg->vertex_buffer.buffer); + glDrawArrays(GL_LINE_LOOP, 0, rg->vertex_buffer.buffer_len / 3); + glDisableVertexAttribArray(0); } -#endif void freeBuffers() { - std::vector groups = {g_filled_hex_render_group, g_hex_line_render_group}; + std::vector groups = { + g_filled_hex_render_group, + g_hex_line_render_group, + g_debug_render_group + }; for (gl_render_group group : groups) {