diff --git a/Editor/src/Windows/EditorInterface.cpp b/Editor/src/Windows/EditorInterface.cpp index 243430fe..b9531fab 100644 --- a/Editor/src/Windows/EditorInterface.cpp +++ b/Editor/src/Windows/EditorInterface.cpp @@ -55,6 +55,7 @@ #include #include #include "../Commands/Commands/Commands.h" +#include namespace Nuake { @@ -63,6 +64,38 @@ namespace Nuake { ImFont* boldFont; ImFont* EditorInterface::bigIconFont; + glm::vec3 DepthToWorldPosition(const glm::vec2& pixelPos, float depth, const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix, const glm::vec2& viewportSize) + { + // Convert pixel position to normalized device coordinates (NDC) + glm::vec2 ndcPos; + ndcPos.x = (2.0f * pixelPos.x) / viewportSize.x - 1.0f; + ndcPos.y = 1.0f - (2.0f * pixelPos.y) / viewportSize.y; // Y-axis inversion + + // Depth value ranges from 0 to 1 in NDC space + float ndcDepth = depth * 2.0f - 1.0f; + + // Construct the NDC position + glm::vec4 ndcPos4(ndcPos.x, ndcPos.y, ndcDepth, 1.0f); + + // Compute the inverse of the projection and view matrices + glm::mat4 invProj = glm::inverse(projectionMatrix); + glm::mat4 invView = glm::inverse(viewMatrix); + + // Transform the NDC position to eye space + glm::vec4 eyePos4 = invProj * ndcPos4; + eyePos4.z = -1.0f; // Set Z to -1 as it's on the near plane + eyePos4 /= eyePos4.w; + + //eyePos4.w = 0.0f; + + // Transform the eye space position to world space + glm::vec4 worldPos4 = invView * eyePos4; + + // Return the 3D world position + glm::vec3 worldPos(worldPos4.x, worldPos4.y, worldPos4.z); + return worldPos; + } + EditorInterface::EditorInterface(CommandBuffer& commandBuffer) : mCommandBuffer(&commandBuffer) { @@ -98,7 +131,7 @@ namespace Nuake { ImVec2 LastSize = ImVec2(); void EditorInterface::DrawViewport() { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4, 4)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); std::string name = ICON_FA_GAMEPAD + std::string(" Scene"); if (ImGui::Begin(name.c_str())) { @@ -125,12 +158,86 @@ namespace Nuake { ImGui::PopStyleVar(); const Vector2& mousePos = Input::GetMousePosition(); - const ImVec2& windowPos = ImGui::GetWindowPos() + ImVec2(0, 30.0); - const ImVec2& windowSize = ImGui::GetWindowSize() - ImVec2(0, 30.0); + + const ImVec2& windowPos = ImGui::GetWindowPos(); + const auto windowPosNuake = Vector2(windowPos.x, windowPos.y); + const ImVec2& windowSize = ImGui::GetWindowSize(); const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x; const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y; m_IsHoveringViewport = isInsideWidth && isInsideHeight; + + if (ImGui::BeginDragDropTarget()) + { + auto& gbuffer = Engine::GetCurrentScene()->m_SceneRenderer->GetGBuffer(); + Vector2 textureSize = gbuffer.GetTexture(GL_DEPTH_ATTACHMENT)->GetSize(); + auto pixelPos = Input::GetMousePosition() - windowPosNuake; + pixelPos.y = gbuffer.GetSize().y - pixelPos.y; // imgui coords are inverted on the Y axis + + auto gizmoBuffer = Engine::GetCurrentWindow()->GetFrameBuffer(); + gizmoBuffer->Bind(); + bool foundSomethingToSelect = false; + Vector3 dragnDropWorldPos = Vector3(0, 0, 0); + if (const float result = gizmoBuffer->ReadDepth(pixelPos); result > 0) + { + const Matrix4& proj = Engine::GetCurrentScene()->m_EditorCamera->GetPerspective(); + Matrix4 view = Engine::GetCurrentScene()->m_EditorCamera->GetTransform(); + + pixelPos.y = (Input::GetMousePosition() - windowPosNuake).y; + dragnDropWorldPos = DepthToWorldPosition(pixelPos, result, proj, view, textureSize); + + auto renderer = Engine::GetCurrentScene()->m_SceneRenderer; + const ImGuiPayload* payload = ImGui::GetDragDropPayload(); + if(payload && payload->IsDataType("_Model")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath); + + Matrix4 transform = Matrix4(1.0f); + transform = glm::translate(transform, dragnDropWorldPos); + + if (!renderer->IsTempModelLoaded(fullPath)) + { + auto loader = ModelLoader(); + auto modelResource = loader.LoadModel(fullPath); + + Matrix4 transform = Matrix4(1.0f); + transform = glm::translate(transform, dragnDropWorldPos); + renderer->DrawTemporaryModel(fullPath, modelResource, transform); + } + else + { + renderer->DrawTemporaryModel(fullPath, nullptr, transform); + } + + } + + Engine::GetCurrentScene()->m_SceneRenderer->DrawDebugLine(dragnDropWorldPos, dragnDropWorldPos + Vector3{0, 5, 0}, Vector4(1, 0, 1, 1)); + } + gizmoBuffer->Unbind(); + + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath); + + auto loader = ModelLoader(); + auto modelResource = loader.LoadModel(fullPath); + + auto entity = Engine::GetCurrentScene()->CreateEntity(FileSystem::GetFileNameFromPath(fullPath)); + ModelComponent& modelComponent = entity.AddComponent(); + modelComponent.ModelPath = fullPath; + modelComponent.ModelResource = modelResource; + entity.GetComponent().SetLocalPosition(dragnDropWorldPos); + } + } + else + { + Engine::GetCurrentScene()->m_SceneRenderer->ClearTemporaryModels(); + } + ImGuizmo::SetDrawlist(); ImGuizmo::AllowAxisFlip(true); ImGuizmo::SetRect(imagePos.x, imagePos.y + 0.0f, viewportPanelSize.x, viewportPanelSize.y); diff --git a/Nuake/src/Rendering/Renderer.cpp b/Nuake/src/Rendering/Renderer.cpp index 6b8b20a0..28f5cba1 100644 --- a/Nuake/src/Rendering/Renderer.cpp +++ b/Nuake/src/Rendering/Renderer.cpp @@ -281,15 +281,12 @@ namespace Nuake { for (unsigned int i = 0; i < CSM_AMOUNT; i++) { - // Bind shadowmap texture + light.m_Framebuffers[i]->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(17 + i); const uint32_t shadowMapId = shadowmapAmount + i; - Ref shadowMapTexture = light.m_Framebuffers[i]->GetTexture(GL_DEPTH_ATTACHMENT); - deferredShader->SetUniformTex("ShadowMaps[" + std::to_string(shadowMapId) + "]", shadowMapTexture, 17 + i); - - const std::string stringIndex = std::to_string(i); - deferredShader->SetUniform1i("u_DirectionalLight.ShadowMapsIDs[" + stringIndex + "]", shadowMapId); - deferredShader->SetUniform1f("u_DirectionalLight.CascadeDepth[" + stringIndex + "]", light.mCascadeSplitDepth[i]); - deferredShader->SetUniformMat4f("u_DirectionalLight.LightTransforms[" + stringIndex + "]", light.mViewProjections[i]); + deferredShader->SetUniform1i("ShadowMaps[" + std::to_string(shadowMapId) + "]", 17 + i); + deferredShader->SetUniform1i("u_DirectionalLight.ShadowMapsIDs[" + std::to_string(i) + "]", shadowMapId); + deferredShader->SetUniform1f("u_DirectionalLight.CascadeDepth[" + std::to_string(i) + "]", light.mCascadeSplitDepth[i]); + deferredShader->SetUniformMat4f("u_DirectionalLight.LightTransforms[" + std::to_string(i) + "]", light.mViewProjections[i]); } } diff --git a/Nuake/src/Rendering/SceneRenderer.cpp b/Nuake/src/Rendering/SceneRenderer.cpp index 5456d64b..ea6b0656 100644 --- a/Nuake/src/Rendering/SceneRenderer.cpp +++ b/Nuake/src/Rendering/SceneRenderer.cpp @@ -400,7 +400,7 @@ namespace Nuake Shader* shader = ShaderManager::GetShader("Resources/Shaders/shadowMap.shader"); shader->Bind(); - RenderCommand::Disable(RendererEnum::FACE_CULL); + RenderCommand::Enable(RendererEnum::FACE_CULL); glCullFace(GL_BACK); auto meshView = scene.m_Registry.view(); diff --git a/Nuake/src/Scene/Components/LightComponent.h b/Nuake/src/Scene/Components/LightComponent.h index dbfdd312..1ac7e8bd 100644 --- a/Nuake/src/Scene/Components/LightComponent.h +++ b/Nuake/src/Scene/Components/LightComponent.h @@ -53,7 +53,7 @@ namespace Nuake // TODO: Automate this const float nearClip = 0.01f; - const float farClip = 500.0f; + const float farClip = 800.0f; const float clipRange = farClip - nearClip; const float mCascadeNearPlaneOffset = -100.0f; @@ -73,7 +73,7 @@ namespace Nuake mCascadeSplits[i] = (d - nearClip) / clipRange; } - //mCascadeSplits[0] = 0.01f; + mCascadeSplits[0] = 0.01f; //mCascadeSplits[1] = 0.45f; //mCascadeSplits[2] = 1.0f; diff --git a/Nuake/src/Scene/EditorCamera.cpp b/Nuake/src/Scene/EditorCamera.cpp index b6c34d9e..b9f11f74 100644 --- a/Nuake/src/Scene/EditorCamera.cpp +++ b/Nuake/src/Scene/EditorCamera.cpp @@ -198,6 +198,8 @@ namespace Nuake copy->Translation = this->Translation; copy->Yaw = this->Yaw; copy->Pitch = this->Pitch; + copy->TargetYaw = copy->Yaw; + copy->TargetPitch = copy->Pitch; return copy; } @@ -232,7 +234,7 @@ namespace Nuake SERIALIZE_VEC3(Translation); j["Yaw"] = glm::clamp(Yaw, 0.f, 360.f); j["Pitch"] = glm::clamp(Pitch, -90.f, 90.f); - + SERIALIZE_VAL(Speed); return j; } @@ -241,6 +243,8 @@ namespace Nuake DESERIALIZE_VEC3(j["Translation"], Translation); SetYaw(j["Yaw"]); SetPitch(j["Pitch"]); + UpdateDirection(); + DESERIALIZE_VAL(Speed); return true; } diff --git a/Resources/Shaders/deferred.shader b/Resources/Shaders/deferred.shader index dcfa4adb..c857dfbd 100644 --- a/Resources/Shaders/deferred.shader +++ b/Resources/Shaders/deferred.shader @@ -198,7 +198,7 @@ float ShadowCalculation(vec3 FragPos, vec3 normal) const float NUM_SAMPLES = 4.f; const float SAMPLES_START = (NUM_SAMPLES - 1.0f) / 2.0f; const float NUM_SAMPLES_SQUARED = NUM_SAMPLES * NUM_SAMPLES; - vec2 texelSize = 1.0 / vec2(2048, 2048); + vec2 texelSize = 1.0 / vec2(4096, 4096); float result = 0.0f; for (float y = -SAMPLES_START; y <= SAMPLES_START; y += 1.0f)