void FPhysSubstepTask::SubstepSimulationStart() { check(SubTime > 0.f); check(DeltaSeconds > 0.f); check(!CompletionEvent.GetReference()); //should be done CompletionEvent = FGraphEvent::CreateGraphEvent(); PhysXCompletionTask* SubstepTask = new PhysXCompletionTask(CompletionEvent, ApexScene->getTaskManager()); FDelegateGraphTask::CreateAndDispatchWhenReady(FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysSubstepTask::SubstepSimulationEnd), TEXT("ProcessPhysSubstepSimulation"), CompletionEvent); ++CurrentSubStep; if (CurrentSubStep < NumSubsteps) { Alpha += StepScale; TotalSubTime += SubTime; SubstepInterpolation(Alpha); ApexScene->simulate(SubTime, false, SubstepTask); SubstepTask->removeReference(); } else { SubstepInterpolation(1.f); ApexScene->simulate(DeltaSeconds - TotalSubTime, true, SubstepTask); SubstepTask->removeReference(); } }
void FPhysSubstepTask::SubstepSimulationStart() { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_SubstepSimulationStart); #if WITH_PHYSX check(SubTime > 0.f); check(DeltaSeconds > 0.f); check(!CompletionEvent.GetReference()); //should be done CompletionEvent = FGraphEvent::CreateGraphEvent(); PhysXCompletionTask* SubstepTask = new PhysXCompletionTask(CompletionEvent, PST_MAX //we don't care about sub-step time. The full time is recorded by FullSimulationTask ,PAScene->getTaskManager()); ENamedThreads::Type NamedThread = PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread; DECLARE_CYCLE_STAT(TEXT("FDelegateGraphTask.ProcessPhysSubstepSimulation"), STAT_FDelegateGraphTask_ProcessPhysSubstepSimulation, STATGROUP_TaskGraphTasks); FDelegateGraphTask::CreateAndDispatchWhenReady( FDelegateGraphTask::FDelegate::CreateRaw(this, &FPhysSubstepTask::SubstepSimulationEnd), GET_STATID(STAT_FDelegateGraphTask_ProcessPhysSubstepSimulation), CompletionEvent, NamedThread, NamedThread); ++CurrentSubStep; bool bLastSubstep = CurrentSubStep >= NumSubsteps; if (!bLastSubstep) { Alpha += StepScale; TotalSubTime += SubTime; } float DeltaTime = bLastSubstep ? (DeltaSeconds - TotalSubTime) : SubTime; float Interpolation = bLastSubstep ? 1.f : Alpha; #if WITH_VEHICLE if (VehicleManager) { VehicleManager->Update(DeltaTime); } #endif SubstepInterpolation(Interpolation, DeltaTime); #if WITH_APEX PAScene->simulate(DeltaTime, bLastSubstep, SubstepTask); #else PAScene->lockWrite(); PAScene->simulate(DeltaTime, SubstepTask); PAScene->unlockWrite(); #endif SubstepTask->removeReference(); #endif }
/** Exposes ticking of physics-engine scene outside Engine. */ void FPhysScene::TickPhysScene(uint32 SceneType, FGraphEventRef& InOutCompletionEvent) { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_PhysicsKickOffDynamicsTime); check(SceneType < NumPhysScenes); if (bPhysXSceneExecuting[SceneType] != 0) { // Already executing this scene, must call WaitPhysScene before calling this function again. UE_LOG(LogPhysics, Log, TEXT("TickPhysScene: Already executing scene (%d) - aborting."), SceneType); return; } #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) //we don't bother sub-stepping cloth { //We're about to start stepping so swap buffers. Might want to find a better place for this? PhysSubSteppers[SceneType]->SwapBuffers(); } #endif /** * clamp down... if this happens we are simming physics slower than real-time, so be careful with it. * it can improve framerate dramatically (really, it is the same as scaling all velocities down and * enlarging all timesteps) but at the same time, it will screw with networking (client and server will * diverge a lot more.) */ float UseDelta = FMath::Min(UseSyncTime(SceneType) ? SyncDeltaSeconds : DeltaSeconds, MaxPhysicsDeltaTime); // Only simulate a positive time step. if (UseDelta <= 0.f) { if (UseDelta < 0.f) { // only do this if negative. Otherwise, whenever we pause, this will come up UE_LOG(LogPhysics, Warning, TEXT("TickPhysScene: Negative timestep (%f) - aborting."), UseDelta); } return; } #if WITH_PHYSX GatherPhysXStats(GetPhysXScene(SceneType), SceneType); #endif /** * Weight frame time according to PhysScene settings. */ AveragedFrameTime[SceneType] *= FrameTimeSmoothingFactor[SceneType]; AveragedFrameTime[SceneType] += (1.0f - FrameTimeSmoothingFactor[SceneType])*UseDelta; // Set execution flag bPhysXSceneExecuting[SceneType] = true; check(!InOutCompletionEvent.GetReference()); // these should be gone because nothing is outstanding InOutCompletionEvent = FGraphEvent::CreateGraphEvent(); bool bTaskOutstanding = false; #if WITH_PHYSX #if WITH_VEHICLE if (VehicleManager && SceneType == PST_Sync) { float TickTime = AveragedFrameTime[SceneType]; #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) { TickTime = UseSyncTime(SceneType) ? SyncDeltaSeconds : DeltaSeconds; } #endif VehicleManager->PreTick(TickTime); #if WITH_SUBSTEPPING if (IsSubstepping(SceneType) == false) #endif { VehicleManager->Update(AveragedFrameTime[SceneType]); } } #endif #if !WITH_APEX PxScene* PScene = GetPhysXScene(SceneType); if (PScene && (UseDelta > 0.f)) { PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager()); PScene->lockWrite(); PScene->simulate(AveragedFrameTime[SceneType], Task); PScene->unlockWrite(); Task->removeReference(); bTaskOutstanding = true; } #else // #if !WITH_APEX // The APEX scene calls the simulate function for the PhysX scene, so we only call ApexScene->simulate(). NxApexScene* ApexScene = GetApexScene(SceneType); if(ApexScene && UseDelta > 0.f) { #if WITH_SUBSTEPPING if (IsSubstepping(SceneType)) //we don't bother sub-stepping cloth { bTaskOutstanding = SubstepSimulation(SceneType, InOutCompletionEvent); }else #endif { PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, ApexScene->getTaskManager()); ApexScene->simulate(AveragedFrameTime[SceneType], true, Task); Task->removeReference(); bTaskOutstanding = true; } } #endif // #if !WITH_APEX #endif // WITH_PHYSX if (!bTaskOutstanding) { InOutCompletionEvent->DispatchSubsequents(); // nothing to do, so nothing to wait for } #if WITH_SUBSTEPPING bSubstepping = UPhysicsSettings::Get()->bSubstepping; bSubsteppingAsync = UPhysicsSettings::Get()->bSubsteppingAsync; #endif }