diff --git a/src/camera.cpp b/src/camera.cpp index c21411b..7b50a0a 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -1,6 +1,11 @@ +#include + #include "camera.h" +#define MOVE_SPEED 5.f +#define ROTATE_SPEED 0.005f +#define CAMERA_Z_CLAMP_ANGLE 85.f void cameraInitPerspective(camera& cam, glm::vec3 position, glm::vec3 target, glm::vec3 up) @@ -27,3 +32,114 @@ cameraInitPerspective(camera& cam, glm::vec3 position, glm::vec3 target, glm::ve cam.model = glm::mat4(1.0f); cam.MVP = cam.projection * cam.view * cam.model; } + +void +cameraInitOrthographic(/*camera& cam, */) +{ +#if 0 + // left, right, bottom, top, zNear, zFar + cam.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); + cam.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 + ); + + cam.model = glm::mat4(1.0f); + cam.MVP = cam.projection * cam.view * cam.model; +#endif +} + +v2f +cameraUnproject(camera& cam, int x, int y, int vp_width, int vp_height) +{ + // NOTE: using depth buffer may not be as accurate as doing ray-cast + GLfloat depth; + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); + glm::vec4 viewport = glm::vec4(0, 0, vp_width, vp_height); + glm::vec3 wincoord = glm::vec3(x, y, depth); + glm::vec3 vU = glm::unProject(wincoord, cam.view, cam.projection, viewport); + v2f v(vU.x, vU.y); + + return v; +} + +void +cameraMove(camera& cam, bool up, bool left, bool down, bool right, bool forward, bool backward) +{ + if (!up && !left && !down && !right && !forward && !backward) + return; + + glm::vec3 f = cam.forward; + glm::vec3 u = cam.up; + glm::vec3 old = cam.position; + glm::vec3 &p = cam.position; + glm::vec3 v(0.f); // normalized direction + + // TODO: still seems like we're adding magnitude when moving in 2 directions +#if 0 + if (forward) v = glm::normalize(v + f); + if (backward) v = glm::normalize(v - f); + if (up) v = glm::normalize(v + u); + if (down) v = glm::normalize(v - u); + if (left) v -= glm::normalize(glm::cross(f, u)); + if (right) v -= glm::normalize(glm::cross(u, f)); +#else + if (forward) v += f; + if (backward) v -= f; + if (up) v += u; + if (down) v -= u; + if (left) v -= glm::cross(f, u); + if (right) v -= glm::cross(u, f); +#endif + + p += (v * MOVE_SPEED); + glm::vec3 diff = old - p; + cam.view = glm::translate(cam.view, diff); + cam.MVP = cam.projection * cam.view * cam.model; +} + +void +cameraRotate(camera& cam, int32 xrel, int32 yrel) +{ + float &h = cam.hAngle; + float &v = cam.vAngle; + h += ROTATE_SPEED * xrel; + v -= ROTATE_SPEED * yrel; + + // clamp vAngle to prevent gimbal lock + float a = glm::radians(CAMERA_Z_CLAMP_ANGLE); + if (v < (-1 * a)) v = (-1 * a); + if (v > a) v = a; + + cam.forward = glm::vec3( + glm::cos(v) * glm::sin(h), + glm::cos(v) * glm::cos(h), + glm::sin(v) + ); + + glm::normalize(cam.forward); + cam.up = glm::vec3(0,0,1); + cam.left = glm::normalize(glm::cross(cam.forward, cam.up)); + cam.up = glm::normalize(glm::cross(cam.left, cam.forward)); + + cam.view = glm::lookAt(cam.position, cam.position + cam.forward, cam.up); + cam.MVP = cam.projection * cam.view * cam.model; +} + +void +cameraRoll(camera& cam, bool CW, bool CCW) +{ + if ((!CW && !CCW) || (CW && CCW)) + return; + + float a = 0.005f; + if (CW) a *= 1; + if (CCW) a *= -1; + glm::mat4 m = glm::rotate(glm::mat4(1.f), a, cam.forward); + glm::vec4 v(cam.up.x, cam.up.y, cam.up.z, 0); + v = v * m; + cam.up = glm::vec3(v.x, v.y, v.z); + cam.view *= m; + cam.MVP = cam.projection * cam.view * cam.model; +} diff --git a/src/camera.h b/src/camera.h index d018e8b..004dd70 100644 --- a/src/camera.h +++ b/src/camera.h @@ -5,7 +5,6 @@ #include "util.h" // TODO: move other camera functions here from renderer.h and pass in camera references -// TODO: store scene matrices on camera struct instead of global in renderer.h // TODO: add these props to scene json @@ -36,7 +35,8 @@ enum projection_type }; +v2f cameraUnproject(camera& cam, int x, int y, int vp_width, int vp_height); void cameraInitPerspective(camera& cam, glm::vec3 position, glm::vec3 target, glm::vec3 up); -void cameraMove(bool up, bool left, bool down, bool right, bool forward, bool backward); -void CameraRotate(int32 xrel, int32 yrel); -void cameraRoll(bool CW, bool CCW); +void cameraMove(camera& cam, bool up, bool left, bool down, bool right, bool forward, bool backward); +void cameraRotate(camera& cam, int32 xrel, int32 yrel); +void cameraRoll(camera& cam, bool CW, bool CCW); diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 2af2e5d..07719fa 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -99,7 +99,7 @@ hex_info * getSingleHex(int32 x, int32 y) { v2i dims = g_render_state->viewport_dims; - v2f v = getUnprojectedCoords(x, y, dims.x, dims.y); + v2f v = cameraUnproject(g_render_state->cam, x, y, dims.x, dims.y); Point p(v.x, v.y); Hex h = hex_round(pixel_to_hex(g_game_state->grid.hexlib_layout, p)); @@ -417,7 +417,7 @@ processSDLEvents() if (!gooey_wants && g->grid.is_selecting) handleMouseMove(e.motion); else if(!gooey_wants && g->is_camera_rotate) - rotateCamera(e.motion.xrel, e.motion.yrel); + cameraRotate(g_render_state->cam, e.motion.xrel, e.motion.yrel); break; default: break; @@ -536,7 +536,7 @@ int main(int argc, char* argv[]) return 1; } - slParseCamera(sd, renGetCamera()); + slParseCamera(sd, rs->cam); slParseHexGrid(sd, g->grid); if (!slParseLights(sd, rs->lights, rs->num_lights, rs->max_lights)) { @@ -578,7 +578,7 @@ int main(int argc, char* argv[]) 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, + cameraMove(r->cam, g->is_moveup, g->is_moveleft, g->is_movedown, g->is_moveright, g->is_moveforward, g->is_movebackward); renderFrame(r, g->grid.hex_array, g->entities, g->entity_count); @@ -586,9 +586,9 @@ int main(int argc, char* argv[]) if (r->is_debug_draw && g->grid.draw_mode == CONE_FILL) renderDebug(r, g_polygon_select_vertices); - renderGooey(g_render_state->handles, &g->grid, r->is_debug_draw, &renGetCamera()); + renderGooey(r->handles, &g->grid, r->is_debug_draw, &r->cam); - SDL_GL_SwapWindow(g_render_state->handles.window); + SDL_GL_SwapWindow(r->handles.window); // TODO: test SDL_Delay on Win32 //platform_wait_for_vblank(VSYNC_ENABLED); diff --git a/src/renderer.cpp b/src/renderer.cpp index 1be80d4..a5013e3 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -20,11 +20,6 @@ #include "renderer.h" #include "render_group.h" -#define MOVE_SPEED 5.f -#define ROTATE_SPEED 0.005f -#define CAMERA_Z_CLAMP_ANGLE 85.f -//#define PROJ_TYPE ORTHOGRAPHIC -#define PROJ_TYPE PERSPECTIVE #define DEFAULT_VERTEX_SHADER_FILE "../data/default.vs" #define DEFAULT_FRAGMENT_SHADER_FILE "../data/default.fs" #define MAX_LIGHTS 10 // NOTE: needs to match the fragment shader source @@ -185,26 +180,6 @@ addTexture(SDL_Handles &handles, const char * path) return true; } -camera& -renGetCamera() -{ - return g_render_state->cam; -} - -v2f -getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height) -{ - // NOTE: using depth buffer may not be as accurate as doing ray-cast - GLfloat depth; - glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); - glm::vec4 viewport = glm::vec4(0, 0, vp_width, vp_height); - glm::vec3 wincoord = glm::vec3(x, y, depth); - glm::vec3 vU = glm::unProject(wincoord, g_render_state->cam.view, g_render_state->cam.projection, viewport); - v2f v(vU.x, vU.y); - - return v; -} - bool createScene(render_state* rs, std::vector* hexes, Entity* entities, uint32 entity_count) { @@ -215,9 +190,6 @@ createScene(render_state* rs, std::vector* hexes, Entity* entities, ui entities[i].ren_group->shader = g_default_shader; } - // TODO: rename/alter this now that we init camera in sceneloader - initMatrices(PROJ_TYPE); - if (!initHexGridBuffers(hexes)) return false; @@ -250,91 +222,6 @@ createScene(render_state* rs, std::vector* hexes, Entity* entities, ui return true; } -void -moveCamera(bool up, bool left, bool down, bool right, bool forward, bool backward) -{ - if (!up && !left && !down && !right && !forward && !backward) - return; - - glm::vec3 f = g_render_state->cam.forward; - glm::vec3 u = g_render_state->cam.up; - glm::vec3 old = g_render_state->cam.position; - glm::vec3 &p = g_render_state->cam.position; - glm::vec3 v(0.f); // normalized direction - - // TODO: still seems like we're adding magnitude when moving in 2 directions -#if 0 - if (forward) v = glm::normalize(v + f); - if (backward) v = glm::normalize(v - f); - if (up) v = glm::normalize(v + u); - if (down) v = glm::normalize(v - u); - if (left) v -= glm::normalize(glm::cross(f, u)); - if (right) v -= glm::normalize(glm::cross(u, f)); -#else - if (forward) v += f; - if (backward) v -= f; - if (up) v += u; - if (down) v -= u; - if (left) v -= glm::cross(f, u); - if (right) v -= glm::cross(u, f); -#endif - - p += (v * MOVE_SPEED); - glm::vec3 diff = old - p; - g_render_state->cam.view = glm::translate(g_render_state->cam.view, diff); - g_render_state->cam.MVP = g_render_state->cam.projection * g_render_state->cam.view * g_render_state->cam.model; -} - -void -rotateCamera(int32 xrel, int32 yrel) -{ - camera &c = g_render_state->cam; - float &h = c.hAngle; - float &v = c.vAngle; - h += ROTATE_SPEED * xrel; - v -= ROTATE_SPEED * yrel; - - // clamp vAngle to prevent gimbal lock - float a = glm::radians(CAMERA_Z_CLAMP_ANGLE); - if (v < (-1 * a)) v = (-1 * a); - if (v > a) v = a; - - c.forward = glm::vec3( - glm::cos(v) * glm::sin(h), - glm::cos(v) * glm::cos(h), - glm::sin(v) - ); - - glm::normalize(c.forward); - c.up = glm::vec3(0,0,1); - c.left = glm::normalize(glm::cross(c.forward, c.up)); - c.up = glm::normalize(glm::cross(c.left, c.forward)); - - g_render_state->cam.view = glm::lookAt(c.position, c.position + c.forward, c.up); - g_render_state->cam.MVP = g_render_state->cam.projection * g_render_state->cam.view * g_render_state->cam.model; -} - -// NOTE: don't need this yet -void -rollCamera(bool CW, bool CCW) -{ -#if 0 - if ((!CW && !CCW) || (CW && CCW)) - return; - - float a = 0.005f; - if (CW) a *= 1; - if (CCW) a *= -1; - camera &c = g_render_state->cam; - glm::mat4 m = glm::rotate(glm::mat4(1.f), a, c.forward); - glm::vec4 v(c.up.x, c.up.y, c.up.z, 0); - v = v * m; - g_render_state->cam.up = glm::vec3(v.x, v.y, v.z); - g_render_state->cam.view *= m; - g_render_state->cam.MVP = g_render_state->cam.projection * g_render_state->cam.view * g_render_state->cam.model; -#endif -} - void renderFrame(render_state* rs, std::vector *hexes, Entity* entities, uint32 entity_count) { @@ -382,33 +269,6 @@ renderDebug(render_state* rs, std::vector &vertices) // internal -void -initMatrices(projection_type p) -{ - // TODO: many constants used here should be passed as args - - if (p == PERSPECTIVE) - { - g_render_state->cam.projection = g_render_state->cam.projection; - g_render_state->cam.view = g_render_state->cam.view; - //g_render_state->cam.model = g_render_state->cam.model; - //g_render_state->cam.MVP = g_render_state->cam.MVP; - } - else // ORTHO - { - // left, right, bottom, top, zNear, zFar - g_render_state->cam.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); - g_render_state->cam.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_render_state->cam.model = glm::mat4(1.0f); - g_render_state->cam.MVP = g_render_state->cam.projection * g_render_state->cam.view * g_render_state->cam.model; -} - void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) diff --git a/src/renderer.h b/src/renderer.h index e6ddfcf..bfcb168 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -42,12 +42,8 @@ struct render_state bool initRenderer(render_state* rs); void freeBuffers(render_state* rs); bool addTexture(SDL_Handles &handles, const char * path); -camera& renGetCamera(); v2f getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height); bool createScene(render_state* rs, std::vector* hexes, Entity* entities, uint32 entity_count); -void moveCamera(bool up, bool left, bool down, bool right, bool forward, bool backward); -void rollCamera(bool CW, bool CCW); -void rotateCamera(int32 xrel, int32 yrel); void renderFrame(render_state* rs, std::vector *hexes, Entity* entities, uint32 entity_count); void renderDebug(render_state* rs, std::vector &vertices);