diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index c6da6f1f..202a3852 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -56,46 +56,58 @@ namespace Sandbox ) { // Set working directory - SHADE::SHFileUtilities::SetWorkDirToExecDir(); + SHFileUtilities::SetWorkDirToExecDir(); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); // Create Systems - SHADE::SHSystemManager::CreateSystem(); - SHADE::SHSystemManager::CreateSystem(); - SHADE::SHSystemManager::CreateSystem(); - SHADE::SHSystemManager::CreateSystem(); - SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); - SHADE::SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + SHGraphicsSystem* graphicsSystem = static_cast(SHSystemManager::GetSystem()); + SHSystemManager::CreateSystem(); + +#ifdef SHEDITOR + SDL_Init(SDL_INIT_VIDEO); + sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); + SHSystemManager::CreateSystem(); + SHSystemManager::GetSystem()->SetSDLWindow(sdlWindow); +#endif // Create Routines - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + +#ifdef SHEDITOR + SHSystemManager::RegisterRoutine(); +#endif - SHADE::SHComponentManager::CreateComponentSparseSet(); - SHADE::SHComponentManager::CreateComponentSparseSet(); - SHADE::SHComponentManager::CreateComponentSparseSet(); - SHADE::SHComponentManager::CreateComponentSparseSet(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); //TODO: REMOVE AFTER PRESENTATION - //SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf"); - SHADE::SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh"); - //SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); - //SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); - SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex"); + //SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf"); + SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh"); + //SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); + //SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); + SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex"); //TODO: REMOVE AFTER PRESENTATION @@ -103,19 +115,12 @@ namespace Sandbox auto id2 = SHFamilyID::GetID(); auto id3 = SHFamilyID::GetID(); - SHADE::SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); // Set up graphics system and windows graphicsSystem->SetWindow(&window); - SHADE::SHSystemManager::Init(); - #ifdef SHEDITOR - SDL_Init(SDL_INIT_VIDEO); - sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); - SHADE::SHEditor::Initialise(sdlWindow); - #else - #endif - + SHSystemManager::Init(); SHSceneManager::InitSceneManager("TestScene"); @@ -124,26 +129,15 @@ namespace Sandbox void SBApplication::Update(void) { - SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); + SHGraphicsSystem* graphicsSystem = SHADE::SHSystemManager::GetSystem(); //TODO: Change true to window is open while (!window.WindowShouldClose()) { SHFrameRateController::UpdateFRC(); SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime()); SHSceneManager::UpdateSceneManager(); - SHSceneManager::SceneUpdate(1/60.0f); - //#ifdef SHEDITOR - //#endif - graphicsSystem->BeginRender(); - - #ifdef SHEDITOR - SHADE::SHEditor::Update(0.16f); - #endif - - graphicsSystem->Run(1.0f); - graphicsSystem->EndRender(); - - SHADE::SHSystemManager::RunRoutines(false, 0.016f); + SHSceneManager::SceneUpdate(0.016f); + SHSystemManager::RunRoutines(false, 0.016f); } // Finish all graphics jobs first @@ -154,13 +148,12 @@ namespace Sandbox void SBApplication::Exit(void) { #ifdef SHEDITOR - SHADE::SHEditor::Exit(); SDL_DestroyWindow(sdlWindow); SDL_Quit(); - #endif + #endif SHSceneManager::Exit(); - SHADE::SHSystemManager::Exit(); + SHSystemManager::Exit(); } } diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 3b277e6c..f1d656ee 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -99,13 +99,15 @@ namespace Sandbox renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f)); //Set initial positions - transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f)}); + transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) }); //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldScale(TEST_OBJ_SCALE); - auto* box = collider.AddBoundingBox(); - box->SetHalfExtents(transform.GetWorldScale() * 0.5f); + if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) + collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero); + else + collider.AddBoundingSphere(0.5f, SHVec3::Zero); stressTestObjects.emplace_back(entity); } @@ -133,12 +135,12 @@ namespace Sandbox floorRenderable.SetMaterial(customMat); floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); - floorTransform.SetWorldScale({7.5f, 0.5f, 7.5}); - floorTransform.SetWorldPosition({0.0f, -3.0f, -5.0f}); + floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 }); + floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f }); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); - auto* floorBox = floorCollider.AddBoundingBox(); + auto* floorBox = floorCollider.AddBoundingBox(); floorBox->SetHalfExtents(floorTransform.GetWorldScale() * 0.5f); // Create blank entity with a script diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 25cd5a6a..0f25175f 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -6,11 +6,11 @@ //#==============================================================# //|| SHADE Includes || //#==============================================================# +#include "Editor/SHEditor.hpp" #include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHEditorWidgets.hpp" #include "SHHierarchyPanel.h" #include "ECS_Base/Managers/SHEntityManager.h" -#include "Editor/SHEditor.hpp" #include "Scene/SHSceneManager.h" #include "Editor/DragDrop/SHDragDrop.hpp" #include "Tools/SHException.h" @@ -62,7 +62,8 @@ namespace SHADE if(ImGui::IsWindowHovered() && !SHDragDrop::hasDragDrop && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { - SHEditor::selectedEntities.clear(); + if(auto editor = SHSystemManager::GetSystem()) + editor->selectedEntities.clear(); } ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal); ImGui::End(); @@ -102,7 +103,9 @@ namespace SHADE //Get node data (Children, eid, selected) auto& children = currentNode->GetChildren(); EntityID eid = currentNode->GetEntityID(); - const bool isSelected = (std::ranges::find(SHEditor::selectedEntities, eid) != SHEditor::selectedEntities.end()); + auto editor = SHSystemManager::GetSystem(); + + const bool isSelected = (std::ranges::find(editor->selectedEntities, eid) != editor->selectedEntities.end()); const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow); @@ -140,8 +143,8 @@ namespace SHADE { if(!isSelected) { - SHEditor::selectedEntities.clear(); - SHEditor::selectedEntities.push_back(eid); + editor->selectedEntities.clear(); + editor->selectedEntities.push_back(eid); } if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) { @@ -163,19 +166,19 @@ namespace SHADE if (!isSelected) { if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) - SHEditor::selectedEntities.clear(); - SHEditor::selectedEntities.push_back(eid); + editor->selectedEntities.clear(); + editor->selectedEntities.push_back(eid); }//if not selected else { if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) { - auto it = std::ranges::remove(SHEditor::selectedEntities, eid).begin(); + auto it = std::ranges::remove(editor->selectedEntities, eid).begin(); }//if mod ctrl is not pressed else { - SHEditor::selectedEntities.clear(); - SHEditor::selectedEntities.push_back(eid); + editor->selectedEntities.clear(); + editor->selectedEntities.push_back(eid); } }//if selected }//if left mouse button released diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 93ad344b..77ec5b03 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -12,19 +12,20 @@ #include "Editor/IconsMaterialDesign.h" #include "ECS_Base/Components/SHComponent.h" #include "Editor/SHEditorWidgets.hpp" +#include "Physics/Components/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" namespace SHADE { template::value, bool> = true> static void DrawContextMenu(T* component) { - if(!component) + if (!component) return; rttr::string_view componentName = rttr::type::get().get_name(); if (ImGui::BeginPopupContextItem(componentName.data())) { - + if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data())) { //SHClipboardUtil::WriteStringToClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT, SHComponentToString(component)); @@ -56,26 +57,26 @@ namespace SHADE { auto const& type = property.get_type(); - if(type.is_enumeration()) + if (type.is_enumeration()) { auto enumAlign = type.get_enumeration(); auto names = enumAlign.get_names(); std::vector list; - for(auto const& name : names) + for (auto const& name : names) list.push_back(name.data()); - SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx) - { - auto enumAlign = property.get_enumeration(); - auto values = enumAlign.get_values(); - auto it = std::next(values.begin(), idx); - property.set_value(component, *it); - }); + SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& idx) + { + auto enumAlign = property.get_enumeration(); + auto values = enumAlign.get_values(); + auto it = std::next(values.begin(), idx); + property.set_value(component, *it); + }); } - else if(type.is_arithmetic()) + else if (type.is_arithmetic()) { if (type == rttr::type::get()) { - SHEditorWidgets::CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);}); + SHEditorWidgets::CheckBox(property.get_name().data(), [component, property] {return property.get_value(component).to_bool(); }, [component, property](bool const& result) {property.set_value(component, result); }); } //else if (type == rttr::type::get()) //{ @@ -85,39 +86,39 @@ namespace SHADE { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin && metaMax) + if (metaMin && metaMax) { - SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); + SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); + SHEditorWidgets::DragInt(property.get_name().data(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); } } else if (type == rttr::type::get()) { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin.is_valid() && metaMax.is_valid()) + if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value(), metaMax.template get_value(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, "%zu"); } else { - SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); + SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U8, [component, property] {return property.get_value(component).to_uint8(); }, [component, property](uint8_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu"); } } else if (type == rttr::type::get()) { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin.is_valid() && metaMax.is_valid()) + if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMin.template get_value(), [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},"%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); } else { - SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); + SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U16, [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu"); } } else if (type == rttr::type::get()) @@ -126,50 +127,50 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMin.template get_value(), [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },"%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMin.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); } else { - SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu"); + SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U32, [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu"); } } else if (type == rttr::type::get()) { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin.is_valid() && metaMax.is_valid()) + if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMin.template get_value(), [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},"%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); } else { - SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); + SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_U64, [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, 0.1f, 0, 0, "%zu"); } } else if (type == rttr::type::get()) { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin.is_valid() && metaMax.is_valid()) + if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); + SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragFloat(property.get_name().data(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); + SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); } } else if (type == rttr::type::get()) { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); - if(metaMin.is_valid() && metaMax.is_valid()) + if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMin.template get_value(), [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f); + SHEditorWidgets::DragScalar(property.get_name().data(), ImGuiDataType_Double, [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }, 0.1f); } } } @@ -183,9 +184,74 @@ namespace SHADE } else if (type == rttr::type::get()) { - SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); }); + SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y" }, [component, property]() {return property.get_value(component).template convert(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); }); } - + + } + } + else DrawContextMenu(component); + } + + template<> + static void DrawComponent(SHColliderComponent* component) + { + if (!component) + return; + const auto componentType = rttr::type::get(*component); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); + ImGui::SameLine(); + if (ImGui::CollapsingHeader(componentType.get_name().data())) + { + DrawContextMenu(component); + + auto& colliders = component->GetColliders(); + int const size = static_cast(colliders.size()); + ImGui::BeginChild("Colliders", {0.0f, colliders.empty() ? 1.0f : 250.0f}, true); + for (int i{}; i < size; ++i) + { + SHCollider& collider = component->GetCollider(i); + auto cursorPos = ImGui::GetCursorPos(); + + if (collider.GetType() == SHCollider::Type::BOX) + { + SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_MD_VIEW_IN_AR, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); + auto box = reinterpret_cast(collider.GetShape()); + SHEditorWidgets::DragVec3("Half Extents", { "X", "Y", "Z" }, [box] {return box->GetHalfExtents(); }, [box](SHVec3 const& vec) {box->SetHalfExtents(vec);}); + } + else if (collider.GetType() == SHCollider::Type::SPHERE) + { + SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); + auto sphere = reinterpret_cast(collider.GetShape()); + SHEditorWidgets::DragFloat("Radius", [sphere] {return sphere->GetRadius(); }, [sphere](float const& value) {sphere->SetRadius(value);}); + } + else if (collider.GetType() == SHCollider::Type::CAPSULE) + { + + } + { + SHEditorWidgets::BeginPanel("Offset", { ImGui::GetContentRegionAvail().x, 30.0f }); + SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider.GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider.SetPositionOffset(vec); }); + SHEditorWidgets::EndPanel(); + } + if(ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data())) + { + component->RemoveCollider(i); + } + SHEditorWidgets::EndPanel(); + } + ImGui::EndChild(); + + if (ImGui::BeginMenu("Add Collider")) + { + if(ImGui::Selectable("Box Collider")) + { + component->AddBoundingBox(); + } + if(ImGui::Selectable("Sphere Collider")) + { + component->AddBoundingSphere(); + } + ImGui::EndMenu(); } } else DrawContextMenu(component); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index 3d00ac4b..a9b1c724 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -1,5 +1,6 @@ #include "SHpch.h" +#include "Editor/SHEditor.hpp" #include "SHEditorInspector.h" #include "ECS_Base/SHECSMacros.h" @@ -7,7 +8,6 @@ #include "ECS_Base/Managers/SHEntityManager.h" #include "Math/Transform/SHTransformComponent.h" -#include "Editor/SHEditor.hpp" #include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHEditorWidgets.hpp" #include "SHEditorComponentView.hpp" @@ -24,12 +24,15 @@ namespace SHADE { template, bool> = true> - void DrawAddComponentButton(EntityID const& eid) + bool DrawAddComponentButton(EntityID const& eid) { - if(!SHComponentManager::HasComponent(eid) && ImGui::Selectable(std::format("Add {}", rttr::type::get().get_name().data()).data())) + bool selected = false; + if(!SHComponentManager::HasComponent(eid)) { - SHComponentManager::AddComponent(eid); + if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get().get_name().data()).data()); selected) + SHComponentManager::AddComponent(eid); } + return selected; } SHEditorInspector::SHEditorInspector() @@ -47,15 +50,10 @@ namespace SHADE SHEditorWindow::Update(); if (Begin()) { - if (ImGui::Button("AUDIO")) + auto editor = SHSystemManager::GetSystem(); + if (editor && !editor->selectedEntities.empty()) { - auto audioSystem = SHSystemManager::GetSystem(); - audioSystem->PlayEventOnce("event:/Characters/sfx_footsteps_raccoon"); - } - - if (!SHEditor::selectedEntities.empty()) - { - EntityID const& eid = SHEditor::selectedEntities[0]; + EntityID const& eid = editor->selectedEntities[0]; SHEntity* entity = SHEntityManager::GetEntityByID(eid); ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid); @@ -90,7 +88,13 @@ namespace SHADE DrawAddComponentButton(eid); DrawAddComponentButton(eid); DrawAddComponentButton(eid); - DrawAddComponentButton(eid); + if(DrawAddComponentButton(eid)) + { + if(SHComponentManager::GetComponent_s(eid) == nullptr) + { + SHComponentManager::AddComponent(eid); + } + } ImGui::EndMenu(); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 8e26ae78..a49af994 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -3,11 +3,11 @@ //#==============================================================# //|| SHADE Includes || //#==============================================================# +#include "Editor/SHEditor.hpp" #include "SHEditorMenuBar.h" #include "Editor/IconsMaterialDesign.h" #include "Editor/Command/SHCommandManager.h" #include "Scripting/SHScriptEngine.h" -#include "Editor/SHEditor.hpp" #include "ECS_Base/Managers/SHSystemManager.h" //#==============================================================# @@ -95,7 +95,8 @@ namespace SHADE { if(ImGui::Selectable(style.to_string().c_str())) { - SHEditor::SetStyle(style.convert()); + if(auto editor = SHSystemManager::GetSystem()) + editor->SetStyle(style.convert()); } } ImGui::EndMenu(); diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index e94f7398..d9fc8373 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -60,18 +60,18 @@ RTTR_REGISTRATION namespace SHADE { //#==============================================================# - //|| Initialise static members || + //|| Init static members || //#==============================================================# - Handle SHEditor::imguiCommandPool; - Handle SHEditor::imguiCommandBuffer; - SHEditor::EditorWindowMap SHEditor::editorWindows{}; - SHEditor::EditorWindowID SHEditor::windowCount{}; - std::vector SHEditor::selectedEntities; + //Handle SHEditor::imguiCommandPool; + //Handle SHEditor::imguiCommandBuffer; + SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{}; + SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{}; + //std::vector SHEditor::selectedEntities; //#==============================================================# //|| Public Member Functions || //#==============================================================# - void SHEditor::Initialise(SDL_Window* const sdlWindow) + void SHEditor::Init() { IMGUI_CHECKVERSION(); if(auto context = ImGui::CreateContext()) @@ -90,28 +90,28 @@ namespace SHADE InitFonts(); - auto id = SHFamilyID::GetID(); auto id2 = SHFamilyID::GetID(); auto id3 = SHFamilyID::GetID(); - InitBackend(sdlWindow); + + InitBackend(); SetStyle(Style::SHADE); //Add editor windows - CreateEditorWindow(); - CreateEditorWindow(); - CreateEditorWindow(); - CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); SHLOG_INFO("Successfully initialised SHADE Engine Editor") } - void SHEditor::Update(float const dt) + void SHEditor::Update(double const dt) { (void)dt; NewFrame(); - for (const auto& window : editorWindows | std::views::values) + for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) { if(window->isOpen) window->Update(); @@ -147,7 +147,7 @@ namespace SHADE ImFont* mainFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path static const ImWchar icon_ranges[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 }; - ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.PixelSnapH = true; + ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f; ImFont* UIFont = io.Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges); //TODO: Change to config based assets path io.Fonts->Build(); @@ -260,7 +260,7 @@ namespace SHADE //#==============================================================# //|| Private Member Functions || //#==============================================================# - void SHEditor::InitBackend(SDL_Window* sdlWindow) + void SHEditor::InitBackend() { if(ImGui_ImplSDL2_InitForVulkan(sdlWindow) == false) { @@ -322,4 +322,9 @@ namespace SHADE } + void SHEditor::EditorRoutine::Execute(double dt) noexcept + { + reinterpret_cast(system)->Update(dt); + } + }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/SHEditor.hpp b/SHADE_Engine/src/Editor/SHEditor.hpp index 467cbcd0..d579a9b5 100644 --- a/SHADE_Engine/src/Editor/SHEditor.hpp +++ b/SHADE_Engine/src/Editor/SHEditor.hpp @@ -11,6 +11,8 @@ //#==============================================================# #include "SH_API.h" #include "ECS_Base/SHECSMacros.h" +#include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/System/SHSystemRoutine.h" #include "Resource/Handle.h" #include "EditorWindow/SHEditorWindow.h" #include "Tools/SHLogger.h" @@ -28,11 +30,7 @@ namespace SHADE class SHVkCommandBuffer; class SHVkCommandPool; - /** - * @brief SHEditor static class contains editor variables and implementation of editor functions. - * - */ - class SH_API SHEditor + class SHEditorWindowManager { public: //#==============================================================# @@ -41,46 +39,6 @@ namespace SHADE using EditorWindowID = uint8_t; using EditorWindowPtr = std::unique_ptr; using EditorWindowMap = std::unordered_map; - - /** - * @brief Style options - * - */ - enum class Style : uint8_t - { - SHADE, - DARK, - LIGHT, - CLASSIC - }; - - /** - * @brief Initialise the editor - * - * @param sdlWindow pointer to SDL_Window object created in application - */ - static void Initialise(SDL_Window* sdlWindow); - - /** - * @brief Update the editor and add to ImGui DrawList - * - * @param dt Delta-time of the frame - */ - static void Update(float dt); - - /** - * @brief Safely shutdown the editor - * - */ - static void Exit(); - - /** - * @brief Set the Style for the editor - * - * @param style Desired style - */ - static void SetStyle(Style style); - /** * @brief Get ID for the Editor Window Type * @@ -100,39 +58,6 @@ namespace SHADE return id; } - /** - * @brief Get pointer to the Editor Window - * - * @tparam T Type of editor window to retrieve - * @return T* Pointer to the editor window - */ - template , bool> = true> - static T* GetEditorWindow() - { - return reinterpret_cast(editorWindows[GetEditorWindowID()].get()); - } - - // List of selected entities - static std::vector selectedEntities; - - private: - /** - * @brief Initialise Backend for ImGui (SDL and Vulkan backend) - * - * @param sdlWindow Pointer to SDL_Window - */ - static void InitBackend(SDL_Window* sdlWindow); - /** - * @brief Start new frame for editor - * - */ - static void NewFrame(); - /** - * @brief Perform ImGui and ImGui Backend Render - * - */ - static void Render(); - /** * @brief Create an Editor Window * @@ -153,16 +78,114 @@ namespace SHADE } } - static void InitFonts() noexcept; - - // Handle to command pool used for ImGui Vulkan Backend - static Handle imguiCommandPool; - // Handle to command buffer used for ImGui Vulkan Backend - static Handle imguiCommandBuffer; + /** + * @brief Get pointer to the Editor Window + * + * @tparam T Type of editor window to retrieve + * @return T* Pointer to the editor window + */ + template , bool> = true> + static T* GetEditorWindow() + { + return reinterpret_cast(editorWindows[GetEditorWindowID()].get()); + } + private: // Number of windows; used for Editor Window ID Generation static EditorWindowID windowCount; // Map of Editor Windows static EditorWindowMap editorWindows; + friend class SHEditor; + }; + + /** + * @brief SHEditor static class contains editor variables and implementation of editor functions. + * + */ + class SH_API SHEditor final : public SHSystem + { + public: + + + class SH_API EditorRoutine final : public SHSystemRoutine + { + public: + EditorRoutine() = default; + void Execute(double dt) noexcept override final; + }; + + /** + * @brief Style options + * + */ + enum class Style : uint8_t + { + SHADE, + DARK, + LIGHT, + CLASSIC + }; + + /** + * @brief Initialise the editor + * + * @param sdlWindow pointer to SDL_Window object created in application + */ + void Init(); + + /** + * @brief Update the editor and add to ImGui DrawList + * + * @param dt Delta-time of the frame + */ + void Update(double dt); + + /** + * @brief Safely shutdown the editor + * + */ + void Exit(); + + /** + * @brief Set the Style for the editor + * + * @param style Desired style + */ + void SetStyle(Style style); + + /** + * @brief Initialise Backend for ImGui (SDL and Vulkan backend) + * + * @param sdlWindow Pointer to SDL_Window + */ + void InitBackend(); + + void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;}; + + // List of selected entities + std::vector selectedEntities; + + private: + /** + * @brief Start new frame for editor + * + */ + void NewFrame(); + /** + * @brief Perform ImGui and ImGui Backend Render + * + */ + void Render(); + + + + void InitFonts() noexcept; + + // Handle to command pool used for ImGui Vulkan Backend + Handle imguiCommandPool; + // Handle to command buffer used for ImGui Vulkan Backend + Handle imguiCommandBuffer; + + SDL_Window* sdlWindow; };//class SHEditor }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 8d2adcc6..3fa1789e 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -26,7 +26,7 @@ namespace SHADE { class SH_API SHEditorWidgets { - public: + public: //#==============================================================# //|| Constructor || //#==============================================================# @@ -35,6 +35,118 @@ namespace SHADE //#==============================================================# //|| Custom Widgets || //#==============================================================# + inline static ImVector panelStack{}; + static void BeginPanel(std::string_view const& name, const ImVec2& size) + { + ImGui::BeginGroup(); + + auto cursorPos = ImGui::GetCursorScreenPos(); + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + ImGui::BeginGroup(); + + ImVec2 effectiveSize = size; + if (size.x < 0.0f) + effectiveSize.x = ImGui::GetContentRegionAvail().x; + else + effectiveSize.x = size.x; + ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f)); + + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::BeginGroup(); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::TextUnformatted(name.data()); + auto labelMin = ImGui::GetItemRectMin(); + auto labelMax = ImGui::GetItemRectMax(); + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y)); + ImGui::BeginGroup(); + + ImGui::PopStyleVar(2); + + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f; + + ImGui::GetCurrentWindow()->Size.x -= frameHeight; + + auto itemWidth = ImGui::CalcItemWidth(); + ImGui::PushItemWidth(ImMax(0.0f, itemWidth - frameHeight)); + + panelStack.push_back(ImRect(labelMin, labelMax)); + } + + static void EndPanel() + { + ImGui::PopItemWidth(); + + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + + ImGui::EndGroup(); + + ImGui::EndGroup(); + + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y)); + + ImGui::EndGroup(); + + auto itemMin = ImGui::GetItemRectMin(); + auto itemMax = ImGui::GetItemRectMax(); + + auto labelRect = panelStack.back(); + panelStack.pop_back(); + + ImVec2 halfFrame = ImVec2(frameHeight * 0.25f, frameHeight) * 0.5f; + ImRect frameRect = ImRect(itemMin + halfFrame, itemMax - ImVec2(halfFrame.x, 0.0f)); + labelRect.Min.x -= itemSpacing.x; + labelRect.Max.x += itemSpacing.x; + for (int i = 0; i < 4; ++i) + { + switch (i) + { + // left half-plane + case 0: ImGui::PushClipRect(ImVec2(-FLT_MAX, -FLT_MAX), ImVec2(labelRect.Min.x, FLT_MAX), true); break; + // right half-plane + case 1: ImGui::PushClipRect(ImVec2(labelRect.Max.x, -FLT_MAX), ImVec2(FLT_MAX, FLT_MAX), true); break; + // top + case 2: ImGui::PushClipRect(ImVec2(labelRect.Min.x, -FLT_MAX), ImVec2(labelRect.Max.x, labelRect.Min.y), true); break; + // bottom + case 3: ImGui::PushClipRect(ImVec2(labelRect.Min.x, labelRect.Max.y), ImVec2(labelRect.Max.x, FLT_MAX), true); break; + } + + ImGui::GetWindowDrawList()->AddRect( + frameRect.Min, frameRect.Max, + ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Button)), + halfFrame.x); + + ImGui::PopClipRect(); + } + + ImGui::PopStyleVar(2); + + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f; + + ImGui::GetCurrentWindow()->Size.x += frameHeight; + + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + + ImGui::EndGroup(); + } + static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f) { ImGuiWindow* window = ImGui::GetCurrentWindow(); @@ -44,7 +156,7 @@ namespace SHADE bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness)); return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f); } - + template static bool DragN(const std::string& fieldLabel, std::vectorconst& componentLabels, std::vector values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), @@ -53,7 +165,7 @@ namespace SHADE const ImGuiWindow* const window = ImGui::GetCurrentWindow(); if (window->SkipItems) return false; - + const ImGuiContext& g = *GImGui; bool valueChanged = false; ImGui::BeginGroup(); @@ -69,15 +181,15 @@ namespace SHADE ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine(); ImGui::SetNextItemWidth(80.0f); valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags); - + const ImVec2 min = ImGui::GetItemRectMin(); const ImVec2 max = ImGui::GetItemRectMax(); const float spacing = g.Style.FrameRounding; const float halfSpacing = spacing / 2; - + window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing }, ImGuiColors::colors[i], 4); - + ImGui::SameLine(0, g.Style.ItemInnerSpacing.x); ImGui::PopID(); ImGui::PopItemWidth(); @@ -85,10 +197,10 @@ namespace SHADE ImGui::EndColumns(); ImGui::PopID(); ImGui::EndGroup(); - + return valueChanged; } - + static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) @@ -99,98 +211,98 @@ namespace SHADE { changed = true; } - + if (changed) { if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); } - + return changed; } - + static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) + if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) { changed = true; } - + if (changed) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); } - + return changed; } - + static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) + if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) { changed = true; } - + if (changed) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); } - + return changed; } - + //#==============================================================# //|| Widget Extensions || //#==============================================================# - + static bool CheckBox(std::string const& label, std::function get, std::function set) { bool value = get(); if (ImGui::Checkbox(label.c_str(), &value)) { - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); return true; } return false; } - + template - static bool RadioButton(std::vector const& listLabels, std::vector const& listTypes, std::function get, std::function set) + static bool RadioButton(std::vector const& listLabels, std::vector const& listTypes, std::function get, std::function set) { T type = get(); for (size_t i = 0; i < listTypes.size(); i++) { if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i])) { - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), listTypes[i], set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), listTypes[i], set)), false); } ImGui::SameLine(); } return true; } - + static bool InputText(const std::string& label, const std::function get, const std::function set, ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) @@ -199,35 +311,35 @@ namespace SHADE if (ImGui::InputText(label.c_str(), &text, flag, callback, userData)) { if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), text, set)), false); - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), text, set)), false); + return true; } return false; } - + template static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function get, std::function set, float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - std::cout << value <<" \n"; + std::cout << value << " \n"; //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); - + if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags)) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + return true; } return false; } - + static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { @@ -236,18 +348,18 @@ namespace SHADE if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + return true; } - + return false; } - + static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { @@ -256,35 +368,35 @@ namespace SHADE if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) { if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + return true; } - + return false; } - template - static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, + template + static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) + { + T value = get(); + if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) { - T value = get(); - if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) - { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - - return true; - } - - return false; + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + + return true; } - + + return false; + } + static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { @@ -292,17 +404,17 @@ namespace SHADE if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) { if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + + return true; } - + return false; } - + static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { @@ -310,26 +422,26 @@ namespace SHADE if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) { if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + return true; } - + return false; } - + static bool ComboBox(const std::string& fieldLabel, std::vector list, std::function get, std::function set) { bool edited = false; int selected = get(); ImGui::PushID(fieldLabel.c_str()); ImGui::Text(fieldLabel.c_str()); ImGui::SameLine(); - + if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast(list.size()))) { - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), selected, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), selected, set)), false); } ImGui::PopID(); return edited; diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h index 648a07e8..e931fec5 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h @@ -105,6 +105,17 @@ namespace SHADE vk::Buffer GetVkBuffer (void) const noexcept; vk::BufferUsageFlags GetUsageBits(void) const noexcept; + template + T GetDataFromMappedPointer(uint32_t index) const noexcept + { + if (mappedPtr && index < sizeStored / sizeof (T)) + { + return (static_cast(mappedPtr))[index]; + } + else + return {}; + }; + }; } diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 9ebbd227..4501ba7b 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -461,6 +461,11 @@ namespace SHADE ); } + void SHVkCommandBuffer::CopyImageToBuffer(const vk::Image& src, const vk::Buffer& dst, const std::vector& copyInfo) + { + vkCommandBuffer.copyImageToBuffer (src, vk::ImageLayout::eTransferSrcOptimal, dst, copyInfo); + } + void SHVkCommandBuffer::PipelineBarrier( vk::PipelineStageFlags srcStage, vk::PipelineStageFlags dstStage, diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index c18527b3..9416a1aa 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h @@ -120,7 +120,8 @@ namespace SHADE void DrawMultiIndirect (Handle indirectDrawData, uint32_t drawCount); // Buffer Copy - void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo); + void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo); + void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector& copyInfo); // memory barriers void PipelineBarrier ( diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 181c1f22..2705b4d1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -110,6 +110,7 @@ namespace SHADE // Clear CPU buffers drawData.clear(); transformData.clear(); + eidData.clear(); matPropsData.reset(); matPropsDataSize = 0; @@ -119,6 +120,7 @@ namespace SHADE { drawDataBuffer[i].Free(); transformDataBuffer[i].Free(); + eidBuffer[i].Free(); matPropsBuffer[i].Free(); } } @@ -206,7 +208,31 @@ namespace SHADE transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); } - void SHBatch::Build(Handle _device, Handle descPool, uint32_t frameIndex) + void SHBatch::UpdateEIDBuffer(uint32_t frameIndex) + { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update eid buffers with an invalid frame index."); + return; + } + + // Reset Transform Data + eidData.clear(); + + // Populate on the CPU + for (auto& subBatch : subBatches) + for (const SHRenderable* renderable : subBatch.Renderables) + { + eidData.emplace_back(renderable->GetEID()); + } + + // Transfer to GPU + if (eidBuffer[frameIndex]) + eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast(eidData.size() * sizeof(EntityID)), 0, 0); + + } + + void SHBatch::Build(Handle _device, Handle descPool, uint32_t frameIndex) { if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { @@ -237,6 +263,11 @@ namespace SHADE // - Transform data transformData.reserve(numTotalElements); transformData.clear(); + // - EID data + eidData.reserve(numTotalElements); + eidData.clear(); + + // - Material Properties Data const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface ( @@ -277,7 +308,8 @@ namespace SHADE for (const SHRenderable* renderable : subBatch.Renderables) { // Transform - auto transform = SHComponentManager::GetComponent_s(renderable->GetEID()); + EntityID eid = renderable->GetEID(); + auto transform = SHComponentManager::GetComponent_s(eid); if (!transform) { SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); @@ -287,6 +319,8 @@ namespace SHADE { transformData.emplace_back(transform->GetTRS()); } + + eidData.emplace_back(eid); // Material Properties if (!EMPTY_MAT_PROPS) @@ -317,6 +351,12 @@ namespace SHADE device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, BuffUsage::eVertexBuffer ); + const uint32_t EID_DATA_BYTES = static_cast(eidData.size() * sizeof(EntityID)); + SHVkUtil::EnsureBufferAndCopyHostVisibleData + ( + device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES, + BuffUsage::eVertexBuffer + ); // - Material Properties Buffer rebuildMaterialBuffers(frameIndex, descPool); @@ -339,6 +379,7 @@ namespace SHADE static std::array dynamicOffset { 0 }; cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0); if (matPropsDescSet[frameIndex]) { cmdBuffer->BindDescriptorSet diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index abe691ca..37c57396 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Math/SHMatrix.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" +#include "ECS_Base/SHECSMacros.h" namespace SHADE { @@ -78,6 +79,7 @@ namespace SHADE void Clear(); void UpdateMaterialBuffer(uint32_t frameIndex, Handle descPool); void UpdateTransformBuffer(uint32_t frameIndex); + void UpdateEIDBuffer(uint32_t frameIndex); void Build(Handle device, Handle descPool, uint32_t frameIndex) ; void Draw(Handle cmdBuffer, uint32_t frameIndex); @@ -109,14 +111,16 @@ namespace SHADE // CPU Buffers std::vector drawData; std::vector transformData; + std::vector eidData; std::unique_ptr matPropsData; Byte matPropsDataSize = 0; Byte singleMatPropAlignedSize = 0; - Byte singleMatPropSize = 0; + Byte singleMatPropSize = 0; bool isCPUBuffersDirty = true; // GPU Buffers TripleBuffer drawDataBuffer; TripleBuffer transformDataBuffer; + TripleBuffer eidBuffer; TripleBuffer matPropsBuffer; TripleDescSet matPropsDescSet; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index 0d75dca8..add51196 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -83,8 +83,9 @@ namespace SHADE { for (auto& batch : batches) { - batch.UpdateMaterialBuffer(frameIndex, descPool); + batch.UpdateMaterialBuffer(frameIndex, descPool); batch.UpdateTransformBuffer(frameIndex); + batch.UpdateEIDBuffer(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index 6a7b23f2..d8b1bad1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -91,9 +91,10 @@ namespace SHADE { defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1 - defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Normals at binding 2 - defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Tangents at binding 3 - defaultVertexInputState.AddBinding(true, true, {SHVertexAttribute(SHAttribFormat::MAT_4D)}); // Transform at binding 4 - 7 (4 slots) + defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2 + defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3 + defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots) + defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8 } void SHGraphicsGlobalData::Init(Handle logicalDevice) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index 0818ebab..ac2f1f8c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -144,6 +144,14 @@ namespace SHADE */ /***************************************************************************/ static constexpr uint32_t TRANSFORM = 4; + /***************************************************************************/ + /*! + \brief + Vertex buffer bindings for the eid buffer. + */ + /***************************************************************************/ + static constexpr uint32_t EID = 5; + }; /*******************************************************************************/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 6957aa93..09f1c93e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -32,6 +32,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Images/SHVkSampler.h" #include "Assets/Asset Types/SHTextureAsset.h" +#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" namespace SHADE { @@ -143,26 +144,22 @@ namespace SHADE // Initialize world render graph worldRenderGraph->Init(device, swapchain); + worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); + worldRenderGraph->AddResource("Entity ID", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + //worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm); - worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second); - auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Depth Buffer", "Present" }, {}); // no predecessors + auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Present"}, {}); // no predecessors //First subpass to write to G-Buffer auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); - //gBufferWriteSubpass->AddColorOutput("Scene"); gBufferWriteSubpass->AddColorOutput("Present"); + gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL); - //writeSubpass->AddColorOutput("Normals"); - // //Second subpass to read from G-Buffer - //auto compositeSubpass = node->AddSubpass("G-Buffer Composite"); - //compositeSubpass->AddColorOutput("Present"); // TODO: This should be "Composite" and then composite will write to swapchain image "Present" - //compositeSubpass->AddInput("Normals"); - //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"}); @@ -201,6 +198,15 @@ namespace SHADE cubeFS->Reflect(); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); + + mousePickSystem = resourceManager.Create(); + + std::vector> cmdPools; + cmdPools.reserve(swapchain->GetNumImages()); + for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) + cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]); + + mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID")); } /***************************************************************************/ @@ -400,10 +406,10 @@ namespace SHADE } - const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame(); auto& currFrameData = renderContext.GetCurrentFrameData(); + mousePickSystem->Run(graphicsQueue, CURR_FRAME_IDX); // #BackEndTest: queues an image for presentation if (auto result = graphicsQueue->Present(swapchain, { currFrameData.semRenderFinishHdl }, CURR_FRAME_IDX); result != vk::Result::eSuccess) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index c89e6ebc..3160cd57 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -52,6 +52,7 @@ namespace SHADE class SHVkShaderModule; class SHMaterial; class SHMaterialInstance; + class SHMousePickSystem; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -268,6 +269,7 @@ namespace SHADE Handle GetQueue() const { return graphicsQueue; } Handle GetDescriptorPool() const { return descPool; } Handle GetDefaultViewport() const {return defaultViewport;} + Handle GetMousePickSystem(void) const noexcept {return mousePickSystem;}; //SHRenderGraph const& GetRenderGraph(void) const noexcept; //Handle GetRenderPass() const { return renderPass; } @@ -294,7 +296,7 @@ namespace SHADE SHWindow* window = nullptr; // Middle End Resources - ResourceManager resourceManager; + ResourceManager resourceManager; SHMeshLibrary meshLibrary; SHTextureLibrary texLibrary; SHSamplerCache samplerCache; @@ -322,5 +324,8 @@ namespace SHADE Handle defaultMaterial; Handle worldRenderGraph; + + // Sub systems + Handle mousePickSystem; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp new file mode 100644 index 00000000..ee8665d5 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp @@ -0,0 +1,71 @@ +#include "SHpch.h" +#include "SHMousePickSystem.h" +#include "Input/SHInputManager.h" +#include "Graphics/Commands/SHVkCommandPool.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Graphics/Synchronization/SHVkFence.h" +#include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/SHVkUtil.h" + +namespace SHADE +{ + void SHMousePickSystem::Init(Handle logicalDevice, std::span> cmdPools, Handle eidAttachment) noexcept + { + pickedEID = 0; + + // Create command buffers + for (auto& pool : cmdPools) + { + commandBuffers.push_back(pool->RequestCommandBuffer (SH_CMD_BUFFER_TYPE::PRIMARY)); + } + + // assign the attachment + entityIDAttachment = eidAttachment; + + // Create the fence + afterCopyFence = logicalDevice->CreateFence(); + + uint32_t bufferSize = entityIDAttachment->GetWidth() * eidAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat()); + + // Create the buffer + imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + } + + void SHMousePickSystem::Run(Handle queue, uint32_t frameIndex) noexcept + { + // if input detected + if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::LEFT_CTRL) && SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB)) + { + afterCopyFence->Reset(); + + // begin command buffer for recording + commandBuffers[frameIndex]->BeginRecording(); + + // transition the image for optimized copying + entityIDAttachment->TransitionImage (vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal, commandBuffers[frameIndex], vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eTransfer, 0); + + // copy the image here. Last argument is 0 because the attachment isn't a swapchain image. + entityIDAttachment->CopyToBuffer(imageDataDstBuffer, commandBuffers[frameIndex], 0); + + // end command buffer for recording + commandBuffers[frameIndex]->EndRecording(); + + // submit the command buffer to copy image to buffer + queue->SubmitCommandBuffer({ commandBuffers[frameIndex] }, {}, {}, vk::PipelineStageFlagBits::eColorAttachmentOutput, afterCopyFence); + + // wait for the copy to be done + afterCopyFence->Wait(true, std::numeric_limits::max()); + + int mouseX = 0, mouseY = 0; + SHInputManager::GetMouseWindowPosition(&mouseX, &mouseY); + + pickedEID = imageDataDstBuffer->GetDataFromMappedPointer(mouseY * entityIDAttachment->GetWidth() + mouseX); + } + } + + EntityID SHMousePickSystem::GetPickedEntity(void) const noexcept + { + return pickedEID; + } + +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h new file mode 100644 index 00000000..080a192c --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Graphics/RenderGraph/SHRenderGraphResource.h" +#include "ECS_Base/SHECSMacros.h" +#include "Math/Vector/SHVec2.h" +#include + +namespace SHADE +{ + class SHVkLogicalDevice; + class SHVkCommandPool; + class SHVkCommandBuffer; + class SHVkFence; + class SHVkQueue; + class SHVkBuffer; + + class SHMousePickSystem + { + private: + //! Handle to the render graph resource that will contain the entity IDs + Handle entityIDAttachment; + + //! Command buffers meant for copying image to buffer + std::vector> commandBuffers; + + //! After the attachment has copied its data to a buffer, we want to signal this fence + Handle afterCopyFence; + + //! buffer to contain the attachment data after copying + Handle imageDataDstBuffer; + + //! eid picked from screen + EntityID pickedEID; + public: + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void Init(Handle logicalDevice, std::span> cmdPools, Handle eidAttachment) noexcept; + void Run (Handle queue, uint32_t frameIndex) noexcept; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + EntityID GetPickedEntity (void) const noexcept; + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp index 10b42a9e..682b549c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp @@ -2,6 +2,8 @@ #include "SHPipelineLibrary.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" +#include "Graphics/RenderGraph/SHSubpass.h" +#include "Graphics/SHVkUtil.h" namespace SHADE { @@ -20,6 +22,31 @@ namespace SHADE // Create the pipeline and configure the default vertex input state auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsGlobalData::GetDefaultViState()); + + SHColorBlendState colorBlendState{}; + colorBlendState.logic_op_enable = VK_FALSE; + colorBlendState.logic_op = vk::LogicOp::eCopy; + + auto const& subpassColorReferences = subpass->GetColorAttachmentReferences(); + colorBlendState.attachments.reserve(subpassColorReferences.size()); + + for (auto& att : subpassColorReferences) + { + colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState + { + .blendEnable = SHVkUtil::IsBlendCompatible (subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false, + .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eOne, + .dstAlphaBlendFactor = vk::BlendFactor::eZero, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + } + ); + } + + newPipeline->GetPipelineState().SetColorBlenState(colorBlendState); // Actually construct the pipeline newPipeline->ConstructPipeline(); diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h index 2769d6cc..4c8d679a 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h @@ -137,22 +137,9 @@ namespace SHADE { VkBool32 logic_op_enable{ VK_FALSE }; - vk::LogicOp logic_op{ VK_LOGIC_OP_COPY }; + vk::LogicOp logic_op{ vk::LogicOp::eCopy }; - std::vector attachments = - { - vk::PipelineColorBlendAttachmentState - { - .blendEnable = true, - .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, - .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, - .colorBlendOp = vk::BlendOp::eAdd, - .srcAlphaBlendFactor = vk::BlendFactor::eOne, - .dstAlphaBlendFactor = vk::BlendFactor::eZero, - .alphaBlendOp = vk::BlendOp::eAdd, - .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, - } - }; + std::vector attachments{}; }; // TODO: Specialization constants diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index cad6a78e..1861f6d2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -40,7 +40,7 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) + void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/) { // If we set to if (w == static_cast(-1) && h == static_cast(-1)) @@ -50,7 +50,7 @@ namespace SHADE format = swapchainHdl->GetSurfaceFormatKHR().format; } - graphResources.try_emplace(resourceName, resourceManager.Create(logicalDeviceHdl, swapchainHdl, resourceName, type, format, w, h, levels, createFlags)); + graphResources.try_emplace(resourceName, resourceManager.Create(logicalDeviceHdl, swapchainHdl, resourceName, type, format, w, h, levels, usageFlags, createFlags)); } /***************************************************************************/ @@ -498,4 +498,13 @@ namespace SHADE } + Handle SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept + { + if (graphResources.contains(resourceName)) + { + return graphResources.at(resourceName); + } + return {}; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index a3140a4f..cfc29bc2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -75,7 +75,7 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void Init (Handle const& logicalDevice, Handle const& swapchain) noexcept; - void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); + void AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; void Generate (void) noexcept; void Execute (uint32_t frameIndex, Handle cmdBuffer, Handle descPool) noexcept; @@ -85,7 +85,8 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ - Handle GetNode (std::string const& nodeName) const noexcept; + Handle GetNode (std::string const& nodeName) const noexcept; + Handle GetRenderGraphResource (std::string const& resourceName) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 05232af3..ea09dd47 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -261,6 +261,7 @@ namespace SHADE return {}; } + Handle pipeline = pipelineLibrary.GetDrawPipline(vsFsPair); if (!pipeline) { @@ -301,4 +302,12 @@ namespace SHADE return subpasses[subpassIndexing.at(subpassName.data())]; } + Handle SHRenderGraphNode::GetResource(uint32_t resourceIndex) const noexcept + { + if (resourceIndex < attResources.size()) + return attResources[resourceIndex]; + else + return {}; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index c713f402..28527a92 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -105,6 +105,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ Handle GetRenderpass(void) const noexcept; Handle GetSubpass(std::string_view subpassName) const noexcept; + Handle GetResource (uint32_t resourceIndex) const noexcept; friend class SHRenderGraph; }; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp index cc881867..bcd1dc9f 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp @@ -3,6 +3,8 @@ #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Images/SHVkImageView.h" +#include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/SHVkUtil.h" namespace SHADE { @@ -43,7 +45,7 @@ namespace SHADE */ /***************************************************************************/ - SHRenderGraphResource::SHRenderGraphResource(Handle const& logicalDevice, Handle const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept + SHRenderGraphResource::SHRenderGraphResource(Handle const& logicalDevice, Handle const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept : logicalDevice {logicalDevice} , swapchain{ swapchain } , resourceType{ type } @@ -59,7 +61,7 @@ namespace SHADE if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT) { imageAspectFlags = vk::ImageAspectFlags{}; - usage = {}; + usage = usageFlags; // Check the resource type and set image usage flags and image aspect flags accordingly switch (resourceType) @@ -242,4 +244,59 @@ namespace SHADE } } + void SHRenderGraphResource::TransitionImage(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, Handle commandBuffer, vk::PipelineStageFlagBits srcStage, vk::PipelineStageFlagBits dstStage, uint32_t frameIndex) noexcept + { + vk::ImageMemoryBarrier barrier; + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = images[frameIndex]->GetVkImage(), + barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format. + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = mipLevels; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; // always 1 since we wont have array of images for attachments + + commandBuffer->PipelineBarrier(srcStage, dstStage, {}, {}, {}, {barrier}); + } + + void SHRenderGraphResource::CopyToBuffer(Handle dstBuffer, Handle commandBuffer, uint32_t frameIndex) const noexcept + { + vk::ImageSubresourceLayers subResource + { + .aspectMask = SHVkUtil::IsDepthOnlyFormat(resourceFormat) ? vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 + }; + + vk::BufferImageCopy region + { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = subResource, + .imageOffset = vk::Offset3D {0,0,0}, + .imageExtent = vk::Extent3D {width, height, 1} + }; + + commandBuffer->CopyImageToBuffer(images[frameIndex]->GetVkImage(), dstBuffer->GetVkBuffer(), {region}); + } + + vk::Format SHRenderGraphResource::GetResourceFormat(void) const noexcept + { + return resourceFormat; + } + + uint32_t SHRenderGraphResource::GetWidth(void) const noexcept + { + return width; + } + + uint32_t SHRenderGraphResource::GetHeight(void) const noexcept + { + return height; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h index ebb699d8..66f0677b 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h @@ -13,6 +13,8 @@ namespace SHADE class SHVkImageView; class SHVkLogicalDevice; class SHVkSwapchain; + class SHVkCommandBuffer; + class SHVkBuffer; class SH_API SHRenderGraphResource { @@ -65,12 +67,24 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ - SHRenderGraphResource(Handle const& logicalDevice, Handle const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept; + SHRenderGraphResource(Handle const& logicalDevice, Handle const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept; SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; ~SHRenderGraphResource(void) noexcept; + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; + void TransitionImage(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, Handle commandBuffer, vk::PipelineStageFlagBits srcStage, vk::PipelineStageFlagBits dstStage, uint32_t frameIndex) noexcept; + void CopyToBuffer (Handle dstBuffer, Handle commandBuffer, uint32_t frameIndex = 0) const noexcept; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + vk::Format GetResourceFormat (void) const noexcept; + uint32_t GetWidth (void) const noexcept; + uint32_t GetHeight (void) const noexcept; friend class SHRenderGraphNode; friend class SHRenderGraph; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 007502dd..abd3a7be 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -2,6 +2,8 @@ #include "SHSubpass.h" #include "Graphics/MiddleEnd/Batching/SHSuperBatch.h" #include "Graphics/Devices/SHVkLogicalDevice.h" +#include "SHRenderGraphNode.h" +#include "SHRenderGraphResource.h" namespace SHADE { @@ -207,4 +209,15 @@ namespace SHADE { return superBatch; } + + std::vector const& SHSubpass::GetColorAttachmentReferences(void) const noexcept + { + return colorReferences; + } + + vk::Format SHSubpass::GetFormatFromAttachmentReference(uint32_t attachmentReference) const noexcept + { + return parentNode->GetResource(attachmentReference)->GetResourceFormat(); + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index b8b8717f..aba282b9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -86,7 +86,8 @@ namespace SHADE Handle const& GetParentNode(void) const noexcept; SHSubPassIndex GetIndex() const noexcept; Handle GetSuperBatch(void) const noexcept; - + std::vector const& GetColorAttachmentReferences (void) const noexcept; + vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept; friend class SHRenderGraphNode; friend class SHRenderGraph; diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index e4f9f37e..c8c563a1 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -23,6 +23,38 @@ namespace SHADE IsDepthOnlyFormat(format); } + bool SHVkUtil::IsBlendCompatible(vk::Format format) noexcept + { + // TODO: Update with all formats + switch (format) + { + case vk::Format::eR32Sint: + case vk::Format::eR32G32Sint: + case vk::Format::eR32G32B32Sint: + case vk::Format::eR32G32B32A32Sint: + return false; + case vk::Format::eR32Sfloat: + case vk::Format::eR32G32Sfloat: + case vk::Format::eR32G32B32Sfloat: + case vk::Format::eR32G32B32A32Sfloat: + return true; + } + return false; + } + + uint32_t SHVkUtil::GetBytesPerPixelFromFormat(vk::Format format) noexcept + { + // TODO: Update with all formats + switch (format) + { + case vk::Format::eR32Sint: + case vk::Format::eR32Uint: + case vk::Format::eR32Sfloat: + return 4; + } + return 0; + } + void SHVkUtil::EnsureBufferAndCopyData(Handle device, Handle cmdBuffer, Handle& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) { if (bufferHandle) diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.h b/SHADE_Engine/src/Graphics/SHVkUtil.h index cba5b062..ca3b6f83 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.h +++ b/SHADE_Engine/src/Graphics/SHVkUtil.h @@ -19,9 +19,12 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ class SHVkUtil { - public: - static bool IsDepthOnlyFormat (vk::Format format) noexcept; - static bool IsDepthStencilAttachment(vk::Format format) noexcept; + public: + static bool IsDepthOnlyFormat (vk::Format format) noexcept; + static bool IsDepthStencilAttachment (vk::Format format) noexcept; + static bool IsBlendCompatible (vk::Format format) noexcept; + static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept; + /***********************************************************************************/ /*! diff --git a/SHADE_Engine/src/Input/SHInputManager.cpp b/SHADE_Engine/src/Input/SHInputManager.cpp index 04f2b02e..18d9e3e2 100644 --- a/SHADE_Engine/src/Input/SHInputManager.cpp +++ b/SHADE_Engine/src/Input/SHInputManager.cpp @@ -43,7 +43,10 @@ namespace SHADE void SHInputManager::UpdateInput(double dt) noexcept { - //Keyboard and Mouse Buttons//////////////////////////////////////////////// + //Keyboard and Mouse Buttons//////////////////////////////////////////////// + //Write to lastKeys + memcpy(keysLast, keys, sizeof(keys)); + //Poll unsigned char keyboardState[MAX_KEYS]; //if (GetKeyboardState(keyboardState) == false) return; @@ -96,9 +99,6 @@ namespace SHADE } } - //Write to lastKeys - memcpy(keysLast, keys, sizeof(keys)); - //Mouse Positioning///////////////////////////////////// //https://stackoverflow.com/a/6423739 diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp index 3abcc315..d0ba2f14 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp @@ -14,6 +14,9 @@ #include "SHBoundingBox.h" // Project Headers #include "Math/SHMathHelpers.h" +#include "Math/SHRay.h" + +using namespace DirectX; namespace SHADE { @@ -21,89 +24,53 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ + SHBoundingBox::SHBoundingBox() noexcept + { + type = Type::BOX; + } + SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept - : SHShape {} - , center { c } - , halfExtents { hE } { - type = Type::BOUNDING_BOX; + type = Type::BOX; + + Center = c; + Extents = hE; } - SHBoundingBox::SHBoundingBox(const SHVec3* vertices, size_t numVertices) noexcept - : SHShape {} - { - type = Type::BOUNDING_BOX; - - if (vertices == nullptr || numVertices < 2) - { - SHLOG_ERROR("Insufficient number of vertices passed into bounding box constructor!") - return; - } - - SHVec3 min { std::numeric_limits::max() }; - SHVec3 max { std::numeric_limits::min() }; - - for (size_t i = 0; i < numVertices; ++i) - { - const SHVec3& v = vertices[i]; - - min.x = SHMath::Min(min.x, v.x); - min.y = SHMath::Min(min.y, v.y); - min.z = SHMath::Min(min.z, v.z); - - max.x = SHMath::Max(max.x, v.x); - max.y = SHMath::Max(max.y, v.y); - max.z = SHMath::Max(max.z, v.z); - } - - center = SHVec3::Lerp(min, max, 0.5f); - halfExtents = SHVec3::Abs((max - min) * 0.5f); - } - - SHBoundingBox::SHBoundingBox(const SHBoundingBox* boxes, size_t numBoxes) noexcept - : SHShape {} - { - type = Type::BOUNDING_BOX; - - if (boxes == nullptr || numBoxes == 0) - { - SHLOG_ERROR("Insufficient number of boxes passed into bounding box constructor!") - return; - } - - center = boxes->center; - halfExtents = boxes->halfExtents; - - for (size_t i = 1; i < numBoxes; ++i) - *this = Combine(*this, boxes[i]); - } SHBoundingBox::SHBoundingBox(const SHBoundingBox& rhs) noexcept - : SHShape {} - , center { rhs.center } - , halfExtents { rhs.halfExtents } { - type = Type::BOUNDING_BOX; + if (this == &rhs) + return; + + type = Type::BOX; + + Center = rhs.Center; + Extents = rhs.Extents; } SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept - : SHShape {} - , center { rhs.center } - , halfExtents { rhs.halfExtents } { - type = Type::BOUNDING_BOX; + type = Type::BOX; + + Center = rhs.Center; + Extents = rhs.Extents; } + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + SHBoundingBox& SHBoundingBox::operator=(const SHBoundingBox& rhs) noexcept { - if (rhs.type != Type::BOUNDING_BOX) + if (rhs.type != Type::BOX) { SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") } - else + else if (this != &rhs) { - center = rhs.center; - halfExtents = rhs.halfExtents; + Center = rhs.Center; + Extents = rhs.Extents; } return *this; @@ -111,14 +78,14 @@ namespace SHADE SHBoundingBox& SHBoundingBox::operator=(SHBoundingBox&& rhs) noexcept { - if (rhs.type != Type::BOUNDING_BOX) + if (rhs.type != Type::BOX) { SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") } else { - center = rhs.center; - halfExtents = rhs.halfExtents; + Center = rhs.Center; + Extents = rhs.Extents; } return *this; @@ -128,24 +95,24 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - const SHVec3& SHBoundingBox::GetCenter() const noexcept + SHVec3 SHBoundingBox::GetCenter() const noexcept { - return center; + return Center; } - const SHVec3& SHBoundingBox::GetHalfExtents() const noexcept + SHVec3 SHBoundingBox::GetHalfExtents() const noexcept { - return halfExtents; + return Extents; } SHVec3 SHBoundingBox::GetMin() const noexcept { - return center - halfExtents; + return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; } SHVec3 SHBoundingBox::GetMax() const noexcept { - return center + halfExtents; + return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; } /*-----------------------------------------------------------------------------------*/ @@ -154,36 +121,42 @@ namespace SHADE void SHBoundingBox::SetCenter(const SHVec3& newCenter) noexcept { - center = newCenter; + Center = newCenter; } void SHBoundingBox::SetHalfExtents(const SHVec3& newHalfExtents) noexcept { - halfExtents = newHalfExtents; + Extents = newHalfExtents; } void SHBoundingBox::SetMin(const SHVec3& min) noexcept { - const SHVec3 MAX = center + halfExtents; + const SHVec3 MAX = GetMax(); - center = SHVec3::Lerp(min, MAX, 0.5f); - halfExtents = SHVec3::Abs((MAX - min) * 0.5f); + Center = SHVec3::Lerp(min, MAX, 0.5f); + Extents = SHVec3::Abs((MAX - min) * 0.5f); } void SHBoundingBox::SetMax(const SHVec3& max) noexcept { - const SHVec3 MIN = center - halfExtents; + const SHVec3 MIN = GetMin(); - center = SHVec3::Lerp(MIN, max, 0.5f); - halfExtents = SHVec3::Abs((max - MIN) * 0.5f); + Center = SHVec3::Lerp(MIN, max, 0.5f); + Extents = SHVec3::Abs((max - MIN) * 0.5f); } void SHBoundingBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept { - center = SHVec3::Lerp(min, max, 0.5f); - halfExtents = SHVec3::Abs((max - min) * 0.5f); + Center = SHVec3::Lerp(min, max, 0.5f); + Extents = SHVec3::Abs((max - min) * 0.5f); } + std::vector SHBoundingBox::GetVertices() const noexcept + { + std::vector vertices{ 8 }; + GetCorners(vertices.data()); + return vertices; + } /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ @@ -191,38 +164,29 @@ namespace SHADE bool SHBoundingBox::TestPoint(const SHVec3& point) noexcept { - const SHVec3 V = SHVec3::Abs(point - center); - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > halfExtents[i]) - return false; - } + return BoundingBox::Contains(point); + } - return true; + bool SHBoundingBox::Raycast(const SHRay& ray, float& distance) noexcept + { + return BoundingBox::Intersects(ray.position, ray.direction, distance); } bool SHBoundingBox::Contains(const SHBoundingBox& rhs) const noexcept { - const SHVec3 V = SHVec3::Abs(rhs.center - center); - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > rhs.halfExtents[i]) - return false; - } - - return true; + return BoundingBox::Contains(rhs); } float SHBoundingBox::Volume() const noexcept { - return 8.0f * (halfExtents.x * halfExtents.y * halfExtents.z); + return 8.0f * (Extents.x * Extents.y * Extents.z); } float SHBoundingBox::SurfaceArea() const noexcept { - return 8.0f * ((halfExtents.x * halfExtents.y) - + (halfExtents.x * halfExtents.z) - + (halfExtents.y * halfExtents.z)); + return 8.0f * ((Extents.x * Extents.y) + + (Extents.x * Extents.z) + + (Extents.y * Extents.z)); } /*-----------------------------------------------------------------------------------*/ @@ -231,37 +195,31 @@ namespace SHADE SHBoundingBox SHBoundingBox::Combine(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept { - if (lhs.Contains(rhs)) - return lhs; - - if (rhs.Contains(lhs)) - return rhs; - - const SHVec3 LHS_MIN = lhs.GetMin(); - const SHVec3 LHS_MAX = lhs.GetMax(); - const SHVec3 RHS_MIN = rhs.GetMin(); - const SHVec3 RHS_MAX = rhs.GetMax(); - - SHVec3 min = SHVec3::Min({ LHS_MIN, RHS_MIN }); - SHVec3 max = SHVec3::Max({ LHS_MAX, RHS_MAX }); - - SHBoundingBox result{ lhs }; - result.SetMinMax(min, max); + SHBoundingBox result; + CreateMerged(result, lhs, rhs); return result; } bool SHBoundingBox::Intersect(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept { - const SHVec3 V = SHVec3::Abs(lhs.center - rhs.center); - const SHVec3 D = lhs.halfExtents + rhs.halfExtents; + return lhs.Intersects(rhs); + } - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (V[i] > D[i]) - return false; - } + SHBoundingBox SHBoundingBox::BuildFromBoxes(const SHBoundingBox* boxes, size_t numBoxes) noexcept + { + SHBoundingBox result; - return true; + for (size_t i = 1; i < numBoxes; ++i) + CreateMerged(result, boxes[i - 1], boxes[i]); + + return result; + } + + SHBoundingBox SHBoundingBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + { + SHBoundingBox result; + CreateFromPoints(result, numVertices, vertices, stride); + return result; } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h index a89c5965..5b3d26d5 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h @@ -22,32 +22,43 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - // TODO(Diren): Use DirectX BoundingBox instead of custom - class SH_API SHBoundingBox : public SHShape + class SH_API SHBoundingBox : public SHShape, + private DirectX::BoundingBox { public: + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static constexpr size_t NUM_VERTICES = 8; + /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBoundingBox (const SHVec3* vertices, size_t numVertices) noexcept; - SHBoundingBox (const SHBoundingBox* boxes, size_t numBoxes) noexcept; + ~SHBoundingBox () override = default; - SHBoundingBox (const SHBoundingBox& rhs) noexcept; - SHBoundingBox (SHBoundingBox&& rhs) noexcept; + SHBoundingBox () noexcept; + SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHBoundingBox (const SHBoundingBox& rhs) noexcept; + SHBoundingBox (SHBoundingBox&& rhs) noexcept; - SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; - SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; + SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] const SHVec3& GetCenter () const noexcept; - [[nodiscard]] const SHVec3& GetHalfExtents () const noexcept; - [[nodiscard]] SHVec3 GetMin () const noexcept; - [[nodiscard]] SHVec3 GetMax () const noexcept; + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] SHVec3 GetHalfExtents() const noexcept; + [[nodiscard]] SHVec3 GetMin () const noexcept; + [[nodiscard]] SHVec3 GetMax () const noexcept; + [[nodiscard]] std::vector GetVertices () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ @@ -59,31 +70,25 @@ namespace SHADE void SetMax (const SHVec3& max) noexcept; void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept; - /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; - [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; + [[nodiscard]] bool Contains (const SHBoundingBox& rhs) const noexcept; + [[nodiscard]] float Volume () const noexcept; + [[nodiscard]] float SurfaceArea () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - SHVec3 center; - SHVec3 halfExtents; + [[nodiscard]] static SHBoundingBox Combine (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; + [[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept; + [[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; }; diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp new file mode 100644 index 00000000..62bf12b2 --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp @@ -0,0 +1,183 @@ +/**************************************************************************************** + * \file SHBoundingSphere.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Bounding Sphere + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHBoundingSphere.h" +// Project Headers +#include "Math/SHMathHelpers.h" +#include "Math/SHRay.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere::SHBoundingSphere() noexcept + { + type = Type::SPHERE; + } + + SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept + { + type = Type::SPHERE; + + Center = center; + Radius = radius; + } + + SHBoundingSphere::SHBoundingSphere(const SHBoundingSphere& rhs) noexcept + { + if (this == &rhs) + return; + + type = Type::SPHERE; + + Center = rhs.Center; + Radius = rhs.Radius; + } + + SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept + { + type = Type::SPHERE; + + Center = rhs.Center; + Radius = rhs.Radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere& SHBoundingSphere::operator=(const SHBoundingSphere& rhs) noexcept + { + if (rhs.type != Type::SPHERE) + { + SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") + } + else if (this != &rhs) + { + Center = rhs.Center; + Radius = rhs.Radius; + } + + return *this; + } + + SHBoundingSphere& SHBoundingSphere::operator=(SHBoundingSphere&& rhs) noexcept + { + if (rhs.type != Type::SPHERE) + { + SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") + } + else + { + Center = rhs.Center; + Radius = rhs.Radius; + } + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHVec3 SHBoundingSphere::GetCenter() const noexcept + { + return Center; + } + + float SHBoundingSphere::GetRadius() const noexcept + { + return Radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHBoundingSphere::SetCenter(const SHVec3& center) noexcept + { + Center = center; + } + + void SHBoundingSphere::SetRadius(float radius) noexcept + { + Radius = radius; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHBoundingSphere::TestPoint(const SHVec3& point) noexcept + { + return BoundingSphere::Contains(point); + } + + bool SHBoundingSphere::Raycast(const SHRay& ray, float& distance) noexcept + { + return Intersects(ray.position, ray.direction, distance); + } + + bool SHBoundingSphere::Contains(const SHBoundingSphere& rhs) const noexcept + { + return BoundingSphere::Contains(rhs); + } + + float SHBoundingSphere::Volume() const noexcept + { + return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); + } + + float SHBoundingSphere::SurfaceArea() const noexcept + { + return 4.0f * SHMath::PI * (Radius * Radius); + } + + /*-----------------------------------------------------------------------------------*/ + /* Static Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBoundingSphere SHBoundingSphere::Combine(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + { + SHBoundingSphere result; + CreateMerged(result, lhs, rhs); + return result; + } + + bool SHBoundingSphere::Intersect(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + { + return lhs.Intersects(rhs); + } + + SHBoundingSphere SHBoundingSphere::BuildFromSpheres(const SHBoundingSphere* spheres, size_t numSpheres) noexcept + { + SHBoundingSphere result; + + for (size_t i = 1; i < numSpheres; ++i) + CreateMerged(result, spheres[i - 1], spheres[i]); + + return result; + } + + SHBoundingSphere SHBoundingSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + { + SHBoundingSphere result; + CreateFromPoints(result, numVertices, vertices, stride); + return result; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h new file mode 100644 index 00000000..001e889b --- /dev/null +++ b/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h @@ -0,0 +1,83 @@ +/**************************************************************************************** + * \file SHBoundingSphere.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Bounding Sphere. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SHShape.h" +#include "SH_API.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHBoundingSphere : public SHShape, + private DirectX::BoundingSphere + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingSphere () noexcept; + SHBoundingSphere (const SHVec3& center, float radius) noexcept; + SHBoundingSphere (const SHBoundingSphere& rhs) noexcept; + SHBoundingSphere (SHBoundingSphere&& rhs) noexcept; + + ~SHBoundingSphere () override = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHBoundingSphere& operator= (const SHBoundingSphere& rhs) noexcept; + SHBoundingSphere& operator= (SHBoundingSphere&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] float GetRadius () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetCenter (const SHVec3& center) noexcept; + void SetRadius (float radius) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override; + [[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override; + + [[nodiscard]] bool Contains (const SHBoundingSphere& rhs) const noexcept; + [[nodiscard]] float Volume () const noexcept; + [[nodiscard]] float SurfaceArea () const noexcept; + + + /*---------------------------------------------------------------------------------*/ + /* Static Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] static SHBoundingSphere Combine (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept; + [[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept; + [[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + + }; +} // namespace SHADE diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.h b/SHADE_Engine/src/Math/Geometry/SHShape.h index e33ca583..18f54fe6 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.h +++ b/SHADE_Engine/src/Math/Geometry/SHShape.h @@ -11,8 +11,9 @@ #pragma once // Project Headers -#include "Math/Transform/SHTransform.h" #include "SH_API.h" +#include "Math/SHRay.h" + namespace SHADE { @@ -29,11 +30,10 @@ namespace SHADE enum class Type { - BOUNDING_BOX + BOX , SPHERE , CAPSULE , CONVEX_HULL - , TRIANGLE , COUNT , NONE = -1 @@ -69,7 +69,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] virtual bool TestPoint (const SHVec3& point) noexcept = 0; + [[nodiscard]] virtual bool TestPoint (const SHVec3& point) noexcept = 0; + [[nodiscard]] virtual bool Raycast (const SHRay& ray, float& distance) noexcept = 0; protected: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHColour.cpp b/SHADE_Engine/src/Math/SHColour.cpp new file mode 100644 index 00000000..8aae2cb3 --- /dev/null +++ b/SHADE_Engine/src/Math/SHColour.cpp @@ -0,0 +1,297 @@ +/**************************************************************************************** + * \file SHColour.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Colour. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + + +#include + +// Primary Header +#include "SHColour.h" +// Project Headers +#include "SHMathHelpers.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHColour SHColour::BEIGE = DirectX::Colors::Beige; + const SHColour SHColour::BLACK = DirectX::Colors::Black; + const SHColour SHColour::BLUE = DirectX::Colors::Blue; + const SHColour SHColour::BROWN = DirectX::Colors::Brown; + const SHColour SHColour::CHOCOLATE = DirectX::Colors::Chocolate; + const SHColour SHColour::CORAL = DirectX::Colors::Coral; + const SHColour SHColour::CRIMSON = DirectX::Colors::Crimson; + const SHColour SHColour::CYAN = DirectX::Colors::Cyan; + const SHColour SHColour::DARKBLUE = DirectX::Colors::DarkBlue; + const SHColour SHColour::DARKGRAY = DirectX::Colors::DarkGray; + const SHColour SHColour::DARKGREEN = DirectX::Colors::DarkGreen; + const SHColour SHColour::DARKMAGENTA = DirectX::Colors::DarkMagenta; + const SHColour SHColour::DARKORANGE = DirectX::Colors::DarkOrange; + const SHColour SHColour::DARKRED = DirectX::Colors::DarkRed; + const SHColour SHColour::DEEPPINK = DirectX::Colors::DeepPink; + const SHColour SHColour::FORESTGREEN = DirectX::Colors::ForestGreen; + const SHColour SHColour::FUCHSIA = DirectX::Colors::Fuchsia; + const SHColour SHColour::GOLD = DirectX::Colors::Gold; + const SHColour SHColour::GRAY = DirectX::Colors::Gray; + const SHColour SHColour::GREEN = DirectX::Colors::Green; + const SHColour SHColour::HOTPINK = DirectX::Colors::HotPink; + const SHColour SHColour::INDIGO = DirectX::Colors::Indigo; + const SHColour SHColour::LAVENDER = DirectX::Colors::Lavender; + const SHColour SHColour::LIGHTBLUE = DirectX::Colors::LightBlue; + const SHColour SHColour::LIGHTGRAY = DirectX::Colors::LightGray; + const SHColour SHColour::LIGHTGREEN = DirectX::Colors::LightGreen; + const SHColour SHColour::LIGHTPINK = DirectX::Colors::LightPink; + const SHColour SHColour::LIGHTYELLOW = DirectX::Colors::LightYellow; + const SHColour SHColour::LIME = DirectX::Colors::Lime; + const SHColour SHColour::LIMEGREEN = DirectX::Colors::LimeGreen; + const SHColour SHColour::MAGENTA = DirectX::Colors::Magenta; + const SHColour SHColour::MAROON = DirectX::Colors::Maroon; + const SHColour SHColour::MEDIUMBLUE = DirectX::Colors::MediumBlue; + const SHColour SHColour::MEDIUMPURPLE = DirectX::Colors::MediumPurple; + const SHColour SHColour::NAVY = DirectX::Colors::Navy; + const SHColour SHColour::OLIVE = DirectX::Colors::Olive; + const SHColour SHColour::ORANGE = DirectX::Colors::Orange; + const SHColour SHColour::ORCHID = DirectX::Colors::Orchid; + const SHColour SHColour::PINK = DirectX::Colors::Pink; + const SHColour SHColour::PURPLE = DirectX::Colors::Purple; + const SHColour SHColour::RED = DirectX::Colors::Red; + const SHColour SHColour::ROYALBLUE = DirectX::Colors::RoyalBlue; + const SHColour SHColour::SALMON = DirectX::Colors::Salmon; + const SHColour SHColour::SANDYBROWN = DirectX::Colors::SandyBrown; + const SHColour SHColour::SILVER = DirectX::Colors::Silver; + const SHColour SHColour::SKYBLUE = DirectX::Colors::SkyBlue; + const SHColour SHColour::SLATEGRAY = DirectX::Colors::SlateGray; + const SHColour SHColour::SNOW = DirectX::Colors::Snow; + const SHColour SHColour::STEELBLUE = DirectX::Colors::SteelBlue; + const SHColour SHColour::TAN = DirectX::Colors::Tan; + const SHColour SHColour::TEAL = DirectX::Colors::Teal; + const SHColour SHColour::TURQUOISE = DirectX::Colors::Turquoise; + const SHColour SHColour::VIOLET = DirectX::Colors::Violet; + const SHColour SHColour::WHITE = DirectX::Colors::White; + const SHColour SHColour::YELLOW = DirectX::Colors::Yellow; + + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColour::SHColour() noexcept + : SHVec4 { 0.0f, 0.0f, 0.0f, 1.0f } + {} + + SHColour::SHColour(float r, float g, float b) noexcept + : SHVec4 { r, g, b, 1.0f } + {} + + SHColour::SHColour(float r, float g, float b, float a) noexcept + : SHVec4 { r, g, b, a } + {} + + SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b) noexcept + : SHVec4 + { + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + 1.0f + } + {} + + SHColour::SHColour(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept + : SHVec4 + { + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + static_cast(a) / 255.0f + } + {} + + SHColour::SHColour(const DirectX::XMFLOAT3& colour) noexcept + : SHVec4 { colour.x, colour.y, colour.z, 1.0f } + {} + + SHColour::SHColour(const DirectX::XMVECTORF32& colour) noexcept + : SHVec4 + { + XMVectorGetX(colour), + XMVectorGetY(colour), + XMVectorGetZ(colour), + XMVectorGetW(colour) + } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHColour::operator==(const SHColour& rhs) const noexcept + { + return XMColorEqual(*this, rhs); + } + + bool SHColour::operator!=(const SHColour& rhs) const noexcept + { + return XMColorNotEqual(*this, rhs); + } + + /*-----------------------------------------------------------------------------------*/ + /* Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColourHSV SHColour::ToHSV() noexcept + { + SHColourHSV hsv; + + const float MIN = SHMath::Min({ x, y, z }); + const float MAX = SHMath::Max({ x, y, z }); + + hsv.v = MAX; + + const float DELTA = MAX - MIN; + hsv.s = (MAX != 0.0f) ? DELTA / MAX : 0.0f; + + static const float SIN_60 = sin(SHMath::DegreesToRadians(60.0f)); + + if (DELTA == 0.0f) + hsv.h = 0.0f; + else if (x == MAX) + hsv.h = (y - z) / DELTA; + else if (y == MAX) + hsv.h = 2.0f + (z - x) / DELTA; + else + hsv.h = 4.0f + (x - y) / DELTA; + + hsv.h *= 60; + if (hsv.h < 0.0f) + hsv.h += 360.f; + + return hsv; + } + + void SHColour::Negate() noexcept + { + XMStoreFloat4(this, XMColorNegative(*this)); + } + + void SHColour::Saturate() noexcept + { + XMStoreFloat4(this, XMVectorSaturate(*this)); + } + + void SHColour::AdjustSaturation(float saturation) noexcept + { + XMStoreFloat4(this, XMColorAdjustSaturation(*this, saturation)); + } + + void SHColour::AdjustContrast(float contrast) noexcept + { + XMStoreFloat4(this, XMColorAdjustContrast(*this, contrast)); + } + + /*-----------------------------------------------------------------------------------*/ + /* Static Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHColour SHColour::Modulate(const SHColour& lhs, const SHColour& rhs) noexcept + { + SHColour result; + XMStoreFloat4(&result, XMColorModulate(lhs, rhs)); + return result; + } + + SHColour SHColour::FromHSV(float hue, float saturation, float value) + { + if (hue < 0.0f || saturation < 0.0f || value < 0.0f) + throw std::invalid_argument("One or more of the hsv values are invalid!"); + + SHColour colour; + + if (saturation == 0.0f) + { + colour.x = colour.y = colour.z = value; + } + else + { + hue /= 60.0f; + + const int SECTOR = static_cast(hue); + + const float F = hue - static_cast(SECTOR); + const float P = value * (1.0f - saturation); + const float Q = value * (1.0f - saturation * F); + const float T = value * (1.0f - saturation * (1.0f - F)); + + switch (SECTOR) + { + case 0: + { + colour.x = value; + colour.y = T; + colour.z = P; + + break; + } + case 1: + { + colour.x = Q; + colour.y = value; + colour.z = P; + + break; + } + case 2: + { + colour.x = P; + colour.y = value; + colour.z = T; + + break; + } + case 3: + { + colour.x = P; + colour.y = Q; + colour.z = value; + + break; + } + case 4: + { + colour.x = T; + colour.y = P; + colour.z = value; + + break; + } + default: + { + colour.x = value; + colour.y = P; + colour.z = Q; + + break; + } + } + } + + return colour; + } + + SHColour SHColour::FromHSV(const SHColourHSV& hsv) + { + return FromHSV(hsv.h, hsv.s, hsv.v); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHColour.h b/SHADE_Engine/src/Math/SHColour.h new file mode 100644 index 00000000..bd2bc9e7 --- /dev/null +++ b/SHADE_Engine/src/Math/SHColour.h @@ -0,0 +1,166 @@ +/**************************************************************************************** + * \file SHColour.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Colour. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SH_API.h" +#include "Vector/SHVec3.h" +#include "Vector/SHVec4.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHColour; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SH_API SHColourHSV + { + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + float h = 0.0f; + float s = 0.0f; + float v = 0.0f; + }; + + class SH_API SHColour : private SHVec4 + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHColour () noexcept; + SHColour (float r, float g, float b) noexcept; + SHColour (float r, float g, float b, float a) noexcept; + SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept; + SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; + + SHColour (const SHVec3& colour) noexcept; + SHColour (const DirectX::XMFLOAT3& colour) noexcept; + SHColour (const DirectX::XMVECTORF32& colour) noexcept; + + SHColour (const SHColour&) = default; + SHColour (SHColour&&) = default; + + ~SHColour () = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHColour& operator= (const SHColour&) = default; + SHColour& operator= (SHColour&&) = default; + + bool operator== (const SHColour& rhs) const noexcept; + bool operator!= (const SHColour& rhs) const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] inline float& r() noexcept { return x; } + [[nodiscard]] inline float& g() noexcept { return y; } + [[nodiscard]] inline float& b() noexcept { return z; } + [[nodiscard]] inline float& a() noexcept { return w; } + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + SHColourHSV ToHSV () noexcept; + + void Negate () noexcept; + void Saturate () noexcept; + + void AdjustSaturation (float saturation) noexcept; + void AdjustContrast (float contrast) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Static Function Members */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] static SHColour Modulate (const SHColour& lhs, const SHColour& rhs) noexcept; + [[nodiscard]] static SHColour FromHSV (float hue, float saturation, float value); + [[nodiscard]] static SHColour FromHSV (const SHColourHSV& hsv); + + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static const SHColour BEIGE ; + static const SHColour BLACK ; + static const SHColour BLUE ; + static const SHColour BROWN ; + static const SHColour CHOCOLATE ; + static const SHColour CORAL ; + static const SHColour CRIMSON ; + static const SHColour CYAN ; + static const SHColour DARKBLUE ; + static const SHColour DARKGRAY ; + static const SHColour DARKGREEN ; + static const SHColour DARKMAGENTA ; + static const SHColour DARKORANGE ; + static const SHColour DARKRED ; + static const SHColour DEEPPINK ; + static const SHColour FORESTGREEN ; + static const SHColour FUCHSIA ; + static const SHColour GOLD ; + static const SHColour GRAY ; + static const SHColour GREEN ; + static const SHColour HOTPINK ; + static const SHColour INDIGO ; + static const SHColour LAVENDER ; + static const SHColour LIGHTBLUE ; + static const SHColour LIGHTGRAY ; + static const SHColour LIGHTGREEN ; + static const SHColour LIGHTPINK ; + static const SHColour LIGHTYELLOW ; + static const SHColour LIME ; + static const SHColour LIMEGREEN ; + static const SHColour MAGENTA ; + static const SHColour MAROON ; + static const SHColour MEDIUMBLUE ; + static const SHColour MEDIUMPURPLE; + static const SHColour NAVY ; + static const SHColour OLIVE ; + static const SHColour ORANGE ; + static const SHColour ORCHID ; + static const SHColour PINK ; + static const SHColour PURPLE ; + static const SHColour RED ; + static const SHColour ROYALBLUE ; + static const SHColour SALMON ; + static const SHColour SANDYBROWN ; + static const SHColour SILVER ; + static const SHColour SKYBLUE ; + static const SHColour SLATEGRAY ; + static const SHColour SNOW ; + static const SHColour STEELBLUE ; + static const SHColour TAN ; + static const SHColour TEAL ; + static const SHColour TURQUOISE ; + static const SHColour VIOLET ; + static const SHColour WHITE ; + static const SHColour YELLOW; + }; + + +} // namespace SHADE diff --git a/SHADE_Engine/src/Math/SHMatrix.cpp b/SHADE_Engine/src/Math/SHMatrix.cpp index 94c17914..571fa4e0 100644 --- a/SHADE_Engine/src/Math/SHMatrix.cpp +++ b/SHADE_Engine/src/Math/SHMatrix.cpp @@ -334,6 +334,39 @@ namespace SHADE return ss.str(); } + bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept + { + XMVECTOR s, r, t; + const XMMATRIX M = XMLoadFloat4x4(this); + + if (!XMMatrixDecompose(&s, &r, &t, M)) + return false; + + SHQuaternion orientation; + + XMStoreFloat3(&scale, s); + XMStoreFloat4(&orientation, r); + XMStoreFloat3(&translation, t); + + rotation = orientation.ToEuler(); + + return true; + } + + bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept + { + XMVECTOR s, r, t; + const XMMATRIX M = XMLoadFloat4x4(this); + + if (!XMMatrixDecompose(&s, &r, &t, M)) + return false; + + XMStoreFloat3(&scale, s); + XMStoreFloat4(&orientation, r); + XMStoreFloat3(&translation, t); + + return true; + } /*-----------------------------------------------------------------------------------*/ /* Static Function Member Definitions */ diff --git a/SHADE_Engine/src/Math/SHMatrix.h b/SHADE_Engine/src/Math/SHMatrix.h index 3666fbe6..7a662478 100644 --- a/SHADE_Engine/src/Math/SHMatrix.h +++ b/SHADE_Engine/src/Math/SHMatrix.h @@ -16,7 +16,6 @@ // Project Headers #include "SH_API.h" #include "Vector/SHVec4.h" -#include "SH_API.h" namespace SHADE { @@ -25,7 +24,6 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ class SHVec2; class SHVec3; - class SHVec4; class SHQuaternion; /*-----------------------------------------------------------------------------------*/ @@ -109,6 +107,24 @@ namespace SHADE [[nodiscard]] float Determinant () const noexcept; [[nodiscard]] std::string ToString () const noexcept; + /** + * @brief Decomposes a transformation matrix into translation, euler angles and scale. + * @param[out] scale The scaling factor of the matrix. + * @param[out] rotation The euler angles of the matrix. + * @param[out] translation The translation of the matrix. + * @return True if decomposition was successful. + */ + bool Decompose (SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept; + + /** + * @brief Decomposes a transformation matrix into translation, orientation and scale. + * @param[out] scale The scaling factor of the matrix. + * @param[out] orientation The orientation of the matrix. + * @param[out] translation The translation of the matrix. + * @return True if decomposition was successful. + */ + bool Decompose (SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept; + /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index a6428d30..33c568a5 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -67,6 +67,19 @@ namespace SHADE XMStoreFloat4(this, XMQuaternionRotationMatrix(M)); } + SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept + : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) + { + const SHVec3& SHADE_VEC{ rp3dEuler }; + + const XMVECTOR V = XMLoadFloat3(&SHADE_VEC); + XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); + } + + SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept + : XMFLOAT4( rp3dQuat.x, rp3dQuat.y, rp3dQuat.z, rp3dQuat.w ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -176,6 +189,16 @@ namespace SHADE return XMQuaternionNotEqual(Q1, Q2); } + SHQuaternion::operator reactphysics3d::Quaternion() const noexcept + { + return reactphysics3d::Quaternion{ x, y, z, w }; + } + + SHQuaternion::operator reactphysics3d::Vector3() const noexcept + { + return reactphysics3d::Vector3{ ToEuler() }; + } + SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept { return rhs * lhs; diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index 61b55ef9..c94907b5 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -11,6 +11,8 @@ #pragma once #include +#include + #include // Project Headers @@ -46,12 +48,17 @@ namespace SHADE SHQuaternion (const SHQuaternion& rhs) = default; SHQuaternion (SHQuaternion&& rhs) = default; - SHQuaternion () noexcept; - SHQuaternion (float x, float y, float z, float w) noexcept; - SHQuaternion (float yaw, float pitch, float roll) noexcept; - SHQuaternion (const SHVec3& eulerAngles) noexcept; - SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; - SHQuaternion (const SHMatrix& rotationMatrix) noexcept; + SHQuaternion () noexcept; + SHQuaternion (float x, float y, float z, float w) noexcept; + SHQuaternion (float yaw, float pitch, float roll) noexcept; + SHQuaternion (const SHVec3& eulerAngles) noexcept; + SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; + SHQuaternion (const SHMatrix& rotationMatrix) noexcept; + + // Conversion from other math types + + SHQuaternion (const reactphysics3d::Vector3& rp3dEuler) noexcept; + SHQuaternion (const reactphysics3d::Quaternion& rp3dQuat) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -76,6 +83,11 @@ namespace SHADE [[nodiscard]] bool operator== (const SHQuaternion& rhs) const noexcept; [[nodiscard]] bool operator!= (const SHQuaternion& rhs) const noexcept; + // Conversion to other math types used by SHADE + + operator reactphysics3d::Quaternion () const noexcept; + operator reactphysics3d::Vector3 () const noexcept; + /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/SHRay.cpp b/SHADE_Engine/src/Math/SHRay.cpp new file mode 100644 index 00000000..87f12b81 --- /dev/null +++ b/SHADE_Engine/src/Math/SHRay.cpp @@ -0,0 +1,60 @@ +/**************************************************************************************** + * \file SHRay.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Ray. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHRay.h" + +using namespace DirectX; + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHRay::SHRay() noexcept + : direction { 0.0f, 0.0f, 1.0f } + {} + + SHRay::SHRay(const SHVec3& pos, const SHVec3& dir) noexcept + : position { pos } + , direction { dir } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHRay::operator==(const SHRay& rhs) noexcept + { + const XMVECTOR LHS_POS = XMLoadFloat3(&position); + const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position); + + const XMVECTOR LHS_DIR = XMLoadFloat3(&direction); + const XMVECTOR RHS_DIR = XMLoadFloat3(&rhs.direction); + + return XMVector3Equal(LHS_POS, RHS_POS) && XMVector3NotEqual(LHS_DIR, RHS_DIR); + } + + bool SHRay::operator!=(const SHRay& rhs) noexcept + { + const XMVECTOR LHS_POS = XMLoadFloat3(&position); + const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position); + + const XMVECTOR LHS_DIR = XMLoadFloat3(&direction); + const XMVECTOR RHS_DIR = XMLoadFloat3(&rhs.direction); + + return XMVector3NotEqual(LHS_POS, RHS_POS) || XMVector3NotEqual(LHS_DIR, RHS_DIR); + } + + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHRay.h b/SHADE_Engine/src/Math/SHRay.h new file mode 100644 index 00000000..29d55b16 --- /dev/null +++ b/SHADE_Engine/src/Math/SHRay.h @@ -0,0 +1,54 @@ +/**************************************************************************************** + * \file SHRay.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Ray. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "SH_API.h" +#include "Vector/SHVec3.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SH_API SHRay + { + public: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + SHVec3 position; + SHVec3 direction; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHRay() noexcept; + SHRay(const SHVec3& pos, const SHVec3& dir) noexcept; + SHRay(const SHRay& rhs) noexcept = default; + SHRay(SHRay&& rhs) noexcept = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHRay& operator= (const SHRay& rhs) noexcept = default; + SHRay& operator= (SHRay&& rhs) noexcept = default; + + [[nodiscard]] bool operator==(const SHRay& rhs) noexcept; + [[nodiscard]] bool operator!=(const SHRay& rhs) noexcept; + }; +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.cpp b/SHADE_Engine/src/Math/Vector/SHVec2.cpp index 545492cb..195a8b14 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec2.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT2( 0.0f, 0.0f ) {} + SHVec2::SHVec2(const XMFLOAT2& xmfloat2) noexcept + : XMFLOAT2 ( xmfloat2.x, xmfloat2.y ) + {} + SHVec2::SHVec2(float n) noexcept : XMFLOAT2( n, n ) {} @@ -46,10 +50,19 @@ namespace SHADE : XMFLOAT2( _x, _y ) {} + SHVec2::SHVec2(const reactphysics3d::Vector2& rp3dVec2) noexcept + : XMFLOAT2( rp3dVec2.x, rp3dVec2.y ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec2::operator XMVECTOR() const noexcept + { + return XMLoadFloat2(this); + } + SHVec2& SHVec2::operator+=(const SHVec2& rhs) noexcept { return *this = *this + rhs; @@ -83,22 +96,16 @@ namespace SHADE SHVec2 SHVec2::operator+(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorAdd(V1, V2)); + XMStoreFloat2(&result, XMVectorAdd(*this, rhs)); return result; } SHVec2 SHVec2::operator-(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat2(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -110,59 +117,43 @@ namespace SHADE SHVec2 SHVec2::operator*(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat2(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec2 SHVec2::operator*(float rhs) const noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(this); - XMStoreFloat2(&result, XMVectorScale(V, rhs)); + XMStoreFloat2(&result, XMVectorScale(*this, rhs)); return result; } SHVec2 SHVec2::operator/(const SHVec2& rhs) const noexcept { SHVec2 result; - - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorDivide(V1, V2)); + XMStoreFloat2(&result, XMVectorDivide(*this, rhs)); return result; } SHVec2 SHVec2::operator/(float rhs) const noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(this); - XMStoreFloat2(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat2(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec2::operator==(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVector2Equal(V1, V2); + return XMVector2Equal(*this, rhs); } bool SHVec2::operator!=(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVector2NotEqual(V1, V2); + return XMVector2NotEqual(*this, rhs); } float& SHVec2::operator[](int index) @@ -213,13 +204,16 @@ namespace SHADE } } + SHVec2::operator reactphysics3d::Vector2() const noexcept + { + return reactphysics3d::Vector2{ x, y }; + } + SHVec2 operator* (float lhs, const SHVec2& rhs) noexcept { SHVec2 result; - - const XMVECTOR V = XMLoadFloat2(&rhs); - XMStoreFloat2(&result, XMVectorScale(V, lhs)); + XMStoreFloat2(&result, XMVectorScale(rhs, lhs)); return result; } @@ -229,16 +223,12 @@ namespace SHADE float SHVec2::Length() const noexcept { - const XMVECTOR V = XMLoadFloat2(this); - - return XMVectorGetX(XMVector2Length(V)); + return XMVectorGetX(XMVector2Length(*this)); } float SHVec2::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat2(this); - - return XMVectorGetX(XMVector2LengthSq(V)); + return XMVectorGetX(XMVector2LengthSq(*this)); } std::string SHVec2::ToString() const noexcept @@ -251,20 +241,14 @@ namespace SHADE float SHVec2::Dot(const SHVec2& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVectorGetX(XMVector2Dot(V1, V2)); + return XMVectorGetX(XMVector2Dot(*this, rhs)); } SHVec2 SHVec2::Cross(const SHVec2& rhs) const noexcept { SHVec2 result; - const XMVECTOR V1 = XMLoadFloat2(this); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - XMStoreFloat2(&result, XMVector2Cross(V1, V2)); + XMStoreFloat2(&result, XMVector2Cross(*this, rhs)); return result; } @@ -276,9 +260,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&vec2); - - XMStoreFloat2(&result, XMVector2Normalize(V)); + XMStoreFloat2(&result, XMVector2Normalize(vec2)); return result; } @@ -297,10 +279,10 @@ namespace SHADE SHVec2 result; - XMVECTOR min = XMLoadFloat2(&(*vec2s.begin())); + XMVECTOR min = *vec2s.begin(); for (auto it = vec2s.begin() + 1; it != vec2s.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat2(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -318,10 +300,10 @@ namespace SHADE SHVec2 result; - XMVECTOR max = XMLoadFloat2(&(*vec2s.begin())); + XMVECTOR max = *vec2s.begin(); for (auto it = vec2s.begin() + 1; it != vec2s.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat2(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -333,11 +315,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); - const XMVECTOR MIN = XMLoadFloat2(&vMin); - const XMVECTOR MAX = XMLoadFloat2(&vMax); - - XMStoreFloat2(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat2(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -345,10 +323,7 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V1 = XMLoadFloat2(&a); - const XMVECTOR V2 = XMLoadFloat2(&b); - - XMStoreFloat2(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat2(&result, XMVectorLerp(a, b, t)); return result; } @@ -369,10 +344,7 @@ namespace SHADE float SHVec2::Angle(const SHVec2& lhs, const SHVec2& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat2(&lhs); - const XMVECTOR V2 = XMLoadFloat2(&rhs); - - return XMVectorGetX(XMVector2AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector2AngleBetweenVectors(lhs, rhs)); } float SHVec2::Dot(const SHVec2& lhs, const SHVec2& rhs) noexcept @@ -384,11 +356,10 @@ namespace SHADE { SHVec2 result; - const XMVECTOR U = XMLoadFloat2(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat2(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat2(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } @@ -396,10 +367,8 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); - const XMVECTOR N = XMLoadFloat2(&normal); - XMStoreFloat2(&result, XMVector2Reflect(V, N)); + XMStoreFloat2(&result, XMVector2Reflect(v, normal)); return result; } @@ -407,10 +376,9 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); const XMMATRIX R = XMMatrixRotationZ(angleInRad); - XMStoreFloat2(&result, XMVector2Transform(V, R)); + XMStoreFloat2(&result, XMVector2Transform(v, R)); return result; } @@ -418,10 +386,9 @@ namespace SHADE { SHVec2 result; - const XMVECTOR V = XMLoadFloat2(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat2(&result, XMVector2TransformCoord(V, TF)); + XMStoreFloat2(&result, XMVector2TransformCoord(v, TF)); return result; } diff --git a/SHADE_Engine/src/Math/Vector/SHVec2.h b/SHADE_Engine/src/Math/Vector/SHVec2.h index 17642126..e780d3ac 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec2.h +++ b/SHADE_Engine/src/Math/Vector/SHVec2.h @@ -11,6 +11,8 @@ #pragma once #include +#include + #include #include @@ -52,9 +54,14 @@ namespace SHADE SHVec2 (SHVec2&& rhs) = default; ~SHVec2 () = default; - SHVec2 () noexcept; - SHVec2 (float n) noexcept; - SHVec2 (float x, float y) noexcept; + SHVec2 () noexcept; + SHVec2 (const XMFLOAT2& xmfloat2) noexcept; + SHVec2 (float n) noexcept; + SHVec2 (float x, float y) noexcept; + + // Conversion from other math types to SHADE + + SHVec2 (const reactphysics3d::Vector2& rp3dVec2) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -63,6 +70,11 @@ namespace SHADE SHVec2& operator= (const SHVec2& rhs) = default; SHVec2& operator= (SHVec2&& rhs) = default; + // Conversion to other math types used by SHADE + + operator DirectX::XMVECTOR () const noexcept; + operator reactphysics3d::Vector2 () const noexcept; + SHVec2& operator+= (const SHVec2& rhs) noexcept; SHVec2& operator-= (const SHVec2& rhs) noexcept; SHVec2& operator*= (const SHVec2& rhs) noexcept; @@ -86,6 +98,7 @@ namespace SHADE [[nodiscard]] float operator[] (int index) const; [[nodiscard]] float operator[] (size_t index) const; + /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.cpp b/SHADE_Engine/src/Math/Vector/SHVec3.cpp index 1bcb47b3..c3e3acf2 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec3.cpp @@ -14,6 +14,7 @@ #include "SHVec3.h" // Project Headers #include "Math/SHMatrix.h" +#include "Math/SHQuaternion.h" #include "Tools/SHLogger.h" using namespace DirectX; @@ -23,6 +24,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec3 const SHVec3::Zero { 0.0f, 0.0f, 0.0f }; SHVec3 const SHVec3::One { 1.0f, 1.0f, 1.0f }; SHVec3 const SHVec3::Left { -1.0f, 0.0f, 0.0f }; @@ -43,6 +45,10 @@ namespace SHADE : XMFLOAT3( 0.0f, 0.0f, 0.0f ) {} + SHVec3::SHVec3(const XMFLOAT3& xmfloat3) noexcept + : XMFLOAT3 ( xmfloat3.x, xmfloat3.y, xmfloat3.z ) + {} + SHVec3::SHVec3(float n) noexcept : XMFLOAT3( n, n, n ) {} @@ -51,10 +57,24 @@ namespace SHADE : XMFLOAT3( _x, _y, _z ) {} + SHVec3::SHVec3(const reactphysics3d::Vector3& rp3dVec3) noexcept + : XMFLOAT3( rp3dVec3.x, rp3dVec3.y, rp3dVec3.z ) + {} + + SHVec3::SHVec3(const reactphysics3d::Quaternion& rp3dVec3) noexcept + : XMFLOAT3( SHQuaternion{rp3dVec3}.ToEuler() ) + {} + /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec3::operator XMVECTOR() const noexcept + { + return XMLoadFloat3(this); + } + + SHVec3& SHVec3::operator+=(const SHVec3& rhs) noexcept { return *this = *this + rhs; @@ -88,22 +108,16 @@ namespace SHADE SHVec3 SHVec3::operator+(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorAdd(V1, V2)); + XMStoreFloat3(&result, XMVectorAdd(*this, rhs)); return result; } SHVec3 SHVec3::operator-(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat3(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -116,59 +130,43 @@ namespace SHADE SHVec3 SHVec3::operator*(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat3(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec3 SHVec3::operator*(float rhs) const noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(this); - XMStoreFloat3(&result, XMVectorScale(V, rhs)); + XMStoreFloat3(&result, XMVectorScale(*this, rhs)); return result; } SHVec3 SHVec3::operator/(const SHVec3& rhs) const noexcept { SHVec3 result; - - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorDivide(V1, V2)); + XMStoreFloat3(&result, XMVectorDivide(*this, rhs)); return result; } SHVec3 SHVec3::operator/(float rhs) const noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(this); - XMStoreFloat3(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat3(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec3::operator==(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVector3Equal(V1, V2); + return XMVector3Equal(*this, rhs); } bool SHVec3::operator!=(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVector3NotEqual(V1, V2); + return XMVector3NotEqual(*this, rhs); } float& SHVec3::operator[](int index) @@ -223,13 +221,21 @@ namespace SHADE } } + SHVec3::operator reactphysics3d::Vector3() const noexcept + { + return reactphysics3d::Vector3{ x, y , z }; + } + + SHVec3::operator reactphysics3d::Quaternion() const noexcept + { + return reactphysics3d::Quaternion::fromEulerAngles(x, y, z); + } + SHVec3 operator* (float lhs, const SHVec3& rhs) noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(&rhs); - XMStoreFloat3(&result, XMVectorScale(V, lhs)); + XMStoreFloat3(&result, XMVectorScale(rhs, lhs)); return result; } @@ -239,16 +245,12 @@ namespace SHADE float SHVec3::Length() const noexcept { - const XMVECTOR V = XMLoadFloat3(this); - - return XMVectorGetX(XMVector3Length(V)); + return XMVectorGetX(XMVector3Length(*this)); } float SHVec3::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat3(this); - - return XMVectorGetX(XMVector3LengthSq(V)); + return XMVectorGetX(XMVector3LengthSq(*this)); } std::string SHVec3::ToString() const noexcept @@ -261,20 +263,14 @@ namespace SHADE float SHVec3::Dot(const SHVec3& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - return XMVectorGetX(XMVector3Dot(V1, V2)); + return XMVectorGetX(XMVector3Dot(*this, rhs)); } SHVec3 SHVec3::Cross(const SHVec3& rhs) const noexcept { SHVec3 result; - const XMVECTOR V1 = XMLoadFloat3(this); - const XMVECTOR V2 = XMLoadFloat3(&rhs); - - XMStoreFloat3(&result, XMVector3Cross(V1, V2)); + XMStoreFloat3(&result, XMVector3Cross(*this, rhs)); return result; } @@ -286,9 +282,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - - XMStoreFloat3(&result, XMVector3Normalize(V)); + XMStoreFloat3(&result, XMVector3Normalize(v)); return result; } @@ -307,10 +301,10 @@ namespace SHADE SHVec3 result; - XMVECTOR min = XMLoadFloat3(&(*vs.begin())); + XMVECTOR min = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat3(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -328,10 +322,10 @@ namespace SHADE SHVec3 result; - XMVECTOR max = XMLoadFloat3(&(*vs.begin())); + XMVECTOR max = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat3(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -343,11 +337,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMVECTOR MIN = XMLoadFloat3(&vMin); - const XMVECTOR MAX = XMLoadFloat3(&vMax); - - XMStoreFloat3(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat3(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -355,10 +345,7 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V1 = XMLoadFloat3(&a); - const XMVECTOR V2 = XMLoadFloat3(&b); - - XMStoreFloat3(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat3(&result, XMVectorLerp(a, b, t)); return result; } @@ -382,7 +369,7 @@ namespace SHADE const XMVECTOR V1 = XMLoadFloat3(&lhs); const XMVECTOR V2 = XMLoadFloat3(&rhs); - return XMVectorGetX(XMVector3AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector3AngleBetweenVectors(lhs, rhs)); } float SHVec3::Dot(const SHVec3& lhs, const SHVec3& rhs) noexcept @@ -399,22 +386,18 @@ namespace SHADE { SHVec3 result; - const XMVECTOR U = XMLoadFloat3(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat3(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat3(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } SHVec3 SHVec3::Reflect(const SHVec3& v, const SHVec3& normal) noexcept { SHVec3 result; - - const XMVECTOR V = XMLoadFloat3(&v); - const XMVECTOR N = XMLoadFloat3(&normal); - XMStoreFloat3(&result, XMVector3Reflect(V, N)); + XMStoreFloat3(&result, XMVector3Reflect(v, normal)); return result; } @@ -422,12 +405,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); + const XMVECTOR Q = XMQuaternionRotationAxis(axis, angleInRad); - const XMVECTOR AXIS = XMLoadFloat3(&axis); - const XMVECTOR Q = XMQuaternionRotationAxis(AXIS, angleInRad); - - XMStoreFloat3(&result, XMVector3Rotate(V, Q)); + XMStoreFloat3(&result, XMVector3Rotate(v, Q)); return result; } @@ -435,10 +415,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationX(angleInRad); + const XMMATRIX R = XMMatrixRotationX(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -446,10 +425,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationY(angleInRad); + const XMMATRIX R = XMMatrixRotationY(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -457,10 +435,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); - const XMMATRIX R = XMMatrixRotationZ(angleInRad); + const XMMATRIX R = XMMatrixRotationZ(angleInRad); - XMStoreFloat3(&result, XMVector3TransformCoord(V, R)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, R)); return result; } @@ -468,10 +445,9 @@ namespace SHADE { SHVec3 result; - const XMVECTOR V = XMLoadFloat3(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat3(&result, XMVector3TransformCoord(V, TF)); + XMStoreFloat3(&result, XMVector3TransformCoord(v, TF)); return result; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec3.h b/SHADE_Engine/src/Math/Vector/SHVec3.h index cc0e043e..eab96b30 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec3.h +++ b/SHADE_Engine/src/Math/Vector/SHVec3.h @@ -11,6 +11,9 @@ #pragma once #include +#include +#include + #include #include @@ -58,39 +61,50 @@ namespace SHADE ~SHVec3 () = default; SHVec3 () noexcept; + SHVec3 (const XMFLOAT3& xmfloat3) noexcept; SHVec3 (float n) noexcept; SHVec3 (float x, float y, float z) noexcept; + // Conversion from other math types to SHADE + + SHVec3 (const reactphysics3d::Vector3& rp3dVec3) noexcept; + SHVec3 (const reactphysics3d::Quaternion& rp3dVec3) noexcept; + /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHVec3& operator= (const SHVec3& rhs) = default; - SHVec3& operator= (SHVec3&& rhs) = default; + SHVec3& operator= (const SHVec3& rhs) = default; + SHVec3& operator= (SHVec3&& rhs) = default; - SHVec3& operator+= (const SHVec3& rhs) noexcept; - SHVec3& operator-= (const SHVec3& rhs) noexcept; - SHVec3& operator*= (const SHVec3& rhs) noexcept; - SHVec3& operator*= (float rhs) noexcept; - SHVec3& operator/= (const SHVec3& rhs) noexcept; - SHVec3& operator/= (float rhs) noexcept; + // Conversion to other math types used by SHADE - [[nodiscard]] SHVec3 operator+ (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator- (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator- () const noexcept; - [[nodiscard]] SHVec3 operator* (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator* (float rhs) const noexcept; - [[nodiscard]] SHVec3 operator/ (const SHVec3& rhs) const noexcept; - [[nodiscard]] SHVec3 operator/ (float rhs) const noexcept; + operator reactphysics3d::Vector3 () const noexcept; + operator reactphysics3d::Quaternion () const noexcept; + operator DirectX::XMVECTOR () const noexcept; - [[nodiscard]] bool operator== (const SHVec3& rhs) const noexcept; - [[nodiscard]] bool operator!= (const SHVec3& rhs) const noexcept; + SHVec3& operator+= (const SHVec3& rhs) noexcept; + SHVec3& operator-= (const SHVec3& rhs) noexcept; + SHVec3& operator*= (const SHVec3& rhs) noexcept; + SHVec3& operator*= (float rhs) noexcept; + SHVec3& operator/= (const SHVec3& rhs) noexcept; + SHVec3& operator/= (float rhs) noexcept; - [[nodiscard]] float& operator[] (int index); - [[nodiscard]] float& operator[] (size_t index); - [[nodiscard]] float operator[] (int index) const; - [[nodiscard]] float operator[] (size_t index) const; + [[nodiscard]] SHVec3 operator+ (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator- (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator- () const noexcept; + [[nodiscard]] SHVec3 operator* (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator* (float rhs) const noexcept; + [[nodiscard]] SHVec3 operator/ (const SHVec3& rhs) const noexcept; + [[nodiscard]] SHVec3 operator/ (float rhs) const noexcept; + [[nodiscard]] bool operator== (const SHVec3& rhs) const noexcept; + [[nodiscard]] bool operator!= (const SHVec3& rhs) const noexcept; + + [[nodiscard]] float& operator[] (int index); + [[nodiscard]] float& operator[] (size_t index); + [[nodiscard]] float operator[] (int index) const; + [[nodiscard]] float operator[] (size_t index) const; /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index d1c87865..bcf2ef97 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ) {} + SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept + : XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w ) + {} + SHVec4::SHVec4(float _x, float _y, float _z, float _w) noexcept : XMFLOAT4( _x, _y, _z, _w ) {} @@ -46,6 +50,11 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ + SHVec4::operator XMVECTOR() const noexcept + { + return XMLoadFloat4(this); + } + SHVec4& SHVec4::operator+=(const SHVec4& rhs) noexcept { return *this = *this + rhs; @@ -79,22 +88,16 @@ namespace SHADE SHVec4 SHVec4::operator+(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorAdd(V1, V2)); + XMStoreFloat4(&result, XMVectorAdd(*this, rhs)); return result; } SHVec4 SHVec4::operator-(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorSubtract(V1, V2)); + XMStoreFloat4(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -106,59 +109,43 @@ namespace SHADE SHVec4 SHVec4::operator*(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorMultiply(V1, V2)); + XMStoreFloat4(&result, XMVectorMultiply(*this, rhs)); return result; } SHVec4 SHVec4::operator*(float rhs) const noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(this); - XMStoreFloat4(&result, XMVectorScale(V, rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, rhs)); return result; } SHVec4 SHVec4::operator/(const SHVec4& rhs) const noexcept { SHVec4 result; - - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorDivide(V1, V2)); + XMStoreFloat4(&result, XMVectorDivide(*this, rhs)); return result; } SHVec4 SHVec4::operator/(float rhs) const noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(this); - XMStoreFloat4(&result, XMVectorScale(V, 1.0f / rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, 1.0f / rhs)); return result; } bool SHVec4::operator==(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVector4Equal(V1, V2); + return XMVector4Equal(*this, rhs); } bool SHVec4::operator!=(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVector4NotEqual(V1, V2); + return XMVector4NotEqual(*this, rhs); } float& SHVec4::operator[](int index) @@ -220,10 +207,8 @@ namespace SHADE SHVec4 operator* (float lhs, const SHVec4& rhs) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&rhs); - XMStoreFloat4(&result, XMVectorScale(V, lhs)); + XMStoreFloat4(&result, XMVectorScale(rhs, lhs)); return result; } @@ -233,30 +218,22 @@ namespace SHADE float SHVec4::Length() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector4Length(V)); + return XMVectorGetX(XMVector4Length(*this)); } float SHVec4::Length3D() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector3Length(V)); + return XMVectorGetX(XMVector3Length(*this)); } float SHVec4::LengthSquared() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector4LengthSq(V)); + return XMVectorGetX(XMVector4LengthSq(*this)); } float SHVec4::LengthSquared3D() const noexcept { - const XMVECTOR V = XMLoadFloat4(this); - - return XMVectorGetX(XMVector3LengthSq(V)); + return XMVectorGetX(XMVector3LengthSq(*this)); } std::string SHVec4::ToString() const noexcept @@ -269,28 +246,19 @@ namespace SHADE float SHVec4::Dot(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector4Dot(V1, V2)); + return XMVectorGetX(XMVector4Dot(*this, rhs)); } float SHVec4::Dot3D(const SHVec4& rhs) const noexcept { - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector3Dot(V1, V2)); + return XMVectorGetX(XMVector3Dot(*this, rhs)); } SHVec4 SHVec4::Cross3D(const SHVec4& rhs) const noexcept { SHVec4 result; - const XMVECTOR V1 = XMLoadFloat4(this); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVector3Cross(V1, V2)); + XMStoreFloat4(&result, XMVector3Cross(*this, rhs)); result.w = 1.0f; return result; } @@ -299,11 +267,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V3 = XMLoadFloat4(this); - const XMVECTOR V1 = XMLoadFloat4(&v1); - const XMVECTOR V2 = XMLoadFloat4(&v2); - - XMStoreFloat4(&result, XMVector4Cross(V3, V1, V2)); + XMStoreFloat4(&result, XMVector4Cross(*this, v1, v2)); return result; } @@ -315,9 +279,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - - XMStoreFloat4(&result, XMVector4Normalize(V)); + XMStoreFloat4(&result, XMVector4Normalize(v)); return result; } @@ -325,9 +287,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - - XMStoreFloat4(&result, XMVector3Normalize(V)); + XMStoreFloat4(&result, XMVector3Normalize(v)); result.w = 1.0f; return result; } @@ -347,10 +307,10 @@ namespace SHADE SHVec4 result; - XMVECTOR min = XMLoadFloat4(&(*vs.begin())); + XMVECTOR min = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat4(&(*it)); + const XMVECTOR tmp = *it; min = XMVectorMin(min, tmp); } @@ -368,10 +328,10 @@ namespace SHADE SHVec4 result; - XMVECTOR max = XMLoadFloat4(&(*vs.begin())); + XMVECTOR max = *vs.begin(); for (auto it = vs.begin() + 1; it != vs.end(); ++it) { - const XMVECTOR tmp = XMLoadFloat4(&(*it)); + const XMVECTOR tmp = *it; max = XMVectorMax(max, tmp); } @@ -383,11 +343,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR MIN = XMLoadFloat4(&vMin); - const XMVECTOR MAX = XMLoadFloat4(&vMax); - - XMStoreFloat4(&result, XMVectorClamp(V, MIN, MAX)); + XMStoreFloat4(&result, XMVectorClamp(v, vMin, vMax)); return result; } @@ -395,10 +351,7 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V1 = XMLoadFloat4(&a); - const XMVECTOR V2 = XMLoadFloat4(&b); - - XMStoreFloat4(&result, XMVectorLerp(V1, V2, t)); + XMStoreFloat4(&result, XMVectorLerp(a, b, t)); return result; } @@ -429,18 +382,12 @@ namespace SHADE float SHVec4::Angle(const SHVec4& lhs, const SHVec4& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat4(&lhs); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector4AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector4AngleBetweenVectors(lhs,rhs)); } float SHVec4::Angle3D(const SHVec4& lhs, const SHVec4& rhs) noexcept { - const XMVECTOR V1 = XMLoadFloat4(&lhs); - const XMVECTOR V2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMVector3AngleBetweenVectors(V1, V2)); + return XMVectorGetX(XMVector3AngleBetweenVectors(lhs,rhs)); } float SHVec4::Dot(const SHVec4& lhs, const SHVec4& rhs) noexcept @@ -467,11 +414,10 @@ namespace SHADE { SHVec4 result; - const XMVECTOR U = XMLoadFloat4(&u); const float V_DOT_U = Dot(v, u); const float U_LENSQ = u.LengthSquared(); - XMStoreFloat4(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat4(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); return result; } @@ -479,11 +425,10 @@ namespace SHADE { SHVec4 result; - const XMVECTOR U = XMLoadFloat4(&u); const float V_DOT_U = Dot3D(v, u); const float U_LENSQ = u.LengthSquared3D(); - XMStoreFloat4(&result, XMVectorScale(U, V_DOT_U / U_LENSQ)); + XMStoreFloat4(&result, XMVectorScale(u, V_DOT_U / U_LENSQ)); result.w = 1.0f; return result; } @@ -491,11 +436,8 @@ namespace SHADE SHVec4 SHVec4::Reflect(const SHVec4& v, const SHVec4& normal) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR N = XMLoadFloat4(&normal); - XMStoreFloat4(&result, XMVector4Reflect(V, N)); + XMStoreFloat4(&result, XMVector4Reflect(v, normal)); result.w = 1.0f; return result; } @@ -503,11 +445,8 @@ namespace SHADE SHVec4 SHVec4::Reflect3D(const SHVec4& v, const SHVec4& normal) noexcept { SHVec4 result; - - const XMVECTOR V = XMLoadFloat4(&v); - const XMVECTOR N = XMLoadFloat4(&normal); - XMStoreFloat4(&result, XMVector3Reflect(V, N)); + XMStoreFloat4(&result, XMVector3Reflect(v, normal)); result.w = 1.0f; return result; } @@ -516,10 +455,9 @@ namespace SHADE { SHVec4 result; - const XMVECTOR V = XMLoadFloat4(&v); const XMMATRIX TF = XMLoadFloat4x4(&transformMtx); - XMStoreFloat4(&result, XMVector3TransformCoord(V, TF)); + XMStoreFloat4(&result, XMVector3TransformCoord(v, TF)); return result; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.h b/SHADE_Engine/src/Math/Vector/SHVec4.h index 59038065..911a714e 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.h +++ b/SHADE_Engine/src/Math/Vector/SHVec4.h @@ -52,8 +52,9 @@ namespace SHADE SHVec4 (SHVec4&& rhs) = default; ~SHVec4 () = default; - SHVec4 () noexcept; - SHVec4 (float x, float y, float z, float w) noexcept; + SHVec4 () noexcept; + SHVec4 (const XMFLOAT4& xmfloat4) noexcept; + SHVec4 (float x, float y, float z, float w) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -62,6 +63,8 @@ namespace SHADE SHVec4& operator= (const SHVec4& rhs) = default; SHVec4& operator= (SHVec4&& rhs) = default; + operator DirectX::XMVECTOR () const noexcept; + SHVec4& operator+= (const SHVec4& rhs) noexcept; SHVec4& operator-= (const SHVec4& rhs) noexcept; SHVec4& operator*= (const SHVec4& rhs) noexcept; diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index 73e7ccbd..71183f00 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" +#include "Math/SHMathHelpers.h" #include "Physics/SHPhysicsSystem.h" namespace SHADE @@ -24,7 +25,8 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHColliderComponent::SHColliderComponent() noexcept - : system { nullptr } + : system { nullptr } + , colliders {} {} /*-----------------------------------------------------------------------------------*/ @@ -87,12 +89,17 @@ namespace SHADE system->RemoveCollider(GetEID()); } - SHBoundingBox* SHColliderComponent::AddBoundingBox() noexcept + SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept { const auto TYPE = SHCollider::Type::BOX; - const auto BOX_PAIR = std::make_pair(SHCollider{TYPE}, true); - auto& collider = colliders.emplace_back(BOX_PAIR).first; + auto boxPair = std::make_pair(SHCollider{TYPE}, true); + auto& collider = colliders.emplace_back(boxPair).first; + + const auto* tf = SHComponentManager::GetComponent(GetEID()); + + collider.SetPositionOffset(posOffset); + collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents); if (!system) { @@ -101,23 +108,37 @@ namespace SHADE } // Notify Physics System - system->AddCollisionShape(GetEID(), collider.GetShape()); + system->AddCollisionShape(GetEID(), &collider); return reinterpret_cast(collider.GetShape()); } - //void SHColliderComponent::AddSphere() noexcept - //{ - // const auto TYPE = SHCollider::Type::SPHERE; + SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept + { + const auto TYPE = SHCollider::Type::SPHERE; - // if (!system) - // { - // SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") - // return; - // } + auto spherePair = std::make_pair(SHCollider{ TYPE }, true); + auto& collider = colliders.emplace_back(spherePair).first; - // // Notify Physics System - //} + const auto* tf = SHComponentManager::GetComponent(GetEID()); + + collider.SetPositionOffset(posOffset); + + const SHVec3 TF_WORLD_SCALE = tf->GetWorldScale(); + const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); + collider.SetAsBoundingSphere(MAX_SCALE * 0.5f); + + if (!system) + { + SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") + return nullptr; + } + + // Notify Physics System + system->AddCollisionShape(GetEID(), &collider); + + return reinterpret_cast(collider.GetShape()); + } void SHColliderComponent::RemoveCollider(int index) { diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h index cb9696d9..22d5ceee 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h @@ -15,6 +15,13 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" #include "Physics/SHCollider.h" +#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHBoundingSphere.h" + +//namespace SHADE +//{ +// class SHPhysicsSystem; +//} namespace SHADE { @@ -30,6 +37,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObject; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -76,10 +84,11 @@ namespace SHADE void OnCreate () override; void OnDestroy () override; - SHBoundingBox* AddBoundingBox () noexcept; - void RemoveCollider (int index); + SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept; + SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; + private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 5f961de4..e5938717 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -392,9 +392,9 @@ RTTR_REGISTRATION registration::enumeration("RigidBody Type") ( - value("Static", SHRigidBodyComponent::Type::STATIC), - value("Dynamic", SHRigidBodyComponent::Type::DYNAMIC), - value("Kinematic", SHRigidBodyComponent::Type::KINEMATIC) + value("Static", SHRigidBodyComponent::Type::STATIC), + value("Kinematic", SHRigidBodyComponent::Type::KINEMATIC), + value("Dynamic", SHRigidBodyComponent::Type::DYNAMIC) ); registration::class_("RigidBody Component") diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h index 0793b2ff..03b350e1 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h @@ -14,7 +14,13 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Physics/SHPhysicsObject.h" +#include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" + +//namespace SHADE +//{ +// class SHPhysicsSystem; +//} namespace SHADE { @@ -30,6 +36,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObject; public: /*---------------------------------------------------------------------------------*/ @@ -137,6 +144,9 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ + static constexpr size_t NUM_FLAGS = 8; + static constexpr size_t NUM_DIRTY_FLAGS = 16; + Type type; // rX rY rZ pX pY pZ slp g @@ -162,10 +172,6 @@ namespace SHADE SHVec3 position; SHQuaternion orientation; - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - RTTR_ENABLE() }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHCollider.cpp b/SHADE_Engine/src/Physics/SHCollider.cpp index 724db19c..f5899cfc 100644 --- a/SHADE_Engine/src/Physics/SHCollider.cpp +++ b/SHADE_Engine/src/Physics/SHCollider.cpp @@ -12,6 +12,9 @@ // Primary Header #include "SHCollider.h" +// Project Headers +#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHBoundingSphere.h" namespace SHADE { @@ -25,34 +28,41 @@ namespace SHADE , dirty { true } , shape { nullptr } { - CreateShape(); + switch (type) + { + case Type::BOX: + { + SetAsBoundingBox(SHVec3::One); + break; + } + case Type::SPHERE: + { + SetAsBoundingSphere(1.0f); + break; + } + default: break; + } } SHCollider::SHCollider(const SHCollider& rhs) noexcept - : type { rhs.type} - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - { - CreateShape(); - - // TODO(Diren): Copy transform data over - } + : type { rhs.type} + , isTrigger { rhs.isTrigger } + , dirty { true } + , shape { rhs.shape } + , positionOffset { rhs.positionOffset } + {} SHCollider::SHCollider(SHCollider&& rhs) noexcept - : type { rhs.type} - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - { - CreateShape(); - - // TODO(Diren): Copy transform data over - } + : type { rhs.type} + , isTrigger { rhs.isTrigger } + , dirty { true } + , shape { rhs.shape } + , positionOffset { rhs.positionOffset } + {} SHCollider::~SHCollider() noexcept { - delete shape; + shape = nullptr; } /*-----------------------------------------------------------------------------------*/ @@ -61,26 +71,25 @@ namespace SHADE SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept { - type = rhs.type; - isTrigger = rhs.isTrigger; - dirty = true; - - CreateShape(); - - // TODO(Diren): Copy transform data over + if (this == &rhs) + return *this; + + type = rhs.type; + isTrigger = rhs.isTrigger; + dirty = true; + shape = rhs.shape; + positionOffset = rhs.positionOffset; return *this; } SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept { - type = rhs.type; - isTrigger = rhs.isTrigger; - dirty = true; - - CreateShape(); - - // TODO(Diren): Copy transform data over + type = rhs.type; + isTrigger = rhs.isTrigger; + dirty = true; + shape = rhs.shape; + positionOffset = rhs.positionOffset; return *this; } @@ -104,11 +113,6 @@ namespace SHADE return type; } - SHShape* SHCollider::GetShape() const noexcept - { - return shape; - } - float SHCollider::GetFriction() const noexcept { // TODO(Diren): Fix after implementing materials @@ -126,36 +130,37 @@ namespace SHADE return 0.0f; } - SHVec3 SHCollider::GetPosition() const noexcept - { - // TODO(Diren): Fix after linking transform data - return SHVec3::Zero; - } - const SHVec3& SHCollider::GetPositionOffset() const noexcept { return positionOffset; } - SHQuaternion SHCollider::GetOrientation() const noexcept + SHShape* SHCollider::GetShape() noexcept { - // TODO(Diren): Fix after linking transform data - return SHQuaternion::Identity; + dirty = true; + return shape; } /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHCollider::SetType(Type newType) noexcept + void SHCollider::SetAsBoundingBox(const SHVec3& halfExtents) { - if (type == newType) - return; - dirty = true; + type = Type::BOX; - type = newType; - CreateShape(); + delete shape; + shape = new SHBoundingBox{ positionOffset, halfExtents }; + } + + void SHCollider::SetAsBoundingSphere(float radius) + { + dirty = true; + type = Type::SPHERE; + + delete shape; + shape = new SHBoundingSphere{ positionOffset, radius }; } void SHCollider::SetIsTrigger(bool trigger) noexcept @@ -184,32 +189,21 @@ namespace SHADE dirty = true; positionOffset = posOffset; } +} // namespace SHADE - /*-----------------------------------------------------------------------------------*/ - /* Private Member Function Definitions */ - /*-----------------------------------------------------------------------------------*/ +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; - void SHCollider::CreateShape() - { - // Remove current shape - delete shape; + registration::enumeration("Collider Type") + ( + value("Box", SHCollider::Type::BOX), + value("Sphere", SHCollider::Type::SPHERE) + // TODO(Diren): Add More Shapes + ); - switch (type) - { - case Type::BOX: CreateBoundingBox(); break; - case Type::SPHERE: CreateSphere(); break; - default: break; - } - } - - void SHCollider::CreateBoundingBox() - { - shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; - } - - void SHCollider::CreateSphere() - { - - } - -} // namespace SHADE \ No newline at end of file + registration::class_("Collider") + .property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset); + // TODO(Diren): Add Physics Materials +} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHCollider.h b/SHADE_Engine/src/Physics/SHCollider.h index fce4a5b2..0e024f09 100644 --- a/SHADE_Engine/src/Physics/SHCollider.h +++ b/SHADE_Engine/src/Physics/SHCollider.h @@ -10,8 +10,10 @@ #pragma once +#include + // Project Headers -#include "Math/Geometry/SHBoundingBox.h" +#include "Math/Geometry/SHShape.h" #include "Math/SHQuaternion.h" namespace SHADE @@ -32,15 +34,13 @@ namespace SHADE BOX , SPHERE , CAPSULE - , CONVEX_HULL - , CONVEX_MESH }; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHCollider (Type colliderType); + SHCollider (Type colliderType = Type::BOX); SHCollider (const SHCollider& rhs) noexcept; SHCollider (SHCollider&& rhs) noexcept; @@ -62,28 +62,28 @@ namespace SHADE [[nodiscard]] bool IsTrigger () const noexcept; [[nodiscard]] Type GetType () const noexcept; - [[nodiscard]] SHShape* GetShape () const noexcept; [[nodiscard]] float GetFriction () const noexcept; [[nodiscard]] float GetBounciness () const noexcept; [[nodiscard]] float GetDensity () const noexcept; - [[nodiscard]] SHVec3 GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; - [[nodiscard]] SHQuaternion GetOrientation () const noexcept; + + [[nodiscard]] SHShape* GetShape () noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetType (Type newType) noexcept; + void SetAsBoundingBox (const SHVec3& halfExtents); + void SetAsBoundingSphere (float radius); - void SetIsTrigger (bool isTrigger) noexcept; - void SetFriction (float friction) noexcept; - void SetBounciness (float bounciness) noexcept; - void SetDensity (float density) noexcept; + void SetIsTrigger (bool isTrigger) noexcept; + void SetFriction (float friction) noexcept; + void SetBounciness (float bounciness) noexcept; + void SetDensity (float density) noexcept; - void SetPositionOffset (const SHVec3& positionOffset) noexcept; + void SetPositionOffset (const SHVec3& positionOffset) noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -96,13 +96,7 @@ namespace SHADE SHShape* shape; SHVec3 positionOffset; - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void CreateShape (); - void CreateBoundingBox (); - void CreateSphere (); + RTTR_ENABLE() }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 844803b1..36f7c57e 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -15,7 +15,8 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" -#include "SHPhysicsSystem.h" +#include "ECS_Base/Managers/SHComponentManager.h" + namespace SHADE { @@ -23,16 +24,20 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHPhysicsObject::SHPhysicsObject() noexcept - : entityID { MAX_EID } + SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept + : entityID { eid } , isRigidBody { false } , hasColliders{ false } + , factory { physicsFactory } + , world { physicsWorld } , rp3dBody { nullptr } {} SHPhysicsObject::~SHPhysicsObject() noexcept { - rp3dBody = nullptr; + factory = nullptr; + world = nullptr; + rp3dBody = nullptr; } /*-----------------------------------------------------------------------------------*/ @@ -44,10 +49,7 @@ namespace SHADE SHVec3 result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getPosition(); - result = SHVec3{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z }; - } + result = SHVec3{ rp3dBody->getTransform().getPosition() }; return result; } @@ -57,10 +59,7 @@ namespace SHADE SHQuaternion result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation(); - result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }; - } + result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }; return result; } @@ -70,10 +69,7 @@ namespace SHADE SHVec3 result; if (rp3dBody) - { - const auto& RP3D_RESULT = rp3dBody->getTransform().getOrientation(); - result = SHQuaternion{ RP3D_RESULT.x, RP3D_RESULT.y, RP3D_RESULT.z, RP3D_RESULT.w }.ToEuler(); - } + result = SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler(); return result; } @@ -84,10 +80,14 @@ namespace SHADE void SHPhysicsObject::SetPosition(const SHVec3& position) noexcept { - const rp3d::Vector3 RP3D_POS { position.x, position.y, position.z }; + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set position of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; - rp3dTF.setPosition(RP3D_POS); + rp3dTF.setPosition(position); rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation()); rp3dBody->setTransform(rp3dTF); @@ -96,11 +96,15 @@ namespace SHADE void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) noexcept { - const rp3d::Quaternion RP3D_ORIENTATION { orientation.x, orientation.y, orientation.z, orientation.w }; + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set orientation of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(RP3D_ORIENTATION); + rp3dTF.setOrientation(orientation); rp3dBody->setTransform(rp3dTF); prevTransform = rp3dTF; @@ -108,14 +112,253 @@ namespace SHADE void SHPhysicsObject::SetRotation(const SHVec3& rotation) noexcept { - const rp3d::Quaternion RP3D_ORIENTATION = rp3d::Quaternion::fromEulerAngles( rotation.x, rotation.y, rotation.z ); + if (!rp3dBody) + { + SHLOG_ERROR("Cannot set rotation of a non-existent physics body for Entity {}", entityID) + return; + } rp3d::Transform rp3dTF; rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); - rp3dTF.setOrientation(RP3D_ORIENTATION); + rp3dTF.setOrientation(rotation); rp3dBody->setTransform(rp3dTF); prevTransform = rp3dTF; } + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c) + { + // If collider already exists, recreate the collision body as a rigid body + if (hasColliders) + world->destroyCollisionBody(rp3dBody); + + rp3dBody = world->createRigidBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); + isRigidBody = true; + + rb->position = tf->GetWorldPosition(); + rb->orientation = tf->GetWorldRotation(); + + if (hasColliders) + { + c->position = tf->GetWorldPosition(); + c->orientation = tf->GetWorldRotation(); + // Get array of colliders and add them back into the rigidbody + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + } + + void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c) + { + if (rp3dBody == nullptr) + rp3dBody = world->createCollisionBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); + + hasColliders = true; + + c->position = tf->GetWorldPosition(); + c->orientation = tf->GetWorldRotation(); + + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + + int SHPhysicsObject::AddCollider(SHCollider* collider) + { + switch (collider->GetType()) + { + case SHCollider::Type::BOX: + { + const auto* box = reinterpret_cast(collider->GetShape()); + rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents()); + + rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); + break; + } + case SHCollider::Type::SPHERE: + { + const auto* sphere = reinterpret_cast(collider->GetShape()); + rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius()); + + rp3dBody->addCollider(newSphere, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity }); + break; + } + // TODO(Diren): Add more collider shapes + default: break; + } + + return static_cast(rp3dBody->getNbColliders()) - 1; + } + + void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept + { + world->destroyRigidBody(reinterpret_cast(rp3dBody)); + + if (hasColliders) + { + // Preserve colliders as a collision body + rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation }); + for (auto& collider : c->colliders | std::views::keys) + AddCollider(&collider); + } + + isRigidBody = false; + } + + void SHPhysicsObject::DestroyCollisionBody() noexcept + { + // Remove all colliders + for (uint32_t i = 0; i < rp3dBody->getNbColliders(); ++i) + { + auto* collider = rp3dBody->getCollider(i); + rp3dBody->removeCollider(collider); + } + } + + void SHPhysicsObject::RemoveCollider(int index) + { + const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); + if (NUM_COLLIDERS == 0) + return; + + if (index < 0 || index >= NUM_COLLIDERS) + throw std::invalid_argument("Index out of range!"); + + auto* collider = rp3dBody->getCollider(index); + rp3dBody->removeCollider(collider); + } + + void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept + { + SHASSERT(rp3dBody != nullptr, "ReactPhysics body does not exist!") + + if (rb->dirtyFlags == 0) + return; + + auto* rigidBody = reinterpret_cast(rp3dBody); + + const uint16_t RB_FLAGS = rb->dirtyFlags; + for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i) + { + // Check if current dirty flag has been set to true + if (RB_FLAGS & 1U << i) + { + switch (i) + { + case 0: // Gravity + { + rigidBody->enableGravity(rb->IsGravityEnabled()); + break; + } + case 1: // Sleeping + { + rigidBody->setIsAllowedToSleep(rb->IsAllowedToSleep()); + break; + } + case 2: // Linear Constraints + { + const rp3d::Vector3 CONSTRAINTS + { + rb->flags & 1U << 2 ? 0.0f : 1.0f, + rb->flags & 1U << 3 ? 0.0f : 1.0f, + rb->flags & 1U << 4 ? 0.0f : 1.0f + }; + + + rigidBody->setLinearLockAxisFactor(CONSTRAINTS); + break; + } + case 3: // Angular Constraints + { + const rp3d::Vector3 CONSTRAINTS + { + rb->flags & 1U << 5 ? 0.0f : 1.0f, + rb->flags & 1U << 6 ? 0.0f : 1.0f, + rb->flags & 1U << 7 ? 0.0f : 1.0f + }; + + rigidBody->setAngularLockAxisFactor(CONSTRAINTS); + break; + } + case 4: // Type + { + rigidBody->setType(static_cast(rb->GetType())); + break; + } + case 5: // Mass + { + rigidBody->setMass(rb->GetMass()); + break; + } + case 6: // Drag + { + rigidBody->setLinearDamping(rb->GetDrag()); + break; + } + case 7: // Angular Drag + { + rigidBody->setAngularDamping(rb->GetAngularDrag()); + break; + } + case 8: // Linear Velocity + { + rigidBody->setLinearVelocity(rb->GetLinearVelocity()); + break; + } + case 9: // Angular Velocity + { + rigidBody->setAngularVelocity(rb->GetAngularVelocity()); + break; + } + default: break; + } + } + } + + rb->dirtyFlags = 0; + } + + void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept + { + int index = 0; + for (auto& [collider, dirty] : c->colliders) + { + if (!dirty) + continue; + + // Update offsets + auto* rp3dCollider = rp3dBody->getCollider(index); + rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity)); + + switch (collider.GetType()) + { + case SHCollider::Type::BOX: + { + const auto* box = reinterpret_cast(collider.GetShape()); + + auto* rp3dBoxShape = reinterpret_cast(rp3dCollider->getCollisionShape()); + rp3dBoxShape->setHalfExtents(box->GetHalfExtents()); + + break; + } + case SHCollider::Type::SPHERE: + { + const auto* sphere = reinterpret_cast(collider.GetShape()); + + auto* rp3dSphereShape = reinterpret_cast(rp3dCollider->getCollisionShape()); + rp3dSphereShape->setRadius(sphere->GetRadius()); + + break; + } + default: break; + } + + dirty = false; + ++index; + } + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h index cdff2f5b..39a85421 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -13,9 +13,9 @@ #include // Project Headers -#include "Math/Vector/SHVec3.h" -#include "Math/SHQuaternion.h" -#include "ECS_Base/Entity/SHEntity.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Components/SHRigidBodyComponent.h" +#include "Components/SHColliderComponent.h" namespace SHADE { @@ -31,15 +31,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; - friend class SHRigidBodyComponent; - friend class SHColliderComponent; public: /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject () noexcept; + SHPhysicsObject (EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept; SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default; SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default; virtual ~SHPhysicsObject () noexcept; @@ -63,9 +61,24 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetPosition (const SHVec3& position) noexcept; - void SetOrientation (const SHQuaternion& orientation) noexcept; - void SetRotation (const SHVec3& rotation) noexcept; + void SetPosition (const SHVec3& position) noexcept; + void SetOrientation (const SHQuaternion& orientation) noexcept; + void SetRotation (const SHVec3& rotation) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c); + void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c); + int AddCollider (SHCollider* collider); + + void DestroyRigidBody (SHColliderComponent* c) noexcept; + void RemoveCollider (int index); + void DestroyCollisionBody () noexcept; + + void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept; + void SyncColliders (SHColliderComponent* c) const noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -76,14 +89,9 @@ namespace SHADE bool isRigidBody; bool hasColliders; + rp3d::PhysicsCommon* factory; + rp3d::PhysicsWorld* world; rp3d::CollisionBody* rp3dBody; // Can be either a collision body or a rigid body rp3d::Transform prevTransform; // Cached transform for interpolation - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - - }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index f3a4c276..7dc6c44e 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -68,10 +68,7 @@ namespace SHADE if (world) { - const auto RP3D_GRAVITY = world->getGravity(); - result.x = RP3D_GRAVITY.x; - result.y = RP3D_GRAVITY.y; - result.z = RP3D_GRAVITY.z; + result = world->getGravity(); } else { @@ -112,8 +109,7 @@ namespace SHADE { if (world) { - const rp3d::Vector3 G { gravity.x, gravity.y, gravity.z }; - world->setGravity(G); + world->setGravity(gravity); } else { @@ -161,8 +157,7 @@ namespace SHADE { if (world) { - const rp3d::Vector3 G { settings.gravity.x, settings.gravity.y, settings.gravity.z }; - world->setGravity(G); + world->setGravity(settings.gravity); world->setNbIterationsVelocitySolver(settings.numVelocitySolverIterations); world->setNbIterationsPositionSolver(settings.numPositionSolverIterations); world->enableSleeping(settings.sleepingEnabled); @@ -203,138 +198,33 @@ namespace SHADE void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept { - #ifdef _DEBUG - SHLOG_INFO("Adding a Rigidbody to the Physics World.") - #endif + //#ifdef _DEBUG + // SHLOG_INFO("Adding a Rigidbody to the Physics World.") + //#endif - // Check if entity is already a physics object - auto* physicsObject = GetPhysicsObject(entityID); - if (!physicsObject) - { - physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second); - physicsObject->entityID = entityID; - } + auto* physicsObject = CreatePhysicsObject(entityID); - // Get entity transform - auto const* SHADE_TF = SHComponentManager::GetComponent_s(entityID); - - // Possibly redundant - if (!SHADE_TF) - { - SHComponentManager::AddComponent(entityID); - SHADE_TF = SHComponentManager::GetComponent(entityID); - } - - const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition(); - const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation(); - - const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z }; - const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z ); - - const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT }; - - // If collider already exists - if (physicsObject->hasColliders) - world->destroyCollisionBody(physicsObject->rp3dBody); - - physicsObject->rp3dBody = world->createRigidBody(RP3D_TF); - physicsObject->isRigidBody = true; - - // Recreate colliders - if (physicsObject->hasColliders) - { - const auto& COLLIDERS = SHComponentManager::GetComponent(entityID)->GetColliders(); - for (const auto& collider : COLLIDERS | std::views::keys) - { - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - physicsObject->rp3dBody->addCollider(newBox, RP3D_TF); - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } - } - } - + physicsObject->CreateRigidBody + ( + EnsureTransform(entityID), + SHComponentManager::GetComponent(entityID), + SHComponentManager::GetComponent_s(entityID) + ); } void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept { - #ifdef _DEBUG - SHLOG_INFO("Adding a Collider to the Physics World.") - #endif + //#ifdef _DEBUG + // SHLOG_INFO("Adding a Collider to the Physics World.") + //#endif - // Check if entity is already a physics object - auto* physicsObject = GetPhysicsObject(entityID); - if (!physicsObject) - { - physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second); - physicsObject->entityID = entityID; - } + auto* physicsObject = CreatePhysicsObject(entityID); - // Get entity transform - auto const* SHADE_TF = SHComponentManager::GetComponent_s(entityID); - - // Possibly redundant - if (!SHADE_TF) - { - SHComponentManager::AddComponent(entityID); - SHADE_TF = SHComponentManager::GetComponent(entityID); - } - - const SHVec3& SHADE_POS = SHADE_TF->GetWorldPosition(); - const SHVec3& SHADE_ROT = SHADE_TF->GetWorldRotation(); - - const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z }; - const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles( SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z ); - - const rp3d::Transform RP3D_TF { RP3D_POS, RP3D_ROT }; - - // No rb - if (!physicsObject->isRigidBody) - physicsObject->rp3dBody = world->createCollisionBody(RP3D_TF); - - const auto& COLLIDERS = SHComponentManager::GetComponent(entityID)->GetColliders(); - for (const auto& collider : COLLIDERS | std::views::keys) - { - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - physicsObject->rp3dBody->addCollider(newBox, RP3D_TF); - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } - } - - physicsObject->hasColliders = true; + physicsObject->CreateCollisionBody + ( + EnsureTransform(entityID), + SHComponentManager::GetComponent(entityID) + ); } void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept @@ -343,6 +233,13 @@ namespace SHADE SHLOG_INFO("Removing a Rigidbody from the Physics World.") #endif + auto* physicsObject = GetPhysicsObject(entityID); + SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") + + physicsObject->DestroyRigidBody(SHComponentManager::GetComponent_s(entityID)); + + if (physicsObject->rp3dBody == nullptr) + DestroyPhysicsObject(entityID); } void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept @@ -392,33 +289,10 @@ namespace SHADE } - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHShape* shape) + void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) { auto* physicsObject = GetPhysicsObject(entityID); - - switch (shape->GetType()) - { - case SHShape::Type::BOUNDING_BOX: - { - auto* box = reinterpret_cast(shape); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - rp3d::BoxShape* newBox = factory.createBoxShape(RP3D_EXTENTS); - - // TODO(Diren): Handle offsets - - rp3d::Transform tf = rp3d::Transform::identity(); - physicsObject->rp3dBody->addCollider(newBox, tf); - break; - } - case SHShape::Type::SPHERE: - { - break; - } - // TODO(Diren): Add more collider shapes - default: break; - } + physicsObject->AddCollider(collider); } void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index) @@ -475,6 +349,7 @@ namespace SHADE if (system->worldUpdated) { system->SyncTransforms(); + // TODO(Diren): Handle trigger messages for scripting } } @@ -483,18 +358,43 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept + { + const auto it = map.find(entityID); + if (it == map.end()) + { + auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second; + return newPhysicsObject; + } + + return &(it->second); + } + SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept { const auto it = map.find(entityID); if (it == map.end()) { - SHLOG_ERROR("Entity {} is not in the physics system!", entityID) + //SHLOG_ERROR("Entity {} is not in the physics system!", entityID) return nullptr; } return &(it->second); } + void SHPhysicsSystem::DestroyPhysicsObject(EntityID entityID) noexcept + { + map.erase(entityID); + } + + void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept + { + const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); + if (RP3D_ACTIVE != componentActive) + physicsObject->rp3dBody->setIsActive(componentActive); + } + + void SHPhysicsSystem::SyncRigidBodyComponents(std::vector& denseArray) noexcept { if (denseArray.empty()) @@ -505,23 +405,16 @@ namespace SHADE const EntityID ENTITY_ID = comp.GetEID(); // Get physicsObject - auto const* physicsObject = GetPhysicsObject(ENTITY_ID); + auto* physicsObject = GetPhysicsObject(ENTITY_ID); - const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); // TODO(Diren): Check if active in hierarchy const bool COMPONENT_ACTIVE = comp.isActive; - - if (RP3D_ACTIVE != COMPONENT_ACTIVE) - physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE); + SyncActiveStates(physicsObject, COMPONENT_ACTIVE); if (!COMPONENT_ACTIVE) continue; - if (comp.dirtyFlags > 0) - { - SyncRigidBody(physicsObject, &comp); - comp.dirtyFlags = 0; - } + physicsObject->SyncRigidBody(&comp); } } @@ -535,29 +428,23 @@ namespace SHADE const EntityID ENTITY_ID = comp.GetEID(); // Get physicsObject - auto const* physicsObject = GetPhysicsObject(ENTITY_ID); + auto* physicsObject = GetPhysicsObject(ENTITY_ID); - const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); // TODO(Diren): Check if active in hierarchy const bool COMPONENT_ACTIVE = comp.isActive; - - if (RP3D_ACTIVE != COMPONENT_ACTIVE) - physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE); + SyncActiveStates(physicsObject, COMPONENT_ACTIVE); if (!COMPONENT_ACTIVE) continue; - SyncCollider(physicsObject, &comp); + physicsObject->SyncColliders(&comp); } } void SHPhysicsSystem::SyncTransforms() noexcept { - for (auto& pair : map) + for (auto& [entityID, physicsObject] : map) { - const EntityID ENTITY_ID = pair.first; - SHPhysicsObject& physicsObject = pair.second; - rp3d::Vector3 rp3dPos; rp3d::Quaternion rp3dRot; @@ -567,7 +454,7 @@ namespace SHADE if (physicsObject.isRigidBody) { - auto const* rbComponent = SHComponentManager::GetComponent(ENTITY_ID); + auto* rbComponent = SHComponentManager::GetComponent(entityID); if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC) continue; @@ -585,6 +472,16 @@ namespace SHADE rp3dPos = CURRENT_TF.getPosition(); rp3dRot = CURRENT_TF.getOrientation(); } + + rbComponent->position = CURRENT_TF.getPosition(); + rbComponent->orientation = CURRENT_TF.getOrientation(); + + if (physicsObject.hasColliders) + { + auto* colliderComponent = SHComponentManager::GetComponent(entityID); + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); + } } else { @@ -593,155 +490,29 @@ namespace SHADE } // Convert RP3D Transform to SHADE - const SHVec3 SHADE_POS = SHVec3{ rp3dPos.x, rp3dPos.y, rp3dPos.z }; - const SHVec3 SHADE_ROT = SHQuaternion{ rp3dRot.x, rp3dRot.y, rp3dRot.z, rp3dRot.w }.ToEuler(); + auto* tfComponent = SHComponentManager::GetComponent(entityID); + tfComponent->SetWorldPosition(rp3dPos); + tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler()); - auto* tfComponent = SHComponentManager::GetComponent(ENTITY_ID); - tfComponent->SetWorldPosition(SHADE_POS); - tfComponent->SetWorldRotation(SHADE_ROT); // Cache transforms physicsObject.prevTransform = CURRENT_TF; } } - void SHPhysicsSystem::SyncRigidBody(SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept + SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID) { - auto* rigidBody = reinterpret_cast(physicsObject->rp3dBody); + auto* tf = SHComponentManager::GetComponent_s(entityID); - const uint16_t RB_FLAGS = comp->dirtyFlags; - const size_t NUM_FLAGS = sizeof(RB_FLAGS) * 8U; - for (size_t i = 0; i < NUM_FLAGS; ++i) + // Possibly redundant + if (!tf) { - // Check if current dirty flag has been set to true - if (RB_FLAGS & 1U << i) - { - switch (i) - { - case 0: // Gravity - { - rigidBody->enableGravity(comp->IsGravityEnabled()); - break; - } - case 1: // Sleeping - { - rigidBody->setIsAllowedToSleep(comp->IsAllowedToSleep()); - break; - } - case 2: // Linear Constraints - { - SetRP3DLinearConstraints(rigidBody, comp->flags); - break; - } - case 3: // Angular Constraints - { - SetRP3DAngularConstraints(rigidBody, comp->flags); - break; - } - case 4: // Type - { - rigidBody->setType(static_cast(comp->GetType())); - break; - } - case 5: // Mass - { - rigidBody->setMass(comp->GetMass()); - break; - } - case 6: // Drag - { - rigidBody->setLinearDamping(comp->GetDrag()); - break; - } - case 7: // Angular Drag - { - rigidBody->setAngularDamping(comp->GetAngularDrag()); - break; - } - case 8: // Linear Velocity - { - const SHVec3& SHADE_VEL = comp->GetLinearVelocity(); - rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z }; - - rigidBody->setLinearVelocity(RP3D_VEL); - break; - } - case 9: // Angular Velocity - { - const SHVec3& SHADE_VEL = comp->GetAngularVelocity(); - rp3d::Vector3 RP3D_VEL { SHADE_VEL.x, SHADE_VEL.y, SHADE_VEL.z }; - - rigidBody->setAngularVelocity(RP3D_VEL); - break; - } - default: break; - } - } + SHComponentManager::AddComponent(entityID); + tf = SHComponentManager::GetComponent(entityID); } + + return tf; } - void SHPhysicsSystem::SetRP3DLinearConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept - { - const rp3d::Vector3 CONSTRAINTS - { - rbFlags & 1U << 2 ? 0.0f : 1.0f, - rbFlags & 1U << 3 ? 0.0f : 1.0f, - rbFlags & 1U << 4 ? 0.0f : 1.0f - }; - - - rp3dRigidBody->setLinearLockAxisFactor(CONSTRAINTS); - } - - void SHPhysicsSystem::SetRP3DAngularConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept - { - const rp3d::Vector3 CONSTRAINTS - { - rbFlags & 1U << 5 ? 0.0f : 1.0f, - rbFlags & 1U << 6 ? 0.0f : 1.0f, - rbFlags & 1U << 7 ? 0.0f : 1.0f - }; - - rp3dRigidBody->setAngularLockAxisFactor(CONSTRAINTS); - } - - void SHPhysicsSystem::SyncCollider(SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept - { - int index = 0; - for (auto& [collider, dirty] : comp->colliders) - { - if (!dirty) - continue; - - switch (collider.GetType()) - { - case SHCollider::Type::BOX: - { - SHBoundingBox* box = reinterpret_cast(collider.GetShape()); - const SHVec3& SHADE_EXTENTS = box->GetHalfExtents(); - - rp3d::Vector3 RP3D_EXTENTS { SHADE_EXTENTS.x, SHADE_EXTENTS.y, SHADE_EXTENTS.z }; - - auto* rp3dBoxShape = reinterpret_cast(physicsObject->rp3dBody->getCollider(index)->getCollisionShape()); - rp3dBoxShape->setHalfExtents(RP3D_EXTENTS); - - if (rp3dBoxShape) - { - SHLOG_INFO("Updating box things") - } - - break; - } - case SHCollider::Type::SPHERE: - { - break; - } - default: break; - } - - dirty = false; - ++index; - } - } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index 4eaf4a89..bc6a1ba2 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -19,6 +19,7 @@ #include "SHPhysicsObject.h" #include "Components/SHRigidBodyComponent.h" #include "Components/SHColliderComponent.h" +#include "Math/Transform/SHTransformComponent.h" #include "Scene/SHSceneGraph.h" #include "ECS_Base/System/SHSystemRoutine.h" @@ -81,8 +82,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void Init () override; - void Exit () override; + void Init () override; + void Exit () override; void AddRigidBody (EntityID entityID) noexcept; void AddCollider (EntityID entityID) noexcept; @@ -100,7 +101,7 @@ namespace SHADE void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept; void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept; - void AddCollisionShape (EntityID entityID, SHShape* shape); + void AddCollisionShape (EntityID entityID, SHCollider* collider); void RemoveCollisionShape (EntityID entityID, int index); /*---------------------------------------------------------------------------------*/ @@ -185,18 +186,18 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; + SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept; + SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; + void DestroyPhysicsObject (EntityID entityID) noexcept; - void SyncRigidBodyComponents (std::vector& denseArray) noexcept; - void SyncColliderComponents (std::vector& denseArray) noexcept; - void SyncTransforms () noexcept; + void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept; + void SyncRigidBodyComponents (std::vector& denseArray) noexcept; + void SyncColliderComponents (std::vector& denseArray) noexcept; + void SyncTransforms () noexcept; // TODO(Diren): Trigger handling - static void SyncRigidBody (SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept; - static void SetRP3DLinearConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept; - static void SetRP3DAngularConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept; - - static void SyncCollider (SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept; + // TODO(Diren): Remove when responsibility shifted to editor + SHTransformComponent* EnsureTransform (EntityID entityID); }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 3fe85809..bbbdb7e4 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -571,9 +571,9 @@ namespace SHADE { SHSceneNode* newNode = new SHSceneNode{entityID}; - #ifdef _DEBUG - SHLOG_INFO("Allocated a new Scene Node for Entity {}!", entityID) - #endif + //#ifdef _DEBUG + // SHLOG_INFO("Allocated a new Scene Node for Entity {}!", entityID) + //#endif entityNodeMap.emplace(entityID, newNode); return newNode; diff --git a/SHADE_Managed/premake5.lua b/SHADE_Managed/premake5.lua index 052be24a..6d37122c 100644 --- a/SHADE_Managed/premake5.lua +++ b/SHADE_Managed/premake5.lua @@ -30,8 +30,9 @@ project "SHADE_Managed" "%{IncludeDir.imguizmo}", "%{IncludeDir.imnodes}", "%{IncludeDir.yamlcpp}", - "%{IncludeDir.RTTR}/include", + "%{IncludeDir.RTTR}/include", "%{IncludeDir.dotnet}\\include", + "%{IncludeDir.reactphysics3d}\\include", "%{wks.location}/SHADE_Engine/src" } diff --git a/TempShaderFolder/TestCubeFs.glsl b/TempShaderFolder/TestCubeFs.glsl index 3a25ad71..18890c92 100644 --- a/TempShaderFolder/TestCubeFs.glsl +++ b/TempShaderFolder/TestCubeFs.glsl @@ -22,6 +22,7 @@ layout(location = 0) in struct layout(location = 2) flat in struct { int materialIndex; + uint eid; } In2; //layout (set = 0, binding = ) @@ -33,12 +34,13 @@ layout (set = 3, binding = 0) buffer MaterialProperties // For materials } MatProp; layout(location = 0) out vec4 outColor; +layout(location = 1) out uint outEntityID; void main() { - outColor = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha; + outEntityID = In2.eid; //outColor = vec4 (1.0f); } \ No newline at end of file diff --git a/TempShaderFolder/TestCubeFs.spv b/TempShaderFolder/TestCubeFs.spv index 07f67a45..bde62136 100644 Binary files a/TempShaderFolder/TestCubeFs.spv and b/TempShaderFolder/TestCubeFs.spv differ diff --git a/TempShaderFolder/TestCubeVs.glsl b/TempShaderFolder/TestCubeVs.glsl index eb5b2dff..b7453f13 100644 --- a/TempShaderFolder/TestCubeVs.glsl +++ b/TempShaderFolder/TestCubeVs.glsl @@ -8,6 +8,7 @@ layout(location = 1) in vec2 aUV; layout(location = 2) in vec3 aNormal; layout(location = 3) in vec3 aTangent; layout(location = 4) in mat4 worldTransform; +layout(location = 8) in uint eid; layout(location = 0) out struct @@ -21,6 +22,8 @@ layout(location = 0) out struct layout(location = 2) out struct { int materialIndex; + uint eid; + } Out2; layout(set = 2, binding = 0) uniform CameraData @@ -33,6 +36,7 @@ void main() { Out.uv = aUV; Out2.materialIndex = gl_InstanceIndex; + Out2.eid = eid; gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); Out.vertColor = vec4 (aVertexPos, 1.0f); } \ No newline at end of file diff --git a/TempShaderFolder/TestCubeVs.spv b/TempShaderFolder/TestCubeVs.spv index dfc9eda1..1662cfbd 100644 Binary files a/TempShaderFolder/TestCubeVs.spv and b/TempShaderFolder/TestCubeVs.spv differ