diff --git a/src/main.cc b/src/main.cc index b692f98..a55dbff 100644 --- a/src/main.cc +++ b/src/main.cc @@ -52,13 +52,23 @@ struct Camera { // pitch, yaw glm::vec2 rotation; + + // View matrix to be sent as uniform to the vertex shader + glm::mat4 view_mat; + GLint u_view_idx; + + // Projection matrix to be sent as uniform to the vertex shader + glm::mat4 projection_mat; + GLint u_projection_idx; }; -struct App { - SDL_Window *window; - SDL_GLContext context; - SDL_Event event; +struct Transform { + glm::mat4 translation; + glm::mat4 rotation; + glm::mat4 scale; +}; +struct Mesh { // VAO is an object that stores the state needed to supply the GPU with the vertex data. // Think of it as a specification or a C struct that defines the types of data stored for the // vertex array including the attributes for each vertex as well the indices buffer if it exists. @@ -76,34 +86,31 @@ struct App { GLuint ebo; GLuint shader_program; +}; - Camera camera; - - float speed; - glm::mat4 translation; - glm::mat4 rotation; - glm::mat4 scale; +struct Model { + Transform transform; + Mesh mesh; // Model matrix to be sent as uniform to the vertex shader - glm::mat4 model_mat; - GLint u_model_idx; - - // View matrix to be sent as uniform to the vertex shader - glm::mat4 view_mat; - GLint u_view_idx; - - // Projection matrix to be sent as uniform to the vertex shader - glm::mat4 projection_mat; - GLint u_projection_idx; + glm::mat4 model_mat; + GLint u_model_idx; +}; +struct App { + SDL_Window *window; + SDL_GLContext context; + SDL_Event event; + Model model; + Camera camera; + float speed; glm::vec2 prev_mouse; - bool running; }; int init (App &app); -void create_vertex_spec (App &app); -void create_graphics_pipeline (App &app); +void create_vertex_spec (Model &model); +void create_graphics_pipeline (Model &model, Camera &camera); void run_main_loop (App &app); void cleanup (App &app); GLuint create_shader_program (const std::string &vertex_shader_source, const std::string &fragment_shader_source); @@ -121,10 +128,10 @@ int main() { } // Setup the geometry - create_vertex_spec(app); + create_vertex_spec(app.model); // Setup graphics pipeline. At the very minimum creating vertex and fragment shaders - create_graphics_pipeline(app); + create_graphics_pipeline(app.model, app.camera); run_main_loop(app); @@ -175,27 +182,27 @@ int init(App &app) { glGetString(GL_SHADING_LANGUAGE_VERSION) ); - app.speed = 0.04f; - app.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 1.5f)); - app.rotation = glm::mat4(1.0f); - app.scale = glm::mat4(1.0f); - app.camera.rotation = glm::vec2(0.0f, -90.0f); - app.camera.position = glm::vec3(0.0f, 0.0f, 3.0f); - app.camera.view_direction = rotation_to_view_direction(app.camera); - app.camera.up = glm::vec3(0.0f, 1.0f, 0.0f); - app.model_mat = app.translation * app.rotation * app.scale; - app.view_mat = glm::lookAt(app.camera.position, app.camera.position + app.camera.view_direction, app.camera.up); - app.projection_mat = glm::perspective(glm::radians(60.0f), - (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, - 0.1f, - 20.0f - ); - app.prev_mouse = glm::vec2(WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT); + app.speed = 0.04f; + app.model.transform.translation = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 1.5f)); + app.model.transform.rotation = glm::mat4(1.0f); + app.model.transform.scale = glm::mat4(1.0f); + app.camera.rotation = glm::vec2(0.0f, -90.0f); + app.camera.position = glm::vec3(0.0f, 0.0f, 3.0f); + app.camera.view_direction = rotation_to_view_direction(app.camera); + app.camera.up = glm::vec3(0.0f, 1.0f, 0.0f); + app.model.model_mat = app.model.transform.translation * + app.model.transform.rotation * app.model.transform.scale; + app.camera.view_mat = glm::lookAt(app.camera.position, app.camera.position + app.camera.view_direction, app.camera.up); + app.camera.projection_mat = glm::perspective(glm::radians(60.0f), + (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, + 0.1f, + 20.0f); + app.prev_mouse = glm::vec2(WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT); return EXIT_CODE_SUCCESS; } -void create_vertex_spec(App &app) { +void create_vertex_spec(Model &model) { const std::vector vertices = { // vert0 -0.5f, -0.5f, 0.0f, // position @@ -219,12 +226,12 @@ void create_vertex_spec(App &app) { }; // Create and activate the VAO - glGenVertexArrays(1, &app.vao); - glBindVertexArray(app.vao); + glGenVertexArrays(1, &model.mesh.vao); + glBindVertexArray(model.mesh.vao); // Create and set up the VBO - glGenBuffers(1, &app.vbo); - glBindBuffer(GL_ARRAY_BUFFER, app.vbo); + glGenBuffers(1, &model.mesh.vbo); + glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), (void *)vertices.data(), @@ -232,8 +239,8 @@ void create_vertex_spec(App &app) { ); // Create and set up the EBO - glGenBuffers(1, &app.ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, app.ebo); + glGenBuffers(1, &model.mesh.ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.mesh.ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), (void *)indices.data(), @@ -265,27 +272,28 @@ void create_vertex_spec(App &app) { glDisableVertexAttribArray(1); } -void create_graphics_pipeline(App &app) { +void create_graphics_pipeline(Model &model, Camera &camera) { const std::string vs_source = load_shader("shaders/vert.glsl"); const std::string fs_source = load_shader("shaders/frag.glsl"); - app.shader_program = create_shader_program(vs_source, fs_source); + model.mesh.shader_program = create_shader_program(vs_source, fs_source); const char *u_model = "u_model"; - app.u_model_idx = glGetUniformLocation(app.shader_program, u_model); - if (app.u_model_idx < 0) { + model.u_model_idx = glGetUniformLocation(model.mesh.shader_program, u_model); + if (model.u_model_idx < 0) { printf("Failed to find uniform %s\n", u_model); } + // TODO (Abdelrahman): Finding the camera matrices uniforms shouldn't be handled here const char *u_view = "u_view"; - app.u_view_idx = glGetUniformLocation(app.shader_program, u_view); - if (app.u_view_idx < 0) { + camera.u_view_idx = glGetUniformLocation(model.mesh.shader_program, u_view); + if (camera.u_view_idx < 0) { printf("Failed to find uniform %s\n", u_view); } const char *u_projection = "u_projection"; - app.u_projection_idx = glGetUniformLocation(app.shader_program, u_projection); - if (app.u_projection_idx < 0) { + camera.u_projection_idx = glGetUniformLocation(model.mesh.shader_program, u_projection); + if (camera.u_projection_idx < 0) { printf("Failed to find uniform %s\n", u_projection); } } @@ -321,20 +329,20 @@ void run_main_loop(App &app) { glClearColor(0.36f, 0.34f, 0.42f, 1.0f); glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - glUseProgram(app.shader_program); - if (app.u_model_idx >= 0) { - glUniformMatrix4fv(app.u_model_idx, 1, GL_FALSE, glm::value_ptr(app.model_mat)); + glUseProgram(app.model.mesh.shader_program); + if (app.model.u_model_idx >= 0) { + glUniformMatrix4fv(app.model.u_model_idx, 1, GL_FALSE, glm::value_ptr(app.model.model_mat)); } - if (app.u_view_idx >= 0) { - glUniformMatrix4fv(app.u_view_idx, 1, GL_FALSE, glm::value_ptr(app.view_mat)); + if (app.camera.u_view_idx >= 0) { + glUniformMatrix4fv(app.camera.u_view_idx, 1, GL_FALSE, glm::value_ptr(app.camera.view_mat)); } - if (app.u_projection_idx >= 0) { - glUniformMatrix4fv(app.u_projection_idx, 1, GL_FALSE, glm::value_ptr(app.projection_mat)); + if (app.camera.u_projection_idx >= 0) { + glUniformMatrix4fv(app.camera.u_projection_idx, 1, GL_FALSE, glm::value_ptr(app.camera.projection_mat)); } // End pre draw setup // Draw call - glBindVertexArray(app.vao); + glBindVertexArray(app.model.mesh.vao); glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)0); // End draw call @@ -418,37 +426,44 @@ std::string load_shader(const std::string &filepath) { return output; } +// Example of moving an object void handle_object_movement(App &app) { switch (app.event.key.keysym.sym) { case SDLK_w: - app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, app.speed)); + app.model.transform.translation = glm::translate(app.model.transform.translation, + glm::vec3(0.0f, 0.0f, app.speed)); break; case SDLK_s: - app.translation = glm::translate(app.translation, glm::vec3(0.0f, 0.0f, -app.speed)); + app.model.transform.translation = glm::translate(app.model.transform.translation, + glm::vec3(0.0f, 0.0f, -app.speed)); break; case SDLK_d: - app.translation = glm::translate(app.translation, glm::vec3(app.speed, 0.0f, 0.0f)); + app.model.transform.translation = glm::translate(app.model.transform.translation, + glm::vec3(app.speed, 0.0f, 0.0f)); break; case SDLK_a: - app.translation = glm::translate(app.translation, glm::vec3(-app.speed, 0.0f, 0.0f)); + app.model.transform.translation = glm::translate(app.model.transform.translation, + glm::vec3(-app.speed, 0.0f, 0.0f)); break; case SDLK_RIGHT: - app.rotation = glm::rotate(app.rotation, glm::radians(10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + app.model.transform.rotation = glm::rotate(app.model.transform.rotation, + glm::radians(10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; case SDLK_LEFT: - app.rotation = glm::rotate(app.rotation, glm::radians(-10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + app.model.transform.rotation = glm::rotate(app.model.transform.rotation, + glm::radians(-10.0f), glm::vec3(0.0f, 1.0f, 0.0f)); break; case SDLK_r: - app.scale = glm::scale(app.scale, glm::vec3(1.2f)); + app.model.transform.scale = glm::scale(app.model.transform.scale, glm::vec3(1.2f)); break; case SDLK_e: - app.scale = glm::scale(app.scale, glm::vec3(0.8f)); + app.model.transform.scale = glm::scale(app.model.transform.scale, glm::vec3(0.8f)); break; default: return; } - app.model_mat = app.translation * app.rotation * app.scale; + app.model.model_mat = app.model.transform.translation * app.model.transform.rotation * app.model.transform.scale; } void handle_camera_movement(App &app) { @@ -477,7 +492,7 @@ void handle_camera_movement(App &app) { } } - app.view_mat = glm::lookAt(app.camera.position, app.camera.position + app.camera.view_direction, app.camera.up); + app.camera.view_mat = glm::lookAt(app.camera.position, app.camera.position + app.camera.view_direction, app.camera.up); } glm::vec3 rotation_to_view_direction(const Camera &camera) {