diff options
| -rw-r--r-- | assets/shaders/sphere.glsl | 5 | ||||
| -rw-r--r-- | src/engine/engine.cpp | 2 | ||||
| -rw-r--r-- | src/engine/object.h | 2 | ||||
| -rw-r--r-- | src/states/world_builder_state.cpp | 115 | ||||
| -rw-r--r-- | src/states/world_builder_state.h | 3 |
5 files changed, 109 insertions, 18 deletions
diff --git a/assets/shaders/sphere.glsl b/assets/shaders/sphere.glsl index 026f884..23e8f54 100644 --- a/assets/shaders/sphere.glsl +++ b/assets/shaders/sphere.glsl @@ -46,19 +46,18 @@ void main() float diff = max(dot(normal, lightDir), 0.0); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); - vec3 ambient = u_Color * 0.1; vec3 diffuse = u_Color * diff; vec3 specular = vec3(u_Specular) * spec; vec3 emission = u_Color * u_Emission; - vec3 result = ambient + diffuse + specular + emission; + vec3 result = diffuse + specular + emission; if (u_IsSelected > 0) { float ndotv = max(dot(normal, viewDir), 0.0); float rim = 1.0 - ndotv; float width = clamp(u_OutlineWidth, 0.0, 1.0); - float outlineMask = smoothstep(1.0 - width, 1.0, rim); + float outlineMask = step(1.0 - u_OutlineWidth, rim);; result = mix(result, u_OutlineColor, outlineMask); } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index c9a23ca..9577d1e 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -24,8 +24,6 @@ namespace Donut m_objects = { - { glm::vec4(4e11f, 0.00f, 0.00f, 4e10f), glm::vec4(1, 1, 0, 1), static_cast<float>(1.98892e30) }, - { glm::vec4(0.00f, 0.00f, 4e11f, 4e10f), glm::vec4(1, 0, 0, 1), static_cast<float>(1.98892e30) }, { glm::vec4(0.00f, 0.00f, 0.00f, m_sag_a.m_rs), glm::vec4(0, 0, 0, 1), static_cast<float>(m_sag_a.m_mass) } }; diff --git a/src/engine/object.h b/src/engine/object.h index 19938d8..790fe25 100644 --- a/src/engine/object.h +++ b/src/engine/object.h @@ -22,6 +22,7 @@ namespace Donut float m_specular; float m_emission; + Material() : m_color(1.0f, 1.0f, 1.0f), m_specular(0.5f), m_emission(0.0f) { } Material(glm::vec3 c, float s, float e) : m_color(c), m_specular(s), @@ -35,6 +36,7 @@ namespace Donut float m_radius; Material m_material; + Object() : m_centre(0.0f, 0.0f, 0.0f), m_radius(1.0f), m_material() { } Object(glm::vec3 c, float r, Material m) : m_centre(c), m_radius(r), 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]; diff --git a/src/states/world_builder_state.h b/src/states/world_builder_state.h index 4cbe987..866ae59 100644 --- a/src/states/world_builder_state.h +++ b/src/states/world_builder_state.h @@ -69,5 +69,8 @@ namespace Donut glm::vec3 m_outline_color = glm::vec3(1.0f, 1.0f, 1.0f); float m_outline_width = 0.25f; + + Object m_black_hole; + bool m_black_hole_initialized = false; }; }; |
