#include "cgp/cgp.hpp" // Give access to the complete CGP library #include "environment.hpp" // The general scene environment + project variable #include <iostream> // Custom scene of this code #include "scene.hpp" // *************************** // // Custom Scene defined in "scene.hpp" // *************************** // scene_structure scene; // The rest of this code is a generic initialization and animation loop that can be applied to different scenes // *************************** // // Start of the program // *************************** // window_structure standard_window_initialization(int width = 0, int height = 0); void initialize_default_shaders(); void animation_loop(); timer_fps fps_record; int main(int, char* argv[]) { std::cout << "Run " << argv[0] << std::endl; // ************************ // // INITIALISATION // ************************ // // Standard Initialization of an OpenGL ready window scene.window = standard_window_initialization(); // Initialize System Info project::path = cgp::project_path_find(argv[0], "shaders/"); // Initialize default shaders initialize_default_shaders(); // Custom scene initialization std::cout << "Initialize data of the scene ..." << std::endl; scene.initialize(); std::cout << "Initialization finished\n" << std::endl; // ************************ // // Animation Loop // ************************ // std::cout << "Start animation loop ..." << std::endl; fps_record.start(); // Call the main display loop in the function animation_loop // The following part is simply a loop that call the function "animation_loop" // (This call is different when we compile in standard mode with GLFW, than when we compile with emscripten to output the result in a webpage.) #ifndef __EMSCRIPTEN__ // Default mode to run the animation/display loop with GLFW in C++ while (!glfwWindowShouldClose(scene.window.glfw_window)) { animation_loop(); } #else // Specific loop if compiled for EMScripten emscripten_set_main_loop(animation_loop, 0, 1); #endif std::cout << "\nAnimation loop stopped" << std::endl; // Cleanup cgp::imgui_cleanup(); glfwDestroyWindow(scene.window.glfw_window); glfwTerminate(); return 0; } void animation_loop() { emscripten_update_window_size(scene.window.width, scene.window.height); // update window size in case of use of emscripten (not used by default) scene.camera_projection.aspect_ratio = scene.window.aspect_ratio(); scene.environment.camera_projection = scene.camera_projection.matrix(); glViewport(0, 0, scene.window.width, scene.window.height); vec3 const& background_color = scene.environment.background_color; glClearColor(background_color.x, background_color.y, background_color.z, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); float const time_interval = fps_record.update(); if (fps_record.event) { std::string const title = "CGP Display - " + str(fps_record.fps) + " fps"; glfwSetWindowTitle(scene.window.glfw_window, title.c_str()); } imgui_create_frame(); ImGui::GetIO().FontGlobalScale = project::gui_scale; ImGui::Begin("GUI", NULL, ImGuiWindowFlags_AlwaysAutoResize); scene.inputs.mouse.on_gui = ImGui::GetIO().WantCaptureMouse; scene.inputs.time_interval = time_interval; // Display the ImGUI interface (button, sliders, etc) scene.display_gui(); // Handle camera behavior in standard frame scene.idle_frame(); // Call the display of the scene scene.display_frame(); // End of ImGui display and handle GLFW events ImGui::End(); imgui_render_frame(scene.window.glfw_window); glfwSwapBuffers(scene.window.glfw_window); glfwPollEvents(); } void initialize_default_shaders() { // Generate the default directory from which the shaders are found // By default, it should be "shaders/" std::string default_path_shaders = project::path +"shaders/"; // Set standard mesh shader for mesh_drawable mesh_drawable::default_shader.load(default_path_shaders +"mesh/vert.glsl", default_path_shaders +"mesh/frag.glsl"); triangles_drawable::default_shader.load(default_path_shaders +"mesh/vert.glsl", default_path_shaders +"mesh/frag.glsl"); // Set default white texture image_structure const white_image = image_structure{ 1,1,image_color_type::rgba,{255,255,255,255} }; mesh_drawable::default_texture.initialize_texture_2d_on_gpu(white_image); triangles_drawable::default_texture.initialize_texture_2d_on_gpu(white_image); // Set standard uniform color for curve/segment_drawable curve_drawable::default_shader.load(default_path_shaders +"single_color/vert.glsl", default_path_shaders+"single_color/frag.glsl"); } //Callback functions void window_size_callback(GLFWwindow* window, int width, int height); void mouse_move_callback(GLFWwindow* window, double xpos, double ypos); void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset); void mouse_click_callback(GLFWwindow* window, int button, int action, int mods); void keyboard_callback(GLFWwindow* window, int key, int, int action, int mods); // Standard initialization procedure window_structure standard_window_initialization(int width_target, int height_target) { // Create the window using GLFW // ***************************************************** // window_structure window; window.initialize(width_target, height_target, "CGP Display", CGP_OPENGL_VERSION_MAJOR, CGP_OPENGL_VERSION_MINOR); // Display information // ***************************************************** // // Display window size std::cout << "\nWindow (" << window.width << "px x " << window.height << "px) created" << std::endl; std::cout << "Monitor: " << glfwGetMonitorName(window.monitor) << " - Resolution (" << window.screen_resolution_width << "x" << window.screen_resolution_height << ")\n" << std::endl; // Display debug information on command line std::cout << "OpenGL Information:" << std::endl; std::cout << cgp::opengl_info_display() << std::endl; // Initialize ImGUI // ***************************************************** // cgp::imgui_init(window.glfw_window); // Set the callback functions for the inputs glfwSetMouseButtonCallback(window.glfw_window, mouse_click_callback); // Event called when a button of the mouse is clicked/released glfwSetCursorPosCallback(window.glfw_window, mouse_move_callback); // Event called when the mouse is moved glfwSetWindowSizeCallback(window.glfw_window, window_size_callback); // Event called when the window is rescaled glfwSetKeyCallback(window.glfw_window, keyboard_callback); // Event called when a keyboard touch is pressed/released glfwSetScrollCallback(window.glfw_window, mouse_scroll_callback); // Event called when scrolling the mouse return window; } // This function is called everytime the window is resized void window_size_callback(GLFWwindow*, int width, int height) { scene.window.width = width; scene.window.height = height; } // This function is called everytime the mouse is moved void mouse_move_callback(GLFWwindow* /*window*/, double xpos, double ypos) { vec2 const pos_relative = scene.window.convert_pixel_to_relative_coordinates({ xpos, ypos }); scene.inputs.mouse.position.update(pos_relative); scene.mouse_move_event(); } // This function is called everytime a mouse button is clicked/released void mouse_click_callback(GLFWwindow* window, int button, int action, int mods) { ImGui_ImplGlfw_MouseButtonCallback(window, button, action, mods); scene.inputs.mouse.click.update_from_glfw_click(button, action); scene.mouse_click_event(); } // This function is called everytime the mouse is scrolled void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { ImGui_ImplGlfw_ScrollCallback(window, xoffset, yoffset); scene.inputs.mouse.scroll = yoffset; scene.mouse_scroll_event(); } // This function is called everytime a keyboard touch is pressed/released void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { ImGui_ImplGlfw_KeyCallback(window, key, scancode, action, mods); bool imgui_capture_keyboard = ImGui::GetIO().WantCaptureKeyboard; if(!imgui_capture_keyboard){ scene.inputs.keyboard.update_from_glfw_key(key, action); scene.keyboard_event(); // Press 'F' for full screen mode if (key == GLFW_KEY_F && action == GLFW_PRESS && scene.inputs.keyboard.shift) { scene.window.is_full_screen = !scene.window.is_full_screen; if (scene.window.is_full_screen) scene.window.set_full_screen(); else scene.window.set_windowed_screen(); } // Press 'V' for camera frame/view matrix debug if (key == GLFW_KEY_V && action == GLFW_PRESS && scene.inputs.keyboard.shift) { auto const camera_model = scene.camera_control.camera_model; std::cout << "\nDebug camera (position = " << str(camera_model.position()) << "):\n" << std::endl; std::cout << " Frame matrix:" << std::endl; std::cout << str_pretty(camera_model.matrix_frame()) << std::endl; std::cout << " View matrix:" << std::endl; std::cout << str_pretty(camera_model.matrix_view()) << std::endl; } } }