Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Dependencies/assimp/code/Common/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ aiScene::~aiScene() {
delete mCameras[a];
}
}
delete[] mCameras;
delete[] mCameras;if (OvPhysics::Core::PhysicsEngine::IsDispatching())
return;

aiMetadata::Dealloc(mMetaData);

Expand Down
1 change: 1 addition & 0 deletions Sources/OvCore/include/OvCore/ECS/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ namespace OvCore::ECS

void RecursiveActiveUpdate();
void RecursiveWasActiveUpdate();
void ReleaseRemovedComponent(std::shared_ptr<Components::AComponent> p_component);

public:
/* Some events that are triggered when an action occur on the actor instance */
Expand Down
1 change: 1 addition & 0 deletions Sources/OvCore/include/OvCore/ECS/Actor.inl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace OvCore::ECS
{
ComponentRemovedEvent.Invoke(*result.get());
m_components.erase(it);
ReleaseRemovedComponent(std::move(result));
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ namespace OvCore::ECS::Components
* @param p_activationState
*/
void SetActivationState(OvPhysics::Entities::PhysicalObject::EActivationState p_activationState);

/** the component(s) stops emitting events but stays alive */
void MarkForRemoval() { m_pendingRemoval = true; }

/**
* Serialize the component
Expand Down Expand Up @@ -204,6 +207,7 @@ namespace OvCore::ECS::Components

protected:
std::unique_ptr<OvPhysics::Entities::PhysicalObject> m_physicalObject;
bool m_pendingRemoval = false;
};

template<>
Expand Down
16 changes: 16 additions & 0 deletions Sources/OvCore/src/OvCore/ECS/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <OvCore/ECS/Components/CReflectionProbe.h>
#include <OvCore/ECS/Components/CSkinnedMeshRenderer.h>
#include <OvCore/ECS/Components/CSpotLight.h>
#include <OvCore/ECS/Components/CPhysicalObject.h>
#include <OvPhysics/Core/PhysicsEngine.h>

#include <iostream>

Expand Down Expand Up @@ -110,6 +112,18 @@ void OvCore::ECS::Actor::SetActive(bool p_active)
}
}

void OvCore::ECS::Actor::ReleaseRemovedComponent(std::shared_ptr<Components::AComponent> p_component)
{
if (auto* physical = dynamic_cast<Components::CPhysicalObject*>(p_component.get()))
{
physical->MarkForRemoval();

if (OvPhysics::Core::PhysicsEngine::IsDispatching())
OvPhysics::Core::PhysicsEngine::DeferDestruction(std::move(p_component));
}
// otherwise p_component dies here, as before
}

bool OvCore::ECS::Actor::IsSelfActive() const
{
return m_active;
Expand Down Expand Up @@ -390,8 +404,10 @@ bool OvCore::ECS::Actor::RemoveComponent(OvCore::ECS::Components::AComponent& p_
{
if (it->get() == &p_component)
{
auto removed = *it;
ComponentRemovedEvent.Invoke(p_component);
m_components.erase(it);
ReleaseRemovedComponent(std::move(removed));
return true;
}
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,20 +200,23 @@ void OvCore::ECS::Components::CPhysicalObject::BindListener()
/* Collision Events */
m_physicalObject->CollisionStartEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

CollisionEnterEvent.Invoke(otherObject);
owner.OnCollisionEnter(otherObject);
};
m_physicalObject->CollisionStayEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

CollisionStayEvent.Invoke(otherObject);
owner.OnCollisionStay(otherObject);
};
m_physicalObject->CollisionStopEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

CollisionExitEvent.Invoke(otherObject);
Expand All @@ -223,20 +226,23 @@ void OvCore::ECS::Components::CPhysicalObject::BindListener()
/* Trigger Events */
m_physicalObject->TriggerStartEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

TriggerEnterEvent.Invoke(otherObject);
owner.OnTriggerEnter(otherObject);
};
m_physicalObject->TriggerStayEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

TriggerStayEvent.Invoke(otherObject);
owner.OnTriggerStay(otherObject);
};
m_physicalObject->TriggerStopEvent += [this](OvPhysics::Entities::PhysicalObject& otherPhysicalObject)
{
if (m_pendingRemoval) return;
auto& otherObject = otherPhysicalObject.GetUserData<std::reference_wrapper<CPhysicalObject>>().get();

TriggerExitEvent.Invoke(otherObject);
Expand Down
19 changes: 14 additions & 5 deletions Sources/OvCore/src/OvCore/SceneSystem/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <OvCore/SceneSystem/PrefabOperations.h>
#include <OvCore/SceneSystem/Scene.h>
#include <OvTools/Utils/PathParser.h>
#include <OvPhysics/Core/PhysicsEngine.h>

OvCore::SceneSystem::Scene::Scene(
const std::filesystem::path& p_projectAssetsPath,
Expand All @@ -36,7 +37,7 @@ OvCore::SceneSystem::Scene::Scene(
OvCore::SceneSystem::Scene::~Scene()
{
std::for_each(m_actors.begin(), m_actors.end(), [](OvCore::ECS::Actor* element)
{
{
delete element;
});

Expand Down Expand Up @@ -81,7 +82,7 @@ void OvCore::SceneSystem::Scene::AddDefaultSkysphere()

auto skysphereMaterial = Global::ServiceLocator::Get<ResourceManagement::MaterialManager>().GetResource(":Materials\\Skysphere.ovmat");
auto sphereModel = Global::ServiceLocator::Get<ResourceManagement::ModelManager>().GetResource(":Models\\Sphere.fbx");

if (skysphereMaterial)
{
materialRenderer.SetMaterialAtIndex(0, *skysphereMaterial);
Expand Down Expand Up @@ -315,6 +316,12 @@ bool OvCore::SceneSystem::Scene::DestroyActor(ECS::Actor& p_target)

if (found != m_actors.end())
{
if (OvPhysics::Core::PhysicsEngine::IsDispatching())
{
// deleting now wood destroy physical components inside Bullet step.
p_target.MarkAsDestroy();
return true;
}
delete *found;
m_actors.erase(found);
return true;
Expand All @@ -337,8 +344,10 @@ void OvCore::SceneSystem::Scene::MoveActorToBack(ECS::Actor& p_actor)

void OvCore::SceneSystem::Scene::CollectGarbages()
{
if (OvPhysics::Core::PhysicsEngine::IsDispatching())
return;
m_actors.erase(std::remove_if(m_actors.begin(), m_actors.end(), [this](ECS::Actor* element)
{
{
bool isGarbage = !element->IsAlive();
if (isGarbage)
{
Expand All @@ -351,7 +360,7 @@ void OvCore::SceneSystem::Scene::CollectGarbages()
OvCore::ECS::Actor* OvCore::SceneSystem::Scene::FindActorByName(const std::string& p_name) const
{
auto result = std::find_if(m_actors.begin(), m_actors.end(), [p_name](OvCore::ECS::Actor* element)
{
{
return element->GetName() == p_name;
});

Expand Down Expand Up @@ -526,4 +535,4 @@ void OvCore::SceneSystem::Scene::OnDeserialize(tinyxml2::XMLDocument & p_doc, ti
}
}
}
}
}
2 changes: 1 addition & 1 deletion Sources/OvEditor/src/OvEditor/Panels/Inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void OvEditor::Panels::Inspector::FocusActor(Actor& p_target)

m_componentAddedListener = m_targetActor->ComponentAddedEvent += [this] (auto&) { EDITOR_EXEC(DelayAction([this] { Refresh(); })); };
m_behaviourAddedListener = m_targetActor->BehaviourAddedEvent += [this](auto&) { EDITOR_EXEC(DelayAction([this] { Refresh(); })); };
m_componentRemovedListener = m_targetActor->ComponentRemovedEvent += [this](auto&) { EDITOR_EXEC(DelayAction([this] { Refresh(); })); };
m_componentRemovedListener = m_targetActor->ComponentRemovedEvent += [this](auto&) { EDITOR_EXEC(DelayAction([this] { Refresh(); }, 0)); };
m_behaviourRemovedListener = m_targetActor->BehaviourRemovedEvent += [this](auto&) { EDITOR_EXEC(DelayAction([this] { Refresh(); })); };

_Populate();
Expand Down
9 changes: 9 additions & 0 deletions Sources/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <map>
#include <optional>
#include <vector>
#include <memory>

#include <OvPhysics/Entities/PhysicalObject.h>
#include <OvPhysics/Entities/RaycastHit.h>
Expand Down Expand Up @@ -68,6 +69,11 @@ namespace OvPhysics::Core
* Returns the current world gravity
*/
OvMaths::FVector3 GetGravity() const;
/** True while the simulation step and collision stop dispatch are running */
static bool IsDispatching();

/** keeps an object alive until the current physics update finished */
static void DeferDestruction(std::shared_ptr<void> p_object);

private:
void PreUpdate();
Expand Down Expand Up @@ -96,6 +102,9 @@ namespace OvPhysics::Core
std::unique_ptr<btConstraintSolver> m_solver;

static std::map<std::pair<Entities::PhysicalObject*, Entities::PhysicalObject*>, bool> m_collisionEvents;
static void FlushGraveyard();
static bool s_dispatching;
static std::vector<std::shared_ptr<void>> s_graveyard;
std::vector<std::reference_wrapper<Entities::PhysicalObject>> m_physicalObjects;
};
}
42 changes: 37 additions & 5 deletions Sources/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ using namespace OvPhysics::Tools;
using namespace OvPhysics::Entities;

std::map<std::pair<PhysicalObject*, PhysicalObject*>, bool> OvPhysics::Core::PhysicsEngine::m_collisionEvents;
bool OvPhysics::Core::PhysicsEngine::s_dispatching = false;
std::vector<std::shared_ptr<void>> OvPhysics::Core::PhysicsEngine::s_graveyard;

OvPhysics::Core::PhysicsEngine::PhysicsEngine(const Settings::PhysicsSettings & p_settings)
{
Expand All @@ -37,6 +39,8 @@ OvPhysics::Core::PhysicsEngine::PhysicsEngine(const Settings::PhysicsSettings &

OvPhysics::Core::PhysicsEngine::~PhysicsEngine()
{
// release physical object(s) whose destruction was deferred during the last update, while the engine and the physics event(s) are still alive.
FlushGraveyard();

}

Expand All @@ -56,15 +60,43 @@ void OvPhysics::Core::PhysicsEngine::PostUpdate()

bool OvPhysics::Core::PhysicsEngine::Update(float p_deltaTime)
{
PreUpdate();
FlushGraveyard(); //release objects removed during the previous update...

if (m_world->stepSimulation(p_deltaTime, 10))
bool simulated = false;
{
PostUpdate();
return true;
struct DispatchScope
{
DispatchScope() { s_dispatching = true; }
~DispatchScope() { s_dispatching = false; }
} scope;

PreUpdate();

if (m_world->stepSimulation(p_deltaTime, 10))
{
PostUpdate();
simulated = true;
}
}

return false;
return simulated; // no flush here
}

bool OvPhysics::Core::PhysicsEngine::IsDispatching()
{
return s_dispatching;
}

void OvPhysics::Core::PhysicsEngine::DeferDestruction(std::shared_ptr<void> p_object)
{
s_graveyard.push_back(std::move(p_object));
}

void OvPhysics::Core::PhysicsEngine::FlushGraveyard()
{
auto dead = std::move(s_graveyard);
s_graveyard.clear();
dead.clear();
}

std::optional<RaycastHit> OvPhysics::Core::PhysicsEngine::Raycast(OvMaths::FVector3 p_origin, OvMaths::FVector3 p_direction, float p_distance)
Expand Down