aboutsummaryrefslogtreecommitdiff
path: root/src
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
commit1bd39d11ff76e61bc3cc8b58286092a84997cc20 (patch)
tree490b5c8a1c18fdd0ee42b74c918511c2ad2a6533 /src
parent137a13e6f9a2b039b486b74747dfa83da30413aa (diff)
[add]: finish most world builder features
Diffstat (limited to 'src')
-rw-r--r--src/Engine/Engine.cpp2
-rw-r--r--src/Engine/Engine.h1
-rw-r--r--src/Engine/Object.h2
-rw-r--r--src/States/WorldBuilderState.cpp122
-rw-r--r--src/States/WorldBuilderState.h3
5 files changed, 113 insertions, 17 deletions
diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp
index 799a516..f6c594c 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_SagA.m_Rs), glm::vec4(0, 0, 0, 1), static_cast<float>(m_SagA.m_Mass) }
};
diff --git a/src/Engine/Engine.h b/src/Engine/Engine.h
index 7b4ced4..05bd96f 100644
--- a/src/Engine/Engine.h
+++ b/src/Engine/Engine.h
@@ -91,7 +91,6 @@ namespace Donut
int GetComputeWidth() const { return (m_Width * m_ComputeHeight) / m_Height; }
void UpdateComputeDimensions();
- // Simulation parameters
int GetMaxStepsMoving() const { return m_MaxStepsMoving; }
int GetMaxStepsStatic() const { return m_MaxStepsStatic; }
float GetEarlyExitDistance() const { return m_EarlyExitDistance; }
diff --git a/src/Engine/Object.h b/src/Engine/Object.h
index 7e620c4..842708e 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/WorldBuilderState.cpp b/src/States/WorldBuilderState.cpp
index 5fc25e8..63ef25c 100644
--- a/src/States/WorldBuilderState.cpp
+++ b/src/States/WorldBuilderState.cpp
@@ -46,6 +46,11 @@ namespace Donut
m_SphereShader = Ref<Shader>(Shader::Create("Assets/Shaders/Sphere.glsl"));
InitializeSphereGeometry();
+ // Initialize the black hole at the center
+ Material blackHoleMaterial(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); // Pure black, no specular, no emission
+ m_BlackHole = Object(glm::vec3(0.0f, 0.0f, 0.0f), 2.0f, blackHoleMaterial); // Position at origin, radius 2
+ m_BlackHoleInitialized = true;
+
m_Initialized = true;
}
@@ -85,7 +90,7 @@ namespace Donut
void WorldBuilderState::OnRender()
{
- RenderCommand::SetClearColor(glm::vec4(0.05f, 0.05f, 0.05f, 1.0f));
+ RenderCommand::SetClearColor(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f));
RenderCommand::Clear();
RenderScene();
}
@@ -128,6 +133,32 @@ namespace Donut
float closestDistance = std::numeric_limits<float>::max();
int closestObjectIndex = -1;
+ if (m_BlackHoleInitialized)
+ {
+ glm::vec3 oc = rayOrigin - m_BlackHole.m_Centre;
+ float a = glm::dot(rayDir, rayDir);
+ float b = 2.0f * glm::dot(oc, rayDir);
+ float c = glm::dot(oc, oc) - m_BlackHole.m_Radius * m_BlackHole.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 < closestDistance)
+ {
+ closestDistance = t1;
+ closestObjectIndex = -2;
+ }
+ else if (t2 > 0 && t2 < closestDistance)
+ {
+ closestDistance = t2;
+ closestObjectIndex = -2;
+ }
+ }
+ }
+
for (size_t i = 0; i < m_Scene.objs.size(); ++i)
{
const Object& obj = m_Scene.objs[i];
@@ -162,6 +193,12 @@ namespace Donut
DONUT_INFO("Selected object {}", closestObjectIndex);
return true;
}
+ else if (closestObjectIndex == -2)
+ {
+ m_SelectedObjectIndex = -1;
+ DONUT_INFO("Black hole clicked (not selectable)");
+ return true;
+ }
else
{
m_SelectedObjectIndex = -1;
@@ -257,9 +294,9 @@ namespace Donut
ImGui::PopFont();
ImGui::Separator();
- if (ImGui::CollapsingHeader("Scene Info", &m_ShowSceneInfo))
+ if (ImGui::CollapsingHeader("Scene Info", &m_ShowSceneInfo))
{
- 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:");
@@ -310,6 +347,9 @@ namespace Donut
ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "New Sphere");
ImGui::Separator();
+ // Show object count and limit
+ 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_NewObjectPosition.x, 0.1f);
@@ -327,16 +367,40 @@ namespace Donut
ImGui::Spacing();
- if (ImGui::Button("Add Sphere", ImVec2(ImGui::GetWindowWidth() - 20, 30)))
- AddSphere();
+ // Disable button if object limit reached
+ 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)))
+ AddSphere();
+ }
}
ImGui::Spacing();
if (ImGui::CollapsingHeader("Scene Objects", &m_ShowObjectList))
{
+ if (m_BlackHoleInitialized)
+ {
+ 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_BlackHole.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)
@@ -431,7 +495,8 @@ namespace Donut
ImGui::End();
if (m_SelectedObjectIndex >= 0 &&
- m_SelectedObjectIndex < static_cast<int>(m_Scene.objs.size()))
+ m_SelectedObjectIndex < static_cast<int>(m_Scene.objs.size()) &&
+ m_SelectedObjectIndex != -2)
{
glm::mat4 view = m_Camera.GetViewMatrix();
glm::mat4 projection = m_Camera.GetProjectionMatrix();
@@ -458,32 +523,43 @@ namespace Donut
glm::vec3 newPosition = glm::vec3(objectTransform[3][0], objectTransform[3][1], objectTransform[3][2]);
selectedObj.m_Centre = newPosition;
- glm::vec3 scale = glm::vec3(
+ glm::vec3 scale = glm::vec3
+ (
glm::length(glm::vec3(objectTransform[0])),
glm::length(glm::vec3(objectTransform[1])),
glm::length(glm::vec3(objectTransform[2]))
);
- selectedObj.m_Radius = (scale.x + scale.y + scale.z) / 3.0f; // Average scale
+ selectedObj.m_Radius = (scale.x + scale.y + scale.z) / 3.0f;
DONUT_INFO("Matrix [3]: ({}, {}, {}, {})", objectTransform[3][0], objectTransform[3][1], objectTransform[3][2], objectTransform[3][3]);
DONUT_INFO("New position: ({}, {}, {})", newPosition.x, newPosition.y, newPosition.z);
}
}
- }
+ }
void WorldBuilderState::AddSphere()
{
+ // Check if we've reached the object limit (16 objects)
+ if (m_Scene.objs.size() >= 16)
+ {
+ DONUT_WARN("Cannot add more objects. Maximum of 16 objects reached.");
+ return;
+ }
+
Material material(m_NewObjectColor, m_NewObjectSpecular, m_NewObjectEmission);
Object sphere(m_NewObjectPosition, m_NewObjectRadius, material);
m_Scene.objs.push_back(sphere);
+ // Automatically select the newly created object
+ m_SelectedObjectIndex = static_cast<int>(m_Scene.objs.size() - 1);
+
m_NewObjectPosition = glm::vec3(0.0f, 0.0f, 0.0f);
m_NewObjectRadius = 1.0f;
m_NewObjectColor = glm::vec3(1.0f, 1.0f, 1.0f);
m_NewObjectSpecular = 0.5f;
m_NewObjectEmission = 0.0f;
- DONUT_INFO("Added sphere to scene");
+ DONUT_INFO("Added sphere to scene and selected it");
}
void WorldBuilderState::RemoveSelectedObject()
@@ -500,7 +576,7 @@ namespace Donut
{
m_Scene.objs.clear();
m_SelectedObjectIndex = -1;
- DONUT_INFO("Cleared scene");
+ DONUT_INFO("Cleared scene (black hole remains at center)");
}
void WorldBuilderState::SaveScene()
@@ -536,7 +612,7 @@ namespace Donut
{
file << sceneData.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");
@@ -584,7 +660,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");
@@ -681,6 +757,24 @@ namespace Donut
m_SphereShader->SetFloat3("u_OutlineColor", m_OutlineColor);
m_SphereShader->SetFloat("u_OutlineWidth", m_OutlineWidth);
+ if (m_BlackHoleInitialized)
+ {
+ glm::mat4 blackHoleTransform = glm::translate(glm::mat4(1.0f), m_BlackHole.m_Centre);
+ blackHoleTransform = glm::scale(blackHoleTransform, glm::vec3(m_BlackHole.m_Radius));
+
+ m_SphereShader->SetMat4("u_Transform", blackHoleTransform);
+ m_SphereShader->SetInt("u_IsSelected", 1);
+ m_SphereShader->SetFloat3("u_Color", m_BlackHole.m_Material.m_Color);
+ m_SphereShader->SetFloat("u_Emission", m_BlackHole.m_Material.m_Emission);
+ m_SphereShader->SetFloat("u_Specular", m_BlackHole.m_Material.m_Specular);
+ m_SphereShader->SetFloat("u_OutlineWidth", 0.3f);
+
+ m_SphereVAO->Bind();
+ RenderCommand::DrawIndexed(m_SphereVAO);
+
+ m_SphereShader->SetFloat("u_OutlineWidth", m_OutlineWidth);
+ }
+
for (size_t i = 0; i < m_Scene.objs.size(); ++i)
{
const auto& obj = m_Scene.objs[i];
diff --git a/src/States/WorldBuilderState.h b/src/States/WorldBuilderState.h
index af7d918..cbe8b9e 100644
--- a/src/States/WorldBuilderState.h
+++ b/src/States/WorldBuilderState.h
@@ -69,5 +69,8 @@ namespace Donut
glm::vec3 m_OutlineColor = glm::vec3(1.0f, 1.0f, 1.0f);
float m_OutlineWidth = 0.25f;
+
+ Object m_BlackHole;
+ bool m_BlackHoleInitialized = false;
};
};