#include "simulation_state.h" #include "rendering/renderer.h" #include "core/application.h" #include "core/window.h" #include "core/event.h" #include #include namespace Donut { void SimulationState::on_enter() { DONUT_INFO("Entering Simulation State"); m_initialized = true; } void SimulationState::on_exit() { DONUT_INFO("Exiting Simulation State"); } void SimulationState::on_update(float delta_time) { m_engine.update_performance(delta_time); m_engine.update_window_dimensions(); m_engine.update_physics(delta_time); if (m_engine.get_camera().is_dragging()) { GLFWwindow* window = static_cast(Application::get().get_window().get_native_window()); double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); m_engine.get_camera().process_orbital_mouse_move(xpos, ypos); } } void SimulationState::on_render() { RenderCommand::set_clear_color(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); RenderCommand::clear(); RenderCommand::set_viewport(0, 0, m_engine.get_width(), m_engine.get_height()); m_engine.dispatch_compute(m_engine.get_camera()); m_engine.draw_full_screen_quad(); } void SimulationState::on_event(Event& event) { if (event.get_event_type() == EventType::MouseButtonPressed) { MouseButtonPressedEvent& e = (MouseButtonPressedEvent&)event; int button = e.get_mouse_button(); GLFWwindow* window = static_cast(Application::get().get_window().get_native_window()); Camera& camera = m_engine.get_camera(); double last_x = camera.get_last_x(); double last_y = camera.get_last_y(); glfwGetCursorPos(window, &last_x, &last_y); camera.process_orbital_mouse_button(button, GLFW_PRESS, 0); } else if (event.get_event_type() == EventType::MouseButtonReleased) { MouseButtonReleasedEvent& e = (MouseButtonReleasedEvent&)event; int button = e.get_mouse_button(); m_engine.get_camera().process_orbital_mouse_button(button, GLFW_RELEASE, 0); } if (event.get_event_type() == EventType::MouseScrolled) { MouseScrolledEvent& e = (MouseScrolledEvent&)event; m_engine.get_camera().process_orbital_scroll(e.get_x_offset(), e.get_y_offset()); } if (event.get_event_type() == EventType::KeyPressed) { KeyPressedEvent& e = (KeyPressedEvent&)event; if (e.get_key_code() == GLFW_KEY_G) { m_engine.get_gravity() = !m_engine.get_gravity(); DONUT_INFO("Gravity turned {}", m_engine.get_gravity() ? "ON" : "OFF"); } } } void SimulationState::on_im_ui_render() { ImGui::Begin("Simulation Controls"); ImGui::Text("Black Hole Simulation"); if (ImGui::Button("Back to Config")) Application::get().get_state_manager().switch_to_state("Config"); ImGui::Separator(); ImGui::Text("Simulation Info:"); ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate); ImGui::Text("Frame Time: %.3f ms", 1000.0f / ImGui::GetIO().Framerate); ImGui::Text("Resolution: %dx%d", m_engine.get_width(), m_engine.get_height()); ImGui::Text("Compute Resolution: %dx%d", m_engine.get_compute_width(), m_engine.get_compute_height()); ImGui::Text("Objects: %zu", m_engine.get_objects().size()); ImGui::Separator(); ImGui::Text("Performance:"); ImGui::Text("Engine FPS: %.1f", m_engine.get_current_fps()); ImGui::Text("Target FPS: %d", m_engine.get_target_fps()); int target_fps = m_engine.get_target_fps(); if (ImGui::SliderInt("Target FPS", &target_fps, 30, 120)) { m_engine.set_target_fps(target_fps); } int compute_height = m_engine.get_compute_height(); if (ImGui::SliderInt("Compute Height", &compute_height, 64, 2048)) { m_engine.set_compute_height(compute_height); m_engine.update_compute_dimensions(); } ImGui::Text("Compute Width: %d (auto-calculated)", m_engine.get_compute_width()); ImGui::Separator(); ImGui::Text("Simulation Quality:"); int max_steps_moving = m_engine.get_max_steps_moving(); if (ImGui::SliderInt("Max Steps (Moving)", &max_steps_moving, 1000, 60000)) m_engine.set_max_steps_moving(max_steps_moving); int max_steps_static = m_engine.get_max_steps_static(); if (ImGui::SliderInt("Max Steps (Static)", &max_steps_static, 1000, 30000)) m_engine.set_max_steps_static(max_steps_static); float early_exit_distance = m_engine.get_early_exit_distance(); if (ImGui::SliderFloat("Early Exit Distance", &early_exit_distance, 1e11f, 1e13f, "%.2e")) m_engine.set_early_exit_distance(early_exit_distance); ImGui::Separator(); ImGui::Text("Controls:"); ImGui::Text("Left Mouse: Orbit camera"); ImGui::Text("Scroll: Zoom in/out"); ImGui::Text("G: Toggle gravity"); ImGui::Text("Right Mouse: Enable gravity (hold)"); ImGui::Separator(); ImGui::Text("Physics:"); bool& gravity = m_engine.get_gravity(); ImGui::Checkbox("Gravity Enabled", &gravity); ImGui::Text("Camera:"); ImGui::Text("Position: (%.2e, %.2e, %.2e)", m_engine.get_camera().get_orbital_position().x, m_engine.get_camera().get_orbital_position().y, m_engine.get_camera().get_orbital_position().z); ImGui::Text("Radius: %.2e", m_engine.get_camera().get_orbital_radius()); ImGui::Text("Azimuth: %.2f", m_engine.get_camera().get_azimuth()); ImGui::Text("Elevation: %.2f", m_engine.get_camera().get_elevation()); ImGui::End(); } };