void FPhysScene::TermPhysScene(uint32 SceneType) { check(SceneType < NumPhysScenes); #if WITH_PHYSX PxScene* PScene = GetPhysXScene(SceneType); if(PScene != NULL) { #if WITH_APEX NxApexScene* ApexScene = GetApexScene(SceneType); if(ApexScene != NULL) { GPhysCommandHandler->DeferredRelease(ApexScene); } #endif // #if WITH_APEX if ( SceneType == PST_Sync && VehicleManager != NULL ) { delete VehicleManager; VehicleManager = NULL; } #if WITH_SUBSTEPPING delete PhysSubSteppers[SceneType]; PhysSubSteppers[SceneType] = NULL; #endif // @todo block on any running scene before calling this GPhysCommandHandler->DeferredRelease(PScene); // Remove from the map GPhysXSceneMap.Remove(PhysXSceneIndex[SceneType]); } #endif }
void FPhysScene::ProcessPhysScene(uint32 SceneType) { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_PhysicsFetchDynamicsTime); check(SceneType < NumPhysScenes); if (bPhysXSceneExecuting[SceneType] == 0) { // Not executing this scene, must call TickPhysScene before calling this function again. UE_LOG(LogPhysics, Log, TEXT("WaitPhysScene`: Not executing this scene (%d) - aborting."), SceneType); return; } if (FrameLagAsync()) { static_assert(PST_MAX == 3, "Physics scene static test failed."); // Here we assume the PST_Sync is the master and never fame lagged if (SceneType == PST_Sync) { // the one frame lagged one should be done by now. check(!FrameLaggedPhysicsSubsceneCompletion[PST_Async].GetReference() || FrameLaggedPhysicsSubsceneCompletion[PST_Async]->IsComplete()); } else if (SceneType == PST_Async) { FrameLaggedPhysicsSubsceneCompletion[PST_Async] = NULL; } } // Reset execution flag //This fetches and gets active transforms. It's important that the function that calls this locks because getting the transforms and using the data must be an atomic operation #if WITH_PHYSX PxScene* PScene = GetPhysXScene(SceneType); check(PScene); PxU32 OutErrorCode = 0; #if !WITH_APEX PScene->lockWrite(); PScene->fetchResults(true, &OutErrorCode); PScene->unlockWrite(); #else // #if !WITH_APEX // The APEX scene calls the fetchResults function for the PhysX scene, so we only call ApexScene->fetchResults(). NxApexScene* ApexScene = GetApexScene(SceneType); check(ApexScene); ApexScene->fetchResults(true, &OutErrorCode); #endif // #if !WITH_APEX UpdateActiveTransforms(SceneType); if (OutErrorCode != 0) { UE_LOG(LogPhysics, Log, TEXT("PHYSX FETCHRESULTS ERROR: %d"), OutErrorCode); } #endif // WITH_PHYSX PhysicsSubsceneCompletion[SceneType] = NULL; bPhysXSceneExecuting[SceneType] = false; }
void FPhysScene::ProcessPhysScene(uint32 SceneType) { SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime); SCOPE_CYCLE_COUNTER(STAT_PhysicsFetchDynamicsTime); check(SceneType < NumPhysScenes); if( bPhysXSceneExecuting[SceneType] == 0 ) { // Not executing this scene, must call TickPhysScene before calling this function again. UE_LOG(LogPhysics, Log, TEXT("WaitPhysScene`: Not executing this scene (%d) - aborting."), SceneType); return; } PhysicsSubsceneCompletion[SceneType] = NULL; if (FrameLagAsync()) { checkAtCompileTime(PST_MAX == 2, Assumtiopns_about_physics_scenes); // Here we assume the PST_Sync is the master and never fame lagged if (SceneType == PST_Sync) { // the one frame lagged one should be done by now. check(!FrameLaggedPhysicsSubsceneCompletion[PST_Async].GetReference() || FrameLaggedPhysicsSubsceneCompletion[PST_Async]->IsComplete()); } else { FrameLaggedPhysicsSubsceneCompletion[PST_Async] = NULL; } } #if WITH_PHYSX PxScene* PScene = GetPhysXScene(SceneType); check(PScene); PxU32 OutErrorCode = 0; #if !WITH_APEX PScene->lockWrite(); PScene->fetchResults( true, &OutErrorCode ); PScene->unlockWrite(); #else // #if !WITH_APEX // The APEX scene calls the fetchResults function for the PhysX scene, so we only call ApexScene->fetchResults(). NxApexScene* ApexScene = GetApexScene(SceneType); check(ApexScene); ApexScene->fetchResults( true, &OutErrorCode ); #endif // #if !WITH_APEX if(OutErrorCode != 0) { UE_LOG(LogPhysics, Log, TEXT("PHYSX FETCHRESULTS ERROR: %d"), OutErrorCode); } #endif // WITH_PHYSX // Reset execution flag bPhysXSceneExecuting[SceneType] = false; }
void FPhysScene::TermPhysScene(uint32 SceneType) { check(SceneType < NumPhysScenes); #if WITH_PHYSX PxScene* PScene = GetPhysXScene(SceneType); if (PScene != NULL) { #if WITH_APEX NxApexScene* ApexScene = GetApexScene(SceneType); if (ApexScene != NULL) { GPhysCommandHandler->DeferredRelease(ApexScene); } #endif // #if WITH_APEX #if WITH_VEHICLE if (SceneType == PST_Sync && VehicleManager != NULL) { delete VehicleManager; VehicleManager = NULL; } #endif #if WITH_SUBSTEPPING if (SceneType == PST_Sync && PhysSubSteppers[SceneType]) { PhysSubSteppers[SceneType]->SetVehicleManager(NULL); } delete PhysSubSteppers[SceneType]; PhysSubSteppers[SceneType] = NULL; #endif // @todo block on any running scene before calling this GPhysCommandHandler->DeferredRelease(PScene); GPhysCommandHandler->DeferredDeleteSimEventCallback(SimEventCallback[SceneType]); // Commands may have accumulated as the scene is terminated - flush any commands for this scene. GPhysCommandHandler->Flush(); // Remove from the map GPhysXSceneMap.Remove(PhysXSceneIndex[SceneType]); } #endif }
bool FPhysScene::SubstepSimulation(uint32 SceneType, FGraphEventRef &InOutCompletionEvent) { float UseDelta = UseSyncTime(SceneType)? SyncDeltaSeconds : DeltaSeconds; float SubTime = PhysSubSteppers[SceneType]->UpdateTime(UseDelta); PxScene* PScene = GetPhysXScene(SceneType); #if WITH_APEX NxApexScene* ApexScene = GetApexScene(SceneType); if(!ApexScene || SubTime <= 0.f) { return false; }else { //we have valid scene and subtime so enqueue task PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager()); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(FSimpleDelegateGraphTask::FDelegate::CreateRaw(PhysSubSteppers[SceneType], &FPhysSubstepTask::StepSimulation, ApexScene, Task), TEXT("SubstepSimulationImp")); return true; } #endif }
/** Add any debug lines from the physics scene to the supplied line batcher. */ void FPhysScene::AddDebugLines(uint32 SceneType, class ULineBatchComponent* LineBatcherToUse) { check(SceneType < NumPhysScenes); if (LineBatcherToUse) { #if WITH_PHYSX // Render PhysX debug data PxScene* PScene = GetPhysXScene(SceneType); const PxRenderBuffer& DebugData = PScene->getRenderBuffer(); BatchPxRenderBufferLines(*LineBatcherToUse, DebugData); #if WITH_APEX // Render APEX debug data NxApexScene* ApexScene = GetApexScene(SceneType); const PxRenderBuffer* RenderBuffer = ApexScene->getRenderBuffer(); if (RenderBuffer != NULL) { BatchPxRenderBufferLines(*LineBatcherToUse, *RenderBuffer); ApexScene->updateRenderResources(); } #endif // WITH_APEX #endif // WITH_PHYSX } }
/** Exposes creation of physics-engine scene outside Engine (for use with PhAT for example). */ FPhysScene::FPhysScene() #if WITH_APEX : PendingApexDamageManager(new FPendingApexDamageManager) #endif { LineBatcher = NULL; OwningWorld = NULL; #if WITH_PHYSX #if WITH_VEHICLE VehicleManager = NULL; #endif PhysxUserData = FPhysxUserData(this); // Create dispatcher for tasks if (PhysSingleThreadedMode()) { CPUDispatcher = new FPhysXCPUDispatcherSingleThread(); } else { CPUDispatcher = new FPhysXCPUDispatcher(); } // Create sim event callback SimEventCallback = new FPhysXSimEventCallback(); #endif //#if WITH_PHYSX // initialize console variable - this console variable change requires it to restart scene. static bool bInitializeConsoleVariable = true; static float InitialAverageFrameRate = 0.016f; UPhysicsSettings * PhysSetting = UPhysicsSettings::Get(); if (bInitializeConsoleVariable) { InitialAverageFrameRate = PhysSetting->InitialAverageFrameRate; FrameTimeSmoothingFactor[PST_Sync] = PhysSetting->SyncSceneSmoothingFactor; FrameTimeSmoothingFactor[PST_Async] = PhysSetting->AsyncSceneSmoothingFactor; bInitializeConsoleVariable = false; } #if WITH_SUBSTEPPING bSubstepping = PhysSetting->bSubstepping; bSubsteppingAsync = PhysSetting->bSubsteppingAsync; #endif bAsyncSceneEnabled = PhysSetting->bEnableAsyncScene; NumPhysScenes = bAsyncSceneEnabled ? PST_Async + 1 : PST_Cloth + 1; // Create scenes of all scene types for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType) { // Create the physics scene InitPhysScene(SceneType); // Also initialize scene data bPhysXSceneExecuting[SceneType] = false; // Initialize to a value which would be acceptable if FrameTimeSmoothingFactor[i] = 1.0f, i.e. constant simulation substeps AveragedFrameTime[SceneType] = InitialAverageFrameRate; // gets from console variable, and clamp to [0, 1] - 1 should be fixed time as 30 fps FrameTimeSmoothingFactor[SceneType] = FMath::Clamp<float>(FrameTimeSmoothingFactor[SceneType], 0.f, 1.f); } if (!bAsyncSceneEnabled) { PhysXSceneIndex[PST_Async] = 0; } // Make sure we use the sync scene for apex world support of destructibles in the async scene #if WITH_APEX NxApexScene* ApexScene = GetApexScene(bAsyncSceneEnabled ? PST_Async : PST_Sync); check(ApexScene); PxScene* SyncPhysXScene = GetPhysXScene(PST_Sync); check(SyncPhysXScene); check(GApexModuleDestructible); GApexModuleDestructible->setWorldSupportPhysXScene(*ApexScene, SyncPhysXScene); GApexModuleDestructible->setDamageApplicationRaycastFlags(NxDestructibleActorRaycastFlags::AllChunks, *ApexScene); #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 }