SP3-2 Bugfixes #202

Merged
direnbharwani merged 4 commits from SP3-2-Physics into main 2022-11-14 16:07:51 +08:00
7 changed files with 129 additions and 79 deletions
Showing only changes of commit fe1b9d14f5 - Show all commits

View File

@ -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
Scripts: ~

View File

@ -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.

View File

@ -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 */

View File

@ -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<SHColliderComponent>();
for (const auto& COLLIDER : COLLIDER_SET)
{
// Skip inactive colliders
//if (!SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(COLLIDER.GetEID()))
// continue;
for (auto& collisionShape : COLLIDER.GetCollisionShapes())
{
switch (collisionShape.GetType())

View File

@ -387,7 +387,7 @@ namespace SHADE
, SHColliderComponent* colliderComponent
) noexcept
{
if (!transformComponent)
if (!transformComponent || !SHSceneManager::CheckNodeAndComponentsActive<SHTransformComponent>(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<SHRigidBodyComponent>(physicsObject.entityID))
{
rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT;
}
if (colliderComponent)
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(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<SHRigidBodyComponent>(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<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = CURRENT_TF.getPosition();
colliderComponent->orientation = CURRENT_TF.getOrientation();
}
// Set transform for rendering
if (transformComponent)
if (transformComponent && SHSceneManager::CheckNodeAndComponentsActive<SHTransformComponent>(physicsObject.entityID))
{
transformComponent->SetWorldPosition(renderPos);
transformComponent->SetWorldOrientation(renderRot);

View File

@ -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

View File

@ -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<SHPhysicsSystem*>(GetSystem());
#ifdef SHEDITOR
auto* editor = SHSystemManager::GetSystem<SHEditor>();
// 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<SHRigidBodyComponent>();
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
for (auto& rigidBodyComponent : rigidBodyDense)
{
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
if (TRANSFORM && TRANSFORM->HasChanged())
{
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
}
}
for (auto& colliderComponent : colliderDense)
{
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(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<SHEditor>();
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<SHRigidBodyComponent>();
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
#endif
for (auto& rigidBodyComponent : rigidBodyDense)
{
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
if (TRANSFORM && TRANSFORM->HasChanged())
{
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
}
}
for (auto& colliderComponent : colliderDense)
{
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(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<SHRigidBodyComponent>(eid))
return;
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(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<SHColliderComponent>(eid);
if (!COLLIDER)
return;
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(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<SHPhysicsSystem*>(GetSystem());
const int NUM_SHAPES = static_cast<int>(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<SHTransformComponent>(eid);