void UWorld::StartAsyncSim() { if (FPhysScene* PhysScene = GetPhysicsScene()) { PhysScene->StartAsync(); } }
void UWorld::StartClothSim() { FPhysScene* PhysScene = GetPhysicsScene(); if (PhysScene == NULL) { return; } PhysScene->StartCloth(); }
void UWorld::FinishPhysicsSim() { FPhysScene* PhysScene = GetPhysicsScene(); if (PhysScene == NULL) { return; } PhysScene->EndFrame(LineBatcher); }
bool UWorld::ComponentOverlapMulti(TArray<struct FOverlapResult>& OutOverlaps, const class UPrimitiveComponent* PrimComp, const FVector& Pos, const FRotator& Rot, ECollisionChannel TestChannel, const struct FComponentQueryParams& Params, const struct FCollisionObjectQueryParams& ObjectQueryParams) const { if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : No PrimComp")); return false; } if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Warning, TEXT("ComponentOverlapMulti : (%s) not supported."), *PrimComp->GetPathName()); return false; } return PrimComp->ComponentOverlapMulti(OutOverlaps, this, Pos, Rot, Params, ObjectQueryParams); }
void UWorld::SetupPhysicsTickFunctions(float DeltaSeconds) { StartPhysicsTickFunction.bCanEverTick = true; StartPhysicsTickFunction.Target = this; EndPhysicsTickFunction.bCanEverTick = true; EndPhysicsTickFunction.Target = this; StartClothTickFunction.bCanEverTick = true; StartClothTickFunction.Target = this; EndClothTickFunction.bCanEverTick = true; EndClothTickFunction.Target = this; // see if we need to update tick registration bool bNeedToUpdateTickRegistration = (bShouldSimulatePhysics != StartPhysicsTickFunction.IsTickFunctionRegistered()) || (bShouldSimulatePhysics != EndPhysicsTickFunction.IsTickFunctionRegistered()) || (bShouldSimulatePhysics != StartClothTickFunction.IsTickFunctionRegistered()) || (bShouldSimulatePhysics != EndClothTickFunction.IsTickFunctionRegistered()); if (bNeedToUpdateTickRegistration && PersistentLevel) { if (bShouldSimulatePhysics && !StartPhysicsTickFunction.IsTickFunctionRegistered()) { StartPhysicsTickFunction.TickGroup = TG_StartPhysics; StartPhysicsTickFunction.RegisterTickFunction(PersistentLevel); } else if (!bShouldSimulatePhysics && StartPhysicsTickFunction.IsTickFunctionRegistered()) { StartPhysicsTickFunction.UnRegisterTickFunction(); } if (bShouldSimulatePhysics && !EndPhysicsTickFunction.IsTickFunctionRegistered()) { EndPhysicsTickFunction.TickGroup = TG_EndPhysics; EndPhysicsTickFunction.RegisterTickFunction(PersistentLevel); EndPhysicsTickFunction.AddPrerequisite(this, StartPhysicsTickFunction); } else if (!bShouldSimulatePhysics && EndPhysicsTickFunction.IsTickFunctionRegistered()) { EndPhysicsTickFunction.RemovePrerequisite(this, StartPhysicsTickFunction); EndPhysicsTickFunction.UnRegisterTickFunction(); } //cloth if (bShouldSimulatePhysics && !StartClothTickFunction.IsTickFunctionRegistered()) { StartClothTickFunction.TickGroup = TG_StartCloth; StartClothTickFunction.RegisterTickFunction(PersistentLevel); } else if (!bShouldSimulatePhysics && StartClothTickFunction.IsTickFunctionRegistered()) { StartClothTickFunction.UnRegisterTickFunction(); } if (bShouldSimulatePhysics && !EndClothTickFunction.IsTickFunctionRegistered()) { EndClothTickFunction.TickGroup = TG_EndCloth; EndClothTickFunction.RegisterTickFunction(PersistentLevel); EndClothTickFunction.AddPrerequisite(this, StartClothTickFunction); } else if (!bShouldSimulatePhysics && EndClothTickFunction.IsTickFunctionRegistered()) { EndClothTickFunction.RemovePrerequisite(this, StartClothTickFunction); EndClothTickFunction.UnRegisterTickFunction(); } } FPhysScene* PhysScene = GetPhysicsScene(); if (PhysicsScene == NULL) { return; } #if WITH_PHYSX // When ticking the main scene, clean up any physics engine resources (once a frame) DeferredPhysResourceCleanup(); #endif // Update gravity in case it changed FVector DefaultGravity( 0.f, 0.f, GetGravityZ() ); static const auto CVar_MaxPhysicsDeltaTime = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("p.MaxPhysicsDeltaTime")); PhysScene->SetUpForFrame(&DefaultGravity, DeltaSeconds, UPhysicsSettings::Get()->MaxPhysicsDeltaTime); }
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FQuat& Quat, const struct FComponentQueryParams& Params) const { if (GetPhysicsScene() == NULL) { return false; } if (PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : No PrimComp")); return false; } ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); // if extent is 0, do line trace if (PrimComp->IsZeroExtent()) { return RaycastMulti(this, OutHits, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())); } OutHits.Reset(); #if UE_WITH_PHYSICS const FBodyInstance* BodyInstance = PrimComp->GetBodyInstance(); if (!BodyInstance || !BodyInstance->IsValidBodyInstance()) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetReadableName()); return false; } #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if(PrimComp->IsA(USkeletalMeshComponent::StaticClass())) { UE_LOG(LogCollision, Warning, TEXT("ComponentSweepMulti : SkeletalMeshComponent support only root body (%s) "), *PrimComp->GetReadableName()); } #endif #endif SCOPE_CYCLE_COUNTER(STAT_Collision_GeomSweepMultiple); bool bHaveBlockingHit = false; #if WITH_PHYSX ExecuteOnPxRigidActorReadOnly(BodyInstance, [&] (const PxRigidActor* PRigidActor) { // Get all the shapes from the actor FInlinePxShapeArray PShapes; const int32 NumShapes = FillInlinePxShapeArray(PShapes, *PRigidActor); // calculate the test global pose of the actor const PxQuat PGeomRot = U2PQuat(Quat); const PxTransform PGlobalStartPose = PxTransform(U2PVector(Start), PGeomRot); const PxTransform PGlobalEndPose = PxTransform(U2PVector(End), PGeomRot); // Iterate over each shape for(int32 ShapeIdx=0; ShapeIdx<NumShapes; ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if (PGeom != NULL) { // Calc shape global pose const PxTransform PLocalShape = PShape->getLocalPose(); const PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape); const PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape); // consider localshape rotation for shape rotation const PxQuat PShapeRot = PGeomRot * PLocalShape.q; if (GeomSweepMulti_PhysX(this, *PGeom, PShapeRot, OutHits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { bHaveBlockingHit = true; } } } }); #endif //WITH_PHYSX //@TODO: BOX2D: Implement UWorld::ComponentSweepMulti #if WITH_BOX2D // if (b2Body* BodyInstance = PrimComp->BodyInstance.BodyInstancePtr) // { // // } #endif return bHaveBlockingHit; }
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const { if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); #if WITH_PHYSX // if extent is 0, do line trace if (PrimComp->IsZeroExtent()) { return RaycastMulti(this, OutHits, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())); } PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } PxScene * const PScene = PRigidActor->getScene(); OutHits.Empty(); // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; { SCOPED_SCENE_READ_LOCK(PScene); PShapes.AddZeroed(PRigidActor->getNbShapes()); PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); } // calculate the test global pose of the actor PxTransform PGlobalStartPose = U2PTransform(FTransform(Start)); PxTransform PGlobalEndPose = U2PTransform(FTransform(End)); bool bHaveBlockingHit = false; PxQuat PGeomRot = U2PQuat(Rot.Quaternion()); // Iterate over each shape SCENE_LOCK_READ(PScene); for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); TArray<struct FHitResult> Hits; // Calc shape global pose PxTransform PLocalShape = PShape->getLocalPose(); PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape); PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape); // consider localshape rotation for shape rotation PxQuat PShapeRot = PGeomRot * PLocalShape.q; GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { SCENE_UNLOCK_READ(PScene); if (GeomSweepMulti(this, *PGeom, PShapeRot, Hits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { bHaveBlockingHit = true; } OutHits.Append(Hits); SCENE_LOCK_READ(PScene); } } SCENE_UNLOCK_READ(PScene); return bHaveBlockingHit; #endif //WITH_PHYSX return false; }
bool UWorld::ComponentSweepSingle(struct FHitResult& OutHit,class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const { OutHit.TraceStart = Start; OutHit.TraceEnd = End; if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepSingle : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepSingle : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); #if WITH_PHYSX // if extent is 0, do line trace if (PrimComp->IsZeroExtent()) { return RaycastSingle(this, OutHit, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())); } PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; PShapes.AddZeroed(PRigidActor->getNbShapes()); int32 NumShapes = PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); // calculate the test global pose of the actor PxTransform PGlobalStartPose = U2PTransform(FTransform(Start)); PxTransform PGlobalEndPose = U2PTransform(FTransform(End)); bool bHaveBlockingHit = false; PxQuat PGeomRot = U2PQuat(Rot.Quaternion()); // Iterate over each shape for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); // Calc shape global pose PxTransform PLocalShape = PShape->getLocalPose(); PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape); PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape); // consider localshape rotation for shape rotation PxQuat PShapeRot = PGeomRot * PLocalShape.q; GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { // @todo UE4, this might not be the best behavior. If we're looking for the most closest, this have to change to save the result, and find the closest one or // any other options, right now if anything hits first, it will return if (GeomSweepSingle(this, *PGeom, PShapeRot, OutHit, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { bHaveBlockingHit = true; break; } } } return bHaveBlockingHit; #endif //WITH_PHYSX return false; }
bool UWorld::ComponentOverlapTest(class UPrimitiveComponent* PrimComp, const FVector& Pos, const FRotator& Rot, const struct FComponentQueryParams& Params) const { if(GetPhysicsScene() == NULL) { return false; } if(PrimComp == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : No PrimComp")); return false; } // if target is skeletalmeshcomponent and do not support singlebody physics, we don't support this yet // talk to @JG, SP, LH if ( !PrimComp->ShouldTrackOverlaps() ) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName()); return false; } #if WITH_PHYSX ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType(); PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor(); if(PRigidActor == NULL) { UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : (%s) No physics data"), *PrimComp->GetPathName()); return false; } // calculate the test global pose of the actor PxTransform PTestGlobalPose = U2PTransform(FTransform(Rot, Pos)); // Get all the shapes from the actor TArray<PxShape*, TInlineAllocator<8>> PShapes; PShapes.AddZeroed(PRigidActor->getNbShapes()); int32 NumShapes = PRigidActor->getShapes(PShapes.GetData(), PShapes.Num()); // Iterate over each shape for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++) { PxShape* PShape = PShapes[ShapeIdx]; check(PShape); // Calc shape global pose PxTransform PLocalPose = PShape->getLocalPose(); PxTransform PShapeGlobalPose = PTestGlobalPose.transform(PLocalPose); GET_GEOMETRY_FROM_SHAPE(PGeom, PShape); if(PGeom != NULL) { if( GeomOverlapTest(this, *PGeom, PShapeGlobalPose, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()))) { // in this test, it only matters true or false. // if we found first true, we don't care next test anymore. return true; } } } #endif //WITH_PHYSX return false; }