Esempio n. 1
0
void FPhysScene::UpdateActiveTransforms(uint32 SceneType)
{
	if (SceneType == PST_Cloth)	//cloth doesn't bother with updating components to bodies so we don't need to store any transforms
	{
		return;
	}
	PxScene* PScene = GetPhysXScene(SceneType);
	check(PScene);
	SCOPED_SCENE_READ_LOCK(PScene);

	PxU32 NumTransforms = 0;
	const PxActiveTransform* PActiveTransforms = PScene->getActiveTransforms(NumTransforms);
	ActiveBodyInstances[SceneType].Empty(NumTransforms);
	ActiveDestructibleActors[SceneType].Empty(NumTransforms);

	for (PxU32 TransformIdx = 0; TransformIdx < NumTransforms; ++TransformIdx)
	{
		const PxActiveTransform& PActiveTransform = PActiveTransforms[TransformIdx];
		PxRigidActor* RigidActor = PActiveTransform.actor->isRigidActor();
		ensure(!RigidActor->userData || !FPhysxUserData::IsGarbage(RigidActor->userData));

		if (FBodyInstance* BodyInstance = FPhysxUserData::Get<FBodyInstance>(RigidActor->userData))
		{
			if (BodyInstance->InstanceBodyIndex == INDEX_NONE && BodyInstance->OwnerComponent.IsValid() && BodyInstance->IsInstanceSimulatingPhysics())
			{
				ActiveBodyInstances[SceneType].Add(BodyInstance);
			}
		}
		else if (const FDestructibleChunkInfo* DestructibleChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(RigidActor->userData))
		{
			ActiveDestructibleActors[SceneType].Add(RigidActor);
		}
		
	}
}
Esempio n. 2
0
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
}
Esempio n. 3
0
void FPhysScene::SetUpForFrame(const FVector* NewGrav, float InDeltaSeconds, float InMaxPhysicsDeltaTime)
{
	DeltaSeconds = InDeltaSeconds;
	MaxPhysicsDeltaTime = InMaxPhysicsDeltaTime;
#if WITH_PHYSX
	if (NewGrav)
	{
		// Loop through scene types to get all scenes
		for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType)
		{
			PxScene* PScene = GetPhysXScene(SceneType);
			if (PScene != NULL)
			{
				//@todo phys_thread don't do this if gravity changes

				//@todo, to me it looks like we should avoid this if the gravity has not changed, the lock is probably expensive
				// Lock scene lock, in case it is required
				SCENE_LOCK_WRITE(PScene);

				PScene->setGravity(U2PVector(*NewGrav));

				// Unlock scene lock, in case it is required
				SCENE_UNLOCK_WRITE(PScene);
			}
		}
	}
#endif
}
Esempio n. 4
0
bool FPhysScene::SubstepSimulation(uint32 SceneType, FGraphEventRef &InOutCompletionEvent)
{
#if WITH_PHYSX
	check(SceneType != PST_Cloth); //we don't bother sub-stepping cloth
	float UseDelta = UseSyncTime(SceneType)? SyncDeltaSeconds : DeltaSeconds;
	float SubTime = PhysSubSteppers[SceneType]->UpdateTime(UseDelta);
	PxScene* PScene = GetPhysXScene(SceneType);
	if(SubTime <= 0.f)
	{
		return false;
	}else
	{
		//we have valid scene and subtime so enqueue task
		PhysXCompletionTask* Task = new PhysXCompletionTask(InOutCompletionEvent, PScene->getTaskManager());
		ENamedThreads::Type NamedThread = PhysSingleThreadedMode() ? ENamedThreads::GameThread : ENamedThreads::AnyThread;

		DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.SubstepSimulationImp"),
			STAT_FSimpleDelegateGraphTask_SubstepSimulationImp,
			STATGROUP_TaskGraphTasks);

		FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(
			FSimpleDelegateGraphTask::FDelegate::CreateRaw(PhysSubSteppers[SceneType], &FPhysSubstepTask::StepSimulation, Task),
			GET_STATID(STAT_FSimpleDelegateGraphTask_SubstepSimulationImp), NULL, NamedThread
		);
		return true;
	}
#endif

}
Esempio n. 5
0
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 AProjectTapGameMode::BeginPlay()
{
    Super::BeginPlay();
    auto gameState = GetGameState<AProjectTapGameState>();
    OnCameraChangedDelegateHandle = gameState->CameraChanged.AddUFunction( this , TEXT( "OnCameraChanged" ) );
    OnGameStateChangedDelegateHandle = gameState->GameStateChanged.AddUFunction( this , TEXT( "OnStateChanged" ) );
    auto physicsWorld = GetWorld()->GetPhysicsScene();
    auto scene = physicsWorld->GetPhysXScene(0);
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
void FPhysScene::EndFrame(ULineBatchComponent* InLineBatcher)
{
	check(IsInGameThread());

	PhysicsSceneCompletion = NULL;

	/**
	* At this point physics simulation has finished. We obtain both scene locks so that the various read/write operations needed can be done quickly.
	* This means that anyone attempting to write on other threads will be blocked. This is OK because acessing any of these game objects from another thread is probably a bad idea!
	*/

	SCOPED_SCENE_WRITE_LOCK(GetPhysXScene(PST_Sync));
	SCOPED_SCENE_WRITE_LOCK(bAsyncSceneEnabled ? GetPhysXScene(PST_Async) : nullptr);

	if (bAsyncSceneEnabled)
	{
		SyncComponentsToBodies_AssumesLocked(PST_Async);
	}

	SyncComponentsToBodies_AssumesLocked(PST_Sync);

	// Perform any collision notification events
	DispatchPhysNotifications_AssumesLocked();

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	// Handle debug rendering
	if (InLineBatcher)
	{
		AddDebugLines(PST_Sync, InLineBatcher);

		if (bAsyncSceneEnabled)
		{
			AddDebugLines(PST_Async, InLineBatcher);
		}

	}
#endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
Esempio n. 9
0
void FPhysScene::SyncComponentsToBodies(uint32 SceneType)
{
#if WITH_PHYSX
	PxScene* PScene = GetPhysXScene(SceneType);
	check(PScene);
	SCENE_LOCK_READ(PScene);

	PxU32 NumTransforms = 0;
	const PxActiveTransform* PActiveTransforms = PScene->getActiveTransforms(NumTransforms);

	SCENE_UNLOCK_READ(PScene);


	for(PxU32 TransformIdx=0; TransformIdx<NumTransforms; TransformIdx++)
	{
		const PxActiveTransform& PActiveTransform = PActiveTransforms[TransformIdx];
		FBodyInstance* BodyInst = FPhysxUserData::Get<FBodyInstance>(PActiveTransform.userData);
		if(	BodyInst != NULL && 
			BodyInst->InstanceBodyIndex == INDEX_NONE && 
			BodyInst->OwnerComponent != NULL &&
			BodyInst->IsInstanceSimulatingPhysics() )
		{
			check(BodyInst->OwnerComponent->IsRegistered()); // shouldn't have a physics body for a non-registered component!

			AActor* Owner = BodyInst->OwnerComponent->GetOwner();

			// See if the transform is actually different, and if so, move the component to match physics
			const FTransform NewTransform = BodyInst->GetUnrealWorldTransform();	
			if(!NewTransform.EqualsNoScale(BodyInst->OwnerComponent->ComponentToWorld))
			{
				const FVector MoveBy = NewTransform.GetLocation() - BodyInst->OwnerComponent->ComponentToWorld.GetLocation();
				const FRotator NewRotation = NewTransform.Rotator();

				//UE_LOG(LogTemp, Log, TEXT("MOVING: %s"), *BodyInst->OwnerComponent->GetPathName());

				//@warning: do not reference BodyInstance again after calling MoveComponent() - events from the move could have made it unusable (destroying the actor, SetPhysics(), etc)
				BodyInst->OwnerComponent->MoveComponent(MoveBy, NewRotation, false, NULL, MOVECOMP_SkipPhysicsMove);
			}

			// Check if we didn't fall out of the world
			if(Owner != NULL && !Owner->IsPendingKill())
			{
				Owner->CheckStillInWorld();
			}
		}
	}
#endif
}
Esempio n. 10
0
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
}
Esempio n. 11
0
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

}
Esempio n. 12
0
void FPhysScene::ApplyWorldOffset(FVector InOffset)
{
#if WITH_PHYSX
	// Loop through scene types to get all scenes
	for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType)
	{
		PxScene* PScene = GetPhysXScene(SceneType);
		if (PScene != NULL)
		{
			// Lock scene lock, in case it is required
			SCENE_LOCK_WRITE(PScene);

			PScene->shiftOrigin(U2PVector(-InOffset));

			// Unlock scene lock, in case it is required
			SCENE_UNLOCK_WRITE(PScene);
		}
	}
#endif
}
Esempio n. 13
0
void FPhysScene::SetIsStaticLoading(bool bStaticLoading)
{
#if WITH_PHYSX
	// Loop through scene types to get all scenes
	for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType)
	{
		PxScene* PScene = GetPhysXScene(SceneType);
		if (PScene != NULL)
		{
			// Lock scene lock, in case it is required
			SCENE_LOCK_WRITE(PScene);

			// Sets the rebuild rate hint, to 1 frame if static loading
			PScene->setDynamicTreeRebuildRateHint(bStaticLoading ? 5 : PhysXSlowRebuildRate);

			// Unlock scene lock, in case it is required
			SCENE_UNLOCK_WRITE(PScene);
		}
	}
#endif
}
Esempio n. 14
0
void FPhysScene::SyncComponentsToBodies(uint32 SceneType)
{
	SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime);
	SCOPE_CYCLE_COUNTER(STAT_SyncComponentsToBodies);

	for (FBodyInstance* BodyInstance : ActiveBodyInstances[SceneType])
	{
		if (BodyInstance == nullptr) { continue; }

		check(BodyInstance->OwnerComponent->IsRegistered()); // shouldn't have a physics body for a non-registered component!

		AActor* Owner = BodyInstance->OwnerComponent->GetOwner();

		// See if the transform is actually different, and if so, move the component to match physics
		const FTransform NewTransform = BodyInstance->GetUnrealWorldTransform();
		if (!NewTransform.EqualsNoScale(BodyInstance->OwnerComponent->ComponentToWorld))
		{
			const FVector MoveBy = NewTransform.GetLocation() - BodyInstance->OwnerComponent->ComponentToWorld.GetLocation();
			const FRotator NewRotation = NewTransform.Rotator();

			//@warning: do not reference BodyInstance again after calling MoveComponent() - events from the move could have made it unusable (destroying the actor, SetPhysics(), etc)
			BodyInstance->OwnerComponent->MoveComponent(MoveBy, NewRotation, false, NULL, MOVECOMP_SkipPhysicsMove);
		}

		// Check if we didn't fall out of the world
		if (Owner != NULL && !Owner->IsPendingKill())
		{
			Owner->CheckStillInWorld();
		}
	}

#if WITH_APEX
	if (ActiveDestructibleActors[SceneType].Num())
	{
		SCOPED_SCENE_READ_LOCK(GetPhysXScene(SceneType));
		UDestructibleComponent::UpdateDestructibleChunkTM(ActiveDestructibleActors[SceneType]);
	}
#endif
}
Esempio n. 15
0
/** 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
	}
}
Esempio n. 16
0
/** 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
}
Esempio n. 17
0
/** 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
}