diff options
| author | hachem <im@hachem.wtf> | 2025-08-18 05:02:13 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-18 05:02:13 +0200 |
| commit | d34925777dd4fac709096f1c18b7d886b43c15b2 (patch) | |
| tree | fac4c30a28784672c701898ff7612dbdfe530d49 /src/States | |
| parent | 1ecaea469e86ef3f5d18122c8b2cc187286e27f7 (diff) | |
[fix]: improvements, bump to c++20 and fix bugs
Diffstat (limited to 'src/States')
| -rw-r--r-- | src/States/WorldBuilderState.cpp | 208 | ||||
| -rw-r--r-- | src/States/WorldBuilderState.h | 8 |
2 files changed, 121 insertions, 95 deletions
diff --git a/src/States/WorldBuilderState.cpp b/src/States/WorldBuilderState.cpp index 807038d..c5ed174 100644 --- a/src/States/WorldBuilderState.cpp +++ b/src/States/WorldBuilderState.cpp @@ -17,17 +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 - -// TODO(Hachem): Remove constant shader and object creation in main loop -// TODO(Hachem): Change selection appearance // TODO(Hachem): JSON Scene saving and loading namespace Donut @@ -45,7 +39,7 @@ namespace Donut m_Camera.SetOrbitalSpeed(0.01f); m_Camera.SetZoomSpeed(2.0f); m_Camera.SetAzimuth(0.0f); - m_Camera.SetElevation(static_cast<float>(M_PI) / 3.0f); + m_Camera.SetElevation(static_cast<float>(std::numbers::pi) / 3.0f); m_Camera.UpdateOrbital(); Material defaultMaterial(glm::vec3(0.8f, 0.2f, 0.2f), 0.5f, 0.0f); @@ -60,6 +54,9 @@ namespace Donut Object sphere3(glm::vec3(0.0f, 2.0f, 0.0f), 0.8f, material3); m_Scene.objs.push_back(sphere3); + m_SphereShader = Ref<Shader>(Shader::Create("Assets/Shaders/Sphere.glsl")); + InitializeSphereGeometry(); + m_Initialized = true; } @@ -87,7 +84,7 @@ namespace Donut float newAzimuth = m_Camera.GetAzimuth() + azimuthDelta; float newElevation = m_Camera.GetElevation() + elevationDelta; - newElevation = glm::clamp(newElevation, 0.01f, static_cast<float>(M_PI) - 0.01f); + newElevation = glm::clamp(newElevation, 0.01f, static_cast<float>(std::numbers::pi) - 0.01f); m_Camera.SetAzimuth(newAzimuth); m_Camera.SetElevation(newElevation); @@ -99,7 +96,7 @@ namespace Donut void WorldBuilderState::OnRender() { - RenderCommand::SetClearColor(glm::vec4(0.1f, 0.1f, 0.1f, 1.0f)); + RenderCommand::SetClearColor(glm::vec4(0.05f, 0.05f, 0.05f, 1.0f)); RenderCommand::Clear(); RenderScene(); } @@ -123,8 +120,8 @@ namespace Donut int width, height; glfwGetFramebufferSize(window, &width, &height); - float ndcX = (2.0f * xpos) / width - 1.0f; - float ndcY = 1.0f - (2.0f * ypos) / height; + float ndcX = (2.0f * static_cast<float>(xpos)) / static_cast<float>(width) - 1.0f; + float ndcY = 1.0f - (2.0f * static_cast<float>(ypos)) / static_cast<float>(height); glm::vec4 rayStart_NDC(ndcX, ndcY, -1.0f, 1.0f); glm::vec4 rayEnd_NDC(ndcX, ndcY, 0.0f, 1.0f); @@ -178,8 +175,9 @@ namespace Donut } else { - m_CameraDragging = true; - m_LastMousePos = glm::vec2(xpos, ypos); + m_SelectedObjectIndex = -1; + m_CameraDragging = true; + m_LastMousePos = glm::vec2(xpos, ypos); } return true; @@ -292,7 +290,7 @@ namespace Donut { m_Camera.SetOrbitalRadius(15.0f); m_Camera.SetAzimuth(0.0f); - m_Camera.SetElevation(static_cast<float>(M_PI) / 3.0f); + m_Camera.SetElevation(static_cast<float>(std::numbers::pi) / 3.0f); m_Camera.SetOrbitalTarget(glm::vec3(0.0f, 0.0f, 0.0f)); m_Camera.UpdateOrbital(); } @@ -381,6 +379,8 @@ namespace Donut } } } + + ImGui::Spacing(); if (ImGui::CollapsingHeader("Gizmo Controls", &m_ShowGizmoControls)) { @@ -399,6 +399,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_ShowOutlineControls)) + { + ImGui::TextColored(ImVec4(0.9f, 0.9f, 1.0f, 1.0f), "Outline Settings:"); + + ImGui::Text("Outline Color:"); + ImGui::ColorEdit3("##OutlineColor", &m_OutlineColor.x); + + ImGui::Text("Outline Width:"); + ImGui::SliderFloat("##OutlineWidth", &m_OutlineWidth, 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(); @@ -554,85 +570,82 @@ namespace Donut DONUT_ERROR("Failed to load scene"); } - void WorldBuilderState::RenderScene() + void WorldBuilderState::InitializeSphereGeometry() { - GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); - int width, height; - glfwGetFramebufferSize(window, &width, &height); - - RenderCommand::SetViewport(0, 0, width, height); - RenderCommand::EnableDepthTest(); + std::vector<float> vertices; + std::vector<uint32_t> indices; - static Ref<VertexArray> sphereVAO = nullptr; - static Ref<Shader> sphereShader = Ref<Shader>(Shader::Create("Assets/Shaders/Sphere.glsl")); + const int segments = 32; + const int rings = 16; - if (!sphereVAO) + 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 sinPhi = sin(phi); + float cosPhi = 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 sinPhi = sin(phi); - float cosPhi = cos(phi); + float theta = 2.0f * static_cast<float>(std::numbers::pi) * segment / segments; + float sinTheta = sin(theta); + float cosTheta = cos(theta); - for (int segment = 0; segment <= segments; ++segment) - { - float theta = 2.0f * static_cast<float>(M_PI) * segment / segments; - float sinTheta = sin(theta); - float cosTheta = cos(theta); - - float x = cosTheta * sinPhi; - float y = cosPhi; - float z = sinTheta * sinPhi; - - 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 = cosTheta * sinPhi; + float y = cosPhi; + float z = sinTheta * sinPhi; + + 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 vertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(float)))); - VertexBufferLayout layout; - layout.Push<float>(3); - layout.Push<float>(3); - vertexBuffer->SetLayout(layout); - - auto indexBuffer = Ref<IndexBuffer>(IndexBuffer::Create(indices.data(), static_cast<uint32_t>(indices.size()))); - - sphereVAO = Ref<VertexArray>(VertexArray::Create()); - sphereVAO->AddVertexBuffer(vertexBuffer); - sphereVAO->SetIndexBuffer(indexBuffer); } + auto vertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(vertices.data(), static_cast<uint32_t>(vertices.size() * sizeof(float)))); + VertexBufferLayout layout; + layout.Push<float>(3); + layout.Push<float>(3); + vertexBuffer->SetLayout(layout); + + auto indexBuffer = Ref<IndexBuffer>(IndexBuffer::Create(indices.data(), static_cast<uint32_t>(indices.size()))); + + m_SphereVAO = Ref<VertexArray>(VertexArray::Create()); + m_SphereVAO->AddVertexBuffer(vertexBuffer); + m_SphereVAO->SetIndexBuffer(indexBuffer); + } + + void WorldBuilderState::RenderScene() + { + GLFWwindow* window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow()); + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + RenderCommand::SetViewport(0, 0, width, height); + RenderCommand::EnableDepthTest(); + glm::mat4 view = m_Camera.GetViewMatrix(); glm::mat4 projection = m_Camera.GetProjectionMatrix(); glm::mat4 viewProjection = projection * view; @@ -640,10 +653,13 @@ namespace Donut glm::vec3 lightPos = m_Scene.m_LightPos; glm::vec3 cameraPos = m_Camera.GetOrbitalPosition(); - sphereShader->Bind(); - sphereShader->SetMat4("u_ViewProjection", viewProjection); - sphereShader->SetFloat3("u_LightPos", lightPos); - sphereShader->SetFloat3("u_CameraPos", cameraPos); + m_SphereShader->Bind(); + m_SphereShader->SetMat4("u_ViewProjection", viewProjection); + m_SphereShader->SetFloat3("u_LightPos", lightPos); + m_SphereShader->SetFloat3("u_CameraPos", cameraPos); + + m_SphereShader->SetFloat3("u_OutlineColor", m_OutlineColor); + m_SphereShader->SetFloat("u_OutlineWidth", m_OutlineWidth); for (size_t i = 0; i < m_Scene.objs.size(); ++i) { @@ -652,25 +668,27 @@ namespace Donut glm::mat4 transform = glm::translate(glm::mat4(1.0f), obj.m_Centre); transform = glm::scale(transform, glm::vec3(obj.m_Radius)); - sphereShader->SetMat4("u_Transform", transform); + m_SphereShader->SetMat4("u_Transform", transform); - if (m_SelectedObjectIndex == static_cast<int>(i)) + bool isSelected = (m_SelectedObjectIndex == static_cast<int>(i)); + m_SphereShader->SetInt("u_IsSelected", isSelected ? 1 : 0); + if (isSelected) { glm::vec3 highlightColor = obj.m_Material.m_Color * 1.5f; highlightColor = glm::clamp(highlightColor, 0.0f, 1.0f); - sphereShader->SetFloat3("u_Color", highlightColor); - sphereShader->SetFloat("u_Emission", 0.2f); + m_SphereShader->SetFloat3("u_Color", highlightColor); + m_SphereShader->SetFloat("u_Emission", 0.2f); } else { - sphereShader->SetFloat3("u_Color", obj.m_Material.m_Color); - sphereShader->SetFloat("u_Emission", obj.m_Material.m_Emission); + m_SphereShader->SetFloat3("u_Color", obj.m_Material.m_Color); + m_SphereShader->SetFloat("u_Emission", obj.m_Material.m_Emission); } - sphereShader->SetFloat("u_Specular", obj.m_Material.m_Specular); + m_SphereShader->SetFloat("u_Specular", obj.m_Material.m_Specular); - sphereVAO->Bind(); - RenderCommand::DrawIndexed(sphereVAO); + m_SphereVAO->Bind(); + RenderCommand::DrawIndexed(m_SphereVAO); } RenderCommand::DisableDepthTest(); diff --git a/src/States/WorldBuilderState.h b/src/States/WorldBuilderState.h index c9b8d00..af7d918 100644 --- a/src/States/WorldBuilderState.h +++ b/src/States/WorldBuilderState.h @@ -39,11 +39,15 @@ namespace Donut void SaveScene(); void LoadScene(); void RenderScene(); + void InitializeSphereGeometry(); private: Scene m_Scene; Camera m_Camera; bool m_Initialized = false; + Ref<Shader> m_SphereShader; + Ref<VertexArray> m_SphereVAO; + glm::vec3 m_NewObjectPosition = glm::vec3(0.0f, 0.0f, 0.0f); float m_NewObjectRadius = 1.0f; glm::vec3 m_NewObjectColor = glm::vec3(1.0f, 1.0f, 1.0f); @@ -61,5 +65,9 @@ namespace Donut bool m_ShowObjectCreator = true; bool m_ShowSceneInfo = true; bool m_ShowGizmoControls = true; + bool m_ShowOutlineControls = true; + + glm::vec3 m_OutlineColor = glm::vec3(1.0f, 1.0f, 1.0f); + float m_OutlineWidth = 0.25f; }; }; |
