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_WRITE_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); } } }
bool UGripMotionControllerComponent::DestroyPhysicsHandle(int32 SceneIndex, physx::PxD6Joint** HandleData, physx::PxRigidDynamic** KinActorData) { #if WITH_PHYSX if (HandleData && *HandleData) { check(*KinActorData); // use correct scene PxScene* PScene = GetPhysXSceneFromIndex(SceneIndex); if (PScene) { SCOPED_SCENE_WRITE_LOCK(PScene); // Destroy joint. (*HandleData)->release(); // Destroy temporary actor. (*KinActorData)->release(); } *KinActorData = NULL; *HandleData = NULL; } else return false; #endif // WITH_PHYSX return true; }
void FPhysScene::SetKinematicTarget(FBodyInstance * BodyInstance, const FTransform & TargetTransform) { TargetTransform.DiagnosticCheckNaN_All(); #if WITH_PHYSX if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic()) { #if WITH_SUBSTEPPING if (IsSubstepping()) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[SceneType(BodyInstance)]; PhysSubStepper->SetKinematicTarget(BodyInstance, TargetTransform); } else #endif { const PxTransform PNewPose = U2PTransform(TargetTransform); check(PNewPose.isValid()); SCOPED_SCENE_WRITE_LOCK(PRigidDynamic->getScene()); PRigidDynamic->setKinematicTarget(PNewPose); } } #endif }
void FConstraintInstance::EnableProjection() { SCOPED_SCENE_WRITE_LOCK(ConstraintData->getScene()); ConstraintData->setProjectionLinearTolerance(ProjectionLinearTolerance); ConstraintData->setProjectionAngularTolerance(ProjectionAngularTolerance); ConstraintData->setConstraintFlag(PxConstraintFlag::ePROJECTION, true); }
void UDestructibleComponent::SetCollisionResponseForActor(const FCollisionResponse& ColResponse, PxRigidDynamic* Actor, int32 ChunkIdx) { // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); if(IsCollisionEnabled()) { AActor* Owner = GetOwner(); CreateShapeFilterData(MoveChannel, (Owner ? Owner->GetUniqueID() : 0), ColResponse.GetResponseContainer(), 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, BodyInstance.bNotifyRigidBodyCollision, false); PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; SCOPED_SCENE_WRITE_LOCK(Actor->getScene()); TArray<PxShape*> Shapes; Shapes.AddUninitialized(Actor->getNbShapes()); int ShapeCount = Actor->getShapes(Shapes.GetTypedData(), Shapes.Num()); for (int32 i=0; i < ShapeCount; ++i) { PxShape* Shape = Shapes[i]; Shape->setQueryFilterData(PQueryFilterData); Shape->setSimulationFilterData(PSimFilterData); Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); Shape->setFlag(PxShapeFlag::eVISUALIZATION, true); } } }
void FPhysScene::FDeferredSceneData::FlushDeferredActors() { check(AddInstances.Num() == AddActors.Num()); if (AddInstances.Num() > 0) { PxScene* Scene = GetPhysXSceneFromIndex(SceneIndex); SCOPED_SCENE_WRITE_LOCK(Scene); Scene->addActors(AddActors.GetData(), AddActors.Num()); int32 Idx = -1; for (FBodyInstance* Instance : AddInstances) { ++Idx; Instance->CurrentSceneState = BodyInstanceSceneState::Added; if(Instance->GetPxRigidDynamic_AssumesLocked()) { // Extra setup necessary for dynamic objects. Instance->InitDynamicProperties_AssumesLocked(); } } AddInstances.Empty(); AddActors.Empty(); } check(RemoveInstances.Num() == RemoveActors.Num()); if (RemoveInstances.Num() > 0) { PxScene* Scene = GetPhysXSceneFromIndex(SceneIndex); SCOPED_SCENE_WRITE_LOCK(Scene); Scene->removeActors(RemoveActors.GetData(), RemoveActors.Num()); for (FBodyInstance* Instance : AddInstances) { Instance->CurrentSceneState = BodyInstanceSceneState::Removed; } RemoveInstances.Empty(); RemoveActors.Empty(); } }
void UDestructibleComponent::RefreshBoneTransforms() { #if WITH_APEX if(ApexDestructibleActor != NULL && SkeletalMesh) { UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh(); // Save a pointer to the APEX NxDestructibleAsset physx::NxDestructibleAsset* ApexDestructibleAsset = TheDestructibleMesh->ApexDestructibleAsset; check(ApexDestructibleAsset); { // Lock here so we don't encounter race conditions with the destruction processing FPhysScene* PhysScene = World->GetPhysicsScene(); check(PhysScene); const uint32 SceneType = (BodyInstance.bUseAsyncScene && PhysScene->HasAsyncScene()) ? PST_Async : PST_Sync; PxScene* PScene = PhysScene->GetPhysXScene(SceneType); check(PScene); SCOPED_SCENE_WRITE_LOCK(PScene); SCOPED_SCENE_READ_LOCK(PScene); // Try to acquire event buffer const physx::NxDestructibleChunkEvent* EventBuffer; physx::PxU32 EventBufferSize; if (ApexDestructibleActor->acquireChunkEventBuffer(EventBuffer, EventBufferSize)) { // Buffer acquired while (EventBufferSize--) { const physx::NxDestructibleChunkEvent& Event = *EventBuffer++; // Right now the only events are visibility changes. So as an optimization we won't check for the event type. // if (Event.event & physx::NxDestructibleChunkEvent::VisibilityChanged) const bool bVisible = (Event.event & physx::NxDestructibleChunkEvent::ChunkVisible) != 0; SetChunkVisible(Event.chunkIndex, bVisible); } // Release buffer (will be cleared) ApexDestructibleActor->releaseChunkEventBuffer(); } } // Update poses for visible chunks const physx::PxU16* VisibleChunks = ApexDestructibleActor->getVisibleChunks(); physx::PxU16 VisibleChunkCount = ApexDestructibleActor->getNumVisibleChunks(); while (VisibleChunkCount--) { const physx::PxU16 ChunkIndex = *VisibleChunks++; // BRGTODO : Make a direct method to access the Px objects' quats const physx::PxMat44 ChunkPoseRT = ApexDestructibleActor->getChunkPose(ChunkIndex); // Unscaled const physx::PxTransform Transform(ChunkPoseRT); SetChunkWorldRT(ChunkIndex, P2UQuat(Transform.q), P2UVector(Transform.p)); } // Send bones to render thread at end of frame MarkRenderDynamicDataDirty(); } #endif // #if WITH_APEX }
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) }
bool UGripMotionControllerComponent::TeleportMoveGrippedActor(AActor * GrippedActorToMove) { if (!GrippedActorToMove || !GrippedActors.Num()) return false; FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { if (GrippedActors[i].Actor == GrippedActorToMove) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Actor->SetActorTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); FBPActorPhysicsHandleInformation * Handle = GetPhysicsGrip(GrippedActors[i]); if (Handle && Handle->KinActorData) { { PxScene* PScene = GetPhysXSceneFromIndex(Handle->SceneIndex); if (PScene) { SCOPED_SCENE_WRITE_LOCK(PScene); Handle->KinActorData->setKinematicTarget(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); } } //Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); UPrimitiveComponent *root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (root) { FBodyInstance * body = root->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } return true; } } return false; }
void UDestructibleComponent::AddImpulse( FVector Impulse, FName BoneName /*= NAME_None*/, bool bVelChange /*= false*/ ) { #if WITH_APEX int32 ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName)); PxRigidDynamic* PActor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx); if (PActor != NULL) { SCOPED_SCENE_WRITE_LOCK(PActor->getScene()); PActor->addForce(U2PVector(Impulse), bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE); } #endif }
void FPhysSubstepTask::SubstepInterpolation(float InAlpha, float DeltaTime) { #if WITH_PHYSX #if WITH_APEX SCOPED_APEX_SCENE_WRITE_LOCK(PAScene); PxScene * PScene = PAScene->getPhysXScene(); #else PxScene * PScene = PAScene; SCOPED_SCENE_WRITE_LOCK(PScene); #endif /** Note: We lock the entire scene before iterating. The assumption is that removing an FBodyInstance from the map will also be wrapped by this lock */ PhysTargetMap& Targets = PhysTargetBuffers[!External]; for (PhysTargetMap::TIterator Itr = Targets.CreateIterator(); Itr; ++Itr) { FPhysTarget & PhysTarget = Itr.Value(); FBodyInstance * BodyInstance = Itr.Key(); PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked(); if (PRigidBody == NULL) { continue; } //We should only be iterating over actors that belong to this scene check(PRigidBody->getScene() == PScene); if (!IsKinematicHelper(PRigidBody)) { ApplyCustomPhysics(PhysTarget, BodyInstance, DeltaTime); ApplyForces_AssumesLocked(PhysTarget, BodyInstance); ApplyTorques_AssumesLocked(PhysTarget, BodyInstance); ApplyRadialForces_AssumesLocked(PhysTarget, BodyInstance); }else { InterpolateKinematicActor_AssumesLocked(PhysTarget, BodyInstance, InAlpha); } } /** Final substep */ if (InAlpha >= 1.f) { Targets.Empty(Targets.Num()); } #endif }
bool FConstraintInstance::ExecuteOnUnbrokenJointReadWrite(TFunctionRef<void(physx::PxD6Joint*)> Func) const { if (ConstraintData) { SCOPED_SCENE_WRITE_LOCK(ConstraintData->getScene()); if (!(ConstraintData->getConstraintFlags()&PxConstraintFlag::eBROKEN)) { Func(ConstraintData); return true; } } return false; }
/** * Create physics engine constraint. */ void FConstraintInstance::InitConstraint(USceneComponent* Owner, FBodyInstance* Body1, FBodyInstance* Body2, float Scale) { OwnerComponent = Owner; #if WITH_PHYSX PhysxUserData = FPhysxUserData(this); // if there's already a constraint, get rid of it first if (ConstraintData) { TermConstraint(); } PxRigidActor* PActor1 = nullptr; PxRigidActor* PActor2 = nullptr; PxScene* PScene = GetPScene_LockFree(Body1, Body2); SCOPED_SCENE_WRITE_LOCK(PScene); const bool bValidConstraintSetup = PScene && GetPActors_AssumesLocked(Body1, Body2, &PActor1, &PActor2) && CreatePxJoint_AssumesLocked(PActor1, PActor2, PScene, Scale); if (!bValidConstraintSetup) { return; } // update mass UpdateAverageMass_AssumesLocked(PActor1, PActor2); //flags and projection settings UpdateConstraintFlags_AssumesLocked(); //limits UpdateAngularLimit(); UpdateLinearLimit(); //breakable UpdateBreakable(); //motors SetLinearDriveParams(LinearDriveSpring, LinearDriveDamping, LinearDriveForceLimit); SetAngularDriveParams(AngularDriveSpring, AngularDriveDamping, AngularDriveForceLimit); UpdateDriveTarget(); EnsureSleepingActorsStaySleeping_AssumesLocked(PActor1, PActor2); #endif // WITH_PHYSX }
bool FConstraintInstance::CreatePxJoint(physx::PxRigidActor* PActor1, physx::PxRigidActor* PActor2, physx::PxScene* PScene, const float Scale) { ConstraintData = nullptr; FTransform Local1 = GetRefFrame(EConstraintFrame::Frame1); Local1.ScaleTranslation(FVector(Scale)); checkf(Local1.IsValid() && !Local1.ContainsNaN(), TEXT("%s"), *Local1.ToString()); FTransform Local2 = GetRefFrame(EConstraintFrame::Frame2); Local2.ScaleTranslation(FVector(Scale)); checkf(Local2.IsValid() && !Local2.ContainsNaN(), TEXT("%s"), *Local2.ToString()); SCOPED_SCENE_WRITE_LOCK(PScene); // Because PhysX keeps limits/axes locked in the first body reference frame, whereas Unreal keeps them in the second body reference frame, we have to flip the bodies here. PxD6Joint* PD6Joint = PxD6JointCreate(*GPhysXSDK, PActor2, U2PTransform(Local2), PActor1, U2PTransform(Local1)); if (PD6Joint == nullptr) { UE_LOG(LogPhysics, Log, TEXT("URB_ConstraintInstance::InitConstraint - Invalid 6DOF joint (%s)"), *JointName.ToString()); return false; } ///////// POINTERS PD6Joint->userData = &PhysxUserData; // Remember reference to scene index. FPhysScene* RBScene = FPhysxUserData::Get<FPhysScene>(PScene->userData); if (RBScene->GetPhysXScene(PST_Sync) == PScene) { SceneIndex = RBScene->PhysXSceneIndex[PST_Sync]; } else if (RBScene->GetPhysXScene(PST_Async) == PScene) { SceneIndex = RBScene->PhysXSceneIndex[PST_Async]; } else { UE_LOG(LogPhysics, Log, TEXT("URB_ConstraintInstance::InitConstraint: PxScene has inconsistent FPhysScene userData. No joint created.")); return false; } ConstraintData = PD6Joint; return true; }
void UDestructibleComponent::SetCollisionResponseForActor(PxRigidDynamic* Actor, int32 ChunkIdx, const FCollisionResponseContainer* ResponseOverride /*= NULL*/) { #if WITH_APEX if (ApexDestructibleActor == NULL) { return; } // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); if(IsCollisionEnabled()) { UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh(); AActor* Owner = GetOwner(); bool bLargeChunk = IsChunkLarge(ChunkIdx); const FCollisionResponseContainer& UseResponse = ResponseOverride == NULL ? (bLargeChunk ? LargeChunkCollisionResponse.GetResponseContainer() : SmallChunkCollisionResponse.GetResponseContainer()) : *ResponseOverride; physx::PxU32 SupportDepth = TheDestructibleMesh->ApexDestructibleAsset->getChunkDepth(ChunkIdx); const bool bEnableImpactDamage = IsImpactDamageEnabled(TheDestructibleMesh, SupportDepth); CreateShapeFilterData(MoveChannel, GetUniqueID(), UseResponse, 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, bEnableImpactDamage, false); PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; SCOPED_SCENE_WRITE_LOCK(Actor->getScene()); TArray<PxShape*> Shapes; Shapes.AddUninitialized(Actor->getNbShapes()); int ShapeCount = Actor->getShapes(Shapes.GetData(), Shapes.Num()); for (int32 i=0; i < ShapeCount; ++i) { PxShape* Shape = Shapes[i]; Shape->setQueryFilterData(PQueryFilterData); Shape->setSimulationFilterData(PSimFilterData); Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); Shape->setFlag(PxShapeFlag::eVISUALIZATION, true); } } #endif }
void FConstraintInstance::TermConstraint() { #if WITH_PHYSX if (!ConstraintData) { return; } // use correct scene if(PxScene* PScene = GetPhysXSceneFromIndex(SceneIndex)) { SCOPED_SCENE_WRITE_LOCK(PScene); ConstraintData->release(); } ConstraintData = nullptr; #endif }
void UGripMotionControllerComponent::UpdatePhysicsHandleTransform(const FBPActorGripInformation &GrippedActor, const FTransform& NewTransform) { if (!GrippedActor.Actor && !GrippedActor.Component) return; FBPActorPhysicsHandleInformation * HandleInfo = GetPhysicsGrip(GrippedActor); if (!HandleInfo || !HandleInfo->KinActorData) return; #if WITH_PHYSX bool bChangedPosition = true; bool bChangedRotation = true; PxRigidDynamic* KinActor = HandleInfo->KinActorData; PxScene* PScene = GetPhysXSceneFromIndex(HandleInfo->SceneIndex); SCOPED_SCENE_WRITE_LOCK(PScene); // Check if the new location is worthy of change PxVec3 PNewLocation = U2PVector(NewTransform.GetTranslation()); PxVec3 PCurrentLocation = KinActor->getGlobalPose().p; if ((PNewLocation - PCurrentLocation).magnitudeSquared() <= 0.01f*0.01f) { PNewLocation = PCurrentLocation; bChangedPosition = false; } // Check if the new rotation is worthy of change PxQuat PNewOrientation = U2PQuat(NewTransform.GetRotation()); PxQuat PCurrentOrientation = KinActor->getGlobalPose().q; if ((FMath::Abs(PNewOrientation.dot(PCurrentOrientation)) > (1.f - SMALL_NUMBER))) { PNewOrientation = PCurrentOrientation; bChangedRotation = false; } // Don't call moveKinematic if it hasn't changed - that will stop bodies from going to sleep. if (bChangedPosition || bChangedRotation) { KinActor->setKinematicTarget(PxTransform(PNewLocation, PNewOrientation)); } #endif // WITH_PHYSX }
bool UDestructibleComponent::ExecuteOnPhysicsReadWrite(TFunctionRef<void()> Func) const { #if WITH_APEX if (ApexDestructibleActor) { FPhysScene* PhysScene = GetWorld()->GetPhysicsScene(); // Destructibles are always dynamic or kinematic, and therefore only go into one of the scenes const uint32 SceneType = BodyInstance.UseAsyncScene(PhysScene) ? PST_Async : PST_Sync; PxScene* PScene = PhysScene->GetPhysXScene(SceneType); SCOPED_SCENE_WRITE_LOCK(PScene); Func(); return true; } #endif return false; }
void FPhysScene::AddTorque(FBodyInstance * BodyInstance, const FVector & Torque) { #if WITH_PHYSX if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic()) { #if WITH_SUBSTEPPING if (IsSubstepping()) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[SceneType(BodyInstance)]; PhysSubStepper->AddTorque(BodyInstance, Torque); } else #endif { SCOPED_SCENE_WRITE_LOCK(PRigidDynamic->getScene()); PRigidDynamic->addTorque(U2PVector(Torque), PxForceMode::eFORCE, true); } } #endif }
void FPhysScene::AddForceAtPosition(FBodyInstance * BodyInstance, const FVector & Force, const FVector & Position) { #if WITH_PHYSX if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic()) { #if WITH_SUBSTEPPING if (IsSubstepping()) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[SceneType(BodyInstance)]; PhysSubStepper->AddForceAtPosition(BodyInstance, Force, Position); } else #endif { SCOPED_SCENE_WRITE_LOCK(PRigidDynamic->getScene()); PxRigidBodyExt::addForceAtPos(*PRigidDynamic, U2PVector(Force), U2PVector(Position), PxForceMode::eFORCE, true); } } #endif }
void FPhysScene::AddForceAtPosition(FBodyInstance* BodyInstance, const FVector& Force, const FVector& Position, bool bAllowSubstepping) { #if WITH_PHYSX if (PxRigidBody * PRigidBody = BodyInstance->GetPxRigidBody()) { #if WITH_SUBSTEPPING uint32 BodySceneType = SceneType(BodyInstance); if (bAllowSubstepping && IsSubstepping(BodySceneType)) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[BodySceneType]; PhysSubStepper->AddForceAtPosition(BodyInstance, Force, Position); } else #endif { SCOPED_SCENE_WRITE_LOCK(PRigidBody->getScene()); PxRigidBodyExt::addForceAtPos(*PRigidBody, U2PVector(Force), U2PVector(Position), PxForceMode::eFORCE, true); } } #endif }
void FPhysScene::AddTorque(FBodyInstance* BodyInstance, const FVector& Torque, bool bAllowSubstepping) { #if WITH_PHYSX if (PxRigidBody * PRigidBody = BodyInstance->GetPxRigidBody()) { #if WITH_SUBSTEPPING uint32 BodySceneType = SceneType(BodyInstance); if (bAllowSubstepping && IsSubstepping(BodySceneType)) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[BodySceneType]; PhysSubStepper->AddTorque(BodyInstance, Torque); } else #endif { SCOPED_SCENE_WRITE_LOCK(PRigidBody->getScene()); PRigidBody->addTorque(U2PVector(Torque), PxForceMode::eFORCE, true); } } #endif }
void UDestructibleComponent::SetCollisionResponseForShape(PxShape* Shape, int32 ChunkIdx) { // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); if (IsCollisionEnabled()) { AActor* Owner = GetOwner(); bool bLargeChunk = IsChunkLarge(ChunkIdx); const FCollisionResponse& ColResponse = bLargeChunk ? LargeChunkCollisionResponse : SmallChunkCollisionResponse; //TODO: we currently assume chunks will not have impact damage as it's very expensive. Should look into exposing this a bit more CreateShapeFilterData(MoveChannel, (Owner ? Owner->GetUniqueID() : 0), ColResponse.GetResponseContainer(), 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, false, false); PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; SCOPED_SCENE_WRITE_LOCK(Shape->getActor()->getScene()); Shape->setQueryFilterData(PQueryFilterData); Shape->setSimulationFilterData(PSimFilterData); Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); Shape->setFlag(PxShapeFlag::eVISUALIZATION, true); } }
void UGripMotionControllerComponent::PostTeleportMoveGrippedActors() { if (!GrippedActors.Num()) return; FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); if (GrippedActors[i].Actor) { // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Actor->SetActorTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); } else if (GrippedActors[i].Component) { // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Component->SetWorldTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); } FBPActorPhysicsHandleInformation * Handle = GetPhysicsGrip(GrippedActors[i]); if (Handle && Handle->KinActorData) { { PxScene* PScene = GetPhysXSceneFromIndex(Handle->SceneIndex); if (PScene) { SCOPED_SCENE_WRITE_LOCK(PScene); Handle->KinActorData->setKinematicTarget(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); } } //Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); if (GrippedActors[i].Actor) { UPrimitiveComponent *root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (root) { FBodyInstance * body = root->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } else if (GrippedActors[i].Component) { FBodyInstance * body = GrippedActors[i].Component->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } /*else { if (bIsServer) { DestroyPhysicsHandle(GrippedActors[i]); GrippedActors.RemoveAt(i); // If it got garbage collected then just remove the pointer, won't happen with new uproperty use, but keeping it here anyway } }*/ } }
void FConstraintInstance::DisableProjection() { SCOPED_SCENE_WRITE_LOCK(ConstraintData->getScene()); ConstraintData->setConstraintFlag(PxConstraintFlag::ePROJECTION, false); }
void UDestructibleComponent::CreatePhysicsState() { // to avoid calling PrimitiveComponent, I'm just calling ActorComponent::CreatePhysicsState // @todo lh - fix me based on the discussion with Bryan G UActorComponent::CreatePhysicsState(); bPhysicsStateCreated = true; // What we want to do with BodySetup is simply use it to store a PhysicalMaterial, and possibly some other relevant fields. Set up pointers from the BodyInstance to the BodySetup and this component UBodySetup* BodySetup = GetBodySetup(); BodyInstance.OwnerComponent = this; BodyInstance.BodySetup = BodySetup; BodyInstance.InstanceBodyIndex = 0; #if WITH_APEX if( SkeletalMesh == NULL ) { return; } FPhysScene* PhysScene = World->GetPhysicsScene(); check(PhysScene); if( GApexModuleDestructible == NULL ) { UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): APEX must be enabled to init UDestructibleComponent physics.") ); return; } if( ApexDestructibleActor != NULL ) { UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): NxDestructibleActor already created.") ); return; } UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh(); if( TheDestructibleMesh == NULL || TheDestructibleMesh->ApexDestructibleAsset == NULL) { UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): No DestructibleMesh or missing ApexDestructibleAsset.") ); return; } int32 ChunkCount = TheDestructibleMesh->ApexDestructibleAsset->getChunkCount(); // Ensure the chunks start off invisible. RefreshBoneTransforms should make them visible. for (int32 ChunkIndex = 0; ChunkIndex < ChunkCount; ++ChunkIndex) { SetChunkVisible(ChunkIndex, false); } #if WITH_EDITOR if (GIsEditor && !World->IsGameWorld()) { // In the editor, only set the 0 chunk to be visible. if (TheDestructibleMesh->ApexDestructibleAsset->getChunkCount() > 0) { SetChunkVisible(0, true); } return; } #endif // WITH_EDITOR // Only create physics in the game if( !World->IsGameWorld() ) { return; } // Set template actor/body/shape properties // Find the PhysicalMaterial we need to apply to the physics bodies. UPhysicalMaterial* PhysMat = BodyInstance.GetSimplePhysicalMaterial(); // Get the default actor descriptor NxParameterized data from the asset NxParameterized::Interface* ActorParams = TheDestructibleMesh->GetDestructibleActorDesc(PhysMat); // Create PhysX transforms from ComponentToWorld const PxMat44 GlobalPose(PxMat33(U2PQuat(ComponentToWorld.GetRotation())), U2PVector(ComponentToWorld.GetTranslation())); const PxVec3 Scale = U2PVector(ComponentToWorld.GetScale3D()); // Set the transform in the actor descriptor verify( NxParameterized::setParamMat44(*ActorParams,"globalPose",GlobalPose) ); verify( NxParameterized::setParamVec3(*ActorParams,"scale",Scale) ); // Set the (initially) dynamic flag in the actor descriptor // See if we are 'static' verify( NxParameterized::setParamBool(*ActorParams,"dynamic", BodyInstance.bSimulatePhysics != false) ); // Set the sleep velocity frame decay constant (was sleepVelocitySmoothingFactor) - a new feature that should help sleeping in large piles verify( NxParameterized::setParamF32(*ActorParams,"sleepVelocityFrameDecayConstant", 20.0f) ); // Set up the shape desc template // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); FCollisionResponseContainer CollResponse; if(IsCollisionEnabled()) { // Only enable a collision response if collision is enabled CollResponse = GetCollisionResponseToChannels(); LargeChunkCollisionResponse.SetCollisionResponseContainer(CollResponse); SmallChunkCollisionResponse.SetCollisionResponseContainer(CollResponse); SmallChunkCollisionResponse.SetResponse(ECC_Pawn, ECR_Overlap); } else { // now since by default it will all block, if collision is disabled, we need to set to ignore MoveChannel = ECC_WorldStatic; CollResponse.SetAllChannels(ECR_Ignore); LargeChunkCollisionResponse.SetAllChannels(ECR_Ignore); SmallChunkCollisionResponse.SetAllChannels(ECR_Ignore); } const bool bEnableImpactDamage = IsImpactDamageEnabled(TheDestructibleMesh, 0); const bool bEnableContactModification = TheDestructibleMesh->DefaultDestructibleParameters.DamageParameters.bCustomImpactResistance && TheDestructibleMesh->DefaultDestructibleParameters.DamageParameters.ImpactResistance > 0.f; // Passing AssetInstanceID = 0 so we'll have self-collision AActor* Owner = GetOwner(); CreateShapeFilterData(MoveChannel, GetUniqueID(), CollResponse, 0, 0, PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, bEnableImpactDamage, false, bEnableContactModification); // Build filterData variations for complex and simple PSimFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; // Set the filterData in the shape descriptor verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word0", PSimFilterData.word0 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word1", PSimFilterData.word1 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word2", PSimFilterData.word2 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word3", PSimFilterData.word3 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word0", PQueryFilterData.word0 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word1", PQueryFilterData.word1 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word2", PQueryFilterData.word2 ) ); verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word3", PQueryFilterData.word3 ) ); // Set the PhysX material in the shape descriptor PxMaterial* PMaterial = PhysMat->GetPhysXMaterial(); verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.material", (physx::PxU64)PMaterial) ); // Set the rest depth to match the skin width in the shape descriptor const physx::PxCookingParams& CookingParams = GApexSDK->getCookingInterface()->getParams(); verify( NxParameterized::setParamF32(*ActorParams,"p3ShapeDescTemplate.restOffset", -CookingParams.skinWidth) ); // Set the PhysX material in the actor descriptor verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eDISABLE_GRAVITY",false) ); verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eVISUALIZATION",true) ); // Set the PxActor's and PxShape's userData fields to this component's body instance verify( NxParameterized::setParamU64(*ActorParams,"p3ActorDescTemplate.userData", 0 ) ); // All shapes created by this DestructibleActor will have the userdata of the owning component. // We need this, as in some cases APEX is moving shapes accross actors ( ex. FormExtended structures ) verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.userData", (PxU64)&PhysxUserData ) ); // Set up the body desc template in the actor descriptor verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.angularDamping", BodyInstance.AngularDamping ) ); verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.linearDamping", BodyInstance.LinearDamping ) ); const PxTolerancesScale& PScale = GPhysXSDK->getTolerancesScale(); PxF32 SleepEnergyThreshold = 0.00005f*PScale.speed*PScale.speed; // 1/1000 Default, since the speed scale is quite high if (BodyInstance.SleepFamily == ESleepFamily::Sensitive) { SleepEnergyThreshold /= 20.0f; } verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.sleepThreshold", SleepEnergyThreshold) ); // NxParameterized::setParamF32(*ActorParams,"bodyDescTemplate.sleepDamping", SleepDamping ); verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.density", 0.001f*PhysMat->Density) ); // Convert from g/cm^3 to kg/cm^3 // Enable CCD if requested verify( NxParameterized::setParamBool(*ActorParams,"p3BodyDescTemplate.flags.eENABLE_CCD", BodyInstance.bUseCCD != 0) ); // Ask the actor to create chunk events, for more efficient visibility updates verify( NxParameterized::setParamBool(*ActorParams,"createChunkEvents", true) ); // Enable hard sleeping if requested verify( NxParameterized::setParamBool(*ActorParams,"useHardSleeping", bEnableHardSleeping) ); // Destructibles are always dynamic or kinematic, and therefore only go into one of the scenes const uint32 SceneType = BodyInstance.UseAsyncScene(PhysScene) ? PST_Async : PST_Sync; NxApexScene* ApexScene = PhysScene->GetApexScene(SceneType); PxScene* PScene = PhysScene->GetPhysXScene(SceneType); BodyInstance.SceneIndexSync = SceneType == PST_Sync ? PhysScene->PhysXSceneIndex[PST_Sync] : 0; BodyInstance.SceneIndexAsync = SceneType == PST_Async ? PhysScene->PhysXSceneIndex[PST_Async] : 0; check(ApexScene); ChunkInfos.Reset(ChunkCount); ChunkInfos.AddZeroed(ChunkCount); PhysxChunkUserData.Reset(ChunkCount); PhysxChunkUserData.AddZeroed(ChunkCount); // Create an APEX NxDestructibleActor from the Destructible asset and actor descriptor ApexDestructibleActor = static_cast<NxDestructibleActor*>(TheDestructibleMesh->ApexDestructibleAsset->createApexActor(*ActorParams, *ApexScene)); check(ApexDestructibleActor); // Make a backpointer to this component PhysxUserData = FPhysxUserData(this); ApexDestructibleActor->userData = &PhysxUserData; // Cache cooked collision data // BRGTODO : cook in asset ApexDestructibleActor->cacheModuleData(); // BRGTODO : Per-actor LOD setting // ApexDestructibleActor->forcePhysicalLod( DestructibleActor->LOD ); // Start asleep if requested PxRigidDynamic* PRootActor = ApexDestructibleActor->getChunkPhysXActor(0); // Put to sleep or wake up only if the component is physics-simulated if (PRootActor != NULL && BodyInstance.bSimulatePhysics) { SCOPED_SCENE_WRITE_LOCK(PScene); //Question, since apex is defer adding actors do we need to lock? Locking the async scene is expensive! PRootActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, !BodyInstance.bEnableGravity); // Sleep/wake up as appropriate if (!BodyInstance.bStartAwake) { ApexDestructibleActor->setChunkPhysXActorAwakeState(0, false); } } UpdateBounds(); #endif // #if WITH_APEX }