|
@@ -129,6 +129,35 @@ void PhysicsSystem::RemoveStepListener(PhysicsStepListener *inListener)
|
|
mStepListeners.pop_back();
|
|
mStepListeners.pop_back();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+void PhysicsSystem::GatherIslandStats()
|
|
|
|
+{
|
|
|
|
+ JPH_PROFILE_FUNCTION();
|
|
|
|
+
|
|
|
|
+ for (uint32 island_idx = 0; island_idx < mIslandBuilder.GetNumIslands(); ++island_idx)
|
|
|
|
+ {
|
|
|
|
+ BodyID *bodies_begin, *bodies_end;
|
|
|
|
+ mIslandBuilder.GetBodiesInIsland(island_idx, bodies_begin, bodies_end);
|
|
|
|
+ uint64 num_bodies = bodies_end - bodies_begin;
|
|
|
|
+
|
|
|
|
+ // Equally distribute the stats over all bodies
|
|
|
|
+ const IslandBuilder::IslandStats &stats = mIslandBuilder.GetIslandStats(island_idx);
|
|
|
|
+ uint64 num_velocity_ticks = stats.mVelocityConstraintTicks / num_bodies;
|
|
|
|
+ uint64 num_position_ticks = stats.mPositionConstraintTicks / num_bodies;
|
|
|
|
+ uint8 num_position_steps = (uint8)mIslandBuilder.GetNumPositionSteps(island_idx);
|
|
|
|
+
|
|
|
|
+ for (BodyID *body_id = bodies_begin; body_id < bodies_end; ++body_id)
|
|
|
|
+ {
|
|
|
|
+ MotionProperties::SimulationStats &out_stats = mBodyManager.GetBody(*body_id).GetMotionProperties()->GetSimulationStats();
|
|
|
|
+ out_stats.mNumVelocitySteps = stats.mNumVelocitySteps;
|
|
|
|
+ out_stats.mNumPositionSteps = num_position_steps;
|
|
|
|
+ out_stats.mVelocityConstraintTicks += num_velocity_ticks; // In case of multiple collision steps we accumulate
|
|
|
|
+ out_stats.mPositionConstraintTicks += num_position_ticks;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+#endif // JPH_TRACK_SIMULATION_STATS
|
|
|
|
+
|
|
EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, TempAllocator *inTempAllocator, JobSystem *inJobSystem)
|
|
EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionSteps, TempAllocator *inTempAllocator, JobSystem *inJobSystem)
|
|
{
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
JPH_PROFILE_FUNCTION();
|
|
@@ -162,6 +191,11 @@ EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionStep
|
|
return EPhysicsUpdateError::None;
|
|
return EPhysicsUpdateError::None;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ // Reset accumulated stats on the active bodies
|
|
|
|
+ mBodyManager.ResetSimulationStats();
|
|
|
|
+#endif
|
|
|
|
+
|
|
// Calculate ratio between current and previous frame delta time to scale initial constraint forces
|
|
// Calculate ratio between current and previous frame delta time to scale initial constraint forces
|
|
float step_delta_time = inDeltaTime / inCollisionSteps;
|
|
float step_delta_time = inDeltaTime / inCollisionSteps;
|
|
float warm_start_impulse_ratio = mPhysicsSettings.mConstraintWarmStart && mPreviousStepDeltaTime > 0.0f? step_delta_time / mPreviousStepDeltaTime : 0.0f;
|
|
float warm_start_impulse_ratio = mPhysicsSettings.mConstraintWarmStart && mPreviousStepDeltaTime > 0.0f? step_delta_time / mPreviousStepDeltaTime : 0.0f;
|
|
@@ -399,6 +433,11 @@ EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionStep
|
|
mBodyManager.ValidateActiveBodyBounds();
|
|
mBodyManager.ValidateActiveBodyBounds();
|
|
#endif // JPH_DEBUG
|
|
#endif // JPH_DEBUG
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ // Gather stats from the islands and distribute them over the bodies
|
|
|
|
+ GatherIslandStats();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Store the number of active bodies at the start of the step
|
|
// Store the number of active bodies at the start of the step
|
|
next_step->mNumActiveBodiesAtStepStart = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
|
|
next_step->mNumActiveBodiesAtStepStart = mBodyManager.GetNumActiveBodies(EBodyType::RigidBody);
|
|
|
|
|
|
@@ -580,6 +619,11 @@ EPhysicsUpdateError PhysicsSystem::Update(float inDeltaTime, int inCollisionStep
|
|
mBodyManager.ValidateActiveBodyBounds();
|
|
mBodyManager.ValidateActiveBodyBounds();
|
|
#endif // JPH_DEBUG
|
|
#endif // JPH_DEBUG
|
|
|
|
|
|
|
|
+#ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ // Gather stats from the islands and distribute them over the bodies
|
|
|
|
+ GatherIslandStats();
|
|
|
|
+#endif
|
|
|
|
+
|
|
// Clear the large island splitter
|
|
// Clear the large island splitter
|
|
mLargeIslandSplitter.Reset(inTempAllocator);
|
|
mLargeIslandSplitter.Reset(inTempAllocator);
|
|
|
|
|
|
@@ -1023,6 +1067,10 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const
|
|
// If the cache hasn't handled this body pair do actual collision detection
|
|
// If the cache hasn't handled this body pair do actual collision detection
|
|
if (!pair_handled)
|
|
if (!pair_handled)
|
|
{
|
|
{
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_ticks = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Create entry in the cache for this body pair
|
|
// Create entry in the cache for this body pair
|
|
// Needs to happen irrespective if we found a collision or not (we want to remember that no collision was found too)
|
|
// Needs to happen irrespective if we found a collision or not (we want to remember that no collision was found too)
|
|
ContactConstraintManager::BodyPairHandle body_pair_handle = mContactManager.AddBodyPair(ioContactAllocator, *body1, *body2);
|
|
ContactConstraintManager::BodyPairHandle body_pair_handle = mContactManager.AddBodyPair(ioContactAllocator, *body1, *body2);
|
|
@@ -1262,6 +1310,24 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const
|
|
|
|
|
|
constraint_created = collector.mConstraintCreated;
|
|
constraint_created = collector.mConstraintCreated;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ // Track time spent processing collision for this body pair
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_ticks;
|
|
|
|
+ if (body1->GetMotionType() > body2->GetMotionType())
|
|
|
|
+ {
|
|
|
|
+ // Assign all ticks to the body with the higher motion type
|
|
|
|
+ body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // When two bodies with the same motion type are involved, we give both bodies half the ticks
|
|
|
|
+ JPH_ASSERT(body1->GetMotionType() == body2->GetMotionType());
|
|
|
|
+ num_ticks /= 2;
|
|
|
|
+ body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ body1->GetMotionProperties()->GetSimulationStats().mNarrowPhaseTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ }
|
|
|
|
+ #endif
|
|
}
|
|
}
|
|
|
|
|
|
// If a contact constraint was created, we need to do some extra work
|
|
// If a contact constraint was created, we need to do some extra work
|
|
@@ -1343,6 +1409,10 @@ void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext,
|
|
{
|
|
{
|
|
case LargeIslandSplitter::EStatus::BatchRetrieved:
|
|
case LargeIslandSplitter::EStatus::BatchRetrieved:
|
|
{
|
|
{
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_tick = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
if (first_iteration)
|
|
if (first_iteration)
|
|
{
|
|
{
|
|
// Iteration 0 is used to warm start the batch (we added 1 to the number of iterations in LargeIslandSplitter::SplitIsland)
|
|
// Iteration 0 is used to warm start the batch (we added 1 to the number of iterations in LargeIslandSplitter::SplitIsland)
|
|
@@ -1365,6 +1435,11 @@ void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext,
|
|
if (last_iteration)
|
|
if (last_iteration)
|
|
mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
|
|
mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_tick;
|
|
|
|
+ mIslandBuilder.GetIslandStats(mLargeIslandSplitter.GetIslandIndex(split_island_index)).mVelocityConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// We processed work, loop again
|
|
// We processed work, loop again
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
@@ -1414,6 +1489,10 @@ void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext,
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_tick = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Sorting is costly but needed for a deterministic simulation, allow the user to turn this off
|
|
// Sorting is costly but needed for a deterministic simulation, allow the user to turn this off
|
|
if (mPhysicsSettings.mDeterministicSimulation)
|
|
if (mPhysicsSettings.mDeterministicSimulation)
|
|
{
|
|
{
|
|
@@ -1426,29 +1505,36 @@ void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext,
|
|
|
|
|
|
// Split up large islands
|
|
// Split up large islands
|
|
CalculateSolverSteps steps_calculator(mPhysicsSettings);
|
|
CalculateSolverSteps steps_calculator(mPhysicsSettings);
|
|
- if (mPhysicsSettings.mUseLargeIslandSplitter
|
|
|
|
- && mLargeIslandSplitter.SplitIsland(island_idx, mIslandBuilder, mBodyManager, mContactManager, active_constraints, steps_calculator))
|
|
|
|
- continue; // Loop again to try to fetch the newly split island
|
|
|
|
|
|
+ if (!mPhysicsSettings.mUseLargeIslandSplitter
|
|
|
|
+ || !mLargeIslandSplitter.SplitIsland(island_idx, mIslandBuilder, mBodyManager, mContactManager, active_constraints, steps_calculator))
|
|
|
|
+ {
|
|
|
|
+ // We didn't create a split, just run the solver now for this entire island. Begin by warm starting.
|
|
|
|
+ ConstraintManager::sWarmStartVelocityConstraints(active_constraints, constraints_begin, constraints_end, warm_start_impulse_ratio, steps_calculator);
|
|
|
|
+ mContactManager.WarmStartVelocityConstraints(contacts_begin, contacts_end, warm_start_impulse_ratio, steps_calculator);
|
|
|
|
+ steps_calculator.Finalize();
|
|
|
|
+
|
|
|
|
+ // Solve velocity constraints
|
|
|
|
+ for (uint velocity_step = 0; velocity_step < steps_calculator.GetNumVelocitySteps(); ++velocity_step)
|
|
|
|
+ {
|
|
|
|
+ bool applied_impulse = ConstraintManager::sSolveVelocityConstraints(active_constraints, constraints_begin, constraints_end, delta_time);
|
|
|
|
+ applied_impulse |= mContactManager.SolveVelocityConstraints(contacts_begin, contacts_end);
|
|
|
|
+ if (!applied_impulse)
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
- // We didn't create a split, just run the solver now for this entire island. Begin by warm starting.
|
|
|
|
- ConstraintManager::sWarmStartVelocityConstraints(active_constraints, constraints_begin, constraints_end, warm_start_impulse_ratio, steps_calculator);
|
|
|
|
- mContactManager.WarmStartVelocityConstraints(contacts_begin, contacts_end, warm_start_impulse_ratio, steps_calculator);
|
|
|
|
- steps_calculator.Finalize();
|
|
|
|
|
|
+ // Save back the lambdas in the contact cache for the warm start of the next physics update
|
|
|
|
+ mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
|
|
|
|
+ }
|
|
|
|
|
|
// Store the number of position steps for later
|
|
// Store the number of position steps for later
|
|
mIslandBuilder.SetNumPositionSteps(island_idx, steps_calculator.GetNumPositionSteps());
|
|
mIslandBuilder.SetNumPositionSteps(island_idx, steps_calculator.GetNumPositionSteps());
|
|
|
|
|
|
- // Solve velocity constraints
|
|
|
|
- for (uint velocity_step = 0; velocity_step < steps_calculator.GetNumVelocitySteps(); ++velocity_step)
|
|
|
|
- {
|
|
|
|
- bool applied_impulse = ConstraintManager::sSolveVelocityConstraints(active_constraints, constraints_begin, constraints_end, delta_time);
|
|
|
|
- applied_impulse |= mContactManager.SolveVelocityConstraints(contacts_begin, contacts_end);
|
|
|
|
- if (!applied_impulse)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Save back the lambdas in the contact cache for the warm start of the next physics update
|
|
|
|
- mContactManager.StoreAppliedImpulses(contacts_begin, contacts_end);
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_tick;
|
|
|
|
+ IslandBuilder::IslandStats &stats = mIslandBuilder.GetIslandStats(island_idx);
|
|
|
|
+ stats.mNumVelocitySteps = (uint8)steps_calculator.GetNumVelocitySteps();
|
|
|
|
+ stats.mVelocityConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ #endif
|
|
|
|
|
|
// We processed work, loop again
|
|
// We processed work, loop again
|
|
continue;
|
|
continue;
|
|
@@ -1716,7 +1802,7 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
|
|
if (idx >= ioStep->mNumCCDBodies)
|
|
if (idx >= ioStep->mNumCCDBodies)
|
|
break;
|
|
break;
|
|
CCDBody &ccd_body = ioStep->mCCDBodies[idx];
|
|
CCDBody &ccd_body = ioStep->mCCDBodies[idx];
|
|
- const Body &body = mBodyManager.GetBody(ccd_body.mBodyID1);
|
|
|
|
|
|
+ Body &body = mBodyManager.GetBody(ccd_body.mBodyID1);
|
|
|
|
|
|
// Filter out layers
|
|
// Filter out layers
|
|
DefaultBroadPhaseLayerFilter broadphase_layer_filter = GetDefaultBroadPhaseLayerFilter(body.GetObjectLayer());
|
|
DefaultBroadPhaseLayerFilter broadphase_layer_filter = GetDefaultBroadPhaseLayerFilter(body.GetObjectLayer());
|
|
@@ -1933,11 +2019,20 @@ void PhysicsSystem::JobFindCCDContacts(const PhysicsUpdateContext *ioContext, Ph
|
|
// Create shape filter
|
|
// Create shape filter
|
|
SimShapeFilterWrapper shape_filter(mSimShapeFilter, &body);
|
|
SimShapeFilterWrapper shape_filter(mSimShapeFilter, &body);
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_tick = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
|
|
// Check if we collide with any other body. Note that we use the non-locking interface as we know the broadphase cannot be modified at this point.
|
|
RShapeCast shape_cast(body.GetShape(), Vec3::sOne(), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
|
|
RShapeCast shape_cast(body.GetShape(), Vec3::sOne(), body.GetCenterOfMassTransform(), ccd_body.mDeltaPosition);
|
|
CCDBroadPhaseCollector bp_collector(ccd_body, body, shape_cast, settings, shape_filter, np_collector, mBodyManager, ioStep, ioContext->mStepDeltaTime);
|
|
CCDBroadPhaseCollector bp_collector(ccd_body, body, shape_cast, settings, shape_filter, np_collector, mBodyManager, ioStep, ioContext->mStepDeltaTime);
|
|
mBroadPhase->CastAABoxNoLock({ shape_cast.mShapeWorldBounds, shape_cast.mDirection }, bp_collector, broadphase_layer_filter, object_layer_filter);
|
|
mBroadPhase->CastAABoxNoLock({ shape_cast.mShapeWorldBounds, shape_cast.mDirection }, bp_collector, broadphase_layer_filter, object_layer_filter);
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_tick;
|
|
|
|
+ body.GetMotionPropertiesUnchecked()->GetSimulationStats().mCCDTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Check if there was a hit
|
|
// Check if there was a hit
|
|
if (ccd_body.mFractionPlusSlop < 1.0f)
|
|
if (ccd_body.mFractionPlusSlop < 1.0f)
|
|
{
|
|
{
|
|
@@ -2402,20 +2497,31 @@ void PhysicsSystem::JobSolvePositionConstraints(PhysicsUpdateContext *ioContext,
|
|
switch (mLargeIslandSplitter.FetchNextBatch(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, first_iteration))
|
|
switch (mLargeIslandSplitter.FetchNextBatch(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, first_iteration))
|
|
{
|
|
{
|
|
case LargeIslandSplitter::EStatus::BatchRetrieved:
|
|
case LargeIslandSplitter::EStatus::BatchRetrieved:
|
|
- // Solve the batch
|
|
|
|
- ConstraintManager::sSolvePositionConstraints(active_constraints, constraints_begin, constraints_end, delta_time, baumgarte);
|
|
|
|
- mContactManager.SolvePositionConstraints(contacts_begin, contacts_end);
|
|
|
|
|
|
+ {
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_tick = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
|
|
- // Mark the batch as processed
|
|
|
|
- bool last_iteration, final_batch;
|
|
|
|
- mLargeIslandSplitter.MarkBatchProcessed(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, last_iteration, final_batch);
|
|
|
|
|
|
+ // Solve the batch
|
|
|
|
+ ConstraintManager::sSolvePositionConstraints(active_constraints, constraints_begin, constraints_end, delta_time, baumgarte);
|
|
|
|
+ mContactManager.SolvePositionConstraints(contacts_begin, contacts_end);
|
|
|
|
|
|
- // The final batch will update all bounds and check sleeping
|
|
|
|
- if (final_batch)
|
|
|
|
- CheckSleepAndUpdateBounds(mLargeIslandSplitter.GetIslandIndex(split_island_index), ioContext, ioStep, bodies_to_sleep);
|
|
|
|
|
|
+ // Mark the batch as processed
|
|
|
|
+ bool last_iteration, final_batch;
|
|
|
|
+ mLargeIslandSplitter.MarkBatchProcessed(split_island_index, constraints_begin, constraints_end, contacts_begin, contacts_end, last_iteration, final_batch);
|
|
|
|
|
|
- // We processed work, loop again
|
|
|
|
- continue;
|
|
|
|
|
|
+ // The final batch will update all bounds and check sleeping
|
|
|
|
+ if (final_batch)
|
|
|
|
+ CheckSleepAndUpdateBounds(mLargeIslandSplitter.GetIslandIndex(split_island_index), ioContext, ioStep, bodies_to_sleep);
|
|
|
|
+
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_tick;
|
|
|
|
+ mIslandBuilder.GetIslandStats(mLargeIslandSplitter.GetIslandIndex(split_island_index)).mPositionConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ #endif
|
|
|
|
+
|
|
|
|
+ // We processed work, loop again
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
case LargeIslandSplitter::EStatus::WaitingForBatch:
|
|
case LargeIslandSplitter::EStatus::WaitingForBatch:
|
|
break;
|
|
break;
|
|
@@ -2451,6 +2557,10 @@ void PhysicsSystem::JobSolvePositionConstraints(PhysicsUpdateContext *ioContext,
|
|
&& num_items >= LargeIslandSplitter::cLargeIslandTreshold)
|
|
&& num_items >= LargeIslandSplitter::cLargeIslandTreshold)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ uint64 start_tick = GetProcessorTickCount();
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Check if this island needs solving
|
|
// Check if this island needs solving
|
|
if (num_items > 0)
|
|
if (num_items > 0)
|
|
{
|
|
{
|
|
@@ -2468,6 +2578,12 @@ void PhysicsSystem::JobSolvePositionConstraints(PhysicsUpdateContext *ioContext,
|
|
// After solving we will update all bounds and check sleeping
|
|
// After solving we will update all bounds and check sleeping
|
|
CheckSleepAndUpdateBounds(island_idx, ioContext, ioStep, bodies_to_sleep);
|
|
CheckSleepAndUpdateBounds(island_idx, ioContext, ioStep, bodies_to_sleep);
|
|
|
|
|
|
|
|
+ #ifdef JPH_TRACK_SIMULATION_STATS
|
|
|
|
+ // Average the total ticks spent over the number of bodies and assign each the average number of ticks per body
|
|
|
|
+ uint64 num_ticks = GetProcessorTickCount() - start_tick;
|
|
|
|
+ mIslandBuilder.GetIslandStats(island_idx).mPositionConstraintTicks.fetch_add(num_ticks, memory_order_relaxed);
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// We processed work, loop again
|
|
// We processed work, loop again
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|