diff --git a/src/.gdb_history b/src/.gdb_history new file mode 100644 index 0000000..bbc42a3 --- /dev/null +++ b/src/.gdb_history @@ -0,0 +1,18 @@ +new-ui mi /dev/pts/4 +break moveCamera +k +q +new-ui mi /dev/pts/6 +break moveCamera(bool, bool, bool, bool) +r +c +n +c +n +delete +set confirm off +break rotateCamera(int, int) +r +n +k +q diff --git a/src/Makefile b/src/Makefile index 17968cf..c7ad3f0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ CXX = g++ -CXXFLAGS = -std=c++11 -g -Wall -I/usr/include/SDL2 -I../ext/aixlog/include +CXXFLAGS = -std=c++11 -g -ggdb -Wall -I/usr/include/SDL2 -I../ext/aixlog/include # IMGUI IMGUI_DIR = ../ext/imgui diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 2123ea0..768b8b9 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -326,7 +326,7 @@ handleMouseUp(SDL_MouseButtonEvent &e) } bool -processSDLEvents(SDL_Handles &handles) +processSDLEvents() { SDL_Event e; bool run = true; @@ -337,6 +337,7 @@ processSDLEvents(SDL_Handles &handles) // 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); + game_state* g = g_game_state; switch (e.type) { @@ -344,26 +345,57 @@ processSDLEvents(SDL_Handles &handles) run = false; break; case SDL_KEYDOWN: - if ( e.key.keysym.sym == SDLK_ESCAPE) - run = false; + switch (e.key.keysym.sym) + { + case SDLK_ESCAPE: run = false; break; + case SDLK_e: g->is_moveup = true; break; + case SDLK_s: g->is_moveleft = true; break; + case SDLK_d: g->is_movedown = true; break; + case SDLK_f: g->is_moveright = true; break; + } + break; + case SDL_KEYUP: + switch (e.key.keysym.sym) + { + case SDLK_e: g->is_moveup = false; break; + case SDLK_s: g->is_moveleft = false; break; + case SDLK_d: g->is_movedown = false; break; + case SDLK_f: g->is_moveright = false; break; + } break; case SDL_MOUSEBUTTONDOWN: if (!gooey_wants) { - g_game_state->is_selecting = true; - handleMouseDown(e.button); + if (e.button.button == SDL_BUTTON_LEFT) + { + g->is_selecting = true; + handleMouseDown(e.button); + } + else if (e.button.button == SDL_BUTTON_RIGHT) + { + g->is_camera_rotate = true; + } } break; case SDL_MOUSEBUTTONUP: if (!gooey_wants) { - g_game_state->is_selecting = false; - handleMouseUp(e.button); + if (e.button.button == SDL_BUTTON_LEFT) + { + g->is_selecting = false; + handleMouseUp(e.button); + } + else if (e.button.button == SDL_BUTTON_RIGHT) + { + g->is_camera_rotate = false; + } } break; case SDL_MOUSEMOTION: - if (!gooey_wants && g_game_state->is_selecting) + if (!gooey_wants && g->is_selecting) handleMouseMove(e.motion); + else if(!gooey_wants && g->is_camera_rotate) + rotateCamera(e.motion.xrel, e.motion.yrel); break; default: break; @@ -470,15 +502,18 @@ int main(int argc, char* argv[]) } // main loop - while (processSDLEvents(handles)) + while (processSDLEvents()) { // 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) + game_state* g = g_game_state; + render_state* r = g_render_state; + moveCamera(g->is_moveup, g->is_moveleft, g->is_movedown, g->is_moveright); + renderFrame(g->hex_array); + if (r->is_debug_draw && g->draw_mode == CONE_FILL) renderDebug(g_polygon_select_vertices); - renderGooey(handles, g_game_state->draw_mode, g_render_state->is_debug_draw, - g_game_state->start_hex, g_game_state->current_hex, g_game_state->is_selecting); + renderGooey(handles, g->draw_mode, r->is_debug_draw, g->start_hex, + g->current_hex, g->is_selecting); SDL_GL_SwapWindow(handles.window); } diff --git a/src/hexgame.h b/src/hexgame.h index 2569963..a07d111 100644 --- a/src/hexgame.h +++ b/src/hexgame.h @@ -85,7 +85,12 @@ struct render_state struct game_state { - bool is_selecting; + bool is_selecting = false; + bool is_camera_rotate = false; + bool is_moveup = false; + bool is_moveleft = false; + bool is_movedown = false; + bool is_moveright = false; std::vector *hex_array; hex_info *start_hex; hex_info *current_hex; diff --git a/src/renderer.h b/src/renderer.h index d3c81f4..ec9e64b 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -12,6 +12,7 @@ #include #include +#include #include #include "hexlib.h" @@ -72,6 +73,20 @@ typedef struct gl_matrix_info glm::mat4 MVP; } gl_matrix_info; +enum projection_type +{ + PERSPECTIVE, + ORTHOGRAPHIC, +}; + +struct camera +{ + glm::vec3 position; + glm::vec3 forward; + glm::vec3 target; + glm::vec3 up; +}; + typedef struct gl_buffer { GLuint buffer_id; @@ -93,12 +108,15 @@ 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; +camera g_camera; // Interface bool initRenderer(SDL_Handles &handles, v2i vpDims); bool addTexture(SDL_Handles &handles, std::string path); bool createScene(std::vector* hexes); +void moveCamera(bool up, bool left, bool down, bool right); +void rotateCamera(int32 xrel, int32 yrel); void renderFrame(const std::vector *hexes); void renderDebug(std::vector &vertices); void freeBuffers(); @@ -116,6 +134,7 @@ 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[]); void drawRenderGroup(gl_render_group* rg, GLenum draw_mode, bool update_vertex_data); +void initMatrices(projection_type p); bool initRenderer(SDL_Handles &handles, v2i vpDims) @@ -161,10 +180,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims) // TODO: blending, these options break the http://www.opengl-tutorial.org tutorials atm // Setup render state: alpha-blending enabled, polygon fill -#if 0 +#if 1 glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_ONE, GL_SRC_ALPHA); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif @@ -241,22 +260,82 @@ initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * fr return true; } -bool -createScene(std::vector* hexes) +void +initMatrices(projection_type p) { - // Model, View, Projection Matrices - - // left, right, bottom, top, zNear, zFar - g_scene_matrices.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); - - g_scene_matrices.view = glm::lookAt( - glm::vec3(0.0f, 0.0f, 2.0f), // camera position - glm::vec3(0.0f, 0.0f, 0.0f), // look at position - glm::vec3(0,1,0) // "up" vector - ); + if (p == PERSPECTIVE) + { + g_scene_matrices.projection = glm::perspective( + glm::radians(45.f), // FoV + 16.f / 9.f, // ascpect ratio + 0.1f, // near clip plane + 1000.0f // far clip plane + ); + + g_camera.position = glm::vec3(640,0,100); + g_camera.target = glm::vec3(640,500,0); + g_camera.up = glm::vec3(0,1,0); + g_camera.forward = glm::normalize(g_camera.target - g_camera.position); + + glm::vec3 P, T, U; + P = normalize(g_camera.position); + T = normalize(g_camera.target); + U = normalize(g_camera.up); + //g_camera.forward = glm::cross(T - P, U); +#if 1 + glm::mat4 mV = glm::lookAt( + g_camera.position, // camera position + g_camera.target, // look at position + g_camera.up // "up" vector + ); + g_scene_matrices.view = mV; +#else + // get normalized vector from pos to target + glm::vec3 N = g_camera.target; + glm::normalize(N); + //glm::vec3 U = glm::vec3(0,1,0); + U = glm::cross(U, N); + glm::vec3 V = glm::cross(N, U); + glm::mat4 mR = glm::mat4(); + + mR[0][0] = U.x; mR[0][1] = U.y; mR[0][2] = U.z; mR[0][3] = 0.f; + mR[1][0] = V.x; mR[1][1] = V.y; mR[1][2] = V.z; mR[1][3] = 0.f; + mR[2][0] = N.x; mR[2][1] = N.y; mR[2][2] = N.z; mR[2][3] = 0.f; + mR[3][0] = 0.f; mR[3][1] = 0.f; mR[3][2] = 0.f; mR[3][3] = 1.f; + + // get translation xfrom + glm::vec3 p = g_camera.position; + glm::mat4 mT = glm::translate(glm::mat4(1.0f), glm::vec3(-1 * p.x, -1 * p.y, -1 * p.z)); + + glm::mat4 mVtemp = mR * mT; + //g_scene_matrices.view = mR * mT; +#endif + } + else // ORTHO + { + // left, right, bottom, top, zNear, zFar + g_scene_matrices.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); + g_scene_matrices.view = glm::lookAt( + glm::vec3(0.0f, 0.0f, 1.0f), // camera position + glm::vec3(0.0f, 0.0f, 0.0f), // look at position + glm::vec3(0,1,0) // "up" vector + ); + } g_scene_matrices.model = glm::mat4(1.0f); g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model; +} + +#if 0 +#define PROJ_TYPE ORTHOGRAPHIC +#else +#define PROJ_TYPE PERSPECTIVE +#endif + +bool +createScene(std::vector* hexes) +{ + initMatrices(PROJ_TYPE); // Vertex Data @@ -313,6 +392,64 @@ createScene(std::vector* hexes) return true; } +void +moveCamera(bool up, bool left, bool down, bool right) +{ + if (!up && !left && !down && !right) + return; + + glm::mat4 &m = g_scene_matrices.view; + float d = 5.f; // units per frame + +#if 0 + if (up) m = glm::translate(m, glm::vec3(0, -1 * d, 0)); + if (left) m = glm::translate(m, glm::vec3(d, 0, 0)); + if (down) m = glm::translate(m, glm::vec3(0, d, 0)); + if (right) m = glm::translate(m, glm::vec3(-1 * d, 0, 0)); +#endif + glm::vec3 f = g_camera.forward; + glm::vec3 u = g_camera.up; + glm::vec3 old = g_camera.position; + glm::vec3 &p = g_camera.position; + if (up) p += (f * d); + if (down) p -= (f * d); + if (left) + { + glm::vec3 l = glm::cross(u, f); + p += l * d; + } + if (right) + { + glm::vec3 r = glm::cross(f, u); + p += r * d; + } + + glm::vec3 diff = old - p; + m = glm::translate(m, diff); + g_scene_matrices.MVP = g_scene_matrices.projection * m * g_scene_matrices.model; +} + +void +rotateCamera(int32 xrel, int32 yrel) +{ +#if 1 + glm::mat4 &m = g_scene_matrices.view; + glm::vec3 &c = g_camera.position; + + m = glm::translate(m, glm::vec3(c.x, c.y, c.z)); + m = glm::rotate(m, glm::radians(0.5f * xrel), glm::vec3(0.f,0.f,1.f)); + m = glm::translate(m, glm::vec3(-1.f * c.x, -1.f * c.y, -1.f * c.z)); + g_scene_matrices.MVP = g_scene_matrices.projection * m * g_scene_matrices.model; +#else + glm::mat4 &m = g_scene_matrices.view; + glm::vec3 &c = g_camera.position; + + m = glm::translate(m, glm::vec3(-1.f * c.x, -1.f * c.y, -1.f * c.z)); + m = glm::rotate(m, glm::radians(0.5f * xrel), glm::vec3(0.f,0.f,1.f)); + g_scene_matrices.MVP = g_scene_matrices.projection * m * g_scene_matrices.model; +#endif +} + void fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex) {