From d36d70e3eb28078a507a86cad7256a51fbba8eaa Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 14 Nov 2022 00:20:54 +0800 Subject: [PATCH 1/5] Added a forced update to the physics system --- .../Physics/PhysicsObject/SHPhysicsObject.cpp | 9 ++ .../PhysicsObject/SHPhysicsObjectManager.cpp | 11 ++ .../PhysicsObject/SHPhysicsObjectManager.h | 4 + .../src/Physics/System/SHPhysicsSystem.cpp | 137 +++++++++++++++++- .../src/Physics/System/SHPhysicsSystem.h | 49 +++---- .../System/SHPhysicsSystemInterface.cpp | 2 +- .../System/SHPhysicsSystemRoutines.cpp | 124 ++-------------- 7 files changed, 194 insertions(+), 142 deletions(-) diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 0c9fa405..4c920bbc 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHComponentManager.h" +#include "Scene/SHSceneManager.h" namespace SHADE @@ -148,6 +149,10 @@ namespace SHADE void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept { + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + if (component.dirtyFlags == 0) return; @@ -267,6 +272,10 @@ namespace SHADE void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept { + // This state is synced in the pre-update routine + if (!rp3dBody->isActive()) + return; + int index = 0; for (auto& collisionShape : component.collisionShapes) { diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp index 13f525e6..f8a4040f 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp @@ -167,6 +167,7 @@ namespace SHADE if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent) { destroyPhysicsObject(COMMAND.eid); + wakeAllObjects(); continue; } @@ -176,6 +177,10 @@ namespace SHADE physicsObject = createPhysicsObject(COMMAND.eid); componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP); + + // If any removal was done, wake all objects + if (COMMAND.command == QueueCommand::Command::REMOVE) + wakeAllObjects(); } } @@ -297,5 +302,11 @@ namespace SHADE physicsObject->RemoveCollisionShape(command.shapeIndex); } + void SHPhysicsObjectManager::wakeAllObjects() noexcept + { + for (auto& physicsObject : physicsObjects | std::views::values) + physicsObject.GetRigidBody()->setIsSleeping(false); + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h index d8c9b805..641fd9df 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h @@ -165,6 +165,8 @@ namespace SHADE SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept; void destroyPhysicsObject (EntityID eid) noexcept; + void wakeAllObjects () noexcept; + static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); @@ -172,6 +174,8 @@ namespace SHADE static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); + + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 34f0c698..d94cfb58 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -20,6 +20,7 @@ #include "Editor/SHEditor.h" #include "Physics/SHPhysicsEvents.h" #include "Scene/SHSceneManager.h" +#include "Scripting/SHScriptEngine.h" /*-------------------------------------------------------------------------------------*/ /* Local Helper Functions */ @@ -34,16 +35,16 @@ namespace SHADE SHPhysicsSystem::SHPhysicsSystem() : worldUpdated { false } , interpolationFactor { 0.0 } - , fixedDT { 60.0 } + , fixedDT { DEFAULT_FIXED_STEP } {} /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - double SHPhysicsSystem::GetFixedDT() const noexcept + double SHPhysicsSystem::GetFixedUpdateRate() const noexcept { - return fixedDT; + return 1.0 / fixedDT; } const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept @@ -76,9 +77,9 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept + void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept { - fixedDT = fixedUpdateRate; + fixedDT = 1.0 / fixedUpdateRate; } void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept @@ -126,6 +127,45 @@ namespace SHADE worldState.DestroyWorld(factory); } + void SHPhysicsSystem::ForceUpdate() + { + if (!worldState.world) + { + SHLOGV_ERROR("Unable to force update without a Physics world!") + return; + } + + auto* scriptingSystem = SHSystemManager::GetSystem(); + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); + } + + // Force the physics world to update once + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteFixedUpdates(); + + worldState.world->update(static_cast(fixedDT)); + + // Sync transforms. No interpolation applied here + for (auto& [entityID, physicsObject] : objectManager.physicsObjects) + { + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + + postUpdateSyncTransforms + ( + physicsObject + , transformComponent + , rigidBodyComponent + , colliderComponent + , 1.0 // We use 1.0 here to avoid any interpolation + ); + } + } + + void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex) { static const auto ADD_SHAPE = [&](EntityID entityID, int index) @@ -339,5 +379,92 @@ namespace SHADE return onStopEvent->handle; } + void SHPhysicsSystem::preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept + { + if (!transformComponent) + return; + + const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation(); + const SHVec3& WORLD_SCL = transformComponent->GetWorldScale(); + + const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; + physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); + + if (rigidBodyComponent) + { + rigidBodyComponent->position = WORLD_POS; + rigidBodyComponent->orientation = WORLD_ROT; + } + + if (colliderComponent) + { + colliderComponent->position = WORLD_POS; + colliderComponent->orientation = WORLD_ROT; + colliderComponent->scale = WORLD_SCL; + + colliderComponent->RecomputeCollisionShapes(); + } + } + + void SHPhysicsSystem::postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept + { + const rp3d::Transform& CURRENT_TF = physicsObject.rp3dBody->getTransform(); + auto renderPos = CURRENT_TF.getPosition(); + auto renderRot = CURRENT_TF.getOrientation(); + + // Cache transforms + physicsObject.prevTransform = CURRENT_TF; + + // Sync with rigid bodies + if (rigidBodyComponent) + { + // Skip static bodies + if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) + return; + + // Check if transform should be interpolated + if (rigidBodyComponent->IsInterpolating()) + { + // Interpolate transforms between current and predicted next transform + + const rp3d::Transform PREV_TF = physicsObject.prevTransform; + const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); + + renderPos = INTERPOLATED_TF.getPosition(); + renderRot = INTERPOLATED_TF.getOrientation(); + } + + rigidBodyComponent->position = CURRENT_TF.getPosition(); + rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); + } + + // Sync with colliders + if (colliderComponent) + { + colliderComponent->position = CURRENT_TF.getPosition(); + colliderComponent->orientation = CURRENT_TF.getOrientation(); + } + + // Set transform for rendering + if (transformComponent) + { + transformComponent->SetWorldPosition(renderPos); + transformComponent->SetWorldOrientation(renderRot); + } + } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 4254efc7..6059970d 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -55,7 +55,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedDT () const noexcept; + [[nodiscard]] double GetFixedUpdateRate () const noexcept; [[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; @@ -67,8 +67,8 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedDT (double fixedUpdateRate) noexcept; - void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; + void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -77,6 +77,8 @@ namespace SHADE void Init () override; void Exit () override; + void ForceUpdate (); + // Specific Handling for Collision Shapes as they are not under the Component System void AddCollisionShape (EntityID eid, int shapeIndex); @@ -121,14 +123,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; - - static void preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept; }; class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine @@ -161,20 +155,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ void Execute(double dt) noexcept override; - - private: - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - - static void postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept; }; private: @@ -208,5 +188,24 @@ namespace SHADE SHEventHandle onPlay (SHEventPtr onPlayEvent); SHEventHandle onStop (SHEventPtr onStopEvent); + + + static void preUpdateSyncTransform + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + ) noexcept; + + static void postUpdateSyncTransforms + ( + SHPhysicsObject& physicsObject + , SHTransformComponent* transformComponent + , SHRigidBodyComponent* rigidBodyComponent + , SHColliderComponent* colliderComponent + , double interpolationFactor + ) noexcept; + }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 30d29167..b142d54c 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -55,7 +55,7 @@ namespace SHADE auto phySystem = SHSystemManager::GetSystem(); if (phySystem) { - return phySystem->GetFixedDT(); + return phySystem->GetFixedUpdateRate(); } SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get fixed delta time. 0.0 returned instead."); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index 059202e5..d2c23006 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -125,18 +125,18 @@ namespace SHADE SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); } - fixedTimeStep = 1.0 / physicsSystem->fixedDT; + const double FIXED_DT = physicsSystem->fixedDT; accumulatedTime += dt; int count = 0; - while (accumulatedTime > fixedTimeStep) + while (accumulatedTime > FIXED_DT) { if (scriptingSystem != nullptr) scriptingSystem->ExecuteFixedUpdates(); - physicsSystem->worldState.world->update(static_cast(fixedTimeStep)); + physicsSystem->worldState.world->update(static_cast(FIXED_DT)); - accumulatedTime -= fixedTimeStep; + accumulatedTime -= FIXED_DT; ++count; } @@ -165,17 +165,14 @@ namespace SHADE auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - if (transformComponent) - { - postUpdateSyncTransforms - ( - physicsObject - , *transformComponent - , rigidBodyComponent - , colliderComponent - , physicsSystem->interpolationFactor - ); - } + postUpdateSyncTransforms + ( + physicsObject + , transformComponent + , rigidBodyComponent + , colliderComponent + , physicsSystem->interpolationFactor + ); } // Collision & Trigger messages @@ -203,7 +200,7 @@ namespace SHADE preUpdateSyncTransform ( physicsObject - , *transformComponent + , transformComponent , rigidBodyComponent , colliderComponent ); @@ -217,99 +214,4 @@ namespace SHADE if (colliderComponent) physicsObject.SyncColliders(*colliderComponent); } - - void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept - { - const SHVec3& WORLD_POS = transformComponent.GetWorldPosition(); - const SHQuaternion& WORLD_ROT = transformComponent.GetWorldOrientation(); - const SHVec3& WORLD_SCL = transformComponent.GetWorldScale(); - - const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; - physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - - if (rigidBodyComponent) - { - rigidBodyComponent->position = WORLD_POS; - rigidBodyComponent->orientation = WORLD_ROT; - } - - if (colliderComponent) - { - colliderComponent->position = WORLD_POS; - colliderComponent->orientation = WORLD_ROT; - colliderComponent->scale = WORLD_SCL; - - colliderComponent->RecomputeCollisionShapes(); - } - } - - void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent& transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept - { - rp3d::Vector3 rp3dPos; - rp3d::Quaternion rp3dRot; - - const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); - - // Check if transform should be interpolated - - if (rigidBodyComponent) - { - // Skip static bodies - if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) - return; - - if (rigidBodyComponent->IsInterpolating()) - { - // Interpolate transforms between current and predicted next transform - - const rp3d::Transform PREV_TF = physicsObject.prevTransform; - const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); - - rp3dPos = INTERPOLATED_TF.getPosition(); - rp3dRot = INTERPOLATED_TF.getOrientation(); - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - rigidBodyComponent->position = CURRENT_TF.getPosition(); - rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - - if (colliderComponent) - { - // Sync with colliders - - colliderComponent->position = CURRENT_TF.getPosition(); - colliderComponent->orientation = CURRENT_TF.getOrientation(); - } - } - else - { - rp3dPos = CURRENT_TF.getPosition(); - rp3dRot = CURRENT_TF.getOrientation(); - } - - // Convert RP3D Transform to SHADE - transformComponent.SetWorldPosition(rp3dPos); - transformComponent.SetWorldOrientation(rp3dRot); - - // Cache transforms - physicsObject.prevTransform = CURRENT_TF; - } - } // namespace SHADE \ No newline at end of file -- 2.40.1 From fe1b9d14f58af8f565aa680998d245fff296cbe4 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 14 Nov 2022 00:25:24 +0800 Subject: [PATCH 2/5] Partial implementation of syncing SHADE and ReactPhysics active states --- Assets/Scenes/M2Scene.shade | 7 +- .../Physics/PhysicsObject/SHPhysicsObject.cpp | 9 +- .../Physics/PhysicsObject/SHPhysicsObject.h | 3 +- .../System/SHPhysicsDebugDrawSystem.cpp | 5 + .../src/Physics/System/SHPhysicsSystem.cpp | 17 +- .../src/Physics/System/SHPhysicsSystem.h | 4 +- .../System/SHPhysicsSystemRoutines.cpp | 163 +++++++++++------- 7 files changed, 129 insertions(+), 79 deletions(-) diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index 21050428..bf910737 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -223,9 +223,4 @@ Bounciness: 0 Density: 1 Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: - - Type: Item - currCategory: 0 - - Type: PickAndThrow - throwForce: [100, 200, 100] - item: 51000 \ No newline at end of file + Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 4c920bbc..0b0dd7a7 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -26,10 +26,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } + : entityID { eid } + , collidersActive { true } + , factory { physicsFactory } + , world { physicsWorld } + , rp3dBody { nullptr } { // Implicitly create a static body. diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h index f18a0738..fefc983f 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h @@ -84,12 +84,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ EntityID entityID; + bool collidersActive; // Only used to sync with SHADE components rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; rp3d::RigidBody* rp3dBody; - rp3d::Transform prevTransform; // Cached transform for interpolation + rp3d::Transform prevTransform; // Cached transform for interpolation /*---------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index ff441ac2..72bcd13f 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" +#include "Scene/SHSceneManager.h" namespace SHADE { @@ -122,6 +123,10 @@ namespace SHADE const auto& COLLIDER_SET = SHComponentManager::GetDense(); for (const auto& COLLIDER : COLLIDER_SET) { + // Skip inactive colliders + //if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) + // continue; + for (auto& collisionShape : COLLIDER.GetCollisionShapes()) { switch (collisionShape.GetType()) diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index d94cfb58..0a7555b1 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -387,7 +387,7 @@ namespace SHADE , SHColliderComponent* colliderComponent ) noexcept { - if (!transformComponent) + if (!transformComponent || !SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) return; const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); @@ -397,13 +397,13 @@ namespace SHADE const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - if (rigidBodyComponent) + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { rigidBodyComponent->position = WORLD_POS; rigidBodyComponent->orientation = WORLD_ROT; } - if (colliderComponent) + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { colliderComponent->position = WORLD_POS; colliderComponent->orientation = WORLD_ROT; @@ -422,15 +422,16 @@ namespace SHADE , double interpolationFactor ) noexcept { - const rp3d::Transform& CURRENT_TF = physicsObject.rp3dBody->getTransform(); + const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); auto renderPos = CURRENT_TF.getPosition(); auto renderRot = CURRENT_TF.getOrientation(); // Cache transforms - physicsObject.prevTransform = CURRENT_TF; + if (physicsObject.GetRigidBody()->isActive()) + physicsObject.prevTransform = CURRENT_TF; // Sync with rigid bodies - if (rigidBodyComponent) + if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { // Skip static bodies if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) @@ -453,14 +454,14 @@ namespace SHADE } // Sync with colliders - if (colliderComponent) + if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { colliderComponent->position = CURRENT_TF.getPosition(); colliderComponent->orientation = CURRENT_TF.getOrientation(); } // Set transform for rendering - if (transformComponent) + if (transformComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) { transformComponent->SetWorldPosition(renderPos); transformComponent->SetWorldOrientation(renderRot); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 6059970d..3891ff48 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -122,7 +122,9 @@ namespace SHADE /* Function Members */ /*-------------------------------------------------------------------------------*/ - static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept; + void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; + static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; }; class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index d2c23006..3376159b 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" +#include "Scene/SHSceneManager.h" #include "Scripting/SHScriptEngine.h" namespace SHADE @@ -43,65 +44,13 @@ namespace SHADE { auto* physicsSystem = reinterpret_cast(GetSystem()); - #ifdef SHEDITOR - - auto* editor = SHSystemManager::GetSystem(); - - // Only Sync on Play. - // Otherwise, Components are only holding data until the world is built on play. - - if (editor) - { - if (editor->editorState != SHEditor::State::STOP) - { - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - syncOnPlay(entityID, physicsObject); - } - } - else - { - auto& rigidBodyDense = SHComponentManager::GetDense(); - auto& colliderDense = SHComponentManager::GetDense(); - - for (auto& rigidBodyComponent : rigidBodyDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); - rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); - } - } - - for (auto& colliderComponent : colliderDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - colliderComponent.position = TRANSFORM->GetWorldPosition(); - colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); - colliderComponent.scale = TRANSFORM->GetWorldScale(); - - colliderComponent.RecomputeCollisionShapes(); - } - } - } - } - - #else - - // Always sync Rigid Body & Collider Components with Physics Objects - // Do not check for an editor here + #ifdef SHEDITOR + // Only Sync on Play. + // Otherwise, Components are only holding data until the world is built on play. + const auto* EDITOR = SHSystemManager::GetSystem(); + if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) + { physicsSystem->objectManager.UpdateCommands(); for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) @@ -110,10 +59,64 @@ namespace SHADE if (physicsObject.rp3dBody == nullptr) continue; + // Sync active states between SHADE & RP3D + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + syncOnPlay(entityID, physicsObject); } + } + else + { + auto& rigidBodyDense = SHComponentManager::GetDense(); + auto& colliderDense = SHComponentManager::GetDense(); - #endif + for (auto& rigidBodyComponent : rigidBodyDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); + rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); + } + } + + for (auto& colliderComponent : colliderDense) + { + const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); + + if (TRANSFORM && TRANSFORM->HasChanged()) + { + colliderComponent.position = TRANSFORM->GetWorldPosition(); + colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); + colliderComponent.scale = TRANSFORM->GetWorldScale(); + + colliderComponent.RecomputeCollisionShapes(); + } + } + } + + #else + + // Always sync Rigid Body & Collider Components with Physics Objects + // Do not check for an editor here + + physicsSystem->objectManager.UpdateCommands(); + + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) + { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + + syncRigidBodyActive(entityID, physicsObject); + syncColliderActive(entityID, physicsObject); + + syncOnPlay(entityID, physicsObject); + } + + #endif } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -188,6 +191,48 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + if (!SHComponentManager::HasComponent(eid)) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive(); + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE) + physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE); + } + + void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept + { + const auto* COLLIDER = SHComponentManager::GetComponent_s(eid); + if (!COLLIDER) + return; + + const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); + const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive; + + if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE) + { + // HACK: If active state turned off, remove all collision shapes. If turned on, add them back. + auto* physicsSystem = reinterpret_cast(GetSystem()); + + const int NUM_SHAPES = static_cast(COLLIDER->GetCollisionShapes().size()); + if (IS_ACTIVE_IN_SCENE) + { + for (int i = 0; i < NUM_SHAPES; ++i) + physicsSystem->objectManager.AddCollisionShape(eid, i); + } + else + { + for (int i = NUM_SHAPES - 1; i >= 0; --i) + physicsSystem->objectManager.RemoveCollisionShape(eid, i); + } + + physicsObject.collidersActive = IS_ACTIVE_IN_SCENE; + } + } + void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept { auto* transformComponent = SHComponentManager::GetComponent_s(eid); -- 2.40.1 From 9515fcca4f746ec4eac2a56eb8ed0834a90e164c Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 14 Nov 2022 15:35:02 +0800 Subject: [PATCH 3/5] Renames & Bugfixes Renamed BoundingBox & BoundingSphere to Box & Sphere Forces are forcefully cleared --- .../Inspector/SHEditorComponentView.hpp | 7 ++- .../Geometry/{SHBoundingBox.cpp => SHBox.cpp} | 62 +++++++++---------- .../Geometry/{SHBoundingBox.h => SHBox.h} | 28 ++++----- .../{SHBoundingSphere.cpp => SHSphere.cpp} | 50 +++++++-------- .../{SHBoundingSphere.h => SHSphere.h} | 28 ++++----- .../Physics/Interface/SHColliderComponent.cpp | 4 +- .../Physics/Interface/SHColliderComponent.h | 4 +- .../Physics/Interface/SHCollisionShape.cpp | 28 ++++----- .../Physics/PhysicsObject/SHPhysicsObject.cpp | 8 +-- .../System/SHPhysicsDebugDrawSystem.cpp | 8 +-- .../src/Physics/System/SHPhysicsSystem.cpp | 29 +++++---- .../System/SHPhysicsSystemRoutines.cpp | 8 +++ .../src/Serialization/SHYAMLConverters.h | 8 +-- SHADE_Managed/src/Components/Collider.cxx | 32 +++++----- SHADE_Managed/src/Components/RigidBody.cxx | 12 +++- SHADE_Managed/src/Components/RigidBody.hxx | 4 ++ 16 files changed, 175 insertions(+), 145 deletions(-) rename SHADE_Engine/src/Math/Geometry/{SHBoundingBox.cpp => SHBox.cpp} (71%) rename SHADE_Engine/src/Math/Geometry/{SHBoundingBox.h => SHBox.h} (80%) rename SHADE_Engine/src/Math/Geometry/{SHBoundingSphere.cpp => SHSphere.cpp} (70%) rename SHADE_Engine/src/Math/Geometry/{SHBoundingSphere.h => SHSphere.h} (76%) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 2e55ea7a..6091556e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -223,7 +223,7 @@ namespace SHADE { if (!component) return; - + ImGui::PushID(component); const auto componentType = rttr::type::get(*component); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); @@ -246,7 +246,7 @@ namespace SHADE if (collider->GetType() == SHCollisionShape::Type::BOX) { SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* BOX = reinterpret_cast(collider->GetShape()); + const auto* BOX = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragVec3 ( "Half Extents", { "X", "Y", "Z" }, @@ -256,7 +256,7 @@ namespace SHADE else if (collider->GetType() == SHCollisionShape::Type::SPHERE) { SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* SPHERE = reinterpret_cast(collider->GetShape()); + const auto* SPHERE = reinterpret_cast(collider->GetShape()); SHEditorWidgets::DragFloat ( "Radius", @@ -322,6 +322,7 @@ namespace SHADE } } else DrawContextMenu(component); + ImGui::PopID(); } template<> diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBox.cpp similarity index 71% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp rename to SHADE_Engine/src/Math/Geometry/SHBox.cpp index 5bbf5e15..cf094a9d 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBox.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingBox.h" +#include "SHBox.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox::SHBoundingBox() noexcept + SHBox::SHBox() noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; } - SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept + SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept : RelativeExtents { SHVec3::One } { type = Type::BOX; @@ -40,7 +40,7 @@ namespace SHADE } - SHBoundingBox::SHBoundingBox(const SHBoundingBox& rhs) noexcept + SHBox::SHBox(const SHBox& rhs) noexcept { if (this == &rhs) return; @@ -52,7 +52,7 @@ namespace SHADE RelativeExtents = rhs.RelativeExtents; } - SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept + SHBox::SHBox(SHBox&& rhs) noexcept { type = Type::BOX; @@ -65,7 +65,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox& SHBoundingBox::operator=(const SHBoundingBox& rhs) noexcept + SHBox& SHBox::operator=(const SHBox& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -81,7 +81,7 @@ namespace SHADE return *this; } - SHBoundingBox& SHBoundingBox::operator=(SHBoundingBox&& rhs) noexcept + SHBox& SHBox::operator=(SHBox&& rhs) noexcept { if (rhs.type != Type::BOX) { @@ -101,27 +101,27 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingBox::GetCenter() const noexcept + SHVec3 SHBox::GetCenter() const noexcept { return Center; } - SHVec3 SHBoundingBox::GetWorldExtents() const noexcept + SHVec3 SHBox::GetWorldExtents() const noexcept { return Extents; } - const SHVec3& SHBoundingBox::GetRelativeExtents() const noexcept + const SHVec3& SHBox::GetRelativeExtents() const noexcept { return RelativeExtents; } - SHVec3 SHBoundingBox::GetMin() const noexcept + SHVec3 SHBox::GetMin() const noexcept { return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; } - SHVec3 SHBoundingBox::GetMax() const noexcept + SHVec3 SHBox::GetMax() const noexcept { return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; } @@ -130,22 +130,22 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingBox::SetCenter(const SHVec3& newCenter) noexcept + void SHBox::SetCenter(const SHVec3& newCenter) noexcept { Center = newCenter; } - void SHBoundingBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept + void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept { Extents = newWorldExtents; } - void SHBoundingBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept + void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept { RelativeExtents = newRelativeExtents; } - void SHBoundingBox::SetMin(const SHVec3& min) noexcept + void SHBox::SetMin(const SHVec3& min) noexcept { const SHVec3 MAX = GetMax(); @@ -153,7 +153,7 @@ namespace SHADE Extents = SHVec3::Abs((MAX - min) * 0.5f); } - void SHBoundingBox::SetMax(const SHVec3& max) noexcept + void SHBox::SetMax(const SHVec3& max) noexcept { const SHVec3 MIN = GetMin(); @@ -161,13 +161,13 @@ namespace SHADE Extents = SHVec3::Abs((max - MIN) * 0.5f); } - void SHBoundingBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept + void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept { Center = SHVec3::Lerp(min, max, 0.5f); Extents = SHVec3::Abs((max - min) * 0.5f); } - std::vector SHBoundingBox::GetVertices() const noexcept + std::vector SHBox::GetVertices() const noexcept { std::vector vertices{ 8 }; GetCorners(vertices.data()); @@ -178,27 +178,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingBox::TestPoint(const SHVec3& point) noexcept + bool SHBox::TestPoint(const SHVec3& point) noexcept { return BoundingBox::Contains(point); } - bool SHBoundingBox::Raycast(const SHRay& ray, float& distance) noexcept + bool SHBox::Raycast(const SHRay& ray, float& distance) noexcept { return BoundingBox::Intersects(ray.position, ray.direction, distance); } - bool SHBoundingBox::Contains(const SHBoundingBox& rhs) const noexcept + bool SHBox::Contains(const SHBox& rhs) const noexcept { return BoundingBox::Contains(rhs); } - float SHBoundingBox::Volume() const noexcept + float SHBox::Volume() const noexcept { return 8.0f * (Extents.x * Extents.y * Extents.z); } - float SHBoundingBox::SurfaceArea() const noexcept + float SHBox::SurfaceArea() const noexcept { return 8.0f * ((Extents.x * Extents.y) + (Extents.x * Extents.z) @@ -209,21 +209,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingBox SHBoundingBox::Combine(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept { - SHBoundingBox result; + SHBox result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingBox::Intersect(const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept + bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingBox SHBoundingBox::BuildFromBoxes(const SHBoundingBox* boxes, size_t numBoxes) noexcept + SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept { - SHBoundingBox result; + SHBox result; for (size_t i = 1; i < numBoxes; ++i) CreateMerged(result, boxes[i - 1], boxes[i]); @@ -231,9 +231,9 @@ namespace SHADE return result; } - SHBoundingBox SHBoundingBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingBox result; + SHBox result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h b/SHADE_Engine/src/Math/Geometry/SHBox.h similarity index 80% rename from SHADE_Engine/src/Math/Geometry/SHBoundingBox.h rename to SHADE_Engine/src/Math/Geometry/SHBox.h index e2757c17..0ea950ab 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingBox.h +++ b/SHADE_Engine/src/Math/Geometry/SHBox.h @@ -22,8 +22,8 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingBox : public SHShape, - private DirectX::BoundingBox + class SH_API SHBox : public SHShape, + private DirectX::BoundingBox { public: /*---------------------------------------------------------------------------------*/ @@ -36,19 +36,19 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - ~SHBoundingBox () override = default; + ~SHBox () override = default; - SHBoundingBox () noexcept; - SHBoundingBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBoundingBox (const SHBoundingBox& rhs) noexcept; - SHBoundingBox (SHBoundingBox&& rhs) noexcept; + SHBox () noexcept; + SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; + SHBox (const SHBox& rhs) noexcept; + SHBox (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingBox& operator= (const SHBoundingBox& rhs) noexcept; - SHBoundingBox& operator= (SHBoundingBox&& rhs) noexcept; + SHBox& operator= (const SHBox& rhs) noexcept; + SHBox& operator= (SHBox&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -79,7 +79,7 @@ namespace SHADE [[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]] bool Contains (const SHBox& rhs) const noexcept; [[nodiscard]] float Volume () const noexcept; [[nodiscard]] float SurfaceArea () const noexcept; @@ -87,10 +87,10 @@ namespace SHADE /* 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; - [[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; + [[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept; + [[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept; + [[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp similarity index 70% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp rename to SHADE_Engine/src/Math/Geometry/SHSphere.cpp index f843a6bb..d310e30e 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp @@ -11,7 +11,7 @@ #include // Primary Header -#include "SHBoundingSphere.h" +#include "SHSphere.h" // Project Headers #include "Math/SHMathHelpers.h" #include "Math/SHRay.h" @@ -24,13 +24,13 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere::SHBoundingSphere() noexcept + SHSphere::SHSphere() noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; } - SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept + SHSphere::SHSphere(const SHVec3& center, float radius) noexcept : RelativeRadius { 1.0f } { type = Type::SPHERE; @@ -39,7 +39,7 @@ namespace SHADE Radius = radius; } - SHBoundingSphere::SHBoundingSphere(const SHBoundingSphere& rhs) noexcept + SHSphere::SHSphere(const SHSphere& rhs) noexcept { if (this == &rhs) return; @@ -51,7 +51,7 @@ namespace SHADE RelativeRadius = rhs.RelativeRadius; } - SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept + SHSphere::SHSphere(SHSphere&& rhs) noexcept { type = Type::SPHERE; @@ -64,7 +64,7 @@ namespace SHADE /* Operator Overload Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere& SHBoundingSphere::operator=(const SHBoundingSphere& rhs) noexcept + SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -80,7 +80,7 @@ namespace SHADE return *this; } - SHBoundingSphere& SHBoundingSphere::operator=(SHBoundingSphere&& rhs) noexcept + SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept { if (rhs.type != Type::SPHERE) { @@ -100,17 +100,17 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - SHVec3 SHBoundingSphere::GetCenter() const noexcept + SHVec3 SHSphere::GetCenter() const noexcept { return Center; } - float SHBoundingSphere::GetWorldRadius() const noexcept + float SHSphere::GetWorldRadius() const noexcept { return Radius; } - float SHBoundingSphere::GetRelativeRadius() const noexcept + float SHSphere::GetRelativeRadius() const noexcept { return RelativeRadius; } @@ -119,17 +119,17 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHBoundingSphere::SetCenter(const SHVec3& center) noexcept + void SHSphere::SetCenter(const SHVec3& center) noexcept { Center = center; } - void SHBoundingSphere::SetWorldRadius(float newWorldRadius) noexcept + void SHSphere::SetWorldRadius(float newWorldRadius) noexcept { Radius = newWorldRadius; } - void SHBoundingSphere::SetRelativeRadius(float newRelativeRadius) noexcept + void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept { RelativeRadius = newRelativeRadius; } @@ -138,27 +138,27 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHBoundingSphere::TestPoint(const SHVec3& point) noexcept + bool SHSphere::TestPoint(const SHVec3& point) noexcept { return BoundingSphere::Contains(point); } - bool SHBoundingSphere::Raycast(const SHRay& ray, float& distance) noexcept + bool SHSphere::Raycast(const SHRay& ray, float& distance) noexcept { return Intersects(ray.position, ray.direction, distance); } - bool SHBoundingSphere::Contains(const SHBoundingSphere& rhs) const noexcept + bool SHSphere::Contains(const SHSphere& rhs) const noexcept { return BoundingSphere::Contains(rhs); } - float SHBoundingSphere::Volume() const noexcept + float SHSphere::Volume() const noexcept { return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); } - float SHBoundingSphere::SurfaceArea() const noexcept + float SHSphere::SurfaceArea() const noexcept { return 4.0f * SHMath::PI * (Radius * Radius); } @@ -167,21 +167,21 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHBoundingSphere SHBoundingSphere::Combine(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept { - SHBoundingSphere result; + SHSphere result; CreateMerged(result, lhs, rhs); return result; } - bool SHBoundingSphere::Intersect(const SHBoundingSphere& lhs, const SHBoundingSphere& rhs) noexcept + bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept { return lhs.Intersects(rhs); } - SHBoundingSphere SHBoundingSphere::BuildFromSpheres(const SHBoundingSphere* spheres, size_t numSpheres) noexcept + SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept { - SHBoundingSphere result; + SHSphere result; for (size_t i = 1; i < numSpheres; ++i) CreateMerged(result, spheres[i - 1], spheres[i]); @@ -189,9 +189,9 @@ namespace SHADE return result; } - SHBoundingSphere SHBoundingSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept + SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept { - SHBoundingSphere result; + SHSphere result; CreateFromPoints(result, numVertices, vertices, stride); return result; } diff --git a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h b/SHADE_Engine/src/Math/Geometry/SHSphere.h similarity index 76% rename from SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h rename to SHADE_Engine/src/Math/Geometry/SHSphere.h index d94722d6..c13076aa 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBoundingSphere.h +++ b/SHADE_Engine/src/Math/Geometry/SHSphere.h @@ -22,27 +22,27 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHBoundingSphere : public SHShape, - private DirectX::BoundingSphere + class SH_API SHSphere : 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; + SHSphere () noexcept; + SHSphere (const SHVec3& center, float radius) noexcept; + SHSphere (const SHSphere& rhs) noexcept; + SHSphere (SHSphere&& rhs) noexcept; - ~SHBoundingSphere () override = default; + ~SHSphere () override = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHBoundingSphere& operator= (const SHBoundingSphere& rhs) noexcept; - SHBoundingSphere& operator= (SHBoundingSphere&& rhs) noexcept; + SHSphere& operator= (const SHSphere& rhs) noexcept; + SHSphere& operator= (SHSphere&& rhs) noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -67,7 +67,7 @@ namespace SHADE [[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]] bool Contains (const SHSphere& rhs) const noexcept; [[nodiscard]] float Volume () const noexcept; [[nodiscard]] float SurfaceArea () const noexcept; @@ -76,10 +76,10 @@ namespace SHADE /* 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; + [[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept; + [[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; + [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 1c8149ad..877d238f 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -95,7 +95,7 @@ namespace SHADE { case SHCollisionShape::Type::BOX: { - auto* box = reinterpret_cast(collisionShape.shape); + auto* box = reinterpret_cast(collisionShape.shape); const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents(); // Recompute world extents based on new scale and fixed relative extents @@ -106,7 +106,7 @@ namespace SHADE } case SHCollisionShape::Type::SPHERE: { - auto* sphere = reinterpret_cast(collisionShape.shape); + auto* sphere = reinterpret_cast(collisionShape.shape); const float RELATIVE_RADIUS = sphere->GetRelativeRadius(); // Recompute world radius based on new scale and fixed radius diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 88dc306f..0781f3cf 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -14,8 +14,8 @@ // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "SHCollisionShape.h" //namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp index 1ea2a7d3..2edca110 100644 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp @@ -13,8 +13,8 @@ // Primary Header #include "SHCollisionShape.h" // Project Headers -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Math/SHMathHelpers.h" #include "Reflection/SHReflectionMetadata.h" #include "SHColliderComponent.h" @@ -37,12 +37,12 @@ namespace SHADE { case Type::BOX: { - shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One }; + shape = new SHBox{ SHVec3::Zero, SHVec3::One }; break; } case Type::SPHERE: { - shape = new SHBoundingSphere{ SHVec3::Zero, 0.5f }; + shape = new SHSphere{ SHVec3::Zero, 0.5f }; break; } default: break; @@ -186,10 +186,10 @@ namespace SHADE type = Type::BOX; delete shape; - shape = new SHBoundingBox{ positionOffset, WORLD_EXTENTS }; + shape = new SHBox{ positionOffset, WORLD_EXTENTS }; } - auto* box = reinterpret_cast(shape); + auto* box = reinterpret_cast(shape); box->SetWorldExtents(WORLD_EXTENTS); box->SetRelativeExtents(halfExtents); } @@ -209,10 +209,10 @@ namespace SHADE type = Type::SPHERE; delete shape; - shape = new SHBoundingSphere{ positionOffset, WORLD_RADIUS }; + shape = new SHSphere{ positionOffset, WORLD_RADIUS }; } - auto* sphere = reinterpret_cast(shape); + auto* sphere = reinterpret_cast(shape); sphere->SetWorldRadius(WORLD_RADIUS); } @@ -255,12 +255,12 @@ namespace SHADE { case Type::BOX: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } case Type::SPHERE: { - reinterpret_cast(shape)->SetCenter(positionOffset); + reinterpret_cast(shape)->SetCenter(positionOffset); break; } default: break; @@ -283,16 +283,16 @@ namespace SHADE { case Type::BOX: { - const auto* RHS_BOX = reinterpret_cast(rhs); + const auto* RHS_BOX = reinterpret_cast(rhs); - shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetWorldExtents() }; + shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() }; break; } case Type::SPHERE: { - const auto* RHS_SPHERE = reinterpret_cast(rhs); + const auto* RHS_SPHERE = reinterpret_cast(rhs); - shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; + shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; break; } default: break; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 0b0dd7a7..346ab4cb 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -309,7 +309,7 @@ namespace SHADE , boxShape.GetRotationOffset() }; - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); rp3dBody->addCollider(newBox, OFFSETS); @@ -317,7 +317,7 @@ namespace SHADE void SHPhysicsObject::syncBoxShape(int index, SHCollisionShape& boxShape) const noexcept { - const auto* BOX = reinterpret_cast(boxShape.GetShape()); + const auto* BOX = reinterpret_cast(boxShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dBox = reinterpret_cast(rp3dCollider->getCollisionShape()); @@ -342,7 +342,7 @@ namespace SHADE , sphereShape.GetRotationOffset() }; - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); rp3dBody->addCollider(newSphere, OFFSETS); @@ -350,7 +350,7 @@ namespace SHADE void SHPhysicsObject::syncSphereShape(int index, SHCollisionShape& sphereShape) const noexcept { - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); + const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); auto* rp3dCollider = rp3dBody->getCollider(index); auto* rp3dSphere = reinterpret_cast(rp3dCollider->getCollisionShape()); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index 72bcd13f..44875289 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -124,8 +124,8 @@ namespace SHADE for (const auto& COLLIDER : COLLIDER_SET) { // Skip inactive colliders - //if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) - // continue; + if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) + continue; for (auto& collisionShape : COLLIDER.GetCollisionShapes()) { @@ -181,7 +181,7 @@ namespace SHADE return; } - auto* BOX = reinterpret_cast(collisionShape.GetShape()); + auto* BOX = reinterpret_cast(collisionShape.GetShape()); // Calculate final position & orientation const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset(); @@ -221,7 +221,7 @@ namespace SHADE return; } - auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); + auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 0a7555b1..5f679655 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -225,44 +225,51 @@ namespace SHADE void SHPhysicsSystem::AddForce(EntityID eid, const SHVec3& force) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); - + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtCenterOfMass(force); } void SHPhysicsSystem::AddForceAtLocalPos(EntityID eid, const SHVec3& force, const SHVec3& localPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos); } void SHPhysicsSystem::AddForceAtWorldPos(EntityID eid, const SHVec3& force, const SHVec3& worldPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos); } void SHPhysicsSystem::AddRelativeForce(EntityID eid, const SHVec3& relativeForce) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce); } void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& localPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos); } void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID eid, const SHVec3& relativeForce, const SHVec3& worldPos) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos); } void SHPhysicsSystem::AddTorque(EntityID eid, const SHVec3& torque) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyWorldTorque(torque); } void SHPhysicsSystem::AddRelativeTorque(EntityID eid, const SHVec3& relativeTorque) noexcept { - auto* physicsObject = objectManager.GetPhysicsObject(eid); + const auto* PHYSICS_OBJECT = objectManager.GetPhysicsObject(eid); + PHYSICS_OBJECT->GetRigidBody()->applyLocalTorque(relativeTorque); } /*-----------------------------------------------------------------------------------*/ @@ -387,7 +394,7 @@ namespace SHADE , SHColliderComponent* colliderComponent ) noexcept { - if (!transformComponent || !SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + if (!transformComponent) return; const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); @@ -461,7 +468,7 @@ namespace SHADE } // Set transform for rendering - if (transformComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) + if (transformComponent) { transformComponent->SetWorldPosition(renderPos); transformComponent->SetWorldOrientation(renderRot); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp index 3376159b..a42da3a6 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp @@ -139,6 +139,14 @@ namespace SHADE physicsSystem->worldState.world->update(static_cast(FIXED_DT)); + // Clear all forces of every body in the scene after each update + for (auto& physicsObject : physicsSystem->objectManager.physicsObjects | std::views::values) + { + auto* rp3dRigidBody = physicsObject.GetRigidBody(); + rp3dRigidBody->resetForce(); + rp3dRigidBody->resetTorque(); + } + accumulatedTime -= FIXED_DT; ++count; } diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 0f8933e2..ce406c77 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -1,8 +1,8 @@ #pragma once #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Math/Geometry/SHBoundingBox.h" -#include "Math/Geometry/SHBoundingSphere.h" +#include "Math/Geometry/SHBox.h" +#include "Math/Geometry/SHSphere.h" #include "Physics/Interface/SHCollisionShape.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" @@ -130,13 +130,13 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - const auto* BOX = reinterpret_cast(rhs.GetShape()); + const auto* BOX = reinterpret_cast(rhs.GetShape()); node[HalfExtents] = BOX->GetRelativeExtents(); } break; case SHCollisionShape::Type::SPHERE: { - const auto* SPHERE = reinterpret_cast(rhs.GetShape()); + const auto* SPHERE = reinterpret_cast(rhs.GetShape()); node[Radius] = SPHERE->GetRelativeRadius(); } break; diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index 0e916b7b..1a53f9e1 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -47,35 +47,35 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 BoxCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeBoundObject().GetCenter()); } void BoxCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeBoundObject().SetCenter(Convert::ToNative(value)); } Vector3 BoxCollider::HalfExtents::get() { - return Convert::ToCLI(getNativeBoundObject().GetWorldExtents()); + return Convert::ToCLI(getNativeBoundObject().GetWorldExtents()); } void BoxCollider::HalfExtents::set(Vector3 value) { - getNativeBoundObject().SetWorldExtents(Convert::ToNative(value)); + getNativeBoundObject().SetWorldExtents(Convert::ToNative(value)); } Vector3 BoxCollider::Min::get() { - return Convert::ToCLI(getNativeBoundObject().GetMin()); + return Convert::ToCLI(getNativeBoundObject().GetMin()); } void BoxCollider::Min::set(Vector3 value) { - getNativeBoundObject().SetMin(Convert::ToNative(value)); + getNativeBoundObject().SetMin(Convert::ToNative(value)); } Vector3 BoxCollider::Max::get() { - return Convert::ToCLI(getNativeBoundObject().GetMax()); + return Convert::ToCLI(getNativeBoundObject().GetMax()); } void BoxCollider::Max::set(Vector3 value) { - getNativeBoundObject().SetMax(Convert::ToNative(value)); + getNativeBoundObject().SetMax(Convert::ToNative(value)); } /*---------------------------------------------------------------------------------*/ @@ -83,11 +83,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool BoxCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } bool BoxCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ @@ -95,19 +95,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 SphereCollider::Center::get() { - return Convert::ToCLI(getNativeBoundObject().GetCenter()); + return Convert::ToCLI(getNativeBoundObject().GetCenter()); } void SphereCollider::Center::set(Vector3 value) { - getNativeBoundObject().SetCenter(Convert::ToNative(value)); + getNativeBoundObject().SetCenter(Convert::ToNative(value)); } float SphereCollider::Radius::get() { - return getNativeBoundObject().GetWorldRadius(); + return getNativeBoundObject().GetWorldRadius(); } void SphereCollider::Radius::set(float value) { - getNativeBoundObject().SetWorldRadius(value); + getNativeBoundObject().SetWorldRadius(value); } /*---------------------------------------------------------------------------------*/ @@ -115,11 +115,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool SphereCollider::TestPoint(Vector3 point) { - return getNativeBoundObject().TestPoint(Convert::ToNative(point)); + return getNativeBoundObject().TestPoint(Convert::ToNative(point)); } bool SphereCollider::Raycast(Ray ray, float maxDistance) { - return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); + return getNativeBoundObject().Raycast(Convert::ToNative(ray), maxDistance); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Components/RigidBody.cxx b/SHADE_Managed/src/Components/RigidBody.cxx index 12861600..a88a2503 100644 --- a/SHADE_Managed/src/Components/RigidBody.cxx +++ b/SHADE_Managed/src/Components/RigidBody.cxx @@ -189,7 +189,11 @@ namespace SHADE { GetNativeComponent()->AddRelativeForceAtWorldPos(Convert::ToNative(relativeForce), Convert::ToNative(worldPos)); } - + + Vector3 RigidBody::GetForce() + { + return Convert::ToCLI(GetNativeComponent()->GetForce()); + } /*---------------------------------------------------------------------------------*/ /* Torque Functions */ /*---------------------------------------------------------------------------------*/ @@ -202,4 +206,10 @@ namespace SHADE { GetNativeComponent()->AddRelativeTorque(Convert::ToNative(relativeTorque)); } + + Vector3 RigidBody::GetTorque() + { + return Convert::ToCLI(GetNativeComponent()->GetTorque()); + } + } \ No newline at end of file diff --git a/SHADE_Managed/src/Components/RigidBody.hxx b/SHADE_Managed/src/Components/RigidBody.hxx index f2953bbd..50147033 100644 --- a/SHADE_Managed/src/Components/RigidBody.hxx +++ b/SHADE_Managed/src/Components/RigidBody.hxx @@ -145,11 +145,15 @@ namespace SHADE void AddRelativeForceAtLocalPos(Vector3 relativeForce, Vector3 localPos); void AddRelativeForceAtWorldPos(Vector3 relativeForce, Vector3 worldPos); + Vector3 GetForce(); + /*-----------------------------------------------------------------------------*/ /* Torque Functions */ /*-----------------------------------------------------------------------------*/ void AddTorque(Vector3 force); void AddRelativeTorque(Vector3 relativeForce); + + Vector3 GetTorque(); }; } \ No newline at end of file -- 2.40.1 From 9e90a78ee43069800fa7bdae9e018befbc168ae3 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Mon, 14 Nov 2022 16:29:53 +0800 Subject: [PATCH 4/5] Added GetComponentsInChildren and GetScriptsInChildren for Scripts and GameObjects --- SHADE_Managed/src/Engine/ECS.cxx | 67 +++++++++++++++++++++++ SHADE_Managed/src/Engine/ECS.hxx | 18 +++++- SHADE_Managed/src/Engine/GameObject.cxx | 15 +++++ SHADE_Managed/src/Engine/GameObject.hxx | 28 ++++++++++ SHADE_Managed/src/Scripts/Script.cxx | 11 ++++ SHADE_Managed/src/Scripts/Script.hxx | 28 ++++++++++ SHADE_Managed/src/Scripts/ScriptStore.cxx | 64 ++++++++++++++++++++++ SHADE_Managed/src/Scripts/ScriptStore.hxx | 23 ++++++++ 8 files changed, 252 insertions(+), 2 deletions(-) diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 80f070e2..76a6a5e2 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -27,6 +27,7 @@ of DigiPen Institute of Technology is prohibited. #include "Scene/SHSceneManager.h" #include "Scene/SHSceneGraph.h" #include "Tools/SHLog.h" +#include "Graphics\MiddleEnd\Interface\SHRenderable.h" // Project Headers #include "Utility/Convert.hxx" #include "Utility/Debug.hxx" @@ -36,6 +37,7 @@ of DigiPen Institute of Technology is prohibited. #include "Components/Camera.hxx" #include "Components/CameraArm.hxx" #include "Components/Light.hxx" +#include "Components\Renderable.hxx" namespace SHADE { @@ -166,6 +168,70 @@ namespace SHADE return T(); } + generic + System::Collections::Generic::IEnumerable^ ECS::GetComponentsInChildren(EntityID entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ECS] Attempted to retrieve Component \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return nullptr; + } + + // Search all elements via a iterative breadth first search + System::Collections::Generic::List^ results; + System::Collections::Generic::Queue^ searchSpace = gcnew System::Collections::Generic::Queue(); + // Start off with direct children + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity); + if (entityNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + } + for (const auto& child : entityNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + // Continue with all subsequent children + while (searchSpace->Count > 0) + { + // Check if this entity has the component we need + Entity curr = searchSpace->Dequeue(); + T component = GetComponent(curr); + if (component != nullptr) + { + // We only construct if we need to + if (results == nullptr) + results = gcnew System::Collections::Generic::List(); + results->Add(component); + } + + // Add children to the queue + SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(curr); + if (sceneGraphNode == nullptr) + { + std::ostringstream oss; + oss << "[ECS_CLI] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + continue; + } + for (const auto& child : sceneGraphNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + } + + // None here + return results; + } + generic T ECS::EnsureComponent(EntityID entity) { @@ -249,6 +315,7 @@ namespace SHADE static ECS::ECS() { componentMap.Add(createComponentSet()); + componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); componentMap.Add(createComponentSet()); diff --git a/SHADE_Managed/src/Engine/ECS.hxx b/SHADE_Managed/src/Engine/ECS.hxx index 0563f678..18acf30d 100644 --- a/SHADE_Managed/src/Engine/ECS.hxx +++ b/SHADE_Managed/src/Engine/ECS.hxx @@ -51,9 +51,9 @@ namespace SHADE /// specified Component. /// generic where T : BaseComponent - static T GetComponent(EntityID entity); + static T GetComponent(EntityID entity); /// - /// Retrieves the first Component from the specified GameObjectt's children that + /// Retrieves the first Component from the specified GameObject's children that /// matches the specified type. /// /// Type of the Component to get. @@ -65,6 +65,20 @@ namespace SHADE generic where T : BaseComponent static T GetComponentInChildren(EntityID entity); /// + /// Retrieves a list of Components from the specified GameObject's children that + /// matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// This does not search the specified entity. + /// + /// Type of the Component to get. + /// Entity object to get the Component from. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + static System::Collections::Generic::IEnumerable^ GetComponentsInChildren(EntityID entity); + /// /// Ensures a Component on the specified Entity. /// /// Type of the Component to ensure. diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 017366fe..200b2079 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -170,6 +170,14 @@ namespace SHADE return ECS::GetComponentInChildren(entity); } + generic + System::Collections::Generic::IEnumerable^ GameObject::GetComponentsInChildren() + { + if (!valid) + throw gcnew System::NullReferenceException(); + return ECS::GetComponentsInChildren(entity); + } + generic T GameObject::EnsureComponent() { @@ -212,6 +220,13 @@ namespace SHADE throw gcnew System::NullReferenceException(); return ScriptStore::GetScriptInChildren(entity); } + generic + System::Collections::Generic::IEnumerable^ GameObject::GetScriptsInChildren() + { + if (!valid) + throw gcnew System::NullReferenceException(); + return ScriptStore::GetScriptsInChildren(entity); + } generic System::Collections::Generic::IEnumerable^ GameObject::GetScripts() diff --git a/SHADE_Managed/src/Engine/GameObject.hxx b/SHADE_Managed/src/Engine/GameObject.hxx index 2e0f360c..64d1b428 100644 --- a/SHADE_Managed/src/Engine/GameObject.hxx +++ b/SHADE_Managed/src/Engine/GameObject.hxx @@ -153,6 +153,7 @@ namespace SHADE /// /// Retrieves the first Component from this GameObject's children that matches /// the specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// Type of the Component to get. /// @@ -162,6 +163,19 @@ namespace SHADE generic where T : BaseComponent T GetComponentInChildren(); /// + /// Retrieves a list of Components from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + System::Collections::Generic::IEnumerable^ GetComponentsInChildren(); + /// /// Ensures a Component on this GameObject. /// /// Type of the Component to ensure. @@ -201,12 +215,26 @@ namespace SHADE /// Retrieves a Script of the specified type from child GameObjects. /// If multiple Scripts of the same specified type are added on the same /// child GameObject, this will retrieve the first one added. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// Type of Script to retrieve. /// Reference to the Script to retrieve. generic where T : ref class, Script T GetScriptInChildren(); /// + /// Retrieves a list of Scripts from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : ref class, Script + System::Collections::Generic::IEnumerable^ GetScriptsInChildren(); + /// /// Retrieves a immutable list of Scripts of the specified type from this /// GameObject. /// diff --git a/SHADE_Managed/src/Scripts/Script.cxx b/SHADE_Managed/src/Scripts/Script.cxx index 017242d6..a2af38a3 100644 --- a/SHADE_Managed/src/Scripts/Script.cxx +++ b/SHADE_Managed/src/Scripts/Script.cxx @@ -42,6 +42,12 @@ namespace SHADE return owner.GetComponentInChildren(); } + generic + System::Collections::Generic::IEnumerable^ Script::GetComponentsInChildren() + { + return owner.GetComponentsInChildren(); + } + generic T Script::EnsureComponent() { @@ -72,6 +78,11 @@ namespace SHADE { return ScriptStore::GetScriptInChildren(owner.GetEntity()); } + generic + System::Collections::Generic::IEnumerable^ Script::GetScriptsInChildren() + { + return ScriptStore::GetScriptsInChildren(owner.GetEntity()); + } generic System::Collections::Generic::IEnumerable^ Script::GetScripts() diff --git a/SHADE_Managed/src/Scripts/Script.hxx b/SHADE_Managed/src/Scripts/Script.hxx index fb564d27..46736245 100644 --- a/SHADE_Managed/src/Scripts/Script.hxx +++ b/SHADE_Managed/src/Scripts/Script.hxx @@ -69,6 +69,7 @@ namespace SHADE /// /// Retrieves the first Component from this GameObject's children that matches /// the specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// /// Type of the Component to get. Must be derived from BaseComponent. @@ -77,6 +78,19 @@ namespace SHADE generic where T : BaseComponent T GetComponentInChildren(); /// + /// Retrieves a list of Components from this GameObject's children that + /// matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : BaseComponent + System::Collections::Generic::IEnumerable^ GetComponentsInChildren(); + /// /// Ensures a Component on the GameObject that this Script belongs to. /// /// @@ -121,6 +135,7 @@ namespace SHADE /// /// Retrieves the first Script from this GameObject's children that matches the /// specified type. + /// Unlike Unity, we do not search this GameObject, only the children. /// /// /// Type of script to get. @@ -130,6 +145,19 @@ namespace SHADE generic where T : ref class, Script T GetScriptInChildren(); /// + /// Retrieves a list of Scripts from this GameObject's children that matches + /// the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetComponentInChildren() instead. + /// Unlike Unity, we do not search this GameObject, only the children. + /// + /// Type of the Component to get. + /// + /// Newly allocated List of components. Will be null if no components are found. + /// + generic where T : ref class, Script + System::Collections::Generic::IEnumerable^ GetScriptsInChildren(); + /// /// Retrieves a immutable list of scripts from the specified Entity that /// matches the specified type. ///
diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 318f5839..2b1540b6 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -211,6 +211,70 @@ namespace SHADE return T(); } + generic + System::Collections::Generic::IEnumerable^ ScriptStore::GetScriptsInChildren(Entity entity) + { + System::Type^ componentType = T::typeid; + + // Check if entity is correct + if (!SHEntityManager::IsValidEID(entity)) + { + std::ostringstream oss; + oss << "[ScriptStore] Attempted to retrieve Script \"" + << Convert::ToNative(componentType->Name) + << "\" from invalid Entity."; + Debug::LogError(oss.str()); + return nullptr; + } + + // Search all elements via a iterative breadth first search + System::Collections::Generic::List^ results; + System::Collections::Generic::Queue^ searchSpace = gcnew System::Collections::Generic::Queue(); + // Start off with direct children + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(entity); + if (entityNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + } + for (const auto& child : entityNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + // Continue with all subsequent children + while (searchSpace->Count > 0) + { + // Check if this entity has the component we need + Entity curr = searchSpace->Dequeue(); + T script = GetScript(curr); + if (script != nullptr) + { + // We only construct if we need to + if (results == nullptr) + results = gcnew System::Collections::Generic::List(); + results->Add(script); + } + + // Add children to the queue + SHSceneNode* sceneGraphNode = SHSceneManager::GetCurrentSceneGraph().GetNode(curr); + if (sceneGraphNode == nullptr) + { + std::ostringstream oss; + oss << "[ScriptStore] Failed to retrieve SceneGraphNode of entity #" << entity << ". This should not happen!"; + SHLog::Warning(oss.str()); + continue; + } + for (const auto& child : sceneGraphNode->GetChildren()) + { + searchSpace->Enqueue(child->GetEntityID()); + } + } + + // None here + return results; + } + generic System::Collections::Generic::IEnumerable^ ScriptStore::GetScripts(Entity entity) { diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index 62e3003a..78f8c787 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -137,6 +137,29 @@ namespace SHADE generic where T : ref class, Script static T GetScriptInChildren(Entity entity); /// + /// Retrieves the list of Scripts from the specified Entity and the Entity's + /// children that matches the specified type. + /// This function performs allocations. If expecting only 1 component, use + /// GetScriptInChildren() instead. + /// This does not search the specified entity. + /// + /// + /// Type of script to get. + /// This needs to be a default constructable Script. + /// + /// + /// The entity which the script to retrieve is attached. + /// + /// + /// Reference to the script. This can be null if no script of the specified + /// type is attached. + /// + /// + /// If the specified Entity is invalid. + /// + generic where T : ref class, Script + static System::Collections::Generic::IEnumerable^ GetScriptsInChildren(Entity entity); + /// /// Retrieves a immutable list of scripts from the specified Entity that /// matches the specified type. ///
-- 2.40.1 From 9e8674859c768fb08c9fedfd53709c493df65a3a Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Mon, 14 Nov 2022 17:05:54 +0800 Subject: [PATCH 5/5] Fixed script serialization for objects with no default values set --- .../MiddleEnd/Interface/SHRenderable.cpp | 7 +++- .../src/Serialization/SHYAMLConverters.h | 10 ++++- .../Serialisation/SerialisationUtilities.h++ | 42 ++++++++++++++++++- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 57762324..c5511606 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -34,8 +34,11 @@ namespace SHADE void SHRenderable::OnDestroy() { // Remove from SuperBatch - Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); - superBatch->Remove(this); + if (sharedMaterial) + { + Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + superBatch->Remove(this); + } // Free resources if (material) diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 0f8933e2..6df65bc3 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -288,7 +288,15 @@ namespace YAML { YAML::Node node; node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMesh()).value_or(0); - node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMaterial()->GetBaseMaterial()).value_or(0); + auto mat = rhs.GetMaterial(); + if (mat) + { + node[MAT_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMaterial()->GetBaseMaterial()).value_or(0); + } + else + { + node[MAT_YAML_TAG.data()] = 0; + } return node; } static bool decode(YAML::Node const& node, SHRenderable& rhs) diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ index 3e756ce4..dde6705a 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ @@ -28,7 +28,47 @@ namespace SHADE template bool SerialisationUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Node& fieldNode) { - return varInsertYamlInternal(fieldInfo->GetValue(object), fieldNode); + // Handle null objects + System::Object^ fieldObject = fieldInfo->GetValue(object); + if (fieldObject == nullptr) + { + // Default construct if null + if (fieldInfo->FieldType == FieldType::typeid) + { + if constexpr (std::is_same_v) + { + fieldNode = 0; + } + else if constexpr (std::is_same_v) + { + fieldNode = ""; + } + else if constexpr (std::is_same_v) + { + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + } + else if constexpr (std::is_same_v) + { + fieldNode.SetStyle(YAML::EmitterStyle::Flow); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + fieldNode.push_back(0.0f); + } + else if constexpr (std::is_same_v) + { + fieldNode = MAX_EID; + } + else + { + fieldNode = FieldType(); + } + return true; + } + return false; + } + return varInsertYamlInternal(fieldObject, fieldNode); } template bool SerialisationUtilities::varInsertYamlInternal(System::Object^ object, YAML::Node& fieldNode) -- 2.40.1