diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 3f56e140..4cdac9dc 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -84,7 +84,7 @@ namespace Sandbox auto& collider = *SHComponentManager::GetComponent_s(entity); //renderable.Mesh = handles.front(); - renderable.Mesh = CUBE_MESH; + renderable.SetMesh(CUBE_MESH); renderable.SetMaterial(customMat); if (y == 50) @@ -96,11 +96,7 @@ namespace Sandbox transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f)); transform.SetWorldScale(TEST_OBJ_SCALE); - //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); - + collider.AddBoundingBox(SHVec3::One, SHVec3::Zero); stressTestObjects.emplace_back(entity); } @@ -108,7 +104,7 @@ namespace Sandbox auto& renderable = *SHComponentManager::GetComponent_s(raccoonSpin); auto& transform = *SHComponentManager::GetComponent_s(raccoonSpin); - renderable.Mesh = handles.front(); + renderable.SetMesh(handles.front()); renderable.SetMaterial(customMat); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); @@ -123,9 +119,8 @@ namespace Sandbox auto& floorRigidBody = *SHComponentManager::GetComponent_s(floor); auto& floorCollider = *SHComponentManager::GetComponent_s(floor); - floorRenderable.Mesh = CUBE_MESH; - floorRenderable.SetMaterial(customMat); - floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); + floorRenderable.SetMesh(CUBE_MESH); + floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance()); floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 }); floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f }); @@ -149,7 +144,7 @@ namespace Sandbox auto& renderableShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); auto& transformShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); - renderableShowcase.Mesh = handles.front(); + renderableShowcase.SetMesh(handles.front()); renderableShowcase.SetMaterial(customMat); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 7fa39d74..4645bf52 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -207,6 +207,10 @@ namespace SHADE { if (!component) return; + + // Get transform component for extrapolating relative sizes + auto* transformComponent = SHComponentManager::GetComponent(component->GetEID()); + const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); ImGui::SameLine(); @@ -221,28 +225,41 @@ namespace SHADE for (int i{}; i < size; ++i) { ImGui::PushID(i); - SHCollider& collider = component->GetCollider(i); + SHCollider* collider = &component->GetCollider(i); auto cursorPos = ImGui::GetCursorPos(); - if (collider.GetType() == SHCollider::Type::BOX) + if (collider->GetType() == SHCollider::Type::BOX) { SHEditorWidgets::BeginPanel( std::format("{} Box Collider #{}", ICON_FA_CUBE, 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);}); + auto box = reinterpret_cast(collider->GetShape()); + SHEditorWidgets::DragVec3 + ( + "Half Extents", { "X", "Y", "Z" }, + [box, transformComponent] { return (transformComponent->GetWorldScale() * 2.0f) * box->GetHalfExtents(); }, + [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); } - else if (collider.GetType() == SHCollider::Type::SPHERE) + 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);}); + auto sphere = reinterpret_cast(collider->GetShape()); + SHEditorWidgets::DragFloat + ( + "Radius", + [sphere, transformComponent] + { + const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale(); + const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); + return sphere->GetRadius() / MAX_SCALE; + }, + [collider](float const& value) { collider->SetBoundingSphere(value);}); } - else if (collider.GetType() == SHCollider::Type::CAPSULE) + 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::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())) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 09fde60f..d07e0f06 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -45,16 +45,20 @@ namespace SHADE void SHBatch::Add(const SHRenderable* renderable) { + // Ignore if null + if (!renderable->GetMesh()) + return; + // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) - { - return batch.Mesh == renderable->Mesh; - }); + { + return batch.Mesh == renderable->GetMesh(); + }); // Create one if not found if (subBatch == subBatches.end()) { - subBatches.emplace_back(renderable->Mesh); + subBatches.emplace_back(renderable->GetMesh()); subBatch = subBatches.end() - 1; } @@ -73,7 +77,7 @@ namespace SHADE // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) { - return batch.Mesh == renderable->Mesh; + return batch.Mesh == renderable->GetMesh(); }); // Attempt to remove if it exists @@ -84,13 +88,18 @@ namespace SHADE // Check if other renderables in subBatches contain the same material instance bool matUnused = true; + + Handle matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial(); + for (const auto& sb : subBatches) + { + // Check material usage for (const auto& rendId : sb.Renderables) { auto rend = SHComponentManager::GetComponent(rendId); if (rend) { - if (rend->GetMaterial() == renderable->GetMaterial()) + if (rend->GetMaterial() == matToCheck) { matUnused = false; break; @@ -101,10 +110,15 @@ namespace SHADE SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } } + } // Material is no longer in this library, so we remove it if (matUnused) - referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); + referencedMatInstances.erase(renderable->HasChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); + + // Mesh is no longer in this batch, so we remove the associated sub batch + if (subBatch->Renderables.empty()) + subBatches.erase(subBatch); // Mark all as dirty setAllDirtyFlags(); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 6fbf5a76..3330a189 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -200,7 +200,6 @@ namespace SHADE auto cubeFS = shaderModuleLibrary.GetBuiltInShaderModule("TestCube_FS"); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass); - } void SHGraphicsSystem::InitMiddleEnd(void) noexcept @@ -680,7 +679,7 @@ namespace SHADE auto& renderables = SHComponentManager::GetDense(); for (auto& renderable : renderables) { - if (!renderable.WasMaterialChanged()) + if (!renderable.HasChanged()) continue; // Remove from old material's SuperBatch @@ -768,5 +767,10 @@ namespace SHADE } + Handle SHGraphicsSystem::GetPrimaryRenderpass() const noexcept + { + return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data()); + } + #pragma endregion MISC } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 426f0abe..f657965c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -135,7 +135,7 @@ namespace SHADE void RemoveViewport(Handle viewport); /*-----------------------------------------------------------------------------*/ - /* Material Creation Functions */ + /* Material Functions */ /*-----------------------------------------------------------------------------*/ Handle AddMaterial(Handle vertShader, Handle fragShader, Handle subpass); void RemoveMaterial(Handle material); @@ -143,6 +143,8 @@ namespace SHADE Handle AddOrGetBaseMaterialInstance(Handle material); Handle AddMaterialInstanceCopy(Handle materialInst); void RemoveMaterialInstance(Handle materialInstance); + Handle GetDefaultMaterial() { return defaultMaterial; } + Handle GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); } /*-----------------------------------------------------------------------------*/ /* Mesh Registration Functions */ @@ -286,12 +288,17 @@ namespace SHADE #endif Handle GetMousePickSystem(void) const noexcept {return mousePickSystem;}; Handle GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;}; + Handle GetPrimaryRenderpass() const noexcept; //SHRenderGraph const& GetRenderGraph(void) const noexcept; //Handle GetRenderPass() const { return renderPass; } private: + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ + static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer"; /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -318,7 +325,7 @@ namespace SHADE SHTextureLibrary texLibrary; SHSamplerCache samplerCache; SHMaterialInstanceCache materialInstanceCache; - // Viewports + // Viewports #ifdef SHEDITOR Handle editorViewport; Handle editorRenderer; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp index 36e30010..b27f48b9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp @@ -4,6 +4,8 @@ #include "Graphics/Pipeline/SHVkPipeline.h" #include "SHGraphicsConstants.h" #include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" namespace SHADE { @@ -23,7 +25,7 @@ namespace SHADE } // Allocate memory for properties - const Handle SHADER_INFO = getShaderBlockInterface(); + const Handle SHADER_INFO = GetShaderBlockInterface(); propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; if (propMemorySize <= 0) { @@ -49,6 +51,22 @@ namespace SHADE // Reset all the properties to default values if (propMemory) memset(propMemory.get(), 0, propMemorySize); + + // Initialize Vectors to all 1.0 by default + const Handle SHADER_INFO = GetShaderBlockInterface(); + for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i) + { + const auto& VAR = SHADER_INFO->GetVariable(i); + switch (VAR->type) + { + case SHShaderBlockInterface::Variable::Type::VECTOR3: + setPropertyUnsafe(VAR->offset, SHVec3::One); + break; + case SHShaderBlockInterface::Variable::Type::VECTOR4: + setPropertyUnsafe(VAR->offset, SHVec4::One); + break; + } + } } void SHMaterial::ExportProperties(void* dest) const noexcept @@ -59,14 +77,14 @@ namespace SHADE size_t SHMaterial::GetPropertiesMemorySize() const noexcept { - const Handle SHADER_INFO = getShaderBlockInterface(); + const Handle SHADER_INFO = GetShaderBlockInterface(); return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; } /*---------------------------------------------------------------------------------*/ /* Helper Functions */ /*---------------------------------------------------------------------------------*/ - Handle SHMaterial::getShaderBlockInterface() const noexcept + Handle SHMaterial::GetShaderBlockInterface() const noexcept { return pipeline->GetPipelineLayout()->GetShaderBlockInterface ( diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h index ec546fd5..964f9e34 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h @@ -50,13 +50,24 @@ namespace SHADE template void SetProperty(const std::string& key, const T& value); template + void SetProperty(uint32_t memOffset, const T& value); + template T& GetProperty(const std::string& key); template const T& GetProperty(const std::string& key) const; + template + T& GetProperty(uint32_t memOffset); + template + const T& GetProperty(uint32_t memOffset) const; void ResetProperties(); void ExportProperties(void* dest) const noexcept; Byte GetPropertiesMemorySize() const noexcept; + /*-----------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------*/ + Handle GetShaderBlockInterface() const noexcept; + private: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -68,7 +79,8 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------*/ - Handle getShaderBlockInterface() const noexcept; + template + inline void setPropertyUnsafe(uint32_t memOffset, const T& value); // SetProperty() but without checks }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp index dceee512..f81cfa5c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp @@ -25,7 +25,7 @@ namespace SHADE template void SHMaterial::SetProperty(const std::string& key, const T& value) { - const auto SHADER_INFO = getShaderBlockInterface(); + const auto SHADER_INFO = GetShaderBlockInterface(); const auto PROP_INFO = SHADER_INFO->GetVariable(key); if (PROP_INFO == nullptr) { @@ -36,14 +36,25 @@ namespace SHADE T* dataPtr = reinterpret_cast(propMemory.get() + PROP_INFO->offset); *dataPtr = value; } + + template + void SHMaterial::SetProperty(uint32_t memOffset, const T& value) + { + // Check if out of bounds + if (memOffset + sizeof(T) > propMemorySize) + throw std::invalid_argument("Attempted to set an invalid property!"); + // Set + setPropertyUnsafe(memOffset, value); + } + template T& SHMaterial::GetProperty(const std::string& key) { - const auto SHADER_INFO = getShaderBlockInterface(); + const auto SHADER_INFO = GetShaderBlockInterface(); const auto PROP_INFO = SHADER_INFO->GetVariable(key); if (PROP_INFO == nullptr) { - throw std::invalid_argument("Attempted to set an invalid property!"); + throw std::invalid_argument("Attempted to retrieve an invalid property!"); } // Get offset and return the memory directly @@ -55,5 +66,25 @@ namespace SHADE { return const_cast(const_cast(this)->GetProperty(key)); } + + template + const T& SHMaterial::GetProperty(uint32_t memOffset) const + { + // Check if out of bounds + if (memOffset + sizeof(T) > propMemorySize) + throw std::invalid_argument("Attempted to retrieve an invalid property!"); + return *(reinterpret_cast(propMemory.get() + memOffset)); + } + template + T& SHMaterial::GetProperty(uint32_t memOffset) + { + return const_cast(const_cast(this)->GetProperty(memOffset)); + } + + template + void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value) + { + (*reinterpret_cast(propMemory.get() + memOffset)) = value; + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 7c4d0bb9..22de83b8 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -23,7 +23,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ void SHRenderable::OnCreate() { - materialChanged = true; + matChanged = true; sharedMaterial = {}; material = {}; oldMaterial = {}; @@ -55,7 +55,7 @@ namespace SHADE return; // Flag that material was changed - materialChanged = true; + matChanged = true; // Free copies of materials if any if (material) @@ -92,15 +92,41 @@ namespace SHADE return material; } - + + /*-----------------------------------------------------------------------------------*/ + /* Mesh Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHRenderable::SetMesh(Handle newMesh) + { + oldMesh = mesh; + mesh = newMesh; + meshChanged = true; + } + + /*-----------------------------------------------------------------------------------*/ + /* Light Functions */ + /*-----------------------------------------------------------------------------------*/ uint8_t SHRenderable::GetLightLayer(void) const noexcept { return lightLayer; } - + + /*-----------------------------------------------------------------------------------*/ + /* Batcher Dispatcher Functions */ + /*-----------------------------------------------------------------------------------*/ void SHRenderable::ResetChangedFlag() { - materialChanged = false; - oldMaterial = {}; + matChanged = false; + meshChanged = false; + oldMaterial = {}; + oldMesh = {}; } } + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::class_("Renderable Component"); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 75e42d60..8893c43b 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -11,9 +11,10 @@ of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ #pragma once +// External Dependencies +#include // Project Includes #include "Resource/SHHandle.h" -//#include "SHTransform.h" #include "ECS_Base/Components/SHComponent.h" #include "Math/SHMatrix.h" #include "SH_API.h" @@ -50,33 +51,42 @@ namespace SHADE void SetMaterial(Handle materialInstance); Handle GetMaterial() const; Handle GetModifiableMaterial(); + Handle GetPrevMaterial() const noexcept { return oldMaterial; } + bool HasMaterialChanged() const noexcept { return matChanged; } /*-------------------------------------------------------------------------------*/ - /* Getter Functions */ + /* Mesh Functions */ + /*-------------------------------------------------------------------------------*/ + void SetMesh(Handle newMesh); + Handle GetMesh() const noexcept { return mesh; } + Handle GetPrevMesh() const noexcept { return oldMesh; } + bool HasMeshChanged() const noexcept { return meshChanged; } + + /*-------------------------------------------------------------------------------*/ + /* Light Functions */ /*-------------------------------------------------------------------------------*/ - bool WasMaterialChanged() const noexcept { return materialChanged; } - Handle GetPrevMaterial() const noexcept { return oldMaterial; } uint8_t GetLightLayer (void) const noexcept; /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-------------------------------------------------------------------------------*/ + bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this - /*-------------------------------------------------------------------------------*/ - /* Data Members */ - /*-------------------------------------------------------------------------------*/ - Handle Mesh; - private: /*-------------------------------------------------------------------------------*/ /* Data Members */ /*-------------------------------------------------------------------------------*/ + Handle mesh; + Handle oldMesh; + bool meshChanged = true; Handle sharedMaterial; Handle material; - bool materialChanged = true; + bool matChanged = true; Handle oldMaterial; uint8_t lightLayer; + + RTTR_ENABLE() }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index c315bffd..607c777a 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -244,7 +244,15 @@ namespace SHADE } // Add subpass to container and create mapping for it - subpasses.emplace_back(graphStorage->resourceManager->Create(graphStorage, GetHandle(), static_cast(subpasses.size()), &resourceAttachmentMapping)); + subpasses.emplace_back + ( + graphStorage->resourceManager->Create + ( + subpassName, + graphStorage, GetHandle(), static_cast(subpasses.size()), + &resourceAttachmentMapping + ) + ); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); subpass->Init(*graphStorage->resourceManager); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index af6f3089..d8f4f8c2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -30,7 +30,7 @@ namespace SHADE */ /***************************************************************************/ - SHSubpass::SHSubpass(Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept + SHSubpass::SHSubpass(const std::string& name, Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept : resourceAttachmentMapping{ mapping } , parentNode{ parent } , subpassIndex{ index } @@ -38,6 +38,7 @@ namespace SHADE , colorReferences{} , depthReferences{} , inputReferences{} + , name { name } , graphStorage{ renderGraphStorage } , inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS} { @@ -411,4 +412,8 @@ namespace SHADE return parentNode->GetResource(attachmentReference)->GetResourceFormat(); } + const std::string& SHSubpass::GetName() const + { + return name; + } } \ 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 166f0d76..c82ebdd0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -77,13 +77,15 @@ namespace SHADE //! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING //! COMPLEX. std::vector&)>> exteriorDrawCalls; + /// For identifying subpasses + std::string name; public: /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ - SHSubpass(Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept; + SHSubpass(const std::string& name, Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept; SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept; @@ -117,6 +119,7 @@ namespace SHADE Handle GetSuperBatch(void) const noexcept; std::vector const& GetColorAttachmentReferences (void) const noexcept; vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept; + const std::string& GetName() const; friend class SHRenderGraphNode; friend class SHRenderGraph; diff --git a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp index 75ede865..f214c094 100644 --- a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp @@ -14,6 +14,7 @@ namespace SHADE return; } variables.emplace_back(std::move(newVariable)); + variableNames.emplace_back(name); variableIndexing.try_emplace(std::move(name), static_cast(variables.size() - 1)); } @@ -41,6 +42,19 @@ namespace SHADE return variableIndexing.at(variableName); } + const std::string& SHShaderBlockInterface::GetVariableName(uint32_t index) const noexcept + { + if (index < variableNames.size()) + return variableNames.at(index); + + return {}; + } + + size_t SHShaderBlockInterface::GetVariableCount() const noexcept + { + return variables.size(); + } + SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept : bytesRequired{ 0 } {} diff --git a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h index e546b452..ae75e2c8 100644 --- a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h +++ b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h @@ -12,13 +12,24 @@ namespace SHADE public: struct Variable { + enum class Type + { + OTHER, + FLOAT, + INT, + VECTOR2, + VECTOR3, + VECTOR4 + }; //! Offset of the variable in the block uint32_t offset; + Type type; }; private: //! containers of variable information std::vector variables; + std::vector variableNames; std::unordered_map variableIndexing; //! bytes required by the block (includes padding). This variable is required @@ -29,6 +40,8 @@ namespace SHADE Variable const* const GetVariable (std::string const& variableName) const noexcept; Variable const* const GetVariable(uint32_t index) const noexcept; uint32_t GetVariableIndex(std::string const& variableName) const; + const std::string& GetVariableName(uint32_t index) const noexcept; + size_t GetVariableCount() const noexcept; /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp index e635f763..f28561c5 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp @@ -97,17 +97,45 @@ namespace SHADE switch (member.type_description->op) { case SpvOp::SpvOpTypeFloat: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable + ( + parentOffset + member.offset, + SHShaderBlockInterface::Variable::Type::FLOAT + ) + ); biggestAlignment = std::max (biggestAlignment, 4u); break; case SpvOp::SpvOpTypeVector: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + SHShaderBlockInterface::Variable::Type varType; + switch (dim) + { + case 2: varType = SHShaderBlockInterface::Variable::Type::VECTOR2; break; + case 3: varType = SHShaderBlockInterface::Variable::Type::VECTOR3; break; + case 4: varType = SHShaderBlockInterface::Variable::Type::VECTOR4; break; + default: varType = SHShaderBlockInterface::Variable::Type::OTHER; break; + } + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable(parentOffset + member.offset, varType) + ); if (dim == 3) dim = 4; biggestAlignment = std::max (biggestAlignment, dim * member.type_description->traits.numeric.scalar.width / 8); break; case SpvOp::SpvOpTypeInt: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable + ( + parentOffset + member.offset, + SHShaderBlockInterface::Variable::Type::INT + ) + ); biggestAlignment = std::max(biggestAlignment, 4u); break; case SpvOp::SpvOpTypeStruct: diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.cpp b/SHADE_Engine/src/Math/Geometry/SHShape.cpp index 3fc5775d..2f869029 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHShape.cpp @@ -27,10 +27,9 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHShape::Type SHShape::GetType() const + SHShape::Type SHShape::GetType() const noexcept { return type; } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.h b/SHADE_Engine/src/Math/Geometry/SHShape.h index 18f54fe6..62198897 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.h +++ b/SHADE_Engine/src/Math/Geometry/SHShape.h @@ -63,7 +63,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] Type GetType() const; + [[nodiscard]] Type GetType () const noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -77,6 +77,6 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - Type type; + Type type; }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index 75a00491..fb999847 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -58,7 +58,7 @@ namespace SHADE if (index < 0 || static_cast(index) >= colliders.size()) throw std::invalid_argument("Out-of-range access!"); - return colliders[index].first; + return colliders[index]; } /*-----------------------------------------------------------------------------------*/ @@ -85,13 +85,11 @@ namespace SHADE static constexpr auto TYPE = SHCollider::Type::BOX; - auto boxPair = std::make_pair(SHCollider{ TYPE }, true); - auto& collider = colliders.emplace_back(boxPair).first; - - const auto* tf = SHComponentManager::GetComponent(GetEID()); + auto& collider = colliders.emplace_back(SHCollider{ GetEID(), TYPE }); + collider.entityID = GetEID(); collider.SetPositionOffset(posOffset); - collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents); + collider.SetBoundingBox(halfExtents); // Notify Physics System system->AddCollisionShape(GetEID(), &collider); @@ -109,16 +107,11 @@ namespace SHADE static constexpr auto TYPE = SHCollider::Type::SPHERE; - auto spherePair = std::make_pair(SHCollider{ TYPE }, true); - auto& collider = colliders.emplace_back(spherePair).first; - - const auto* tf = SHComponentManager::GetComponent(GetEID()); + auto& collider = colliders.emplace_back(SHCollider{ GetEID(), TYPE }); + collider.entityID = 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 * radius); + collider.SetBoundingSphere(radius); // Notify Physics System system->AddCollisionShape(GetEID(), &collider); diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h index 4ecd0e93..af726b51 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h @@ -43,8 +43,7 @@ namespace SHADE /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using ColliderDirtyPair = std::pair; - using Colliders = std::vector; + using Colliders = std::vector; public: diff --git a/SHADE_Engine/src/Physics/SHCollider.cpp b/SHADE_Engine/src/Physics/SHCollider.cpp index f5899cfc..9488042d 100644 --- a/SHADE_Engine/src/Physics/SHCollider.cpp +++ b/SHADE_Engine/src/Physics/SHCollider.cpp @@ -15,6 +15,8 @@ // Project Headers #include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Math/SHMathHelpers.h" namespace SHADE { @@ -22,22 +24,24 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHCollider::SHCollider(Type colliderType) + SHCollider::SHCollider(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial) : type { colliderType } + , entityID { eid } , isTrigger { false } , dirty { true } , shape { nullptr } + , material { physicsMaterial } { switch (type) { case Type::BOX: { - SetAsBoundingBox(SHVec3::One); + shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; break; } case Type::SPHERE: { - SetAsBoundingSphere(1.0f); + shape = new SHBoundingSphere{ SHVec3::Zero, 0.5f }; break; } default: break; @@ -46,19 +50,27 @@ namespace SHADE SHCollider::SHCollider(const SHCollider& rhs) noexcept : type { rhs.type} + , entityID { rhs.entityID } , isTrigger { rhs.isTrigger } , dirty { true } - , shape { rhs.shape } + , shape { nullptr } + , material { rhs.material } , positionOffset { rhs.positionOffset } - {} + { + CopyShape(rhs.shape); + } SHCollider::SHCollider(SHCollider&& rhs) noexcept : type { rhs.type} + , entityID { rhs.entityID } , isTrigger { rhs.isTrigger } , dirty { true } - , shape { rhs.shape } + , shape { nullptr } + , material { rhs.material } , positionOffset { rhs.positionOffset } - {} + { + CopyShape(rhs.shape); + } SHCollider::~SHCollider() noexcept { @@ -75,22 +87,30 @@ namespace SHADE return *this; type = rhs.type; + entityID = rhs.entityID; isTrigger = rhs.isTrigger; dirty = true; - shape = rhs.shape; + material = rhs.material; positionOffset = rhs.positionOffset; + delete shape; + CopyShape(rhs.shape); + return *this; } SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept { type = rhs.type; + entityID = rhs.entityID; isTrigger = rhs.isTrigger; dirty = true; - shape = rhs.shape; + material = rhs.material; positionOffset = rhs.positionOffset; + delete shape; + CopyShape(rhs.shape); + return *this; } @@ -115,19 +135,22 @@ namespace SHADE float SHCollider::GetFriction() const noexcept { - // TODO(Diren): Fix after implementing materials - return 0.0f; + return material.GetFriction(); } float SHCollider::GetBounciness() const noexcept { - // TODO(Diren): Fix after implementing materials - return 0.0f; + return material.GetBounciness(); } + float SHCollider::GetDensity() const noexcept { - // TODO(Diren): Fix after implementing materials - return 0.0f; + return material.GetDensity(); + } + + const SHPhysicsMaterial& SHCollider::GetMaterial() const noexcept + { + return material; } const SHVec3& SHCollider::GetPositionOffset() const noexcept @@ -145,22 +168,60 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHCollider::SetAsBoundingBox(const SHVec3& halfExtents) + void SHCollider::SetBoundingBox(const SHVec3& halfExtents) { dirty = true; - type = Type::BOX; - delete shape; - shape = new SHBoundingBox{ positionOffset, halfExtents }; + // Set the half extents relative to transform + SHVec3 worldHalfExtents = halfExtents; + + const auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + if (transformComponent != nullptr) + worldHalfExtents *= (transformComponent->GetWorldScale() * 0.5f); + + if (type == Type::BOX) + { + auto* box = reinterpret_cast(shape); + box->SetHalfExtents(worldHalfExtents); + } + else + { + type = Type::BOX; + + delete shape; + shape = new SHBoundingBox{ positionOffset, worldHalfExtents }; + } } - void SHCollider::SetAsBoundingSphere(float radius) + void SHCollider::SetBoundingSphere(float radius) { dirty = true; - type = Type::SPHERE; - delete shape; - shape = new SHBoundingSphere{ positionOffset, radius }; + // Set the radius relative to transform + float worldRadius = radius; + + const auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + if (transformComponent != nullptr) + { + const SHVec3 TF_WORLD_SCALE = transformComponent->GetWorldScale(); + const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); + + worldRadius *= MAX_SCALE; + } + + if (type == Type::SPHERE) + { + auto* sphere = reinterpret_cast(shape); + sphere->SetRadius(worldRadius); + } + else + { + type = Type::SPHERE; + + delete shape; + shape = new SHBoundingSphere{ positionOffset, worldRadius }; + } + } void SHCollider::SetIsTrigger(bool trigger) noexcept @@ -172,23 +233,74 @@ namespace SHADE void SHCollider::SetFriction(float friction) noexcept { dirty = true; + material.SetFriction(friction); } void SHCollider::SetBounciness(float bounciness) noexcept { dirty = true; + material.SetBounciness(bounciness); } void SHCollider::SetDensity(float density) noexcept { dirty = true; + material.SetDensity(density); + } + + void SHCollider::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept + { + dirty = true; + material = newMaterial; } void SHCollider::SetPositionOffset(const SHVec3& posOffset) noexcept { dirty = true; positionOffset = posOffset; + + switch (type) + { + case Type::BOX: + { + reinterpret_cast(shape)->SetCenter(positionOffset); + break; + } + case Type::SPHERE: + { + reinterpret_cast(shape)->SetCenter(positionOffset); + break; + } + default: break; + } } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollider::CopyShape(const SHShape* rhs) + { + switch (type) + { + case Type::BOX: + { + const auto* RHS_BOX = reinterpret_cast(rhs); + + shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetHalfExtents() }; + break; + } + case Type::SPHERE: + { + const auto* RHS_SPHERE = reinterpret_cast(rhs); + + shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetRadius() }; + break; + } + default: break; + } + } + } // namespace SHADE RTTR_REGISTRATION @@ -205,5 +317,4 @@ RTTR_REGISTRATION 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 0e024f09..f760ffd0 100644 --- a/SHADE_Engine/src/Physics/SHCollider.h +++ b/SHADE_Engine/src/Physics/SHCollider.h @@ -13,8 +13,10 @@ #include // Project Headers +#include "ECS_Base/Entity/SHEntity.h" #include "Math/Geometry/SHShape.h" #include "Math/SHQuaternion.h" +#include "SHPhysicsMaterial.h" namespace SHADE { @@ -24,6 +26,15 @@ namespace SHADE class SH_API SHCollider { + private: + + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHColliderComponent; + friend class SHPhysicsObject; + public: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -40,7 +51,7 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHCollider (Type colliderType = Type::BOX); + SHCollider (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT); SHCollider (const SHCollider& rhs) noexcept; SHCollider (SHCollider&& rhs) noexcept; @@ -57,31 +68,33 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; + [[nodiscard]] bool HasChanged () const noexcept; - [[nodiscard]] bool IsTrigger () const noexcept; + [[nodiscard]] bool IsTrigger () const noexcept; - [[nodiscard]] Type GetType () const noexcept; + [[nodiscard]] Type GetType () const noexcept; - [[nodiscard]] float GetFriction () const noexcept; - [[nodiscard]] float GetBounciness () const noexcept; - [[nodiscard]] float GetDensity () const noexcept; + [[nodiscard]] float GetFriction () const noexcept; + [[nodiscard]] float GetBounciness () const noexcept; + [[nodiscard]] float GetDensity () const noexcept; + [[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept; - [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; + [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; - [[nodiscard]] SHShape* GetShape () noexcept; + [[nodiscard]] SHShape* GetShape () noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetAsBoundingBox (const SHVec3& halfExtents); - void SetAsBoundingSphere (float radius); + void SetBoundingBox (const SHVec3& halfExtents); + void SetBoundingSphere (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 SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; void SetPositionOffset (const SHVec3& positionOffset) noexcept; @@ -90,11 +103,19 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - Type type; - bool isTrigger; - bool dirty; - SHShape* shape; - SHVec3 positionOffset; + Type type; + EntityID entityID; // The entity this collider belongs to + bool isTrigger; + bool dirty; + SHShape* shape; + SHPhysicsMaterial material; + SHVec3 positionOffset; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void CopyShape(const SHShape* rhs); RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/SHPhysicsMaterial.cpp b/SHADE_Engine/src/Physics/SHPhysicsMaterial.cpp new file mode 100644 index 00000000..677e448f --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsMaterial.cpp @@ -0,0 +1,104 @@ +/**************************************************************************************** + * \file SHPhysicsMaterial.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Physics Material. + * + * \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 "SHPhysicsMaterial.h" +// Project Headers +#include "Math/SHMathHelpers.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + const SHPhysicsMaterial SHPhysicsMaterial::DEFAULT { 0.4f, 0.0f, 1.0f }; + + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsMaterial::SHPhysicsMaterial(float _friction, float _bounciness, float _density) noexcept + : friction { std::clamp(_friction, 0.0f, 1.0f) } + , bounciness{ std::clamp(_bounciness, 0.0f, 1.0f) } + , density { std::fabs(_density) } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHPhysicsMaterial::operator==(const SHPhysicsMaterial& rhs) const noexcept + { + return SHMath::CompareFloat(friction, rhs.friction) + && SHMath::CompareFloat(bounciness, rhs.bounciness) + && SHMath::CompareFloat(density, rhs.density); + } + + bool SHPhysicsMaterial::operator!=(const SHPhysicsMaterial& rhs) const noexcept + { + return !SHMath::CompareFloat(friction, rhs.friction) + || !SHMath::CompareFloat(bounciness, rhs.bounciness) + || !SHMath::CompareFloat(density, rhs.density); + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + float SHPhysicsMaterial::GetFriction() const noexcept + { + return friction; + } + + float SHPhysicsMaterial::GetBounciness() const noexcept + { + return bounciness; + } + + float SHPhysicsMaterial::GetDensity() const noexcept + { + return density; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsMaterial::SetFriction(float newFriction) noexcept + { + if (newFriction < 0.0f || newFriction > 1.0f) + { + SHLOG_WARNING("Clamping friction of Physics Material between [0,1].") + } + friction = std::clamp(newFriction, 0.0f, 1.0f); + } + + void SHPhysicsMaterial::SetBounciness(float newBounciness) noexcept + { + if (newBounciness < 0.0f || newBounciness > 1.0f) + { + SHLOG_WARNING("Clamping bounciness of Physics Material between [0,1].") + } + bounciness = std::clamp(newBounciness, 0.0f, 1.0f); + } + + void SHPhysicsMaterial::SetDensity(float newDensity) noexcept + { + if (newDensity < 0.0f) + { + SHLOG_WARNING("Setting negative density of Physics Material to positive.") + } + density = std::fabs(newDensity); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsMaterial.h b/SHADE_Engine/src/Physics/SHPhysicsMaterial.h new file mode 100644 index 00000000..b3db1655 --- /dev/null +++ b/SHADE_Engine/src/Physics/SHPhysicsMaterial.h @@ -0,0 +1,113 @@ +/**************************************************************************************** + * \file SHPhysicsMaterial.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Physics Material. + * + * \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 + +// Project Headers +#include "SH_API.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHPhysicsMaterial + { + public: + /*---------------------------------------------------------------------------------*/ + /* Static Data Members */ + /*---------------------------------------------------------------------------------*/ + + static const SHPhysicsMaterial DEFAULT; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsMaterial (const SHPhysicsMaterial&) noexcept = default; + SHPhysicsMaterial (SHPhysicsMaterial&&) noexcept = default; + ~SHPhysicsMaterial() = default; + + /** + * @brief Default constructor for a physics material. + * @param friction The friction of the material. Clamped between [0,1]. Defaults to 0.4. + * @param bounciness The bounciness of the material. Clamped between [0,1]. + * @param density The mass density of the material. Always made positive. + */ + SHPhysicsMaterial (float friction = 0.4f, float bounciness = 0.0f, float density = 1.0f) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsMaterial& operator= (const SHPhysicsMaterial&) noexcept = default; + SHPhysicsMaterial& operator= (SHPhysicsMaterial&&) noexcept = default; + + bool operator==(const SHPhysicsMaterial& rhs) const noexcept; + bool operator!=(const SHPhysicsMaterial& rhs) const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + [[nodiscard]] float GetFriction () const noexcept; + [[nodiscard]] float GetBounciness () const noexcept; + [[nodiscard]] float GetDensity () const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief Sets the friction coefficient of the physics material. + * @param newFriction The friction value to set. Clamped between [0,1]. + */ + void SetFriction (float newFriction) noexcept; + + /** + * @brief Sets the bounciness factor of the physics material. + * @param newBounciness The bounciness value to set. Clamped between [0,1]. + */ + void SetBounciness (float newBounciness) noexcept; + + /** + * @brief Sets the mass density of the physics material. + * @param newDensity The density value to set. Always made positive. + */ + void SetDensity (float newDensity) noexcept; + + private: + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief The friction coefficient of the physics object., clamped between [0,1].
+ * 0 means the object will never experience friction. + * 1 means the friction force against the object is equal to the applied force. + */ + float friction; + + /** + * @brief The bounciness factor of the physics object., clamped between [0,1].
+ * 0 means the object will never bounce. + * 1 means the object never loses energy on a bounce. + */ + float bounciness; + + /** + * @brief The density of the collider that determines the mass of the collision shape + * if it is automatically computed. Must be a positive number. + */ + float density; + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 986ce503..4d4d8cd7 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -261,9 +261,9 @@ namespace SHADE void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept { int index = 0; - for (auto& [collider, dirty] : c->colliders) + for (auto& collider : c->colliders) { - if (!dirty) + if (!collider.dirty) continue; // Update offsets @@ -293,7 +293,7 @@ namespace SHADE default: break; } - dirty = false; + collider.dirty = false; ++index; } } diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 1c6e79d7..44142aaf 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -246,21 +246,6 @@ namespace SHADE if (physicsObject.rp3dBody == nullptr) continue; - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - - // Clear all forces and velocities if editor is not in play - if (SHSystemManager::GetSystem()->editorState == SHEditor::State::STOP) - { - if (rigidBodyComponent) - { - auto* rp3dRigidBody = reinterpret_cast(physicsObject.rp3dBody); - rp3dRigidBody->resetForce(); - rp3dRigidBody->resetTorque(); - rp3dRigidBody->setLinearVelocity(SHVec3::Zero); - rp3dRigidBody->setAngularVelocity(SHVec3::Zero); - } - } - const auto* transformComponent = SHComponentManager::GetComponent_s(entityID); if (transformComponent && transformComponent->HasChanged()) { @@ -270,10 +255,21 @@ namespace SHADE physicsObject.SetPosition(WORLD_POS); physicsObject.SetOrientation(WORLD_ROT); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); if (rigidBodyComponent) { rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->orientation = WORLD_ROT; + + // Clear all forces and velocities if editor is stopped + if (SHSystemManager::GetSystem()->editorState == SHEditor::State::STOP) + { + auto* rp3dRigidBody = reinterpret_cast(physicsObject.rp3dBody); + rp3dRigidBody->resetForce(); + rp3dRigidBody->resetTorque(); + rp3dRigidBody->setLinearVelocity(SHVec3::Zero); + rp3dRigidBody->setAngularVelocity(SHVec3::Zero); + } } auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); @@ -517,7 +513,7 @@ namespace SHADE // Add collision shapes back into the body if (colliderComponent != nullptr) { - for (auto& collider : colliderComponent->colliders | std::views::keys) + for (auto& collider : colliderComponent->colliders) physicsObject->AddCollider(&collider); } } @@ -538,7 +534,7 @@ namespace SHADE } // Add Collision Shapes - for (auto& collider : colliderComponent->colliders | std::views::keys) + for (auto& collider : colliderComponent->colliders) physicsObject->AddCollider(&collider); } } @@ -576,7 +572,7 @@ namespace SHADE rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } ); - for (auto& collider : colliderComponent->colliders | std::views::keys) + for (auto& collider : colliderComponent->colliders) physicsObject->AddCollider(&collider); } diff --git a/SHADE_Engine/src/Resource/SHHandle.hpp b/SHADE_Engine/src/Resource/SHHandle.hpp index 91eed058..ff544d3b 100644 --- a/SHADE_Engine/src/Resource/SHHandle.hpp +++ b/SHADE_Engine/src/Resource/SHHandle.hpp @@ -161,7 +161,6 @@ namespace std std::size_t hash, SHADE::Handle>>::operator()( std::pair, SHADE::Handle> const& pair) const { - return std::hash{}(pair.first.GetId().Raw) ^ std::hash{}(pair.second.GetId().Raw); } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index cff4e84b..072adaa2 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -136,11 +136,11 @@ namespace SHADE template std::optional SHResourceManager::GetAssetID(Handle handle) { - const Handle GENERIC_HANDLE = Handle(handle); + const Handle GENERIC_HANDLE = Handle(handle); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); if (typedAssetIdMap.get().contains(GENERIC_HANDLE)) { - return typedAssetIdMap.GetId()[GENERIC_HANDLE]; + return typedAssetIdMap.get()[GENERIC_HANDLE]; } return {}; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 574747ec..df46b3fb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -582,9 +582,9 @@ namespace SHADE ReleaseNode(node); } - void SHSceneGraph::Traverse (const UnaryFunction& predicate) const + void SHSceneGraph::Traverse (const UnaryFunction& function) const { - TraverseAndInvokeFunction(root, predicate); + TraverseAndInvokeFunction(root, function); } /*-----------------------------------------------------------------------------------*/ @@ -621,7 +621,7 @@ namespace SHADE delete node; } - void SHSceneGraph::TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function) + void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function) { for (auto* child : node->children) { diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index b52fd1ff..45ab48e5 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -142,7 +142,7 @@ namespace SHADE bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; void Reset () noexcept; - void Traverse (const UnaryFunction& predicate) const; + void Traverse (const UnaryFunction& function) const; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index f0f8912b..21ce7b82 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -417,13 +417,13 @@ namespace SHADE ( DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_NAMESPACE + ".Collider", - "OnColliderBoundChanged" + "OnCollisionShapeChanged" ); csColliderOnRemoved = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_NAMESPACE + ".Collider", - "OnColliderRemoved" + "OnCollisionShapeRemoved" ); csEditorRenderScripts = dotNet.GetFunctionPtr ( diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 3804db95..79c8308f 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -1,8 +1,8 @@ #include "SHpch.h" -#include "SHSerializationHelper.hpp" -#include "SHSerialization.h" #include +#include "SHSerializationHelper.hpp" +#include "SHSerialization.h" #include "ECS_Base/Managers/SHEntityManager.h" #include "Scene/SHSceneManager.h" @@ -186,7 +186,7 @@ namespace SHADE } if (const auto renderable = SHComponentManager::GetComponent_s(eid)) { - components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable); + components[rttr::type::get().get_name().data()] = *renderable; } if (const auto rigidbody = SHComponentManager::GetComponent_s(eid)) { @@ -259,5 +259,6 @@ namespace SHADE if (!componentsNode) return; SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); + SHSerializationHelper::ConvertNodeToComponent(componentsNode, eid); } } diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index da98c885..a8e46d88 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -1,7 +1,7 @@ #pragma once -#include "ECS_Base/Components/SHComponent.h" #include +#include "ECS_Base/Components/SHComponent.h" #include @@ -9,6 +9,207 @@ #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" +#include "Resource/SHResourceManager.h" +#include "Graphics/MiddleEnd/Interface/SHRenderable.h" +#include "Graphics/MiddleEnd/Interface/SHMaterial.h" +#include "SHSerializationTools.h" + +namespace YAML +{ + using namespace SHADE; + template<> + struct convert + { + static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader"; + static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader"; + static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass"; + static constexpr std::string_view PROPS_YAML_TAG = "Properties"; + + static YAML::Node encode(SHMaterial const& rhs) + { + // Write Properties + YAML::Node propertiesNode; + Handle pipelineProperties = rhs.GetShaderBlockInterface(); + for (int i = 0; i < static_cast(pipelineProperties->GetVariableCount()); ++i) + { + const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i); + if (!VARIABLE) + break; + const std::string& VAR_NAME = pipelineProperties->GetVariableName(i); + YAML::Node propNode; + switch (VARIABLE->type) + { + case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT: + propNode = rhs.GetProperty(VARIABLE->offset); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::INT: + propNode = rhs.GetProperty(VARIABLE->offset); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::OTHER: + default: + continue; + break; + } + propertiesNode[VAR_NAME.data()] = propNode; + } + + // Get Shader Handles + const auto& SHADERS = rhs.GetPipeline()->GetPipelineLayout()->GetShaderModules(); + Handle vertexShader, fragShader; + for (const auto& shader : SHADERS) + { + const auto FLAG_BITS = shader->GetShaderStageFlagBits(); + if (FLAG_BITS & vk::ShaderStageFlagBits::eVertex) + vertexShader = shader; + else if (FLAG_BITS & vk::ShaderStageFlagBits::eFragment) + fragShader = shader; + } + + // Write Material + YAML::Node node; + + node[VERT_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID(vertexShader).value_or(0); + node[FRAG_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID(fragShader).value_or(0); + node[SUBPASS_YAML_TAG.data()] = rhs.GetPipeline()->GetPipelineState().GetSubpass()->GetName(); + node[PROPS_YAML_TAG.data()] = propertiesNode; + + return node; + } + static bool decode(YAML::Node const& node, SHMaterial& rhs) + { + /* + // Retrieve Shader Asset IDs + AssetID vertShaderId = 0; + AssetID fragShaderId = 0; + if (node[VERT_SHADER_YAML_TAG.data()]) + vertShaderId = node[VERT_SHADER_YAML_TAG.data()].as(); + if (node[FRAG_SHADER_YAML_TAG.data()]) + fragShaderId = node[FRAG_SHADER_YAML_TAG.data()].as(); + + // Ensure that both shaders are present + if (vertShaderId == 0 || fragShaderId == 0) + return false; // No pipeline + + // Get Shader Modules + Handle vertexShader, fragShader; + vertexShader = SHResourceManager::LoadOrGet(vertShaderId); + fragShader = SHResourceManager::LoadOrGet(fragShaderId); + + // Get Pipeline Library + if (node[SUBPASS_YAML_TAG.data()]) + { + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + + // Grab subpass from worldRenderer + auto renderPass = gfxSystem->GetPrimaryRenderpass(); + if (!renderPass) + return false; + auto subPass = renderPass->GetSubpass(node[SUBPASS_YAML_TAG.data()].as()); + if (!subPass) + return false; + + // Set Pipeline + rhs.SetPipeline(renderPass->GetOrCreatePipeline + ( + std::make_pair(vertexShader, fragShader), + subPass + )); + } + */ + + // TODO: Load Proper Material! + // Set default material + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + rhs.SetPipeline(gfxSystem->GetDefaultMaterial()->GetPipeline()); + + if (node[PROPS_YAML_TAG.data()]) + { + // Loop through all properties + Handle pipelineProperties = rhs.GetShaderBlockInterface(); + const YAML::Node& PROPS_NODE = node[PROPS_YAML_TAG.data()]; + for (int i = 0; i < static_cast(pipelineProperties->GetVariableCount()); ++i) + { + const std::string& PROP_NAME = pipelineProperties->GetVariableName(i); + const auto& PROP_NODE = PROPS_NODE[PROP_NAME.data()]; + if (PROP_NODE) + { + const std::string& VAR_NAME = pipelineProperties->GetVariableName(i); + const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i); + switch (VARIABLE->type) + { + case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT: + rhs.SetProperty(VARIABLE->offset, PROP_NODE.as()); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::INT: + rhs.SetProperty(VARIABLE->offset, PROP_NODE.as()); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec2(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec3(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec4(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::OTHER: + default: + continue; + break; + } + } + } + } + return true; + } + }; + + template<> + struct convert + { + static constexpr std::string_view MESH_YAML_TAG = "Mesh"; + static constexpr std::string_view MAT_YAML_TAG = "Material"; + + static YAML::Node encode(SHRenderable const& rhs) + { + YAML::Node node; + node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMesh()).value_or(0); + node[MAT_YAML_TAG.data()] = 0; // TODO: Asset ID + return node; + } + static bool decode(YAML::Node const& node, SHRenderable& rhs) + { + if (node[MESH_YAML_TAG.data()]) + { + rhs.SetMesh(SHResourceManager::LoadOrGet(node[MESH_YAML_TAG.data()].as())); + } + if (node[MAT_YAML_TAG.data()]) + { + // TODO: Convert Asset ID To Material HAndle + // Temporarily, use default material + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(gfxSystem->GetDefaultMaterial())); + } + return true; + } + }; +} + namespace SHADE { @@ -126,18 +327,15 @@ namespace SHADE auto propType = prop.get_type(); if (propType == rttr::type::get()) { - SHVec4 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as(), propertyNode["W"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec4(propertyNode)); } else if (propType == rttr::type::get()) { - SHVec3 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec3(propertyNode)); } else if (propType == rttr::type::get()) { - SHVec2 vec{ propertyNode["X"].as(), propertyNode["Y"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec2(propertyNode)); } else if (propType.is_arithmetic()) { @@ -200,5 +398,18 @@ namespace SHADE } } + template , bool> = true> + static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid) + { + auto component = SHComponentManager::GetComponent_s(eid); + if (componentsNode.IsNull() && !component) + return; + auto rttrType = rttr::type::get(); + auto componentNode = componentsNode[rttrType.get_name().data()]; + if (componentsNode.IsNull()) + return; + YAML::convert::decode(componentNode, *component); + } + }; } diff --git a/SHADE_Engine/src/Serialization/SHSerializationTools.cpp b/SHADE_Engine/src/Serialization/SHSerializationTools.cpp new file mode 100644 index 00000000..86a74613 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerializationTools.cpp @@ -0,0 +1,67 @@ +/************************************************************************************//*! +\file SHSerializationTools.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 22, 2022 +\brief Contains the definition of functions of the SHSerializationTools class. + + +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 "SHpch.h" +#include "SHSerializationTools.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* YAML Serialization Functions */ + /*-----------------------------------------------------------------------------------*/ + YAML::Node SHSerializationTools::ValToYAML(const SHVec2& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + return node; + } + YAML::Node SHSerializationTools::ValToYAML(const SHVec3& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + node["Z"] = vec.z; + return node; + } + YAML::Node SHSerializationTools::ValToYAML(const SHVec4& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + node["Z"] = vec.z; + node["W"] = vec.w; + return node; + } + + /*-----------------------------------------------------------------------------------*/ + /* YAML Deserialization Functions */ + /*-----------------------------------------------------------------------------------*/ + SHVec2 SHSerializationTools::YAMLToVec2(const YAML::Node& node) + { + return SHVec2 { node["X"].as(), node["Y"].as() }; + } + + SHVec3 SHSerializationTools::YAMLToVec3(const YAML::Node& node) + { + return SHVec3 { node["X"].as(), node["Y"].as(), node["Z"].as() }; + } + + SHVec4 SHSerializationTools::YAMLToVec4(const YAML::Node& node) + { + return SHVec4 { node["X"].as(), node["Y"].as(), node["Z"].as(), node["W"].as() }; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHSerializationTools.h b/SHADE_Engine/src/Serialization/SHSerializationTools.h new file mode 100644 index 00000000..3a3f6645 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerializationTools.h @@ -0,0 +1,54 @@ +/************************************************************************************//*! +\file SHSerializationTools.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 22, 2022 +\brief Contains the class definition of SHSerializationTools. + + +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 + +// External Dependencies +#include +// Project Includes +#include "SH_API.h" +#include "Math/Vector/SHVec2.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" + +namespace SHADE +{ + /*************************************************************************************/ + /*! + \brief + Static class that contains useful functions for converting values to YAML Nodes + and vice versa. + */ + /*************************************************************************************/ + class SH_API SHSerializationTools + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + SHSerializationTools() = delete; + + /*---------------------------------------------------------------------------------*/ + /* YAML Serialization Functions */ + /*---------------------------------------------------------------------------------*/ + static YAML::Node ValToYAML(const SHVec2& vec); + static YAML::Node ValToYAML(const SHVec3& vec); + static YAML::Node ValToYAML(const SHVec4& vec); + + /*---------------------------------------------------------------------------------*/ + /* YAML Deserialization Functions */ + /*---------------------------------------------------------------------------------*/ + static SHVec2 YAMLToVec2(const YAML::Node& node); + static SHVec3 YAMLToVec3(const YAML::Node& node); + static SHVec4 YAMLToVec4(const YAML::Node& node); + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index 6d2c2f01..f2119b43 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -22,7 +22,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* ColliderBound - Constructors */ /*---------------------------------------------------------------------------------*/ - ColliderBound::ColliderBound(int arrayIdx, Entity attachedEntity) + CollisionShape::CollisionShape(int arrayIdx, Entity attachedEntity) : arrayIndex { arrayIdx } , entity { attachedEntity } {} @@ -30,7 +30,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* ColliderBound - Setter Functions */ /*---------------------------------------------------------------------------------*/ - void ColliderBound::updateArrayIndex(int index) + void CollisionShape::updateArrayIndex(int index) { arrayIndex = index; } @@ -38,42 +38,42 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* BoxColliderBound - Constructors */ /*---------------------------------------------------------------------------------*/ - BoxColliderBound::BoxColliderBound(int arrayIdx, Entity attachedEntity) - : ColliderBound { arrayIndex, attachedEntity } + BoxCollider::BoxCollider(int arrayIdx, Entity attachedEntity) + : CollisionShape { arrayIndex, attachedEntity } {} /*---------------------------------------------------------------------------------*/ /* BoxColliderBound - Properties */ /*---------------------------------------------------------------------------------*/ - Vector3 BoxColliderBound::Center::get() + Vector3 BoxCollider::Center::get() { return Convert::ToCLI(getNativeBoundObject().GetCenter()); } - void BoxColliderBound::Center::set(Vector3 value) + void BoxCollider::Center::set(Vector3 value) { getNativeBoundObject().SetCenter(Convert::ToNative(value)); } - Vector3 BoxColliderBound::HalfExtents::get() + Vector3 BoxCollider::HalfExtents::get() { return Convert::ToCLI(getNativeBoundObject().GetHalfExtents()); } - void BoxColliderBound::HalfExtents::set(Vector3 value) + void BoxCollider::HalfExtents::set(Vector3 value) { getNativeBoundObject().SetHalfExtents(Convert::ToNative(value)); } - Vector3 BoxColliderBound::Min::get() + Vector3 BoxCollider::Min::get() { return Convert::ToCLI(getNativeBoundObject().GetMin()); } - void BoxColliderBound::Min::set(Vector3 value) + void BoxCollider::Min::set(Vector3 value) { getNativeBoundObject().SetMin(Convert::ToNative(value)); } - Vector3 BoxColliderBound::Max::get() + Vector3 BoxCollider::Max::get() { return Convert::ToCLI(getNativeBoundObject().GetMax()); } - void BoxColliderBound::Max::set(Vector3 value) + void BoxCollider::Max::set(Vector3 value) { getNativeBoundObject().SetMax(Convert::ToNative(value)); } @@ -81,11 +81,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* BoxColliderBound - Usage Functions */ /*---------------------------------------------------------------------------------*/ - bool BoxColliderBound::TestPoint(Vector3 point) + bool BoxCollider::TestPoint(Vector3 point) { return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } - bool BoxColliderBound::Raycast(Ray ray, float maxDistance) + bool BoxCollider::Raycast(Ray ray, float maxDistance) { return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } @@ -93,19 +93,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* BoxColliderBound - Properties */ /*---------------------------------------------------------------------------------*/ - Vector3 SphereColliderBound::Center::get() + Vector3 SphereCollider::Center::get() { return Convert::ToCLI(getNativeBoundObject().GetCenter()); } - void SphereColliderBound::Center::set(Vector3 value) + void SphereCollider::Center::set(Vector3 value) { getNativeBoundObject().SetCenter(Convert::ToNative(value)); } - float SphereColliderBound::Radius::get() + float SphereCollider::Radius::get() { return getNativeBoundObject().GetRadius(); } - void SphereColliderBound::Radius::set(float value) + void SphereCollider::Radius::set(float value) { getNativeBoundObject().SetRadius(value); } @@ -113,11 +113,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* SphereColliderBound - Usage Functions */ /*---------------------------------------------------------------------------------*/ - bool SphereColliderBound::TestPoint(Vector3 point) + bool SphereCollider::TestPoint(Vector3 point) { return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } - bool SphereColliderBound::Raycast(Ray ray, float maxDistance) + bool SphereCollider::Raycast(Ray ray, float maxDistance) { return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } @@ -125,8 +125,8 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* SphereColliderBound - Constructors */ /*---------------------------------------------------------------------------------*/ - SphereColliderBound::SphereColliderBound(int arrayIndex, Entity attachedEntity) - : ColliderBound{ arrayIndex, attachedEntity } + SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity) + : CollisionShape{ arrayIndex, attachedEntity } {} /*---------------------------------------------------------------------------------*/ @@ -137,7 +137,7 @@ namespace SHADE { // Create lists if they don't exist if (colliders == nullptr) - colliders = gcnew CollidersMap; + colliders = gcnew ColliderMap; if (!colliders->ContainsKey(entity)) colliders->Add(entity, gcnew WeakReferenceList()); @@ -148,7 +148,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Collider - Properties */ /*---------------------------------------------------------------------------------*/ - int Collider::ColliderBoundsCount::get() + int Collider::CollisionShapeCount::get() { return static_cast(GetNativeComponent()->GetColliders().size()); } @@ -156,7 +156,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Collider - ColliderBound Functions */ /*---------------------------------------------------------------------------------*/ - ColliderBound^ Collider::GetColliderBound(int index) + CollisionShape^ Collider::GetCollisionShape(int index) { // Populate the list if it hasn't been if (subColliderList == nullptr) @@ -172,15 +172,15 @@ namespace SHADE return subColliderList[index]; } generic - T Collider::GetColliderBound(int index) + T Collider::GetCollisionShape(int index) { - return safe_cast(GetColliderBound(index)); + return safe_cast(GetCollisionShape(index)); } /*---------------------------------------------------------------------------------*/ /* Event Handling Functions */ /*---------------------------------------------------------------------------------*/ - void Collider::OnColliderRemoved(EntityID entity) + void Collider::OnCollisionShapeRemoved(EntityID entity) { SAFE_NATIVE_CALL_BEGIN // Check if there are any colliders to update @@ -192,7 +192,7 @@ namespace SHADE SAFE_NATIVE_CALL_END("Collider.OnColliderRemoved") } - void Collider::OnColliderBoundChanged(EntityID entity) + void Collider::OnCollisionShapeChanged(EntityID entity) { SAFE_NATIVE_CALL_BEGIN // Check if there are any colliders to update @@ -226,20 +226,20 @@ namespace SHADE if (subColliderList) subColliderList->Clear(); else - subColliderList = gcnew System::Collections::Generic::List(); + subColliderList = gcnew System::Collections::Generic::List(); // Populate the list int i = 0; for (const auto& collider : GetNativeComponent()->GetColliders()) { - ColliderBound^ bound = nullptr; - switch (collider.first.GetType()) + CollisionShape^ bound = nullptr; + switch (collider.GetType()) { case SHCollider::Type::BOX: - bound = gcnew BoxColliderBound(i, Owner.GetEntity()); + bound = gcnew BoxCollider(i, Owner.GetEntity()); break; case SHCollider::Type::SPHERE: - bound = gcnew SphereColliderBound(i, Owner.GetEntity()); + bound = gcnew SphereCollider(i, Owner.GetEntity()); break; case SHCollider::Type::CAPSULE: // TODO diff --git a/SHADE_Managed/src/Components/Collider.h++ b/SHADE_Managed/src/Components/Collider.h++ index 66f77e18..1f8b43eb 100644 --- a/SHADE_Managed/src/Components/Collider.h++ +++ b/SHADE_Managed/src/Components/Collider.h++ @@ -18,8 +18,8 @@ of DigiPen Institute of Technology is prohibited. #include "Component.hxx" namespace SHADE { - template - ColliderBoundType& SHADE::ColliderBound::getNativeBoundObject() + template + CollisionShapeType& SHADE::CollisionShape::getNativeBoundObject() { SHColliderComponent* collider = SHComponentManager::GetComponent_s(entity); if (!collider) @@ -31,7 +31,7 @@ namespace SHADE if (bounds.GetType() != SHCollider::Type::BOX) throw gcnew System::InvalidOperationException("Attempted to retrieve invalid ColliderBound."); - return reinterpret_cast(bounds); + return reinterpret_cast(bounds); } catch (std::invalid_argument&) { diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index 9f88b983..1d1196f5 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -27,7 +27,7 @@ namespace SHADE /// /// Base interface for all Collider Shapes. /// - public ref class ColliderBound abstract + public ref class CollisionShape abstract { public: /*-----------------------------------------------------------------------------*/ @@ -51,7 +51,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ - ColliderBound(int arrayIdx, Entity attachedEntity); + CollisionShape(int arrayIdx, Entity attachedEntity); /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -62,8 +62,8 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------*/ - template - ColliderBoundType& getNativeBoundObject(); + template + CollisionShapeType& getNativeBoundObject(); internal: /*-----------------------------------------------------------------------------*/ @@ -75,7 +75,7 @@ namespace SHADE /// /// Box-shaped Collider Bound. /// - public ref class BoxColliderBound : public ColliderBound + public ref class BoxCollider : public CollisionShape { public: /*-----------------------------------------------------------------------------*/ @@ -128,13 +128,13 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ - BoxColliderBound(int arrayIndex, Entity attachedEntity); + BoxCollider(int arrayIndex, Entity attachedEntity); }; /// /// Sphere-shaped Collider Bound. /// - public ref class SphereColliderBound : public ColliderBound + public ref class SphereCollider : public CollisionShape { public: /*-----------------------------------------------------------------------------*/ @@ -169,7 +169,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ - SphereColliderBound(int arrayIndex, Entity attachedEntity); + SphereCollider(int arrayIndex, Entity attachedEntity); }; /// @@ -196,7 +196,7 @@ namespace SHADE /// /// Total number of ColliderBounds in the Collider component. /// - property int ColliderBoundsCount + property int CollisionShapeCount { int get(); } @@ -209,7 +209,7 @@ namespace SHADE /// /// Index to retrieve a ColliderBound from. /// ColliderBound for the specified index. - ColliderBound^ GetColliderBound(int index); + CollisionShape^ GetCollisionShape(int index); /// /// Retrieves a ColliderBound at the specified index in the ColliderBound list /// and casts it to the appropriate type. @@ -217,42 +217,42 @@ namespace SHADE /// Type of the ColliderBound to cast to. /// Index to retrieve a ColliderBound from. /// ColliderBound for the specified index. - generic where T:ColliderBound - T GetColliderBound(int index); + generic where T:CollisionShape + T GetCollisionShape(int index); internal: /*-----------------------------------------------------------------------------*/ /* Event Handling Functions */ /*-----------------------------------------------------------------------------*/ /// - /// To be called from native code when a collider has been removed. + /// To be called from native code when a collision shape has been removed. /// - /// The entity which has it's collider removed. - static void OnColliderRemoved(EntityID entity); + /// The entity which has it's collision shape removed. + static void OnCollisionShapeRemoved(EntityID entity); /// - /// To be called from native code when a Collider bound has been removed. + /// To be called from native code when a Collision Shape has been changed. /// /// - /// The entity which has it's collider bounds changed. + /// The entity which has it's collision shape changed. /// - static void OnColliderBoundChanged(EntityID entity); + static void OnCollisionShapeChanged(EntityID entity); private: /*-----------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------*/ using WeakReferenceList = System::Collections::Generic::List; - using CollidersMap = System::Collections::Generic::Dictionary; + using ColliderMap = System::Collections::Generic::Dictionary; /*-----------------------------------------------------------------------------*/ /* Static Data Members */ /*-----------------------------------------------------------------------------*/ - static CollidersMap^ colliders; + static ColliderMap^ colliders; /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ - System::Collections::Generic::List^ subColliderList; + System::Collections::Generic::List^ subColliderList; /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Managed/src/Components/Renderable.cxx b/SHADE_Managed/src/Components/Renderable.cxx index d1bbb4c8..bc01bc03 100644 --- a/SHADE_Managed/src/Components/Renderable.cxx +++ b/SHADE_Managed/src/Components/Renderable.cxx @@ -32,17 +32,17 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHADE::Mesh^ Renderable::Mesh::get() { - return gcnew SHADE::Mesh(GetNativeComponent()->Mesh); + return gcnew SHADE::Mesh(GetNativeComponent()->GetMesh()); } void Renderable::Mesh::set(SHADE::Mesh^ value) { if (value == nullptr) { - GetNativeComponent()->Mesh = Handle(); + GetNativeComponent()->SetMesh(Handle()); } else { - GetNativeComponent()->Mesh = Handle(Convert::ToNative(value->NativeObjectHandle)); + GetNativeComponent()->SetMesh(Handle(Convert::ToNative(value->NativeObjectHandle))); } } SHADE::Material^ Renderable::Material::get() diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index 3e963818..f114d01b 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -184,10 +184,6 @@ namespace SHADE void ReflectionUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) { - if (fieldInfo->FieldType == System::Int16::typeid) - { - fieldInfo->SetValue(object, node.as()); - } if (fieldAssignYaml (fieldInfo, object, node) || fieldAssignYaml (fieldInfo, object, node) || fieldAssignYaml (fieldInfo, object, node) ||