Physics[2|3]D/PhysWorld[2|3]D: Add max step count

This commit is contained in:
Jérôme Leclercq 2018-02-09 17:29:20 +01:00
parent bb7c97ed9a
commit 45af15d802
5 changed files with 35 additions and 2 deletions

View File

@ -65,6 +65,7 @@ Nazara Engine:
- Clock::Restart now returns the elapsed microseconds since construction or last Restart call - Clock::Restart now returns the elapsed microseconds since construction or last Restart call
- Add PhysWorld2D::[Get|Set]IterationCount to control how many iterations chipmunk will perform per step. - Add PhysWorld2D::[Get|Set]IterationCount to control how many iterations chipmunk will perform per step.
- Add PhysWorld2D::UseSpatialHash to use spatial hashing instead of bounding box trees, which may speedup simulation in some cases. - Add PhysWorld2D::UseSpatialHash to use spatial hashing instead of bounding box trees, which may speedup simulation in some cases.
- Add PhysWorld[2D|3D] max step count per Step call (default: 50), to avoid spirals of death when the physics engine simulation time is over step size.
Nazara Development Kit: Nazara Development Kit:
- Added ImageWidget (#139) - Added ImageWidget (#139)

View File

@ -55,6 +55,7 @@ namespace Nz
Vector2f GetGravity() const; Vector2f GetGravity() const;
cpSpace* GetHandle() const; cpSpace* GetHandle() const;
std::size_t GetIterationCount() const; std::size_t GetIterationCount() const;
std::size_t GetMaxStepCount() const;
float GetStepSize() const; float GetStepSize() const;
bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody = nullptr); bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody = nullptr);
@ -71,6 +72,7 @@ namespace Nz
void SetDamping(float dampingValue); void SetDamping(float dampingValue);
void SetGravity(const Vector2f& gravity); void SetGravity(const Vector2f& gravity);
void SetIterationCount(std::size_t iterationCount); void SetIterationCount(std::size_t iterationCount);
void SetMaxStepCount(std::size_t maxStepCount);
void SetStepSize(float stepSize); void SetStepSize(float stepSize);
void Step(float timestep); void Step(float timestep);
@ -144,6 +146,7 @@ namespace Nz
static_assert(std::is_nothrow_move_constructible<PostStepContainer>::value, "PostStepContainer should be noexcept MoveConstructible"); static_assert(std::is_nothrow_move_constructible<PostStepContainer>::value, "PostStepContainer should be noexcept MoveConstructible");
std::size_t m_maxStepCount;
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks; std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
std::unordered_map<RigidBody2D*, PostStepContainer> m_rigidPostSteps; std::unordered_map<RigidBody2D*, PostStepContainer> m_rigidPostSteps;
cpSpace* m_handle; cpSpace* m_handle;

View File

@ -25,9 +25,11 @@ namespace Nz
Vector3f GetGravity() const; Vector3f GetGravity() const;
NewtonWorld* GetHandle() const; NewtonWorld* GetHandle() const;
std::size_t GetMaxStepCount() const;
float GetStepSize() const; float GetStepSize() const;
void SetGravity(const Vector3f& gravity); void SetGravity(const Vector3f& gravity);
void SetMaxStepCount(std::size_t maxStepCount);
void SetSolverModel(unsigned int model); void SetSolverModel(unsigned int model);
void SetStepSize(float stepSize); void SetStepSize(float stepSize);
@ -37,6 +39,7 @@ namespace Nz
PhysWorld3D& operator=(PhysWorld3D&&) = delete; ///TODO PhysWorld3D& operator=(PhysWorld3D&&) = delete; ///TODO
private: private:
std::size_t m_maxStepCount;
Vector3f m_gravity; Vector3f m_gravity;
NewtonWorld* m_world; NewtonWorld* m_world;
float m_stepSize; float m_stepSize;

View File

@ -80,6 +80,7 @@ namespace Nz
} }
PhysWorld2D::PhysWorld2D() : PhysWorld2D::PhysWorld2D() :
m_maxStepCount(50),
m_stepSize(0.005f), m_stepSize(0.005f),
m_timestepAccumulator(0.f) m_timestepAccumulator(0.f)
{ {
@ -149,6 +150,11 @@ namespace Nz
return cpSpaceGetIterations(m_handle); return cpSpaceGetIterations(m_handle);
} }
std::size_t PhysWorld2D::GetMaxStepCount() const
{
return m_maxStepCount;
}
float PhysWorld2D::GetStepSize() const float PhysWorld2D::GetStepSize() const
{ {
return m_stepSize; return m_stepSize;
@ -291,6 +297,11 @@ namespace Nz
cpSpaceSetIterations(m_handle, int(iterationCount)); cpSpaceSetIterations(m_handle, int(iterationCount));
} }
void PhysWorld2D::SetMaxStepCount(std::size_t maxStepCount)
{
m_maxStepCount = maxStepCount;
}
void PhysWorld2D::SetStepSize(float stepSize) void PhysWorld2D::SetStepSize(float stepSize)
{ {
m_stepSize = stepSize; m_stepSize = stepSize;
@ -300,7 +311,8 @@ namespace Nz
{ {
m_timestepAccumulator += timestep; m_timestepAccumulator += timestep;
while (m_timestepAccumulator >= m_stepSize) std::size_t stepCount = 0;
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
{ {
OnPhysWorld2DPreStep(this); OnPhysWorld2DPreStep(this);
@ -319,6 +331,7 @@ namespace Nz
} }
m_timestepAccumulator -= m_stepSize; m_timestepAccumulator -= m_stepSize;
stepCount++;
} }
} }

View File

@ -10,6 +10,7 @@ namespace Nz
{ {
PhysWorld3D::PhysWorld3D() : PhysWorld3D::PhysWorld3D() :
m_gravity(Vector3f::Zero()), m_gravity(Vector3f::Zero()),
m_maxStepCount(50),
m_stepSize(0.005f), m_stepSize(0.005f),
m_timestepAccumulator(0.f) m_timestepAccumulator(0.f)
{ {
@ -32,6 +33,11 @@ namespace Nz
return m_world; return m_world;
} }
std::size_t PhysWorld3D::GetMaxStepCount() const
{
return m_maxStepCount;
}
float PhysWorld3D::GetStepSize() const float PhysWorld3D::GetStepSize() const
{ {
return m_stepSize; return m_stepSize;
@ -42,6 +48,11 @@ namespace Nz
m_gravity = gravity; m_gravity = gravity;
} }
void PhysWorld3D::SetMaxStepCount(std::size_t maxStepCount)
{
m_maxStepCount = maxStepCount;
}
void PhysWorld3D::SetSolverModel(unsigned int model) void PhysWorld3D::SetSolverModel(unsigned int model)
{ {
NewtonSetSolverModel(m_world, model); NewtonSetSolverModel(m_world, model);
@ -56,10 +67,12 @@ namespace Nz
{ {
m_timestepAccumulator += timestep; m_timestepAccumulator += timestep;
while (m_timestepAccumulator >= m_stepSize) std::size_t stepCount = 0;
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
{ {
NewtonUpdate(m_world, m_stepSize); NewtonUpdate(m_world, m_stepSize);
m_timestepAccumulator -= m_stepSize; m_timestepAccumulator -= m_stepSize;
stepCount++;
} }
} }
} }