Sdk/PhysicsComponent3D: Fix cloning by preserving physics states
This commit is contained in:
parent
9272efa159
commit
5aab9b248d
|
|
@ -60,7 +60,10 @@ namespace Ndk
|
||||||
static ComponentIndex componentIndex;
|
static ComponentIndex componentIndex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const;
|
||||||
|
void CopyPhysicsState(const Nz::RigidBody3D& rigidBody);
|
||||||
Nz::RigidBody3D& GetRigidBody();
|
Nz::RigidBody3D& GetRigidBody();
|
||||||
|
const Nz::RigidBody3D& GetRigidBody() const;
|
||||||
|
|
||||||
void OnAttached() override;
|
void OnAttached() override;
|
||||||
void OnComponentAttached(BaseComponent& component) override;
|
void OnComponentAttached(BaseComponent& component) override;
|
||||||
|
|
@ -70,7 +73,19 @@ namespace Ndk
|
||||||
void OnEntityDisabled() override;
|
void OnEntityDisabled() override;
|
||||||
void OnEntityEnabled() override;
|
void OnEntityEnabled() override;
|
||||||
|
|
||||||
|
struct PendingPhysObjectStates
|
||||||
|
{
|
||||||
|
Nz::Vector3f angularDamping;
|
||||||
|
Nz::Vector3f massCenter;
|
||||||
|
bool autoSleep;
|
||||||
|
bool valid = false;
|
||||||
|
float gravityFactor;
|
||||||
|
float linearDamping;
|
||||||
|
float mass;
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<Nz::RigidBody3D> m_object;
|
std::unique_ptr<Nz::RigidBody3D> m_object;
|
||||||
|
PendingPhysObjectStates m_pendingStates;
|
||||||
bool m_nodeSynchronizationEnabled;
|
bool m_nodeSynchronizationEnabled;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ namespace Ndk
|
||||||
inline PhysicsComponent3D::PhysicsComponent3D(const PhysicsComponent3D& physics) :
|
inline PhysicsComponent3D::PhysicsComponent3D(const PhysicsComponent3D& physics) :
|
||||||
m_nodeSynchronizationEnabled(physics.m_nodeSynchronizationEnabled)
|
m_nodeSynchronizationEnabled(physics.m_nodeSynchronizationEnabled)
|
||||||
{
|
{
|
||||||
// No copy of physical object (because we only create it when attached to an entity)
|
// We can't make a copy of the RigidBody3D, as we are not attached yet (and will possibly be attached to another world)
|
||||||
NazaraUnused(physics);
|
CopyPhysicsState(physics.GetRigidBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -383,7 +383,8 @@ namespace Ndk
|
||||||
inline void PhysicsComponent3D::SetMass(float mass)
|
inline void PhysicsComponent3D::SetMass(float mass)
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
NazaraAssert(mass > 0.f, "Mass should be positive");
|
NazaraAssert(mass >= 0.f, "Mass must be positive and finite");
|
||||||
|
NazaraAssert(std::isfinite(mass), "Mass must be positive and finite");
|
||||||
|
|
||||||
m_object->SetMass(mass);
|
m_object->SetMass(mass);
|
||||||
}
|
}
|
||||||
|
|
@ -433,13 +434,44 @@ namespace Ndk
|
||||||
m_object->SetRotation(rotation);
|
m_object->SetRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void PhysicsComponent3D::ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const
|
||||||
|
{
|
||||||
|
assert(m_pendingStates.valid);
|
||||||
|
|
||||||
|
rigidBody.EnableAutoSleep(m_pendingStates.autoSleep);
|
||||||
|
rigidBody.SetAngularDamping(m_pendingStates.angularDamping);
|
||||||
|
rigidBody.SetGravityFactor(m_pendingStates.gravityFactor);
|
||||||
|
rigidBody.SetLinearDamping(m_pendingStates.linearDamping);
|
||||||
|
rigidBody.SetMass(m_pendingStates.mass);
|
||||||
|
rigidBody.SetMassCenter(m_pendingStates.massCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsComponent3D::CopyPhysicsState(const Nz::RigidBody3D& rigidBody)
|
||||||
|
{
|
||||||
|
m_pendingStates.autoSleep = rigidBody.IsAutoSleepEnabled();
|
||||||
|
m_pendingStates.angularDamping = rigidBody.GetAngularDamping();
|
||||||
|
m_pendingStates.gravityFactor = rigidBody.GetGravityFactor();
|
||||||
|
m_pendingStates.linearDamping = rigidBody.GetLinearDamping();
|
||||||
|
m_pendingStates.mass = rigidBody.GetMass();
|
||||||
|
m_pendingStates.massCenter = rigidBody.GetMassCenter(Nz::CoordSys_Local);
|
||||||
|
m_pendingStates.valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the underlying physics object
|
* \brief Gets the underlying physics object
|
||||||
* \return A reference to the physics object
|
* \return A reference to the physics object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline Nz::RigidBody3D& PhysicsComponent3D::GetRigidBody()
|
inline Nz::RigidBody3D& PhysicsComponent3D::GetRigidBody()
|
||||||
{
|
{
|
||||||
return *m_object.get();
|
return *m_object.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the underlying physics object
|
||||||
|
* \return A reference to the physics object
|
||||||
|
*/
|
||||||
|
inline const Nz::RigidBody3D& PhysicsComponent3D::GetRigidBody() const
|
||||||
|
{
|
||||||
|
return *m_object.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,11 @@ namespace Ndk
|
||||||
matrix.MakeIdentity();
|
matrix.MakeIdentity();
|
||||||
|
|
||||||
m_object = std::make_unique<Nz::RigidBody3D>(&world, geom, matrix);
|
m_object = std::make_unique<Nz::RigidBody3D>(&world, geom, matrix);
|
||||||
m_object->SetMass(1.f);
|
|
||||||
|
if (m_pendingStates.valid)
|
||||||
|
ApplyPhysicsState(*m_object);
|
||||||
|
else
|
||||||
|
m_object->SetMass(1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -57,6 +61,7 @@ namespace Ndk
|
||||||
if (IsComponent<CollisionComponent3D>(component))
|
if (IsComponent<CollisionComponent3D>(component))
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid object");
|
NazaraAssert(m_object, "Invalid object");
|
||||||
|
|
||||||
m_object->SetGeom(static_cast<CollisionComponent3D&>(component).GetGeom());
|
m_object->SetGeom(static_cast<CollisionComponent3D&>(component).GetGeom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,6 +79,7 @@ namespace Ndk
|
||||||
if (IsComponent<CollisionComponent3D>(component))
|
if (IsComponent<CollisionComponent3D>(component))
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid object");
|
NazaraAssert(m_object, "Invalid object");
|
||||||
|
|
||||||
m_object->SetGeom(Nz::NullCollider3D::New());
|
m_object->SetGeom(Nz::NullCollider3D::New());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +90,11 @@ namespace Ndk
|
||||||
|
|
||||||
void PhysicsComponent3D::OnDetached()
|
void PhysicsComponent3D::OnDetached()
|
||||||
{
|
{
|
||||||
m_object.reset();
|
if (m_object)
|
||||||
|
{
|
||||||
|
CopyPhysicsState(*m_object);
|
||||||
|
m_object.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsComponent3D::OnEntityDestruction()
|
void PhysicsComponent3D::OnEntityDestruction()
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Physics3D/PhysWorld3D.hpp>
|
#include <Nazara/Physics3D/PhysWorld3D.hpp>
|
||||||
#include <Newton/Newton.h>
|
#include <Newton/Newton.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <Nazara/Physics3D/Debug.hpp>
|
#include <Nazara/Physics3D/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -31,6 +32,7 @@ namespace Nz
|
||||||
|
|
||||||
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
||||||
NewtonBodySetUserData(m_body, this);
|
NewtonBodySetUserData(m_body, this);
|
||||||
|
NewtonBodySetTransformCallback(m_body, &TransformCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidBody3D::RigidBody3D(const RigidBody3D& object) :
|
RigidBody3D::RigidBody3D(const RigidBody3D& object) :
|
||||||
|
|
@ -47,6 +49,7 @@ namespace Nz
|
||||||
|
|
||||||
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
||||||
NewtonBodySetUserData(m_body, this);
|
NewtonBodySetUserData(m_body, this);
|
||||||
|
NewtonBodySetTransformCallback(m_body, &TransformCallback);
|
||||||
|
|
||||||
SetMass(object.m_mass);
|
SetMass(object.m_mass);
|
||||||
SetAngularDamping(object.GetAngularDamping());
|
SetAngularDamping(object.GetAngularDamping());
|
||||||
|
|
@ -293,16 +296,27 @@ namespace Nz
|
||||||
|
|
||||||
void RigidBody3D::SetMass(float mass)
|
void RigidBody3D::SetMass(float mass)
|
||||||
{
|
{
|
||||||
|
NazaraAssert(mass >= 0.f, "Mass must be positive and finite");
|
||||||
|
NazaraAssert(std::isfinite(mass), "Mass must be positive and finite");
|
||||||
|
|
||||||
if (m_mass > 0.f)
|
if (m_mass > 0.f)
|
||||||
{
|
{
|
||||||
// If we already have a mass, we already have an inertial matrix as well, just rescale it
|
if (mass > 0.f)
|
||||||
float Ix, Iy, Iz;
|
{
|
||||||
NewtonBodyGetMassMatrix(m_body, &m_mass, &Ix, &Iy, &Iz);
|
// If we already have a mass, we already have an inertial matrix as well, just rescale it
|
||||||
|
float Ix, Iy, Iz;
|
||||||
|
NewtonBodyGetMassMatrix(m_body, &m_mass, &Ix, &Iy, &Iz);
|
||||||
|
|
||||||
float scale = mass/m_mass;
|
float scale = mass / m_mass;
|
||||||
NewtonBodySetMassMatrix(m_body, mass, Ix*scale, Iy*scale, Iz*scale);
|
NewtonBodySetMassMatrix(m_body, mass, Ix*scale, Iy*scale, Iz*scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewtonBodySetMassMatrix(m_body, 0.f, 0.f, 0.f, 0.f);
|
||||||
|
NewtonBodySetForceAndTorqueCallback(m_body, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mass > 0.f)
|
else
|
||||||
{
|
{
|
||||||
Vector3f inertia, origin;
|
Vector3f inertia, origin;
|
||||||
m_geom->ComputeInertialMatrix(&inertia, &origin);
|
m_geom->ComputeInertialMatrix(&inertia, &origin);
|
||||||
|
|
@ -310,7 +324,6 @@ namespace Nz
|
||||||
NewtonBodySetCentreOfMass(m_body, &origin.x);
|
NewtonBodySetCentreOfMass(m_body, &origin.x);
|
||||||
NewtonBodySetMassMatrix(m_body, mass, inertia.x*mass, inertia.y*mass, inertia.z*mass);
|
NewtonBodySetMassMatrix(m_body, mass, inertia.x*mass, inertia.y*mass, inertia.z*mass);
|
||||||
NewtonBodySetForceAndTorqueCallback(m_body, &ForceAndTorqueCallback);
|
NewtonBodySetForceAndTorqueCallback(m_body, &ForceAndTorqueCallback);
|
||||||
NewtonBodySetTransformCallback(m_body, &TransformCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mass = mass;
|
m_mass = mass;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue