예제 #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_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;
}
예제 #3
0
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
}
예제 #4
0
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);
		}
	}
}
예제 #6
0
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
}
예제 #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)
}
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
}
예제 #11
0
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
}
예제 #12
0
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;
}
예제 #13
0
/** 
 *	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

}
예제 #14
0
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;
}
예제 #15
0
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
}
예제 #16
0
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
}
예제 #18
0
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;
}
예제 #19
0
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
}
예제 #20
0
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
}
예제 #21
0
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
}
예제 #22
0
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
}
예제 #23
0
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
			}
		}*/
	}
}
예제 #25
0
void FConstraintInstance::DisableProjection()
{
	SCOPED_SCENE_WRITE_LOCK(ConstraintData->getScene());
	ConstraintData->setConstraintFlag(PxConstraintFlag::ePROJECTION, false);
}
예제 #26
0
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
}