diff options
| author | hachem <im@hachem.wtf> | 2025-08-21 18:49:50 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-21 18:49:50 +0200 |
| commit | 3d13b496b10f9571b5724ee4df51cfd80f513a62 (patch) | |
| tree | da069a4907bd86e1b540710a7ed901bc6cb8477d /src/states/world_builder_state.cpp | |
| parent | 908db805bd4e8830dc385a07d55c45873babaf7a (diff) | |
feat: finish most world builder features
Diffstat (limited to 'src/states/world_builder_state.cpp')
| -rw-r--r-- | src/states/world_builder_state.cpp | 115 |
1 files changed, 102 insertions, 13 deletions
diff --git a/src/states/world_builder_state.cpp b/src/states/world_builder_state.cpp index 1067d41..a01935c 100644 --- a/src/states/world_builder_state.cpp +++ b/src/states/world_builder_state.cpp @@ -45,6 +45,10 @@ namespace Donut m_sphere_shader = Ref<Shader>(Shader::create("assets/shaders/sphere.glsl")); initialize_sphere_geometry(); + Material black_hole_material(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); + m_black_hole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, black_hole_material); + m_black_hole_initialized = true; + m_initialized = true; } @@ -84,7 +88,7 @@ namespace Donut void WorldBuilderState::on_render() { - RenderCommand::set_clear_color(glm::vec4(0.05f, 0.05f, 0.05f, 1.0f)); + RenderCommand::set_clear_color(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f)); RenderCommand::clear(); render_scene(); } @@ -127,6 +131,32 @@ namespace Donut float closest_distance = std::numeric_limits<float>::max(); int closest_object_index = -1; + if (m_black_hole_initialized) + { + glm::vec3 oc = ray_origin - m_black_hole.m_centre; + float a = glm::dot(ray_dir, ray_dir); + float b = 2.0f * glm::dot(oc, ray_dir); + float c = glm::dot(oc, oc) - m_black_hole.m_radius * m_black_hole.m_radius; + float discriminant = b * b - 4 * a * c; + + if (discriminant > 0) + { + float t1 = (-b - sqrt(discriminant)) / (2.0f * a); + float t2 = (-b + sqrt(discriminant)) / (2.0f * a); + + if (t1 > 0 && t1 < closest_distance) + { + closest_distance = t1; + closest_object_index = -2; + } + else if (t2 > 0 && t2 < closest_distance) + { + closest_distance = t2; + closest_object_index = -2; + } + } + } + for (size_t i = 0; i < m_scene.objs.size(); ++i) { const Object& obj = m_scene.objs[i]; @@ -161,6 +191,12 @@ namespace Donut DONUT_INFO("Selected object {}", closest_object_index); return true; } + else if (closest_object_index == -2) + { + m_selected_object_index = -1; + DONUT_INFO("Black hole clicked (not selectable)"); + return true; + } else { m_selected_object_index = -1; @@ -256,9 +292,9 @@ namespace Donut ImGui::PopFont(); ImGui::Separator(); - if (ImGui::CollapsingHeader("Scene Info", &m_show_scene_info)) + if (ImGui::CollapsingHeader("Scene Info", &m_show_scene_info)) { - ImGui::Text("Objects in scene: %zu", m_scene.objs.size()); + ImGui::Text("Objects in scene: %zu/16 (+ 1 black hole)", m_scene.objs.size()); ImGui::Separator(); ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Camera Info:"); @@ -309,6 +345,8 @@ namespace Donut ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "New Sphere"); ImGui::Separator(); + ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.8f, 1.0f), "Objects: %zu/16", m_scene.objs.size()); + ImGui::Text("Position:"); ImGui::DragFloat3("##Position", &m_new_object_position.x, 0.1f); @@ -326,16 +364,39 @@ namespace Donut ImGui::Spacing(); - if (ImGui::Button("Add Sphere", ImVec2(ImGui::GetWindowWidth() - 20, 30))) - add_sphere(); + if (m_scene.objs.size() >= 16) + { + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f); + ImGui::Button("Add Sphere (Limit Reached)", ImVec2(ImGui::GetWindowWidth() - 20, 30)); + ImGui::PopStyleVar(); + } + else + { + if (ImGui::Button("Add Sphere", ImVec2(ImGui::GetWindowWidth() - 20, 30))) + add_sphere(); + } } ImGui::Spacing(); if (ImGui::CollapsingHeader("Scene Objects", &m_show_object_list)) { + if (m_black_hole_initialized) + { + ImGui::PushID(-1); + + ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "Black Hole (Center)"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Position: (0.00, 0.00, 0.00)"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Radius: %.2f", m_black_hole.m_radius); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Color: Black (with white outline)"); + ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Cannot be removed or modified"); + + ImGui::PopID(); + ImGui::Separator(); + } + if (m_scene.objs.empty()) - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No objects in scene"); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No additional objects in scene"); else { for (size_t i = 0; i < m_scene.objs.size(); ++i) @@ -430,7 +491,8 @@ namespace Donut ImGui::End(); if (m_selected_object_index >= 0 && - m_selected_object_index < static_cast<int>(m_scene.objs.size())) + m_selected_object_index < static_cast<int>(m_scene.objs.size()) && + m_selected_object_index != -2) { glm::mat4 view = m_camera.get_view_matrix(); glm::mat4 projection = m_camera.get_projection_matrix(); @@ -457,7 +519,8 @@ namespace Donut glm::vec3 new_position = glm::vec3(object_transform[3][0], object_transform[3][1], object_transform[3][2]); selected_obj.m_centre = new_position; - glm::vec3 scale = glm::vec3( + glm::vec3 scale = glm::vec3 + ( glm::length(glm::vec3(object_transform[0])), glm::length(glm::vec3(object_transform[1])), glm::length(glm::vec3(object_transform[2])) @@ -468,21 +531,29 @@ namespace Donut DONUT_INFO("New position: ({}, {}, {})", new_position.x, new_position.y, new_position.z); } } - } + } void WorldBuilderState::add_sphere() { + if (m_scene.objs.size() >= 16) + { + DONUT_WARN("Cannot add more objects. Maximum of 16 objects reached."); + return; + } + Material material(m_new_object_color, m_new_object_specular, m_new_object_emission); Object sphere(m_new_object_position, m_new_object_radius, material); m_scene.objs.push_back(sphere); + m_selected_object_index = static_cast<int>(m_scene.objs.size() - 1); + m_new_object_position = glm::vec3(0.0f, 0.0f, 0.0f); m_new_object_radius = 1.0f; m_new_object_color = glm::vec3(1.0f, 1.0f, 1.0f); m_new_object_specular = 0.5f; m_new_object_emission = 0.0f; - DONUT_INFO("Added sphere to scene"); + DONUT_INFO("Added sphere to scene and selected it"); } void WorldBuilderState::remove_selected_object() @@ -499,7 +570,7 @@ namespace Donut { m_scene.objs.clear(); m_selected_object_index = -1; - DONUT_INFO("Cleared scene"); + DONUT_INFO("Cleared scene (black hole remains at center)"); } void WorldBuilderState::save_scene() @@ -535,7 +606,7 @@ namespace Donut { file << scene_data.dump(4); file.close(); - DONUT_INFO("Scene saved to Scene.json"); + DONUT_INFO("Scene saved to Scene.json (black hole always present at center)"); } else DONUT_ERROR("Failed to save scene"); @@ -583,7 +654,7 @@ namespace Donut } file.close(); - DONUT_INFO("Scene loaded from Scene.json"); + DONUT_INFO("Scene loaded from Scene.json (black hole remains at center)"); } else DONUT_ERROR("Failed to load scene"); @@ -680,6 +751,24 @@ namespace Donut m_sphere_shader->set_float3("u_OutlineColor", m_outline_color); m_sphere_shader->set_float("u_OutlineWidth", m_outline_width); + if (m_black_hole_initialized) + { + glm::mat4 black_hole_transform = glm::translate(glm::mat4(1.0f), m_black_hole.m_centre); + black_hole_transform = glm::scale(black_hole_transform, glm::vec3(m_black_hole.m_radius)); + + m_sphere_shader->set_mat4("u_Transform", black_hole_transform); + m_sphere_shader->set_int("u_IsSelected", 1); + m_sphere_shader->set_float3("u_Color", m_black_hole.m_material.m_color); + m_sphere_shader->set_float("u_Emission", m_black_hole.m_material.m_emission); + m_sphere_shader->set_float("u_Specular", m_black_hole.m_material.m_specular); + m_sphere_shader->set_float("u_OutlineWidth", 0.3f); + + m_sphere_vao->bind(); + RenderCommand::draw_indexed(m_sphere_vao); + + m_sphere_shader->set_float("u_OutlineWidth", m_outline_width); + } + for (size_t i = 0; i < m_scene.objs.size(); ++i) { const auto& obj = m_scene.objs[i]; |
