Physics2D: Fix the way newly physics entities are setup
This commit is contained in:
parent
3e99ce6be5
commit
883b54e6d3
|
|
@ -98,6 +98,8 @@ namespace Nz
|
|||
void SetVelocity(const Vector2f& velocity);
|
||||
void SetVelocityFunction(VelocityFunc velocityFunc);
|
||||
|
||||
void TeleportTo(const Vector2f& position, const RadianAnglef& rotation);
|
||||
|
||||
void UpdateVelocity(const Vector2f& gravity, float damping, float deltaTime);
|
||||
|
||||
void Wakeup();
|
||||
|
|
|
|||
|
|
@ -38,9 +38,8 @@ namespace Nz
|
|||
Physics2DSystem& operator=(Physics2DSystem&&) = delete;
|
||||
|
||||
private:
|
||||
static void OnConstruct(entt::registry& registry, entt::entity entity);
|
||||
|
||||
entt::registry& m_registry;
|
||||
entt::observer m_physicsConstructObserver;
|
||||
entt::scoped_connection m_constructConnection;
|
||||
PhysWorld2D m_physWorld;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,12 +135,12 @@ namespace Nz
|
|||
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque.value);
|
||||
}
|
||||
|
||||
bool RigidBody2D::ClosestPointQuery(const Nz::Vector2f& position, Nz::Vector2f* closestPoint, float* closestDistance) const
|
||||
bool RigidBody2D::ClosestPointQuery(const Vector2f& position, Vector2f* closestPoint, float* closestDistance) const
|
||||
{
|
||||
cpVect pos = cpv(cpFloat(position.x), cpFloat(position.y));
|
||||
|
||||
float minDistance = std::numeric_limits<float>::infinity();
|
||||
Nz::Vector2f closest;
|
||||
Vector2f closest;
|
||||
for (cpShape* shape : m_shapes)
|
||||
{
|
||||
cpPointQueryInfo result;
|
||||
|
|
@ -179,7 +179,7 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::ForEachArbiter(std::function<void(Nz::Arbiter2D&)> callback)
|
||||
void RigidBody2D::ForEachArbiter(std::function<void(Arbiter2D&)> callback)
|
||||
{
|
||||
using CallbackType = decltype(callback);
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ namespace Nz
|
|||
|
||||
void RigidBody2D::ForceSleep()
|
||||
{
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_DYNAMIC)
|
||||
cpBodySleep(body->GetHandle());
|
||||
|
|
@ -221,13 +221,13 @@ namespace Nz
|
|||
return float(cpBodyGetAngularVelocity(m_handle));
|
||||
}
|
||||
|
||||
float Nz::RigidBody2D::GetElasticity(std::size_t shapeIndex) const
|
||||
float RigidBody2D::GetElasticity(std::size_t shapeIndex) const
|
||||
{
|
||||
assert(shapeIndex < m_shapes.size());
|
||||
return float(cpShapeGetElasticity(m_shapes[shapeIndex]));
|
||||
}
|
||||
|
||||
float Nz::RigidBody2D::GetFriction(std::size_t shapeIndex) const
|
||||
float RigidBody2D::GetFriction(std::size_t shapeIndex) const
|
||||
{
|
||||
assert(shapeIndex < m_shapes.size());
|
||||
return float(cpShapeGetFriction(m_shapes[shapeIndex]));
|
||||
|
|
@ -290,7 +290,7 @@ namespace Nz
|
|||
return std::distance(m_shapes.begin(), it);
|
||||
}
|
||||
|
||||
Vector2f Nz::RigidBody2D::GetSurfaceVelocity(std::size_t shapeIndex) const
|
||||
Vector2f RigidBody2D::GetSurfaceVelocity(std::size_t shapeIndex) const
|
||||
{
|
||||
assert(shapeIndex < m_shapes.size());
|
||||
cpVect vel = cpShapeGetSurfaceVelocity(m_shapes[shapeIndex]);
|
||||
|
|
@ -421,7 +421,7 @@ namespace Nz
|
|||
{
|
||||
if (mass > 0.f)
|
||||
{
|
||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](RigidBody2D* body)
|
||||
{
|
||||
cpBodySetMass(body->GetHandle(), mass);
|
||||
|
||||
|
|
@ -430,11 +430,11 @@ namespace Nz
|
|||
});
|
||||
}
|
||||
else
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body) { cpBodySetType(body->GetHandle(), (body->IsStatic()) ? CP_BODY_TYPE_STATIC : CP_BODY_TYPE_KINEMATIC); } );
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body) { cpBodySetType(body->GetHandle(), (body->IsStatic()) ? CP_BODY_TYPE_STATIC : CP_BODY_TYPE_KINEMATIC); } );
|
||||
}
|
||||
else if (mass > 0.f)
|
||||
{
|
||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [mass, recomputeMoment](RigidBody2D* body)
|
||||
{
|
||||
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_DYNAMIC)
|
||||
{
|
||||
|
|
@ -470,7 +470,7 @@ namespace Nz
|
|||
void RigidBody2D::SetMomentOfInertia(float moment)
|
||||
{
|
||||
// Even though Chipmunk allows us to change this anytime, we need to do it in a post-step to prevent other post-steps to override this
|
||||
m_world->RegisterPostStep(this, [moment] (Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [moment] (RigidBody2D* body)
|
||||
{
|
||||
cpBodySetMoment(body->GetHandle(), moment);
|
||||
});
|
||||
|
|
@ -482,7 +482,7 @@ namespace Nz
|
|||
cpBodySetPosition(m_handle, cpvadd(cpv(position.x, position.y), cpTransformVect(m_handle->transform, cpv(m_positionOffset.x, m_positionOffset.y))));
|
||||
if (m_isStatic)
|
||||
{
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||
});
|
||||
|
|
@ -491,7 +491,7 @@ namespace Nz
|
|||
|
||||
void RigidBody2D::SetPositionOffset(const Vector2f& offset)
|
||||
{
|
||||
Nz::Vector2f position = GetPosition();
|
||||
Vector2f position = GetPosition();
|
||||
m_positionOffset = offset;
|
||||
SetPosition(position);
|
||||
}
|
||||
|
|
@ -501,7 +501,7 @@ namespace Nz
|
|||
cpBodySetAngle(m_handle, rotation.value);
|
||||
if (m_isStatic)
|
||||
{
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||
});
|
||||
|
|
@ -524,7 +524,7 @@ namespace Nz
|
|||
void RigidBody2D::SetStatic(bool setStaticBody)
|
||||
{
|
||||
m_isStatic = setStaticBody;
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
if (body->IsStatic())
|
||||
{
|
||||
|
|
@ -560,21 +560,35 @@ namespace Nz
|
|||
const auto& callback = rigidBody->GetVelocityFunction();
|
||||
assert(callback);
|
||||
|
||||
callback(*rigidBody, Nz::Vector2f(float(gravity.x), float(gravity.y)), float(damping), float(dt));
|
||||
callback(*rigidBody, Vector2f(float(gravity.x), float(gravity.y)), float(damping), float(dt));
|
||||
};
|
||||
}
|
||||
else
|
||||
m_handle->velocity_func = cpBodyUpdateVelocity;
|
||||
}
|
||||
|
||||
void RigidBody2D::UpdateVelocity(const Nz::Vector2f & gravity, float damping, float deltaTime)
|
||||
void RigidBody2D::TeleportTo(const Vector2f& position, const RadianAnglef& rotation)
|
||||
{
|
||||
// Use cpTransformVect to rotate/scale the position offset
|
||||
cpBodySetPosition(m_handle, cpvadd(cpv(position.x, position.y), cpTransformVect(m_handle->transform, cpv(m_positionOffset.x, m_positionOffset.y))));
|
||||
cpBodySetAngle(m_handle, rotation.value);
|
||||
if (m_isStatic)
|
||||
{
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
cpSpaceReindexShapesForBody(body->GetWorld()->GetHandle(), body->GetHandle());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::UpdateVelocity(const Vector2f & gravity, float damping, float deltaTime)
|
||||
{
|
||||
cpBodyUpdateVelocity(m_handle, cpv(gravity.x, gravity.y), damping, deltaTime);
|
||||
}
|
||||
|
||||
void RigidBody2D::Wakeup()
|
||||
{
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body)
|
||||
m_world->RegisterPostStep(this, [](RigidBody2D* body)
|
||||
{
|
||||
if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_STATIC)
|
||||
cpBodyActivate(body->GetHandle());
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Nz
|
|||
{
|
||||
namespace
|
||||
{
|
||||
inline Nz::RadianAnglef AngleFromQuaternion(const Nz::Quaternionf& quat)
|
||||
inline RadianAnglef AngleFromQuaternion(const Quaternionf& quat)
|
||||
{
|
||||
float siny_cosp = 2.f * (quat.w * quat.z + quat.x * quat.y);
|
||||
float cosy_cosp = 1.f - 2.f * (quat.y * quat.y + quat.z * quat.z);
|
||||
|
|
@ -20,14 +20,16 @@ namespace Nz
|
|||
}
|
||||
|
||||
Physics2DSystem::Physics2DSystem(entt::registry& registry) :
|
||||
m_registry(registry)
|
||||
m_registry(registry),
|
||||
m_physicsConstructObserver(m_registry, entt::collector.group<RigidBody2DComponent, NodeComponent>())
|
||||
{
|
||||
m_constructConnection = registry.on_construct<RigidBody2DComponent>().connect<OnConstruct>();
|
||||
}
|
||||
|
||||
Physics2DSystem::~Physics2DSystem()
|
||||
{
|
||||
// Ensure every NewtonBody is destroyed before world is
|
||||
m_physicsConstructObserver.disconnect();
|
||||
|
||||
// Ensure every body is destroyed before world is
|
||||
auto rigidBodyView = m_registry.view<RigidBody2DComponent>();
|
||||
for (auto [entity, rigidBodyComponent] : rigidBodyView.each())
|
||||
rigidBodyComponent.Destroy();
|
||||
|
|
@ -35,6 +37,15 @@ namespace Nz
|
|||
|
||||
void Physics2DSystem::Update(Time elapsedTime)
|
||||
{
|
||||
// Move newly-created physics entities to their node position/rotation
|
||||
m_physicsConstructObserver.each([&](entt::entity entity)
|
||||
{
|
||||
RigidBody2DComponent& entityPhysics = m_registry.get<RigidBody2DComponent>(entity);
|
||||
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
|
||||
|
||||
entityPhysics.TeleportTo(Vector2f(entityNode.GetPosition()), AngleFromQuaternion(entityNode.GetRotation()));
|
||||
});
|
||||
|
||||
m_physWorld.Step(elapsedTime);
|
||||
|
||||
// Replicate rigid body position to their node components
|
||||
|
|
@ -44,20 +55,7 @@ namespace Nz
|
|||
if (rigidBodyComponent.IsSleeping())
|
||||
continue;
|
||||
|
||||
nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global);
|
||||
nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global);
|
||||
}
|
||||
}
|
||||
|
||||
void Physics2DSystem::OnConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
// If our entity already has a node component when adding a rigid body, initialize it with its position/rotation
|
||||
NodeComponent* node = registry.try_get<NodeComponent>(entity);
|
||||
if (node)
|
||||
{
|
||||
RigidBody2DComponent& rigidBody = registry.get<RigidBody2DComponent>(entity);
|
||||
rigidBody.SetPosition(Vector2f(node->GetPosition()));
|
||||
rigidBody.SetRotation(AngleFromQuaternion(node->GetRotation()));
|
||||
nodeComponent.SetTransform(rigidBodyComponent.GetPosition(), rigidBodyComponent.GetRotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue