From 374f1a961dc3a2e6ad4ef28be6aa7581a74439b6 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 1 Oct 2022 16:50:50 +0800 Subject: [PATCH] Integrated rigidbodies into physics system --- SHADE_Application/src/Scenes/SBTestScene.cpp | 122 ++++++++------- .../Components/SHRigidBodyComponent.cpp | 3 + SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 38 ++++- SHADE_Engine/src/Physics/SHPhysicsObject.h | 12 +- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 148 +++++++++--------- SHADE_Engine/src/Physics/SHPhysicsSystem.h | 5 +- 6 files changed, 180 insertions(+), 148 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 556ff3ac..ce52be95 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -10,6 +10,7 @@ #include "Scripting/SHScriptEngine.h" #include "Math/Transform/SHTransformComponent.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" +#include "Physics/Components/SHRigidBodyComponent.h" #include "Assets/SHAssetManager.h" @@ -75,83 +76,86 @@ namespace Sandbox customMat->SetProperty("data.alpha", 0.1f); // Create Stress Test Objects - static const SHVec3 TEST_OBJ_SCALE = { 0.05f, 0.05f, 0.05f }; - constexpr int NUM_ROWS = 100; - constexpr int NUM_COLS = 100; - static const SHVec3 TEST_OBJ_SPACING = { 0.05f, 0.05f, 0.05f }; - static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; + //static const SHVec3 TEST_OBJ_SCALE = { 0.05f, 0.05f, 0.05f }; + //constexpr int NUM_ROWS = 100; + //constexpr int NUM_COLS = 100; + //static const SHVec3 TEST_OBJ_SPACING = { 0.05f, 0.05f, 0.05f }; + //static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; - for (int y = 0; y < NUM_ROWS; ++y) - for (int x = 0; x < NUM_COLS; ++x) - { - auto entity = SHEntityManager::CreateEntity(); - auto& renderable = *SHComponentManager::GetComponent_s(entity); - auto& transform = *SHComponentManager::GetComponent_s(entity); + //for (int y = 0; y < NUM_ROWS; ++y) + // for (int x = 0; x < NUM_COLS; ++x) + // { + // auto entity = SHEntityManager::CreateEntity(); + // auto& renderable = *SHComponentManager::GetComponent_s(entity); + // auto& transform = *SHComponentManager::GetComponent_s(entity); - renderable.Mesh = handles.front(); - renderable.SetMaterial(customMat); + // //renderable.Mesh = handles.front(); + // renderable.Mesh = CUBE_MESH; + // renderable.SetMaterial(customMat); - if (y == 50) - renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f)); + // if (y == 50) + // renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f)); - //Set initial positions - transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ - x * TEST_OBJ_SPACING.x, - y * TEST_OBJ_SPACING.y, - 0.0f - }); - //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); - //transform.SetWorldRotation(3.14159265f * 1.5f, -3.14159265f / 2.0f, 0.0f); - transform.SetLocalScale(TEST_OBJ_SCALE); + // //Set initial positions + // transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ + // x * TEST_OBJ_SPACING.x, + // y * TEST_OBJ_SPACING.y, + // 0.0f + // }); + // //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); + // //transform.SetWorldRotation(3.14159265f * 1.5f, -3.14159265f / 2.0f, 0.0f); + // transform.SetLocalScale(TEST_OBJ_SCALE); - stressTestObjects.emplace_back(entity); - } + // stressTestObjects.emplace_back(entity); + // } - auto raccoonSpin = SHEntityManager::CreateEntity(); - auto& renderable = *SHComponentManager::GetComponent_s(raccoonSpin); - auto& transform = *SHComponentManager::GetComponent_s(raccoonSpin); + //auto raccoonSpin = SHEntityManager::CreateEntity(); + //auto& renderable = *SHComponentManager::GetComponent_s(raccoonSpin); + //auto& transform = *SHComponentManager::GetComponent_s(raccoonSpin); - renderable.Mesh = 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); - renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); - - transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f }); - transform.SetLocalScale({ 5.0f, 5.0f, 5.0f }); - - //auto entity = SHEntityManager::CreateEntity(); - //auto& renderable = *SHComponentManager::GetComponent_s(entity); - //auto& transform = *SHComponentManager::GetComponent_s(entity); - - //renderable.Mesh = handles.back(); + //renderable.Mesh = 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); + //renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); - //transform.SetLocalScale(TEST_OBJ_SCALE); - //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); + //transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f }); + //transform.SetLocalScale({ 5.0f, 5.0f, 5.0f }); + + auto entity = SHEntityManager::CreateEntity(); + auto& renderable = *SHComponentManager::GetComponent_s(entity); + auto& transform = *SHComponentManager::GetComponent_s(entity); + auto& rb = *SHComponentManager::GetComponent_s(entity); + + renderable.Mesh = CUBE_MESH; + renderable.SetMaterial(customMat); + + transform.SetLocalScale(SHVec3::One * 0.25f); + transform.SetWorldPosition({0.0f, 2.0f, -1.0f}); // Create blank entity with a script //testObj = SHADE::SHEntityManager::CreateEntity(); - //auto& testObjRenderable = *SHComponentManager::GetComponent_s(testObj); + //auto& testObjRenderable = *SHComponentManager::GetComponent(testObj); //testObjRenderable.Mesh = CUBE_MESH; //testObjRenderable.SetMaterial(matInst); - SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); - scriptEngine->AddScript(raccoonSpin, "RaccoonSpin"); - auto raccoonShowcase = SHEntityManager::CreateEntity(); - auto& renderableShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); - auto& transformShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); + //SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); + //scriptEngine->AddScript(raccoonSpin, "RaccoonSpin"); - renderableShowcase.Mesh = 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); - renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); + //auto raccoonShowcase = SHEntityManager::CreateEntity(); + //auto& renderableShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); + //auto& transformShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); - transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); - transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); - scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase"); + //renderableShowcase.Mesh = 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); + //renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 1); + + //transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); + //transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); + //scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase"); } void SBTestScene::Update(float dt) diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 04cb00dd..e2cd1e4b 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -37,6 +37,9 @@ namespace SHADE // Set default flags: Gravity & Sleeping enabled flags |= 1U << 0; flags |= 1U << 1; + + // Set all dirty flags to true + dirtyFlags = 1023; } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 325d860f..f489624d 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -79,14 +79,40 @@ namespace SHADE } /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ + /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHPhysicsObject::SetPosition(const SHVec3& position) const noexcept + { + const rp3d::Vector3 RP3D_POS { position.x, position.y, position.z }; - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ + rp3d::Transform rp3dTF; + rp3dTF.setPosition(RP3D_POS); + rp3dTF.setOrientation(rp3dBody->getTransform().getOrientation()); + + rp3dBody->setTransform(rp3dTF); + } + + void SHPhysicsObject::SetOrientation(const SHQuaternion& orientation) const noexcept + { + const rp3d::Quaternion RP3D_ORIENTATION { orientation.x, orientation.y, orientation.z, orientation.w }; + + rp3d::Transform rp3dTF; + rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); + rp3dTF.setOrientation(RP3D_ORIENTATION); + + rp3dBody->setTransform(rp3dTF); + } + + void SHPhysicsObject::SetRotation(const SHVec3& rotation) const noexcept + { + const rp3d::Quaternion RP3D_ORIENTATION = rp3d::Quaternion::fromEulerAngles( rotation.x, rotation.y, rotation.z ); + + rp3d::Transform rp3dTF; + rp3dTF.setPosition(rp3dBody->getTransform().getPosition()); + rp3dTF.setOrientation(RP3D_ORIENTATION); + + rp3dBody->setTransform(rp3dTF); + } - - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h index e0f0f38f..cd9be57b 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -55,14 +55,18 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] virtual SHVec3 GetPosition () const noexcept; - [[nodiscard]] virtual SHQuaternion GetOrientation () const noexcept; - [[nodiscard]] virtual SHVec3 GetRotation () const noexcept; + [[nodiscard]] SHVec3 GetPosition () const noexcept; + [[nodiscard]] SHQuaternion GetOrientation () const noexcept; + [[nodiscard]] SHVec3 GetRotation () const noexcept; /*---------------------------------------------------------------------------------*/ - /* Function Members */ + /* Setter Functions */ /*---------------------------------------------------------------------------------*/ + void SetPosition (const SHVec3& position) const noexcept; + void SetOrientation (const SHQuaternion& orientation) const noexcept; + void SetRotation (const SHVec3& rotation) const noexcept; + private: /*---------------------------------------------------------------------------------*/ /* Data Members */ diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 9be8a5ef..59d915f9 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -27,7 +27,7 @@ namespace SHADE SHPhysicsSystem::SHPhysicsSystem() : interpolationFactor { 0.0 } - , fixedDT { 1.0 / 60.0 } + , fixedDT { 60.0 } , world { nullptr } {} @@ -204,7 +204,11 @@ namespace SHADE // Check if entity is already a physics object auto* physicsObject = GetPhysicsObject(entityID); if (!physicsObject) + { physicsObject = &(map.emplace(entityID, SHPhysicsObject{}).first->second); + physicsObject->entityID = entityID; + } + // Get entity transform auto const* SHADE_TF = SHComponentManager::GetComponent_s(entityID); @@ -292,9 +296,23 @@ namespace SHADE { auto* system = reinterpret_cast(GetSystem()); + // Get dense arrays + auto& rbDense = SHComponentManager::GetDense(); + auto& cDense = SHComponentManager::GetDense(); + // Update bodies and colliders if component is dirty - const auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - system->SyncComponents(sceneGraph); + system->SyncRigidBodyComponents(rbDense); + + // Sync transforms + for (auto& physicsObject : system->map | std::views::values) + { + const auto* TF = SHComponentManager::GetComponent(physicsObject.entityID); + if (TF->HasChanged()) + { + physicsObject.SetPosition(TF->GetWorldPosition()); + physicsObject.SetRotation(TF->GetWorldRotation()); + } + } } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -322,8 +340,7 @@ namespace SHADE auto* system = reinterpret_cast(GetSystem()); // Interpolate transforms for rendering - const auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - system->SyncTransforms(sceneGraph); + system->SyncTransforms(); // TODO(Diren): Handle trigger messages for scripting } @@ -344,89 +361,67 @@ namespace SHADE return &(it->second); } - void SHPhysicsSystem::SyncComponents(const SHSceneGraph& sceneGraph) noexcept + void SHPhysicsSystem::SyncRigidBodyComponents(std::vector& denseArray) noexcept { - static const auto SYNC_COMPONENTS = [&](SHSceneNode* node) + if (denseArray.empty()) + return; + + for (auto& comp : denseArray) { - const EntityID ENTITY_ID = node->GetEntityID(); + const EntityID ENTITY_ID = comp.GetEID(); - // Get physics object + // Get physicsObject auto const* physicsObject = GetPhysicsObject(ENTITY_ID); - if (!physicsObject) - return; - const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); - const bool NODE_ACTIVE = node->IsActive(); + const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive(); + // TODO(Diren): Check if active in hierarchy + const bool COMPONENT_ACTIVE = comp.isActive; - // Sync rigid body - if (physicsObject->isRigidBody) + if (RP3D_ACTIVE != COMPONENT_ACTIVE) + physicsObject->rp3dBody->setIsActive(COMPONENT_ACTIVE); + + if (!COMPONENT_ACTIVE) + continue; + + if (comp.dirtyFlags > 0) { - auto* rbComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - if (rbComponent->dirtyFlags > 0) - { - SyncRB(physicsObject, rbComponent); - rbComponent->dirtyFlags = 0; - } - - - // Sync active states - const bool SHADE_ACTIVE = NODE_ACTIVE && rbComponent->isActive; - if (SHADE_ACTIVE != RP3D_ACTIVE) - physicsObject->rp3dBody->setIsActive(SHADE_ACTIVE); + SyncRB(physicsObject, &comp); + comp.dirtyFlags = 0; } - - // Sync colliders - if (physicsObject->hasColliders) - { - auto const* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - - } - - // Sync transforms - auto const* tfComponent = SHComponentManager::GetComponent(ENTITY_ID); - if (tfComponent->HasChanged()) - { - const SHVec3& SHADE_POS = tfComponent->GetWorldPosition(); - const SHVec3& SHADE_ROT = tfComponent->GetWorldRotation(); - - const rp3d::Vector3 RP3D_POS { SHADE_POS.x, SHADE_POS.y, SHADE_POS.z }; - const rp3d::Quaternion RP3D_ROT = rp3d::Quaternion::fromEulerAngles(SHADE_ROT.x, SHADE_ROT.y, SHADE_ROT.z); - - physicsObject->rp3dBody->setTransform(rp3d::Transform{ RP3D_POS, RP3D_ROT }); - } - }; - - sceneGraph.Traverse(SYNC_COMPONENTS); + } } - void SHPhysicsSystem::SyncTransforms(const SHSceneGraph& sceneGraph) noexcept + void SHPhysicsSystem::SyncTransforms() noexcept { - static const auto SYNC_TRANSFORMS = [&](SHSceneNode* node) + for (auto& pair : map) { - const EntityID ENTITY_ID = node->GetEntityID(); - - // Get physics object - auto* physicsObject = GetPhysicsObject(ENTITY_ID); - if (!physicsObject) - return; - - auto* tfComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + const EntityID ENTITY_ID = pair.first; + SHPhysicsObject& physicsObject = pair.second; rp3d::Vector3 rp3dPos; rp3d::Quaternion rp3dRot; - const rp3d::Transform CURRENT_TF = physicsObject->rp3dBody->getTransform(); + const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); // Check if transform should be interpolated - auto const* rbComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - if (rbComponent && rbComponent->IsInterpolating()) + + if (physicsObject.isRigidBody) { - const rp3d::Transform PREV_TF = physicsObject->prevTransform; - const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); + auto const* rbComponent = SHComponentManager::GetComponent(ENTITY_ID); + if (rbComponent->IsInterpolating()) + { + 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(); + rp3dPos = INTERPOLATED_TF.getPosition(); + rp3dRot = INTERPOLATED_TF.getOrientation(); + } + else + { + rp3dPos = CURRENT_TF.getPosition(); + rp3dRot = CURRENT_TF.getOrientation(); + } } else { @@ -438,14 +433,13 @@ namespace SHADE const SHVec3 SHADE_POS = SHVec3{ rp3dPos.x, rp3dPos.y, rp3dPos.z }; const SHVec3 SHADE_ROT = SHQuaternion{ rp3dRot.x, rp3dRot.y, rp3dRot.z, rp3dRot.w }.ToEuler(); + auto* tfComponent = SHComponentManager::GetComponent(ENTITY_ID); tfComponent->SetWorldPosition(SHADE_POS); tfComponent->SetWorldRotation(SHADE_ROT); // Cache transforms - physicsObject->prevTransform = CURRENT_TF; - }; - - sceneGraph.Traverse(SYNC_TRANSFORMS); + physicsObject.prevTransform = CURRENT_TF; + } } void SHPhysicsSystem::SyncRB(SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept @@ -527,9 +521,9 @@ namespace SHADE { const rp3d::Vector3 CONSTRAINTS { - rbFlags & 1U << 2 ? 1.0f : 0.0f, - rbFlags & 1U << 3 ? 1.0f : 0.0f, - rbFlags & 1U << 4 ? 1.0f : 0.0f + rbFlags & 1U << 2 ? 0.0f : 1.0f, + rbFlags & 1U << 3 ? 0.0f : 1.0f, + rbFlags & 1U << 4 ? 0.0f : 1.0f }; @@ -540,9 +534,9 @@ namespace SHADE { const rp3d::Vector3 CONSTRAINTS { - rbFlags & 1U << 5 ? 1.0f : 0.0f, - rbFlags & 1U << 6 ? 1.0f : 0.0f, - rbFlags & 1U << 7 ? 1.0f : 0.0f + rbFlags & 1U << 5 ? 0.0f : 1.0f, + rbFlags & 1U << 6 ? 0.0f : 1.0f, + rbFlags & 1U << 7 ? 0.0f : 1.0f }; rp3dRigidBody->setAngularLockAxisFactor(CONSTRAINTS); diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index af615f35..dbf0a597 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -183,8 +183,9 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; - void SyncComponents (const SHSceneGraph& sceneGraph) noexcept; - void SyncTransforms (const SHSceneGraph& sceneGraph) noexcept; + void SyncRigidBodyComponents (std::vector& denseArray) noexcept; + void SyncColliderComponents (std::vector& denseArray) noexcept; + void SyncTransforms () noexcept; // TODO(Diren): Trigger handling static void SyncRB (SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept;