hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-08-18 05:02:13 +0200
committerhachem <im@hachem.wtf>2025-08-18 05:02:13 +0200
commit0c77bdb5a48343005dfdf1509d004b36022efb32 (patch)
tree6bc9df4e16037eb557e5a3ce6d0dce4b3323cd48 /src
parentd65233be9433a01c54e959aea72e87ff2e385937 (diff)
fix: improvements, bump to C++20 and fix bugs
Diffstat (limited to 'src')
-rw-r--r--src/core/camera.cpp4
-rw-r--r--src/core/camera.h7
-rw-r--r--src/engine/engine.h6
-rw-r--r--src/engine/object.h2
-rw-r--r--src/states/world_builder_state.cpp206
-rw-r--r--src/states/world_builder_state.h8
6 files changed, 127 insertions, 106 deletions
diff --git a/src/core/camera.cpp b/src/core/camera.cpp
index bba6ee2..9c2b061 100644
--- a/src/core/camera.cpp
+++ b/src/core/camera.cpp
@@ -163,7 +163,7 @@ namespace Donut
glm::vec3 Camera::get_orbital_position() const
{
- float clamped_elevation = glm::clamp(m_elevation, 0.01f, float(M_PI) - 0.01f);
+ float clamped_elevation = glm::clamp(m_elevation, 0.01f, float(std::numbers::pi) - 0.01f);
return glm::vec3
(
m_orbital_radius * sin(clamped_elevation) * cos(m_azimuth),
@@ -191,7 +191,7 @@ namespace Donut
m_azimuth += dx * m_orbital_speed;
m_elevation -= dy * m_orbital_speed;
- m_elevation = glm::clamp(m_elevation, 0.01f, float(M_PI) - 0.01f);
+ m_elevation = glm::clamp(m_elevation, 0.01f, float(std::numbers::pi) - 0.01f);
}
m_last_x_orbital = x;
diff --git a/src/core/camera.h b/src/core/camera.h
index 809be48..677cb71 100644
--- a/src/core/camera.h
+++ b/src/core/camera.h
@@ -3,10 +3,7 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
-#define _USE_MATH_DEFINES
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <numbers>
namespace Donut
{
@@ -121,7 +118,7 @@ namespace Donut
double m_orbital_min_radius = 1e10;
double m_orbital_max_radius = 1e12;
float m_azimuth = 0.0f;
- float m_elevation = static_cast<float>(M_PI) / 2.0f;
+ float m_elevation = static_cast<float>(std::numbers::pi) / 2.0f;
float m_orbital_speed = 0.01f;
double m_zoom_speed = 25e9f;
bool m_dragging = false;
diff --git a/src/engine/engine.h b/src/engine/engine.h
index 0d0fb1b..124fa39 100644
--- a/src/engine/engine.h
+++ b/src/engine/engine.h
@@ -1,6 +1,7 @@
#pragma once
#include <vector>
+#include <numbers>
#include <iostream>
#include <fstream>
#include <sstream>
@@ -21,11 +22,6 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
-#define _USE_MATH_DEFINES
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
namespace Donut
{
const double c = 299792458.0;
diff --git a/src/engine/object.h b/src/engine/object.h
index c45815b..19938d8 100644
--- a/src/engine/object.h
+++ b/src/engine/object.h
@@ -46,7 +46,7 @@ namespace Donut
float a = glm::dot(ray.m_direction, ray.m_direction);
float b = 2.0f * glm::dot(oc, ray.m_direction);
float c = glm::dot(oc, oc) - m_radius * m_radius;
- double discriminant = b*b - 4*a*c;
+ float discriminant = static_cast<float>(b*b - 4*a*c);
if(discriminant < 0)
return false;
diff --git a/src/states/world_builder_state.cpp b/src/states/world_builder_state.cpp
index 16b7866..ad0e57b 100644
--- a/src/states/world_builder_state.cpp
+++ b/src/states/world_builder_state.cpp
@@ -17,15 +17,11 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
+#include <numbers>
#include <fstream>
#include <sstream>
#include <limits>
-#define _USE_MATH_DEFINES
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
namespace Donut
{
void WorldBuilderState::on_enter()
@@ -41,7 +37,7 @@ namespace Donut
m_camera.set_orbital_speed(0.01f);
m_camera.set_zoom_speed(2.0f);
m_camera.set_azimuth(0.0f);
- m_camera.set_elevation(static_cast<float>(M_PI) / 3.0f);
+ m_camera.set_elevation(static_cast<float>(std::numbers::pi) / 3.0f);
m_camera.update_orbital();
Material default_material(glm::vec3(0.8f, 0.2f, 0.2f), 0.5f, 0.0f);
@@ -56,6 +52,9 @@ namespace Donut
Object sphere3(glm::vec3(0.0f, 2.0f, 0.0f), 0.8f, material3);
m_scene.objs.push_back(sphere3);
+ m_sphere_shader = Ref<Shader>(Shader::create("assets/shaders/sphere.glsl"));
+ initialize_sphere_geometry();
+
m_initialized = true;
}
@@ -83,7 +82,7 @@ namespace Donut
float new_azimuth = m_camera.get_azimuth() + azimuth_delta;
float new_elevation = m_camera.get_elevation() + elevation_delta;
- new_elevation = glm::clamp(new_elevation, 0.01f, static_cast<float>(M_PI) - 0.01f);
+ new_elevation = glm::clamp(new_elevation, 0.01f, static_cast<float>(std::numbers::pi) - 0.01f);
m_camera.set_azimuth(new_azimuth);
m_camera.set_elevation(new_elevation);
@@ -95,7 +94,7 @@ namespace Donut
void WorldBuilderState::on_render()
{
- RenderCommand::set_clear_color(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f));
+ RenderCommand::set_clear_color(glm::vec4(0.05f, 0.05f, 0.05f, 1.0f));
RenderCommand::clear();
render_scene();
}
@@ -119,8 +118,8 @@ namespace Donut
int width, height;
glfwGetFramebufferSize(window, &width, &height);
- float ndc_x = (2.0f * xpos) / width - 1.0f;
- float ndc_y = 1.0f - (2.0f * ypos) / height;
+ float ndc_x = (2.0f * static_cast<float>(xpos)) / static_cast<float>(width) - 1.0f;
+ float ndc_y = 1.0f - (2.0f * static_cast<float>(ypos)) / static_cast<float>(height);
glm::vec4 ray_start_ndc(ndc_x, ndc_y, -1.0f, 1.0f);
glm::vec4 ray_end_ndc(ndc_x, ndc_y, 0.0f, 1.0f);
@@ -174,8 +173,9 @@ namespace Donut
}
else
{
- m_camera_dragging = true;
- m_last_mouse_pos = glm::vec2(xpos, ypos);
+ m_selected_object_index = -1;
+ m_camera_dragging = true;
+ m_last_mouse_pos = glm::vec2(xpos, ypos);
}
return true;
@@ -288,7 +288,7 @@ namespace Donut
{
m_camera.set_orbital_radius(15.0f);
m_camera.set_azimuth(0.0f);
- m_camera.set_elevation(static_cast<float>(M_PI) / 3.0f);
+ m_camera.set_elevation(static_cast<float>(std::numbers::pi) / 3.0f);
m_camera.set_orbital_target(glm::vec3(0.0f, 0.0f, 0.0f));
m_camera.update_orbital();
}
@@ -377,6 +377,8 @@ namespace Donut
}
}
}
+
+ ImGui::Spacing();
if (ImGui::CollapsingHeader("Gizmo Controls", &m_show_gizmo_controls))
{
@@ -395,6 +397,22 @@ namespace Donut
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Hotkeys:");
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "W = Translate, E = Rotate, R = Scale");
}
+
+ ImGui::Spacing();
+
+ if (ImGui::CollapsingHeader("Selection Outline", &m_show_outline_controls))
+ {
+ ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Outline Settings:");
+
+ ImGui::Text("Outline Color:");
+ ImGui::ColorEdit3("##OutlineColor", &m_outline_color.x);
+
+ ImGui::Text("Outline Width:");
+ ImGui::SliderFloat("##OutlineWidth", &m_outline_width, 0.01f, 0.9f, "%.2f");
+
+ ImGui::Spacing();
+ ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "White rim around sphere silhouette");
+ }
ImGui::Spacing();
ImGui::Separator();
@@ -550,85 +568,82 @@ namespace Donut
DONUT_ERROR("Failed to load scene");
}
- void WorldBuilderState::render_scene()
+ void WorldBuilderState::initialize_sphere_geometry()
{
- GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window());
- int width, height;
- glfwGetFramebufferSize(window, &width, &height);
-
- RenderCommand::set_viewport(0, 0, width, height);
- RenderCommand::enable_depth_test();
+ std::vector<float> vertices;
+ std::vector<uint32_t> indices;
- static Ref<VertexArray> sphere_vao = nullptr;
- static Ref<Shader> sphere_shader = Ref<Shader>(Shader::create("assets/shaders/sphere.glsl"));
+ const int segments = 32;
+ const int rings = 16;
- if (!sphere_vao)
+ for (int ring = 0; ring <= rings; ++ring)
{
- std::vector<float> vertices;
- std::vector<uint32_t> indices;
-
- const int segments = 32;
- const int rings = 16;
+ float phi = static_cast<float>(std::numbers::pi) * ring / rings;
+ float sin_phi = sin(phi);
+ float cos_phi = cos(phi);
- for (int ring = 0; ring <= rings; ++ring)
+ for (int segment = 0; segment <= segments; ++segment)
{
- float phi = static_cast<float>(M_PI) * ring / rings;
- float sin_phi = sin(phi);
- float cos_phi = cos(phi);
+ float theta = 2.0f * static_cast<float>(std::numbers::pi) * segment / segments;
+ float sin_theta = sin(theta);
+ float cos_theta = cos(theta);
- for (int segment = 0; segment <= segments; ++segment)
- {
- float theta = 2.0f * static_cast<float>(M_PI) * segment / segments;
- float sin_theta = sin(theta);
- float cos_theta = cos(theta);
-
- float x = cos_theta * sin_phi;
- float y = cos_phi;
- float z = sin_theta * sin_phi;
-
- float nx = x;
- float ny = y;
- float nz = z;
-
- vertices.push_back(x);
- vertices.push_back(y);
- vertices.push_back(z);
- vertices.push_back(nx);
- vertices.push_back(ny);
- vertices.push_back(nz);
- }
+ float x = cos_theta * sin_phi;
+ float y = cos_phi;
+ float z = sin_theta * sin_phi;
+
+ float nx = x;
+ float ny = y;
+ float nz = z;
+
+ vertices.push_back(x);
+ vertices.push_back(y);
+ vertices.push_back(z);
+ vertices.push_back(nx);
+ vertices.push_back(ny);
+ vertices.push_back(nz);
}
-
- for (int ring = 0; ring < rings; ++ring)
+ }
+
+ for (int ring = 0; ring < rings; ++ring)
+ {
+ for (int segment = 0; segment < segments; ++segment)
{
- for (int segment = 0; segment < segments; ++segment)
- {
- uint32_t first = ring * (segments + 1) + segment;
- uint32_t second = first + segments + 1;
-
- indices.push_back(first);
- indices.push_back(second);
- indices.push_back(first + 1);
-
- indices.push_back(second);
- indices.push_back(second + 1);
- indices.push_back(first + 1);
- }
+ uint32_t first = ring * (segments + 1) + segment;
+ uint32_t second = first + segments + 1;
+
+ indices.push_back(first);
+ indices.push_back(second);
+ indices.push_back(first + 1);
+
+ indices.push_back(second);
+ indices.push_back(second + 1);
+ indices.push_back(first + 1);
}
-
- auto vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(float))));
- VertexBufferLayout layout;
- layout.push<float>(3);
- layout.push<float>(3);
- vertex_buffer->set_layout(layout);
-
- auto index_buffer = Ref<IndexBuffer>(IndexBuffer::create(indices.data(), static_cast<uint32_t>(indices.size())));
-
- sphere_vao = Ref<VertexArray>(VertexArray::create());
- sphere_vao->add_vertex_buffer(vertex_buffer);
- sphere_vao->set_index_buffer(index_buffer);
}
+ auto vertex_buffer = Ref<VertexBuffer>(VertexBuffer::create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(float))));
+ VertexBufferLayout layout;
+ layout.push<float>(3);
+ layout.push<float>(3);
+ vertex_buffer->set_layout(layout);
+
+ auto index_buffer = Ref<IndexBuffer>(IndexBuffer::create(indices.data(), static_cast<uint32_t>(indices.size())));
+
+ m_sphere_vao = Ref<VertexArray>(VertexArray::create());
+ m_sphere_vao->add_vertex_buffer(vertex_buffer);
+ m_sphere_vao->set_index_buffer(index_buffer);
+ }
+
+ void WorldBuilderState::render_scene()
+ {
+ GLFWwindow* window = static_cast<GLFWwindow*>(Application::get().get_window().get_native_window());
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+
+ RenderCommand::set_viewport(0, 0, width, height);
+ RenderCommand::enable_depth_test();
+
glm::mat4 view = m_camera.get_view_matrix();
glm::mat4 projection = m_camera.get_projection_matrix();
glm::mat4 view_projection = projection * view;
@@ -636,10 +651,13 @@ namespace Donut
glm::vec3 light_pos = m_scene.m_light_pos;
glm::vec3 camera_pos = m_camera.get_orbital_position();
- sphere_shader->bind();
- sphere_shader->set_mat4("u_ViewProjection", view_projection);
- sphere_shader->set_float3("u_LightPos", light_pos);
- sphere_shader->set_float3("u_CameraPos", camera_pos);
+ m_sphere_shader->bind();
+ m_sphere_shader->set_mat4("u_ViewProjection", view_projection);
+ m_sphere_shader->set_float3("u_LightPos", light_pos);
+ m_sphere_shader->set_float3("u_CameraPos", camera_pos);
+
+ m_sphere_shader->set_float3("u_OutlineColor", m_outline_color);
+ m_sphere_shader->set_float("u_OutlineWidth", m_outline_width);
for (size_t i = 0; i < m_scene.objs.size(); ++i)
{
@@ -648,25 +666,27 @@ namespace Donut
glm::mat4 transform = glm::translate(glm::mat4(1.0f), obj.m_centre);
transform = glm::scale(transform, glm::vec3(obj.m_radius));
- sphere_shader->set_mat4("u_Transform", transform);
+ m_sphere_shader->set_mat4("u_Transform", transform);
- if (m_selected_object_index == static_cast<int>(i))
+ bool is_selected = (m_selected_object_index == static_cast<int>(i));
+ m_sphere_shader->set_int("u_IsSelected", is_selected ? 1 : 0);
+ if (is_selected)
{
glm::vec3 highlight_color = obj.m_material.m_color * 1.5f;
highlight_color = glm::clamp(highlight_color, 0.0f, 1.0f);
- sphere_shader->set_float3("u_Color", highlight_color);
- sphere_shader->set_float("u_Emission", 0.2f);
+ m_sphere_shader->set_float3("u_Color", highlight_color);
+ m_sphere_shader->set_float("u_Emission", 0.2f);
}
else
{
- sphere_shader->set_float3("u_Color", obj.m_material.m_color);
- sphere_shader->set_float("u_Emission", obj.m_material.m_emission);
+ m_sphere_shader->set_float3("u_Color", obj.m_material.m_color);
+ m_sphere_shader->set_float("u_Emission", obj.m_material.m_emission);
}
- sphere_shader->set_float("u_Specular", obj.m_material.m_specular);
+ m_sphere_shader->set_float("u_Specular", obj.m_material.m_specular);
- sphere_vao->bind();
- RenderCommand::draw_indexed(sphere_vao);
+ m_sphere_vao->bind();
+ RenderCommand::draw_indexed(m_sphere_vao);
}
RenderCommand::disable_depth_test();
diff --git a/src/states/world_builder_state.h b/src/states/world_builder_state.h
index c587fbe..4cbe987 100644
--- a/src/states/world_builder_state.h
+++ b/src/states/world_builder_state.h
@@ -39,11 +39,15 @@ namespace Donut
void save_scene();
void load_scene();
void render_scene();
+ void initialize_sphere_geometry();
private:
Scene m_scene;
Camera m_camera;
bool m_initialized = false;
+ Ref<Shader> m_sphere_shader;
+ Ref<VertexArray> m_sphere_vao;
+
glm::vec3 m_new_object_position = glm::vec3(0.0f, 0.0f, 0.0f);
float m_new_object_radius = 1.0f;
glm::vec3 m_new_object_color = glm::vec3(1.0f, 1.0f, 1.0f);
@@ -61,5 +65,9 @@ namespace Donut
bool m_show_object_creator = true;
bool m_show_scene_info = true;
bool m_show_gizmo_controls = true;
+ bool m_show_outline_controls = true;
+
+ glm::vec3 m_outline_color = glm::vec3(1.0f, 1.0f, 1.0f);
+ float m_outline_width = 0.25f;
};
};