bool UWorld::OverlapSingle(struct FOverlapResult& OutOverlap,const FVector& Pos, const FQuat& Rot, const struct FCollisionShape & CollisionShape, const struct FCollisionQueryParams& Params, const struct FCollisionObjectQueryParams& ObjectQueryParams) const { #if WITH_PHYSX switch (CollisionShape.ShapeType) { case ECollisionShape::Box: { PxBoxGeometry PBoxGeom( U2PVector(CollisionShape.GetBox()) ); PxTransform PGeomPose = U2PTransform(FTransform(Rot, Pos)); return GeomOverlapSingle(this, PBoxGeom, PGeomPose, OutOverlap, DefaultCollisionChannel, Params, FCollisionResponseParams::DefaultResponseParam, ObjectQueryParams); } case ECollisionShape::Sphere: { PxSphereGeometry PSphereGeom( CollisionShape.GetSphereRadius() ); PxTransform PGeomPose(U2PVector(Pos), PxQuat::createIdentity()); return GeomOverlapSingle(this, PSphereGeom, PGeomPose, OutOverlap, DefaultCollisionChannel, Params, FCollisionResponseParams::DefaultResponseParam, ObjectQueryParams); } case ECollisionShape::Capsule: { PxCapsuleGeometry PCapsuleGeom( CollisionShape.GetCapsuleRadius(), CollisionShape.GetCapsuleAxisHalfLength() ); PxTransform PGeomPose = ConvertToPhysXCapsulePose( FTransform(Rot,Pos) ); return GeomOverlapSingle(this, PCapsuleGeom, PGeomPose, OutOverlap, DefaultCollisionChannel, Params, FCollisionResponseParams::DefaultResponseParam, ObjectQueryParams); } default: // invalid point ensure(false); } #endif //WITH_PHYSX return false; }
void FConstraintInstance::UpdateDriveTarget() { #if WITH_PHYSX if (PxD6Joint* PJoint = GetUnbrokenJoint()) { FQuat OrientationTargetQuat(AngularOrientationTarget); PJoint->setDrivePosition(PxTransform(U2PVector(LinearPositionTarget), U2PQuat(OrientationTargetQuat))); PJoint->setDriveVelocity(U2PVector(LinearVelocityTarget), U2PVector(RevolutionsToRads(AngularVelocityTarget))); } #endif }
void FConstraintInstance::UpdateDriveTarget() { #if WITH_PHYSX ExecuteOnUnbrokenJointReadWrite([&] (PxD6Joint* Joint) { FQuat OrientationTargetQuat(AngularOrientationTarget); Joint->setDrivePosition(PxTransform(U2PVector(LinearPositionTarget), U2PQuat(OrientationTargetQuat))); Joint->setDriveVelocity(U2PVector(LinearVelocityTarget), U2PVector(RevolutionsToRads(AngularVelocityTarget))); }); #endif }
void UDestructibleComponent::AddForceAtLocation( FVector Force, FVector Location, FName BoneName /*= NAME_None*/ ) { #if WITH_APEX ExecuteOnPhysicsReadWrite([&] { int32 ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName)); if (PxRigidDynamic* Actor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx)) { PxRigidBodyExt::addForceAtPos(*Actor, U2PVector(Force), U2PVector(Location), PxForceMode::eFORCE); } }); #endif }
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; }
EConvertQueryResult AddSweepResults(bool& OutHasValidBlockingHit, const UWorld* World, int32 NumHits, PxSweepHit* Hits, float CheckLength, const PxFilterData& QueryFilter, TArray<FHitResult>& OutHits, const FVector& StartLoc, const FVector& EndLoc, const PxGeometry& Geom, const PxTransform& QueryTM, float MaxDistance, bool bReturnFaceIndex, bool bReturnPhysMat) { OutHits.Reserve(OutHits.Num() + NumHits); EConvertQueryResult ConvertResult = EConvertQueryResult::Valid; bool bHadBlockingHit = false; const PxVec3 PDir = U2PVector((EndLoc - StartLoc).GetSafeNormal()); for(int32 i=0; i<NumHits; i++) { PxSweepHit& PHit = Hits[i]; checkSlow(PHit.flags & PxHitFlag::eDISTANCE); if(PHit.distance <= MaxDistance) { PHit.faceIndex = FindFaceIndex(PHit, PDir); FHitResult& NewResult = OutHits[OutHits.AddDefaulted()]; if (ConvertQueryImpactHit(World, PHit, NewResult, CheckLength, QueryFilter, StartLoc, EndLoc, &Geom, QueryTM, bReturnFaceIndex, bReturnPhysMat) == EConvertQueryResult::Valid) { bHadBlockingHit |= NewResult.bBlockingHit; } else { // Reject invalid result (this should be rare). Remove from the results. OutHits.Pop(/*bAllowShrinking=*/ false); ConvertResult = EConvertQueryResult::Invalid; } } } // Sort results from first to last hit OutHits.Sort( FCompareFHitResultTime() ); OutHasValidBlockingHit = bHadBlockingHit; return ConvertResult; }
void AddRadialImpulseToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bVelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from origin to COM float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // Scale by U2PScale here, because units are velocity * mass. float ImpulseMag = Strength; if (Falloff == RIF_Linear) { ImpulseMag *= (1.0f - (Mag / Radius)); } PxVec3 PImpulse = PDelta * ImpulseMag; PxForceMode::Enum Mode = bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE; PRigidBody.addForce(PImpulse, Mode); } #endif // WITH_PHYSX }
void AddSpheresToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for (int32 i = 0; i < BodySetup->AggGeom.SphereElems.Num(); i++) { const FKSphereElem& SphereElem = BodySetup->AggGeom.SphereElems[i]; PxSphereGeometry PSphereGeom; PSphereGeom.radius = (SphereElem.Radius * MinScaleAbs); if (ensure(PSphereGeom.isValid())) { FVector LocalOrigin = RelativeTM.TransformPosition(SphereElem.Center); PxTransform PLocalPose(U2PVector(LocalOrigin)); PLocalPose.p *= MinScale; ensure(PLocalPose.isValid()); { const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PSphereGeom.radius); AttachShape_AssumesLocked(PSphereGeom, PLocalPose, ContactOffset); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddSpheresToRigidActor: [%s] SphereElem[%d] invalid"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } }
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 }
void AddRadialForceToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bAccelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // If using linear falloff, scale with distance. float ForceMag = Strength; if (Falloff == RIF_Linear) { ForceMag *= (1.0f - (Mag / Radius)); } // Apply force PxVec3 PImpulse = PDelta * ForceMag; PRigidBody.addForce(PImpulse, bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE); } #endif // WITH_PHYSX }
bool UDestructibleComponent::SweepComponent(FHitResult& OutHit, const FVector Start, const FVector End, const FCollisionShape &CollisionShape, bool bTraceComplex/*=false*/) { bool bHaveHit = false; #if WITH_APEX if (ApexDestructibleActor != NULL) { PxF32 HitTime = 0.0f; PxVec3 HitNormal; int32 ChunkIdx = ApexDestructibleActor->obbSweep(HitTime, HitNormal, U2PVector(Start), U2PVector(CollisionShape.GetExtent()), PxMat33::createIdentity(), U2PVector(End - Start), NxDestructibleActorRaycastFlags::AllChunks); if (ChunkIdx != NxModuleDestructibleConst::INVALID_CHUNK_INDEX && HitTime <= 1.0f) { PxRigidDynamic* PActor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx); if (PActor != NULL) { // Store body instance state FFakeBodyInstanceState PrevState; SetupFakeBodyInstance(PActor, ChunkIdx, &PrevState); bHaveHit = Super::SweepComponent(OutHit, Start, End, CollisionShape, bTraceComplex); // Reset original body instance ResetFakeBodyInstance(PrevState); } } } #endif return bHaveHit; }
bool UDestructibleComponent::LineTraceComponent( FHitResult& OutHit, const FVector Start, const FVector End, const FCollisionQueryParams& Params ) { bool bHaveHit = false; #if WITH_APEX if (ApexDestructibleActor != NULL) { PxF32 HitTime = 0.0f; PxVec3 HitNormal; int32 ChunkIdx = ApexDestructibleActor->rayCast(HitTime, HitNormal, U2PVector(Start), U2PVector(End-Start), NxDestructibleActorRaycastFlags::AllChunks); if (ChunkIdx != NxModuleDestructibleConst::INVALID_CHUNK_INDEX && HitTime <= 1.0f) { PxRigidDynamic* PActor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx); if (PActor != NULL) { // Store body instance state FFakeBodyInstanceState PrevState; SetupFakeBodyInstance(PActor, ChunkIdx, &PrevState); bHaveHit = Super::LineTraceComponent(OutHit, Start, End, Params); // Reset original body instance ResetFakeBodyInstance(PrevState); } } } #endif return bHaveHit; }
void AddTriMeshToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for(PxTriangleMesh* TriMesh : BodySetup->TriMeshes) { PxTriangleMeshGeometry PTriMeshGeom; PTriMeshGeom.triangleMesh = TriMesh; PTriMeshGeom.scale.scale = U2PVector(Scale3D); if (BodySetup->bDoubleSidedGeometry) { PTriMeshGeom.meshFlags |= PxMeshGeometryFlag::eDOUBLE_SIDED; } if (PTriMeshGeom.isValid()) { PxTransform PElementTransform = U2PTransform(RelativeTM); // Create without 'sim shape' flag, problematic if it's kinematic, and it gets set later anyway. if (!AttachShape_AssumesLocked(PTriMeshGeom, PElementTransform, MaxContactOffset, PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION)) { UE_LOG(LogPhysics, Log, TEXT("Can't create new mesh shape in AddShapesToRigidActor")); } } else { UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: TriMesh invalid")); } } }
void AddConvexElemsToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for (int32 i = 0; i < BodySetup->AggGeom.ConvexElems.Num(); i++) { const FKConvexElem& ConvexElem = BodySetup->AggGeom.ConvexElems[i]; if (ConvexElem.ConvexMesh) { PxTransform PLocalPose; bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose); PxConvexMeshGeometry PConvexGeom; PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh; PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs()); FTransform ConvexTransform = ConvexElem.GetTransform(); if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0) { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(BodySetup->GetOuter()), i); } if (ConvexTransform.IsValid()) { PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM); PLocalPose.q *= PElementTransform.q; PLocalPose.p = PElementTransform.p; PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; if (PConvexGeom.isValid()) { PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents(); ensure(PLocalPose.isValid()); { const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement()); AttachShape_AssumesLocked(PConvexGeom, PLocalPose, ContactOffset); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *BodySetup->GetPathName()); } } }
PxTransform UMatrix2PTransform(const FMatrix& UTM) { PxQuat PQuat = U2PQuat(UTM.ToQuat()); PxVec3 PPos = U2PVector(UTM.GetOrigin()); PxTransform Result(PPos, PQuat); return Result; }
PxTransform U2PTransform(const FTransform& UTransform) { PxQuat PQuat = U2PQuat(UTransform.GetRotation()); PxVec3 PPos = U2PVector(UTransform.GetLocation()); PxTransform Result(PPos, PQuat); return Result; }
static FVector FindBoxOpposingNormal(const PxLocationHit& PHit, const FVector& TraceDirectionDenorm, const FVector InNormal) { // We require normal info for our algorithm. const bool bNormalData = (PHit.flags & PxHitFlag::eNORMAL); if (!bNormalData) { return InNormal; } PxBoxGeometry PxBoxGeom; const bool bReadGeomSuccess = PHit.shape->getBoxGeometry(PxBoxGeom); check(bReadGeomSuccess); // This function should only be used for box geometry const PxTransform LocalToWorld = PxShapeExt::getGlobalPose(*PHit.shape, *PHit.actor); // Find which faces were included in the contact normal, and for multiple faces, use the one most opposing the sweep direction. const PxVec3 ContactNormalLocal = LocalToWorld.rotateInv(PHit.normal); const float* ContactNormalLocalPtr = &ContactNormalLocal.x; const PxVec3 TraceDirDenormWorld = U2PVector(TraceDirectionDenorm); const float* TraceDirDenormWorldPtr = &TraceDirDenormWorld.x; const PxVec3 TraceDirDenormLocal = LocalToWorld.rotateInv(TraceDirDenormWorld); const float* TraceDirDenormLocalPtr = &TraceDirDenormLocal.x; PxVec3 BestLocalNormal(ContactNormalLocal); float* BestLocalNormalPtr = &BestLocalNormal.x; float BestOpposingDot = FLT_MAX; for (int32 i=0; i < 3; i++) { // Select axis of face to compare to, based on normal. if (ContactNormalLocalPtr[i] > KINDA_SMALL_NUMBER) { const float TraceDotFaceNormal = TraceDirDenormLocalPtr[i]; // TraceDirDenormLocal.dot(BoxFaceNormal) if (TraceDotFaceNormal < BestOpposingDot) { BestOpposingDot = TraceDotFaceNormal; BestLocalNormal = PxVec3(0.f); BestLocalNormalPtr[i] = 1.f; } } else if (ContactNormalLocalPtr[i] < -KINDA_SMALL_NUMBER) { const float TraceDotFaceNormal = -TraceDirDenormLocalPtr[i]; // TraceDirDenormLocal.dot(BoxFaceNormal) if (TraceDotFaceNormal < BestOpposingDot) { BestOpposingDot = TraceDotFaceNormal; BestLocalNormal = PxVec3(0.f); BestLocalNormalPtr[i] = -1.f; } } } // Fill in result const PxVec3 WorldNormal = LocalToWorld.rotate(BestLocalNormal); return P2UVector(WorldNormal); }
void UDestructibleComponent::ApplyRadiusDamage(float BaseDamage, const FVector& HurtOrigin, float DamageRadius, float ImpulseStrength, bool bFullDamage) { #if WITH_APEX if (ApexDestructibleActor != NULL) { // Transfer damage information to the APEX NxDestructibleActor interface ApexDestructibleActor->applyRadiusDamage(BaseDamage, ImpulseStrength, U2PVector( HurtOrigin ), DamageRadius, bFullDamage ? false : true); } #endif }
void UBodySetup::AddTriMeshToRigidActor(PxRigidActor* PDestActor, const FVector& Scale3D, const FVector& Scale3DAbs) const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); PxMaterial* PDefaultMat = GetDefaultPhysMaterial(); if(TriMesh || TriMeshNegX) { PxTransform PLocalPose; bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose); // Only case where TriMeshNegX should be null is BSP, which should not require negX version if (bUseNegX && TriMeshNegX == NULL) { UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: Want to use NegX but it doesn't exist! %s"), *GetPathName()); } PxTriangleMesh* UseTriMesh = bUseNegX ? TriMeshNegX : TriMesh; if (UseTriMesh != NULL) { PxTriangleMeshGeometry PTriMeshGeom; PTriMeshGeom.triangleMesh = bUseNegX ? TriMeshNegX : TriMesh; PTriMeshGeom.scale.scale = U2PVector(Scale3DAbs); if (bDoubleSidedGeometry) { PTriMeshGeom.meshFlags |= PxMeshGeometryFlag::eDOUBLE_SIDED; } if (PTriMeshGeom.isValid()) { ensure(PLocalPose.isValid()); // Create without 'sim shape' flag, problematic if it's kinematic, and it gets set later anyway. PxShape* NewShape = PDestActor->createShape(PTriMeshGeom, *PDefaultMat, PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION); if (NewShape) { NewShape->setLocalPose(PLocalPose); NewShape->setContactOffset(MaxContactOffset); } else { UE_LOG(LogPhysics, Log, TEXT("Can't create new mesh shape in AddShapesToRigidActor")); } } else { UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: TriMesh invalid")); } } } }
void FPhysScene::AddForceAtPosition_AssumesLocked(FBodyInstance* BodyInstance, const FVector& Force, const FVector& Position, bool bAllowSubstepping) { #if WITH_PHYSX if (PxRigidBody * PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked()) { #if WITH_SUBSTEPPING uint32 BodySceneType = SceneType_AssumesLocked(BodyInstance); if (bAllowSubstepping && IsSubstepping(BodySceneType)) { FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[BodySceneType]; PhysSubStepper->AddForceAtPosition_AssumesLocked(BodyInstance, Force, Position); } else #endif { PxRigidBodyExt::addForceAtPos(*PRigidBody, U2PVector(Force), U2PVector(Position), PxForceMode::eFORCE, true); } } #endif }
/** Applies forces - Assumes caller has obtained writer lock */ void FPhysSubstepTask::ApplyForces(const FPhysTarget & PhysTarget, FBodyInstance * BodyInstance) { #if WITH_PHYSX /** Apply Forces */ PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic(); for (int32 i = 0; i < PhysTarget.Forces.Num(); ++i) { const FForceTarget & ForceTarget = PhysTarget.Forces[i]; if (ForceTarget.bPosition) { PxRigidBodyExt::addForceAtPos(*PRigidDynamic, U2PVector(ForceTarget.Force), U2PVector(ForceTarget.Position), PxForceMode::eFORCE, true); } else { PRigidDynamic->addForce(U2PVector(ForceTarget.Force), PxForceMode::eFORCE, true); } } #endif }
/** Applies forces - Assumes caller has obtained writer lock */ void FPhysSubstepTask::ApplyForces_AssumesLocked(const FPhysTarget& PhysTarget, FBodyInstance* BodyInstance) { #if WITH_PHYSX /** Apply Forces */ PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked(); for (int32 i = 0; i < PhysTarget.Forces.Num(); ++i) { const FForceTarget& ForceTarget = PhysTarget.Forces[i]; if (ForceTarget.bPosition) { PxRigidBodyExt::addForceAtPos(*PRigidBody, U2PVector(ForceTarget.Force), U2PVector(ForceTarget.Position), PxForceMode::eFORCE, true); } else { PRigidBody->addForce(U2PVector(ForceTarget.Force), ForceTarget.bAccelChange ? PxForceMode::eACCELERATION : 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 UDestructibleComponent::ApplyDamage(float DamageAmount, const FVector& HitLocation, const FVector& ImpulseDir, float ImpulseStrength) { #if WITH_APEX if (ApexDestructibleActor != NULL) { const FVector& NormalizedImpactDir = ImpulseDir.GetSafeNormal(); // Transfer damage information to the APEX NxDestructibleActor interface ApexDestructibleActor->applyDamage(DamageAmount, ImpulseStrength, U2PVector( HitLocation ), U2PVector( ImpulseDir )); } #endif }
void UDestructibleComponent::AddImpulse( FVector Impulse, FName BoneName /*= NAME_None*/, bool bVelChange /*= false*/ ) { #if WITH_APEX ExecuteOnPhysicsReadWrite([&] { const int32 ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName)); if(PxRigidDynamic* Actor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx)) { Actor->addForce(U2PVector(Impulse), bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE); } }); #endif }
void UDestructibleComponent::AddForce( FVector Force, FName BoneName /*= NAME_None*/, bool bAccelChange /* = false */ ) { #if WITH_APEX ExecuteOnPhysicsReadWrite([&] { const int32 ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName)); if (PxRigidDynamic* Actor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx)) { Actor->addForce(U2PVector(Force), bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE); } }); #endif }
/** Applies torques - Assumes caller has obtained writer lock */ void FPhysSubstepTask::ApplyTorques(const FPhysTarget & PhysTarget, FBodyInstance * BodyInstance) { #if WITH_PHYSX /** Apply Torques */ PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic(); for (int32 i = 0; i < PhysTarget.Torques.Num(); ++i) { const FTorqueTarget & TorqueTarget = PhysTarget.Torques[i]; PRigidDynamic->addTorque(U2PVector(TorqueTarget.Torque), 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 UDestructibleComponent::AddForce( FVector Force, FName BoneName /*= NAME_None*/, bool bAccelChange /* = false */ ) { #if WITH_APEX int32 ChunkIdx = NxModuleDestructibleConst::INVALID_CHUNK_INDEX; if (BoneName != NAME_None) { ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName)); } PxRigidDynamic* Actor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx); Actor->addForce(U2PVector(Force), bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE); #endif }
/** Applies torques - Assumes caller has obtained writer lock */ void FPhysSubstepTask::ApplyTorques_AssumesLocked(const FPhysTarget& PhysTarget, FBodyInstance* BodyInstance) { #if WITH_PHYSX /** Apply Torques */ PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked(); for (int32 i = 0; i < PhysTarget.Torques.Num(); ++i) { const FTorqueTarget& TorqueTarget = PhysTarget.Torques[i]; PRigidBody->addTorque(U2PVector(TorqueTarget.Torque), TorqueTarget.bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE, true); } #endif }