diff --git a/EclipseEngine/EclipseEditor/EditorRenderer.cpp b/EclipseEngine/EclipseEditor/EditorRenderer.cpp index 6588c53d..8b8a9fe4 100644 --- a/EclipseEngine/EclipseEditor/EditorRenderer.cpp +++ b/EclipseEngine/EclipseEditor/EditorRenderer.cpp @@ -51,13 +51,14 @@ void EditorRenderer::Render(Scene* scene, Camera* editorCamera, std::shared_ptr< { if (!scene) return; + // Normal object rendering + glStencilFunc(GL_ALWAYS, 1, 0xFF); // Write 1 to the stencil buffer for all objects + glStencilMask(0xFF); // Enable writing to the stencil buffer + for (auto& object : scene->GetObjects()) { - // Normal object rendering - glStencilFunc(GL_ALWAYS, 1, 0xFF); // Write 1 to the stencil buffer for all objects - glStencilMask(0xFF); // Enable writing to the stencil buffer - glm::mat4 identity = object->transform.GetMatrix(); + object->UpdateAABB(glm::mat4(1.0f)); if (glfwGetKey(core->window->GetWindow(), GLFW_KEY_P) == GLFW_PRESS) { optionShader = posShader; @@ -77,30 +78,30 @@ void EditorRenderer::Render(Scene* scene, Camera* editorCamera, std::shared_ptr< optionShader = normalShader; } object->Draw(*optionShader, *editorCamera, identity); - RenderAABB(object->GetAABB(), *aabbShader); for (auto& child : object->GetChildren()) { RenderAABB(child->GetAABB(), *aabbShader); } + } - if (selectedObject != nullptr) - { - glm::mat4 objectModel = selectedObject->CalculateWorldTransform(selectedObject->transform.GetMatrix()); - - // Outlining: Second pass (draw outline) - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); // Only draw where stencil buffer is not 1 - glStencilMask(0x00); // Disable writing to the stencil buffer - glDisable(GL_DEPTH_TEST); // Disable depth testing for stencil write + if (selectedObject != nullptr) + { + // Calculate the world transform for the selected object + glm::mat4 worldTransform = glm::mat4(1.0f); - selectedObject->Draw(*outliningShader, *editorCamera, identity); // Draw outline - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Reset to fill mode - } + // Outlining: Second pass (draw outline) + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); // Only draw where stencil buffer is not 1 + glStencilMask(0x00); // Disable writing to the stencil buffer + glDisable(GL_DEPTH_TEST); // Disable depth testing for stencil write - glStencilMask(0xFF); // Re-enable writing to stencil buffer for next frame - glStencilFunc(GL_ALWAYS, 1, 0xFF); // Reset stencil function - glEnable(GL_DEPTH_TEST); // Re-enable depth testing + selectedObject->Draw(*outliningShader, *editorCamera, selectedObject->transform.GetMatrix()); // Draw outline + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Reset to fill mode } + glStencilMask(0xFF); // Re-enable writing to stencil buffer for next frame + glStencilFunc(GL_ALWAYS, 1, 0xFF); // Reset stencil function + glEnable(GL_DEPTH_TEST); // Re-enable depth testing + RenderGrid(grid, editorCamera); RenderGuizmo(); glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/EclipseEngine/EclipseEditor/HierarchyPanel.cpp b/EclipseEngine/EclipseEditor/HierarchyPanel.cpp index 47f3798e..7c2323b1 100644 --- a/EclipseEngine/EclipseEditor/HierarchyPanel.cpp +++ b/EclipseEngine/EclipseEditor/HierarchyPanel.cpp @@ -26,17 +26,35 @@ void HierarchyPanel::Render() m_RootObjects = core->scene->GetObjects(); } - if(ImGui::Button("Add Object")) - { - const char* filterPatterns[1] = { "*.fbx" }; - const char* filePath = tinyfd_openFileDialog("Select Object", "", 1, filterPatterns, NULL, 0); - if (filePath) { - std::filesystem::path path(filePath); - ModelLoader modelLoader; - auto gameObject = modelLoader.LoadModel(filePath); - gameObject->name = path.stem().string(); - core->scene->AddGameObject(gameObject); + if (ImGui::IsKeyPressed(ImGuiKey_MouseRight) + && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + { + ImGui::OpenPopup("AddObject"); + } + + if (ImGui::BeginPopup("AddObject")) + { + if (ImGui::MenuItem("Add Object")) + { + const char* filterPatterns[1] = { "*.fbx" }; + const char* filePath = tinyfd_openFileDialog("Select Object", "", 1, filterPatterns, NULL, 0); + if (filePath) { + std::filesystem::path path(filePath); + ModelLoader modelLoader; + auto gameObject = modelLoader.LoadModel(filePath); + gameObject->name = path.stem().string(); + core->scene->AddGameObject(gameObject); + } + } + if (ImGui::MenuItem("Add Empty GameObject")) + { + core->scene->AddEmptyGameObject(); } + if (ImGui::MenuItem("Add Cube")) + { + core->scene->AddCube(); + } + ImGui::EndPopup(); } for (const auto& rootObject : m_RootObjects) { @@ -46,15 +64,6 @@ void HierarchyPanel::Render() ImGui::End(); } -void HierarchyPanel::RemoveObject(std::shared_ptr rootObject) -{ - // TODO: delete method -} - -void HierarchyPanel::AddRootObject(std::shared_ptr rootObject) { - m_RootObjects.emplace_back(rootObject); -} - void HierarchyPanel::RenderGameObjectTree(const std::shared_ptr& gameObject) { // Check if this GameObject is the selected one @@ -72,12 +81,10 @@ void HierarchyPanel::RenderGameObjectTree(const std::shared_ptr& gam m_SelectedObject = gameObject; Logger::Log("Selected object: " + gameObject->GetName()); - if (m_InspectorPanel != nullptr) - { + if (m_InspectorPanel != nullptr) { m_InspectorPanel->SetSelectedObject(m_SelectedObject); } - if (m_ViewportPanel != nullptr) - { + if (m_ViewportPanel != nullptr) { m_ViewportPanel->SetSelectedObject(m_SelectedObject); } } diff --git a/EclipseEngine/EclipseEditor/HierarchyPanel.h b/EclipseEngine/EclipseEditor/HierarchyPanel.h index ecbae08b..3000e628 100644 --- a/EclipseEngine/EclipseEditor/HierarchyPanel.h +++ b/EclipseEngine/EclipseEditor/HierarchyPanel.h @@ -15,8 +15,6 @@ class HierarchyPanel : public Panel HierarchyPanel(const std::string& name, bool isVisible = false); void Render() override; - void RemoveObject(std::shared_ptr rootObject); - void AddRootObject(std::shared_ptr rootObject); std::shared_ptr GetSelectedObject() const { return m_SelectedObject; } void SetInspectorPanel(InspectorPanel* inspectorPanel) { m_InspectorPanel = inspectorPanel; } void SetViewportPanel(ViewportPanel* viewportPanel) { m_ViewportPanel = viewportPanel; } diff --git a/EclipseEngine/EclipseEditor/InspectorPanel.cpp b/EclipseEngine/EclipseEditor/InspectorPanel.cpp index f394f0c5..ac05ffaf 100644 --- a/EclipseEngine/EclipseEditor/InspectorPanel.cpp +++ b/EclipseEngine/EclipseEditor/InspectorPanel.cpp @@ -1,5 +1,6 @@ #include "imgui.h" #include "glm/glm.hpp" +#include "App.h" #include "InspectorPanel.h" #include "tinyfiledialogs.h" @@ -17,7 +18,7 @@ void InspectorPanel::Render() if(ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) { - if (m_SelectedObject) + if (m_SelectedObject != nullptr) { // Display the name of the selected object ImGui::Text("Selected Object: %s", m_SelectedObject->GetName().c_str()); @@ -27,8 +28,7 @@ void InspectorPanel::Render() // Render Transform controls (you already have this implemented) if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) { - ImGui::Text("Transform"); - ImGui::Separator(); + ImGui::Text("TRANSFORM"); // Position glm::vec3 position = m_SelectedObject->transform.position; @@ -53,43 +53,97 @@ void InspectorPanel::Render() m_SelectedObject->transform.SetRotation(rotationQuat); } + // Add Component button with selection menu + if (ImGui::Button("Add Component")) + { + ImGui::OpenPopup("AddComponentPopup"); + } - ImGui::Separator(); - (ImGui::Text("Mesh")); - ImGui::Separator(); - bool temp = false; - ImGui::Checkbox("Active", &temp); - ImGui::SameLine(); - ImGui::Text("File: "); - ImGui::Separator(); - ImGui::Text("Draw:"); - // Display the texture - GLuint textureID = m_SelectedObject.get()->GetTextureID(); - if (textureID) { - ImGui::Image((void*)(intptr_t)textureID, ImVec2(128, 128)); // Adjust size as needed + if (ImGui::BeginPopup("AddComponentPopup")) + { + if (ImGui::MenuItem("Mesh")) + { + //m_SelectedObject->AddComponent(); + } + if (ImGui::MenuItem("Material")) + { + //m_SelectedObject->AddComponent(); + } + if (ImGui::MenuItem("Camera")) + { + m_SelectedObject->AddComponent(1500, 844, m_SelectedObject->transform.position); + } + ImGui::EndPopup(); } - //ImGui::Checkbox("Vertex Normals", &temp); - //ImGui::Checkbox("Face Normals", &temp); - //ImGui::SameLine(); - //ImGui::Separator(); - //ImGui::Text("Indexes: "); - //ImGui::Text("Normals: "); - //ImGui::Text("Vertexs: "); - //ImGui::Text("Faces: "); - //ImGui::Text("Tex coords: "); - //ImGui::Separator(); - //ImGui::SliderFloat("Normals length", nullptr, 0.000f, 1.000f); - ImGui::Separator(); + ImGui::SameLine(0.0f, 1.0f); + if (m_SelectedObject->components.size() > 0) + { + // Remove Component button with selection menu + if (ImGui::Button("Remove Component")) + { + ImGui::OpenPopup("RemoveComponentPopup"); + } + } + + if (ImGui::BeginPopup("RemoveComponentPopup")) + { + if (m_SelectedObject->GetComponent() && ImGui::MenuItem("Mesh")) + { + m_SelectedObject->RemoveComponent(); + } + if (m_SelectedObject->GetComponent() && ImGui::MenuItem("Material")) + { + m_SelectedObject->RemoveComponent(); + } + if (m_SelectedObject->GetComponent() && ImGui::MenuItem("Camera")) + { + m_SelectedObject->RemoveComponent(); + } + ImGui::EndPopup(); + } + + if (m_SelectedObject->GetComponent()) { + ImGui::Separator(); + (ImGui::Text("MESH")); + bool temp = true; + ImGui::Checkbox("Active", &temp); + ImGui::Text("Vertices: %d", m_SelectedObject->GetComponent()->vertices.size()); + ImGui::SameLine(0, 20); + ImGui::Text("Indices: %d", m_SelectedObject->GetComponent()->indices.size()); + } + + if (m_SelectedObject->GetComponent()) { + ImGui::Separator(); + (ImGui::Text("MATERIAL")); + + (ImGui::Text("Texture Preview:")); + // Display the texture + GLuint textureID = m_SelectedObject.get()->GetTextureID(); + if (textureID) { + ImGui::Image((void*)(intptr_t)textureID, ImVec2(256, 256)); + } + } + + if (m_SelectedObject->GetComponent()) { + if (ImGui::Checkbox("Active", &m_SelectedObject->GetComponent()->mainCamera)) { + core->scene->SetActiveCamera(m_SelectedObject->GetComponent()); + } + if (ImGui::SliderFloat("FOV", &m_SelectedObject->GetComponent()->FOVdeg, 1.0f, 179.0f)) + { + //m_SelectedObject->GetComponent()->UpdateProjectionMatrix(); + } + if (ImGui::SliderFloat("Near Plane", &m_SelectedObject->GetComponent()->nearPlane, 0.1f, 100.0f)); + if (ImGui::SliderFloat("Far Plane", &m_SelectedObject->GetComponent()->farPlane, 0.1f, 100.0f)); + } ImGui::Separator(); - (ImGui::Text("Material")); - ImGui::Separator(); - bool temp1; - ImGui::Checkbox("Active", &temp1); + if (ImGui::Button("Delete Object")) { + core->scene->DeleteGameObject(m_SelectedObject); + m_SelectedObject = nullptr; + } ImGui::EndTabBar(); } - } else { diff --git a/EclipseEngine/EclipseEditor/Resources/Assets/Textures/checkerboard.png b/EclipseEngine/EclipseEditor/Resources/Assets/Textures/checkerboard.png deleted file mode 100644 index 92d2bf6d..00000000 Binary files a/EclipseEngine/EclipseEditor/Resources/Assets/Textures/checkerboard.png and /dev/null differ diff --git a/EclipseEngine/EclipseEditor/ViewportPanel.cpp b/EclipseEngine/EclipseEditor/ViewportPanel.cpp index 2ed450a9..abecd837 100644 --- a/EclipseEngine/EclipseEditor/ViewportPanel.cpp +++ b/EclipseEngine/EclipseEditor/ViewportPanel.cpp @@ -97,6 +97,7 @@ void ViewportPanel::Render() Logger::Log("Texture file dropped to selected object: " + std::string(filePath)); std::vector textures{ Texture(filePath, "diffuse", 0, GL_RGBA, GL_UNSIGNED_BYTE) }; + m_SelectedObject->RemoveComponent(); m_SelectedObject->AddComponent(textures); // Display the texture GLuint textureID = m_SelectedObject.get()->GetTextureID(); @@ -104,7 +105,6 @@ void ViewportPanel::Render() ImGui::Image((void*)(intptr_t)textureID, ImVec2(128, 128)); // Adjust size as needed } - // Handle texture file loading } else { diff --git a/EclipseEngine/EclipseEditor/imgui.ini b/EclipseEngine/EclipseEditor/imgui.ini index fc9fbba7..162203cc 100644 --- a/EclipseEngine/EclipseEditor/imgui.ini +++ b/EclipseEngine/EclipseEditor/imgui.ini @@ -1,101 +1,70 @@ -[Window][Debug##Default] -Pos=113,10 -Size=400,400 -Collapsed=0 - -[Window][Dear ImGui Demo] -Pos=446,37 -Size=244,346 -Collapsed=0 - -[Window][Hello, world!] -Pos=5,33 -Size=206,577 -Collapsed=0 - [Window][DockSpace] Pos=0,24 Size=1500,820 Collapsed=0 -[Window][Basic Panel] -Pos=5,29 -Size=1910,217 -Collapsed=0 -DockId=0x00000009,0 - -[Window][FPS Panel] -Pos=1640,795 -Size=275,217 +[Window][Debug##Default] +Pos=60,60 +Size=400,400 Collapsed=0 -DockId=0x00000008,0 [Window][Console Panel] -Pos=1063,657 -Size=432,182 +Pos=859,584 +Size=636,255 Collapsed=0 -DockId=0x00000007,0 +DockId=0x00000009,0 [Window][Hierarchy Panel] -Pos=984,29 -Size=241,626 +Pos=5,29 +Size=204,553 Collapsed=0 DockId=0x00000005,0 -[Window][Settings Panel] -Pos=860,19 -Size=240,478 -Collapsed=0 -DockId=0x00000001,0 - -[Window][Assets Panel] -Pos=5,657 -Size=1056,182 +[Window][Inspector Panel] +Pos=1198,29 +Size=297,553 Collapsed=0 -DockId=0x0000000B,0 +DockId=0x00000004,0 -[Window][Inspector Panel] -Pos=1227,29 -Size=268,626 +[Window][Game] +ViewportPos=-1020,211 +ViewportId=0x83199EB2 +Size=896,457 Collapsed=0 -DockId=0x00000006,0 [Window][Viewport] -Pos=5,29 -Size=977,626 +Pos=211,29 +Size=985,553 Collapsed=0 -DockId=0x00000003,0 +DockId=0x00000006,0 -[Window][Game] -Pos=5,29 -Size=977,626 +[Window][Assets Panel] +Pos=5,584 +Size=852,255 Collapsed=0 -DockId=0x00000003,1 +DockId=0x00000007,0 -[Window][Open mesh##filebrowser_2090517357672] -Pos=396,179 -Size=663,453 +[Window][FPS Panel] +Pos=1688,757 +Size=227,255 Collapsed=0 +DockId=0x0000000A,0 [Window][Delete Confirmation] -Pos=575,355 -Size=258,77 +Pos=568,254 +Size=334,77 Collapsed=0 [Docking][Data] -DockSpace ID=0x3FC20BEE Window=0x9A404470 Pos=186,126 Size=1490,810 Split=Y Selected=0x13926F0B - DockNode ID=0x00000009 Parent=0x3FC20BEE SizeRef=1910,217 Selected=0x89311864 - DockNode ID=0x0000000E Parent=0x3FC20BEE SizeRef=1910,764 Split=Y - DockNode ID=0x00000001 Parent=0x0000000E SizeRef=0,0 Split=Y Selected=0x13926F0B - DockNode ID=0x0000000A Parent=0x00000001 SizeRef=814,626 Split=X - DockNode ID=0x00000003 Parent=0x0000000A SizeRef=977,591 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000004 Parent=0x0000000A SizeRef=511,591 Split=X Selected=0x0E9312B4 - DockNode ID=0x00000005 Parent=0x00000004 SizeRef=241,643 Selected=0xE096E5AE - DockNode ID=0x00000006 Parent=0x00000004 SizeRef=268,643 Selected=0x0E9312B4 - DockNode ID=0x0000000D Parent=0x00000001 SizeRef=814,182 Split=X Selected=0xE86CE49B - DockNode ID=0x0000000B Parent=0x0000000D SizeRef=1056,188 Selected=0xE86CE49B - DockNode ID=0x0000000C Parent=0x0000000D SizeRef=432,188 Split=X Selected=0x3A3DF33A - DockNode ID=0x00000007 Parent=0x0000000C SizeRef=313,264 Selected=0x3A3DF33A - DockNode ID=0x00000008 Parent=0x0000000C SizeRef=311,264 Selected=0x9985E007 - DockNode ID=0x00000002 Parent=0x0000000E SizeRef=1142,153 Selected=0xE86CE49B +DockSpace ID=0x3FC20BEE Window=0x9A404470 Pos=169,216 Size=1490,810 Split=Y + DockNode ID=0x00000001 Parent=0x3FC20BEE SizeRef=1490,726 Split=X Selected=0x13926F0B + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1611,562 Split=X Selected=0x26816F31 + DockNode ID=0x00000005 Parent=0x00000003 SizeRef=204,726 Selected=0xE096E5AE + DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1405,726 CentralNode=1 Selected=0x13926F0B + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=297,562 Selected=0x0E9312B4 + DockNode ID=0x00000002 Parent=0x3FC20BEE SizeRef=1490,255 Split=X Selected=0xE86CE49B + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1093,246 Selected=0xE86CE49B + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=815,246 Split=X Selected=0x9985E007 + DockNode ID=0x00000009 Parent=0x00000008 SizeRef=586,190 Selected=0x3A3DF33A + DockNode ID=0x0000000A Parent=0x00000008 SizeRef=227,190 Selected=0x9985E007 diff --git a/EclipseEngine/EclipseEngine/Camera.cpp b/EclipseEngine/EclipseEngine/Camera.cpp index 5698290c..bec7a3ef 100644 --- a/EclipseEngine/EclipseEngine/Camera.cpp +++ b/EclipseEngine/EclipseEngine/Camera.cpp @@ -1,4 +1,5 @@ #include "Camera.h" +#include "GameObject.h" #include "Logger.h" float Camera::scrollOffset = 0.0f; // Initialize static scroll offset @@ -10,6 +11,12 @@ Camera::Camera(int _width, int _height, glm::vec3 _position) Position = _position; } +void Camera::Update() +{ + UpdatePositionFromOwner(); + UpdateOrientationFromOwner(); +} + void Camera::UpdateMatrix(float nearPlane, float farPlane) { glm::mat4 view = glm::mat4(1.0f); @@ -25,6 +32,21 @@ void Camera::Matrix(Shader& shader, const char* uniform) glUniformMatrix4fv(glGetUniformLocation(shader.ID, uniform), 1, GL_FALSE, glm::value_ptr(cameraMatrix)); } +void Camera::UpdatePositionFromOwner() +{ + if (GameObject* owner = GetOwner()) { + Position = owner->transform.position; + } +} + +void Camera::UpdateOrientationFromOwner() +{ + if (GameObject* owner = GetOwner()) { + Orientation = owner->transform.rotation * glm::vec3(0.0f, 0.0f, 1.0f); + Up = owner->transform.rotation * glm::vec3(0.0f, 1.0f, 0.0f); + } +} + void Camera::Inputs(GLFWwindow* window) { // Normal Camera Movement (Arrow Keys)z diff --git a/EclipseEngine/EclipseEngine/Camera.h b/EclipseEngine/EclipseEngine/Camera.h index 213e0aa6..98227b55 100644 --- a/EclipseEngine/EclipseEngine/Camera.h +++ b/EclipseEngine/EclipseEngine/Camera.h @@ -14,13 +14,13 @@ #include "Shader.h" #include "Component.h" -class Camera +class Camera : public Component + { public: Camera(int widht, int height, glm::vec3 position); - //void Update() override; - + void Update() override; void UpdateMatrix(float nearPlane, float farPlane); void Matrix(Shader& shader, const char* uniform); void Inputs(GLFWwindow* window); //C @@ -30,6 +30,9 @@ class Camera static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); //C glm::vec3 GetRaycastHitPoint(GLFWwindow* window); + void UpdatePositionFromOwner(); + void UpdateOrientationFromOwner(); + public: glm::vec3 Position; // Camera's position glm::vec3 Orientation = glm::vec3(-1.0f, -0.5f, 1.0f); // Camera's orientetion @@ -43,6 +46,7 @@ class Camera int height; float nearPlane; float farPlane; + bool mainCamera = false; float speed = 0.1f; //C float sensitivity = 100.0f; //C diff --git a/EclipseEngine/EclipseEngine/Component.h b/EclipseEngine/EclipseEngine/Component.h index 3af0cf8e..cd62f125 100644 --- a/EclipseEngine/EclipseEngine/Component.h +++ b/EclipseEngine/EclipseEngine/Component.h @@ -8,6 +8,12 @@ class Component public: virtual ~Component() = default; virtual void Update() = 0; // To be overridden in each derived component + + void SetOwner(GameObject* owner) { this->owner = owner; } + GameObject* GetOwner() const { return owner; } + +private: + GameObject* owner = nullptr; // Reference to the owning GameObject }; #endif // COMPONENT_H \ No newline at end of file diff --git a/EclipseEngine/EclipseEngine/Core.cpp b/EclipseEngine/EclipseEngine/Core.cpp index 57ea5638..403ebc64 100644 --- a/EclipseEngine/EclipseEngine/Core.cpp +++ b/EclipseEngine/EclipseEngine/Core.cpp @@ -9,7 +9,7 @@ Core::Core() renderer = new Renderer(window); scene = new Scene(); - Logger::Log("Initialized Engine"); + Logger::Log("Initializing Engine"); } Core::~Core() @@ -22,6 +22,7 @@ bool Core::Initialize() window->Initialize(); renderer->Initialize(); scene->Initialize(); + Logger::Log("Initialized Engine"); return true; } diff --git a/EclipseEngine/EclipseEngine/GameObject.cpp b/EclipseEngine/EclipseEngine/GameObject.cpp index 4e27bc18..5fec5458 100644 --- a/EclipseEngine/EclipseEngine/GameObject.cpp +++ b/EclipseEngine/EclipseEngine/GameObject.cpp @@ -1,5 +1,6 @@ -#include "GameObject.h" #define STB_IMAGE_IMPLEMENTATION + +#include "GameObject.h" #include #include @@ -15,28 +16,20 @@ GameObject::~GameObject() void GameObject::Update() { - // placeholder for Update -} - -// Compute world transform -glm::mat4 GameObject::CalculateWorldTransform(const glm::mat4& parentTransform) const { - - if (parent) - { - return parentTransform * transform.GetMatrix(); // Combine parent's and local transform - } - else { - - return transform.GetMatrix(); + // Update the current GameObject + for (auto& component : components) { + component->Update(); } } -void GameObject::UpdateChildrenTransforms() +// Compute world transform +glm::mat4 GameObject::CalculateWorldTransform(const glm::mat4& parentTransform) const { - for (const auto& child : children) { - child->transform.SetMatrix(CalculateWorldTransform(child->parent->transform.GetMatrix())); - child->UpdateChildrenTransforms(); - } + if (parent){ + return parent->CalculateWorldTransform(parentTransform) * transform.GetMatrix(); // Combine parent's and local transform + } else { + return transform.GetMatrix(); + } } void GameObject::Draw(Shader& shader, Camera& camera, const glm::mat4& parentTransform) @@ -45,22 +38,15 @@ void GameObject::Draw(Shader& shader, Camera& camera, const glm::mat4& parentTra glm::mat4 objectModel = CalculateWorldTransform(parentTransform); // Get the transformation matrix from Transform // Activate the shader program - if(!material) - { - std::vector defaultTex{ Texture("Resources/Assets/Textures/default.png","diffuse", 0, GL_RGBA, GL_UNSIGNED_BYTE) }; - this->AddComponent(defaultTex); // Add a default material if none exists - } - shader.Activate(); shader.SetMat4("model", objectModel); shader.SetFloat("outlining", 1.05f); - - if(material) material.get()->BindTextures(shader); // If it has material, bind it - if (mesh) mesh->Draw(shader, camera); // Code to draw the game object (calls Draw on the mesh if it exists) + + if (Material* material = GetComponent()) material->BindTextures(shader); + if (Mesh* mesh = GetComponent()) mesh->Draw(shader, camera); for (const auto& child : children) { - glm::mat4 childModel = CalculateWorldTransform(parentTransform); - child->Draw(shader, camera, childModel); + child->Draw(shader, camera, objectModel); } } @@ -72,11 +58,6 @@ void GameObject::SetTexture(const std::string& texturePath) } } -GLuint GameObject::GetTextureID() const -{ - return textureID; -} - void GameObject::LoadTexture(const std::string& texturePath) { int width, height, channels; @@ -98,9 +79,9 @@ void GameObject::UpdateTexture(const std::string& texturePath) LoadTexture(texturePath); } -AABB GameObject::GetAABB() const { +AABB GameObject::GetAABB(){ AABB worldAABB; - if (mesh) { + if (Mesh* mesh = GetComponent()) { worldAABB = mesh->GetWorldAABB(transform.GetMatrix()); } for (const auto& child : children) { @@ -108,4 +89,27 @@ AABB GameObject::GetAABB() const { worldAABB.Expand(child->GetAABB().max); } return worldAABB; +} + +void GameObject::UpdateAABB(const glm::mat4& parentTransform) +{ + if (auto mesh = GetComponent()) { + localAABB = mesh->GetWorldAABB(parentTransform); + } + + for (const auto& child : children) { + child->UpdateAABB(CalculateWorldTransform(parentTransform)); + } +} + +void GameObject::DeleteAllComponents() { + components.clear(); +} + +void GameObject::DeleteAllChildren() { + for (auto& child : children) { + child->DeleteAllComponents(); + child->DeleteAllChildren(); + } + children.clear(); } \ No newline at end of file diff --git a/EclipseEngine/EclipseEngine/GameObject.h b/EclipseEngine/EclipseEngine/GameObject.h index 404c34ff..fa83bc1f 100644 --- a/EclipseEngine/EclipseEngine/GameObject.h +++ b/EclipseEngine/EclipseEngine/GameObject.h @@ -7,16 +7,15 @@ #include "Material.h" #include "Mesh.h" #include "Texture.h" +#include "Camera.h" #include "AABB.h" -class Mesh; // Forward declaration class GameObject : public std::enable_shared_from_this { public: std::string name; Transform transform; - std::unique_ptr material; // Using unique_ptr for automatic memory management - std::unique_ptr mesh; // Using unique_ptr for automatic memory management + std::vector> components; // Store components // Parent reference (nullable) std::shared_ptr parent; @@ -28,26 +27,29 @@ class GameObject : public std::enable_shared_from_this void Update(); // Update and draw the game object void Draw(Shader& shader, Camera& camera, const glm::mat4& parentTransform); - AABB GetAABB() const; // Returns the AABB in world space template - void AddComponent(Args&&... args); // Add a component to the game object - inline void AddChild(std::shared_ptr child); // Add a child game object - + T* AddComponent(Args&&... args); // Add a component to the game object template - T* GetComponent(); // Retrieve a component of a specific type - std::string GetName() const { return name; } - const std::list>& GetChildren() const { return children; } // Add a child game object + void RemoveComponent(); // Remove a component of a specific type + template + T* GetComponent(); // Get a component of a specific type + void DeleteAllComponents(); bool HasParent() const { return parent != nullptr; } - void UpdateChildrenTransforms(); + inline void AddChild(std::shared_ptr child); // Add a child game object + void DeleteAllChildren(); + const std::list>& GetChildren() const { return children; } // Add a child game object glm::mat4 CalculateWorldTransform(const glm::mat4& parentTransform) const; // Helper to calculate world transform - + std::string GetName() const { return name; } + AABB GetAABB(); // Returns the AABB in world space + void UpdateAABB(const glm::mat4& parentTransform); void SetTexture(const std::string& texturePath); - GLuint GetTextureID() const; + GLuint GetTextureID() const { return textureID; } private: + AABB localAABB; GLuint textureID; std::string currentTexturePath; void LoadTexture(const std::string& texturePath); @@ -57,26 +59,31 @@ class GameObject : public std::enable_shared_from_this // Template member function definitions should go here as well template -void GameObject::AddComponent(Args&&... args) { - if constexpr (std::is_same::value) { - mesh = std::make_unique(std::forward(args)...); - } - else if constexpr (std::is_same::value) { - material = std::make_unique(std::forward(args)...); - } - // Add more components as needed +T* GameObject::AddComponent(Args&&... args) { + static_assert(std::is_base_of::value, "T must be derived from Component"); + auto component = std::make_unique(std::forward(args)...); + component->SetOwner(this); + T* componentPtr = component.get(); + components.push_back(std::move(component)); + return componentPtr; +} + +template +void GameObject::RemoveComponent() { + static_assert(std::is_base_of::value, "T must be derived from Component"); + components.erase(std::remove_if(components.begin(), components.end(), + [](const std::unique_ptr& component) { + return dynamic_cast(component.get()) != nullptr; + }), components.end()); } template T* GameObject::GetComponent() { - if constexpr (std::is_same::value) { - return &transform; // Return the address of the Transform - } - else if constexpr (std::is_same::value) { - return material.get(); // Return the raw pointer of the unique_ptr - } - else if constexpr (std::is_same::value) { - return mesh.get(); // Return the raw pointer of the unique_ptr + static_assert(std::is_base_of::value, "T must be derived from Component"); + for (const auto& component : components) { + if (T* castedComponent = dynamic_cast(component.get())) { + return castedComponent; + } } return nullptr; // If no matching component, return nullptr } diff --git a/EclipseEngine/EclipseEngine/ModelLoader.cpp b/EclipseEngine/EclipseEngine/ModelLoader.cpp index 3e819d1d..49de2a2d 100644 --- a/EclipseEngine/EclipseEngine/ModelLoader.cpp +++ b/EclipseEngine/EclipseEngine/ModelLoader.cpp @@ -26,7 +26,7 @@ std::shared_ptr ModelLoader::LoadModel(const std::string& path) { ProcessNode(scene->mRootNode->mChildren[i], scene, model); } - return std::move(model); + return model; } std::shared_ptr ModelLoader::ProcessNode(aiNode* node, const aiScene* scene, std::shared_ptr& parent) { @@ -129,34 +129,34 @@ void ModelLoader::ProcessMesh(aiMesh* mesh, const aiScene* scene, } } - // Process textures - //if (mesh->mMaterialIndex >= 0) { - // aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; - // textures = LoadMaterialTextures(material, aiTextureType_DIFFUSE, "diffuse"); - //} + //Process textures + if (mesh->mMaterialIndex >= 0) { + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + textures = LoadMaterialTextures(material, aiTextureType_DIFFUSE, "diffuse"); + } +} + +std::vector ModelLoader::LoadMaterialTextures(aiMaterial* mat, aiTextureType type, const std::string& typeName) +{ + std::vector textures; + std::set loadedTextures; // To track loaded texture paths + + for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) + { + aiString str; // For texture file path + mat->GetTexture(type, i, &str); + + // Check if texture is already loaded + if (loadedTextures.find(str.C_Str()) != loadedTextures.end()) + { + continue; // Skip if already loaded + } + + // Load the texture and add it to the vector + Texture texture(str.C_Str(), typeName, textures.size(), GL_RGBA, GL_UNSIGNED_BYTE); + textures.push_back(texture); + loadedTextures.insert(str.C_Str()); // Track the loaded texture path + } + return textures; } -//std::vector ModelLoader::LoadMaterialTextures(aiMaterial* mat, aiTextureType type, const std::string& typeName) -//{ -// std::vector textures; -// std::set loadedTextures; // To track loaded texture paths -// -// for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) -// { -// aiString str; // For texture file path -// mat->GetTexture(type, i, &str); -// -// // Check if texture is already loaded -// if (loadedTextures.find(str.C_Str()) != loadedTextures.end()) -// { -// continue; // Skip if already loaded -// } -// -// // Load the texture and add it to the vector -// Texture texture(str.C_Str(), typeName, textures.size(), GL_RGBA, GL_UNSIGNED_BYTE); -// textures.push_back(texture); -// loadedTextures.insert(str.C_Str()); // Track the loaded texture path -// } -// return textures; -//} -// diff --git a/EclipseEngine/EclipseEngine/Scene.cpp b/EclipseEngine/EclipseEngine/Scene.cpp index e121d1dd..f197e2f8 100644 --- a/EclipseEngine/EclipseEngine/Scene.cpp +++ b/EclipseEngine/EclipseEngine/Scene.cpp @@ -12,15 +12,27 @@ Scene::~Scene() bool Scene::Initialize() { - activeCamera = new Camera(1500, 844, glm::vec3(7.0f, 4.0f, -7.0f)); - auto initScene = modelLoader.LoadModel("Resources/Assets/fbx_files/Street/untitled.fbx"); - AddGameObject(initScene); + //activeCamera = new Camera(1500, 844, glm::vec3(7.0f, 4.0f, -7.0f)); + auto cameraGO = std::make_shared(); + cameraGO->name = "Main Camera"; + cameraGO->AddComponent(1500, 844, glm::vec3(7.0f, 4.0f, -7.0f)); + SetActiveCamera(cameraGO->GetComponent()); + AddGameObject(cameraGO); + //auto initScene = modelLoader.LoadModel("Resources/Assets/fbx_files/Street/untitled.fbx"); + //AddGameObject(initScene); return true; } bool Scene::Update(double dt) { - activeCamera->UpdateMatrix(0.1f, 100.0f); + if (activeCamera) + { + activeCamera->UpdateMatrix(0.1f, 100.0f); + } + for (auto& obj : gameObjects) + { + obj->Update(); + } return true; } @@ -38,9 +50,18 @@ void Scene::AddGameObject(std::shared_ptr go) gameObjects.push_back(std::move(go)); } -void Scene::SetActiveCamera(Camera camera) +void Scene::AddEmptyGameObject() { - activeCamera = &camera; + auto emptyGameObject = std::make_shared(); + emptyGameObject->name = "Empty GameObject"; + gameObjects.push_back(emptyGameObject); +} + + +void Scene::SetActiveCamera(Camera* camera) +{ + if (activeCamera != camera) + activeCamera = camera; } void Scene::AddCube() @@ -74,28 +95,21 @@ void Scene::AddCube() }; std::vector catTexture { - Texture("Resources/Assets/Textures/checkerboard.png","diffuse", 0, GL_RGBA, GL_UNSIGNED_BYTE) + Texture("Resources/Assets/Textures/default.png","diffuse", 0, GL_RGBA, GL_UNSIGNED_BYTE) }; auto cube = std::make_shared(); // This has to be in the engine side (SCENE) cube.get()->name = "cube"; cube->AddComponent(vertices, indices, catTexture); - cube->AddComponent( catTexture); cube->transform.position = glm::vec3(0.0f, 0.0f, 0.0f); - auto cube2 = std::make_shared(); - cube2.get()->name = "cube2"; - cube2->AddComponent(vertices, indices, catTexture); - cube2->AddComponent(catTexture); - cube2->transform.position = glm::vec3(2.0f, 0.0f, 0.0f); - - auto cube3 = std::make_shared(); - cube3.get()->name = "cube2"; - cube3->AddComponent(vertices, indices, catTexture); - cube3->AddComponent(catTexture); - - cube.get()->AddChild(cube2); - //cube.get()->AddChild(cube3); AddGameObject(cube); Logger::Log("Cube added to the scene"); +} + +void Scene::DeleteGameObject(const std::shared_ptr& go) +{ + go->DeleteAllComponents(); + go->DeleteAllChildren(); + gameObjects.remove(go); } \ No newline at end of file diff --git a/EclipseEngine/EclipseEngine/Scene.h b/EclipseEngine/EclipseEngine/Scene.h index cc33878d..d27254a1 100644 --- a/EclipseEngine/EclipseEngine/Scene.h +++ b/EclipseEngine/EclipseEngine/Scene.h @@ -20,7 +20,9 @@ class Scene Camera* GetActiveCamera() const { return activeCamera; } void AddGameObject(std::shared_ptr go); - void SetActiveCamera(Camera camera); + void AddEmptyGameObject(); + void SetActiveCamera(Camera* camera); + void DeleteGameObject(const std::shared_ptr& go); void AddCube(); diff --git a/EclipseEngine/EclipseEngine/Transform.cpp b/EclipseEngine/EclipseEngine/Transform.cpp index f594b9cf..b6dd3943 100644 --- a/EclipseEngine/EclipseEngine/Transform.cpp +++ b/EclipseEngine/EclipseEngine/Transform.cpp @@ -40,8 +40,7 @@ glm::mat4 Transform::GetMatrix() const glm::mat4 Transform::GetWorldMatrix(const glm::mat4& parentMatrix) const { - glm::mat4 localTransform = GetMatrix(); - return parentMatrix * localTransform; + return parentMatrix * GetMatrix(); } void Transform::SetMatrix(const glm::mat4& matrix) @@ -100,5 +99,4 @@ glm::vec3 Transform::GetEulerAngles() const void Transform::Update() { - // If you need to do any updates before rendering, do it here } diff --git a/Images/AssetsPanel.png b/Images/AssetsPanel.png new file mode 100644 index 00000000..bb6ab046 Binary files /dev/null and b/Images/AssetsPanel.png differ diff --git a/Images/AssetsPanel2.png b/Images/AssetsPanel2.png new file mode 100644 index 00000000..cc2424bd Binary files /dev/null and b/Images/AssetsPanel2.png differ diff --git a/Images/DepthTest.png b/Images/DepthTest.png new file mode 100644 index 00000000..4bd45a3d Binary files /dev/null and b/Images/DepthTest.png differ diff --git a/Images/DepthTest2.png b/Images/DepthTest2.png new file mode 100644 index 00000000..c53e87e1 Binary files /dev/null and b/Images/DepthTest2.png differ diff --git a/Images/NormalsTest.png b/Images/NormalsTest.png new file mode 100644 index 00000000..adacbf6c Binary files /dev/null and b/Images/NormalsTest.png differ diff --git a/Images/NormalsTest2.png b/Images/NormalsTest2.png new file mode 100644 index 00000000..bd69f687 Binary files /dev/null and b/Images/NormalsTest2.png differ diff --git a/Images/PositionTest.png b/Images/PositionTest.png new file mode 100644 index 00000000..2b2e1228 Binary files /dev/null and b/Images/PositionTest.png differ diff --git a/Images/TransformButtons.png b/Images/TransformButtons.png new file mode 100644 index 00000000..8bca15db Binary files /dev/null and b/Images/TransformButtons.png differ diff --git a/Images/demo1.png b/Images/demo1.png new file mode 100644 index 00000000..e8dafe20 Binary files /dev/null and b/Images/demo1.png differ diff --git a/Images/demo2.png b/Images/demo2.png new file mode 100644 index 00000000..67d70dd5 Binary files /dev/null and b/Images/demo2.png differ