hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/src/states
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-08-21 18:49:50 +0200
committerhachem <im@hachem.wtf>2025-08-21 18:49:50 +0200
commit3d13b496b10f9571b5724ee4df51cfd80f513a62 (patch)
treeda069a4907bd86e1b540710a7ed901bc6cb8477d /src/states
parent908db805bd4e8830dc385a07d55c45873babaf7a (diff)
feat: finish most world builder features
Diffstat (limited to 'src/states')
-rw-r--r--src/states/world_builder_state.cpp115
-rw-r--r--src/states/world_builder_state.h3
2 files changed, 105 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];
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;
};
};