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

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

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

		if (FBodyInstance* BodyInstance = FPhysxUserData::Get<FBodyInstance>(RigidActor->userData))
		{
			if (BodyInstance->InstanceBodyIndex == INDEX_NONE && BodyInstance->OwnerComponent.IsValid() && BodyInstance->IsInstanceSimulatingPhysics())
			{
				ActiveBodyInstances[SceneType].Add(BodyInstance);
			}
		}
		else if (const FDestructibleChunkInfo* DestructibleChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(RigidActor->userData))
		{
			ActiveDestructibleActors[SceneType].Add(RigidActor);
		}
		
	}
}
void UShapeComponent::CreateShapeBodySetupIfNeeded()
{
	if (ShapeBodySetup == nullptr || ShapeBodySetup->IsPendingKill())
	{
		ShapeBodySetup = NewObject<UBodySetup>(this);
		if (GUObjectArray.IsDisregardForGC(this))
		{
			ShapeBodySetup->AddToRoot();
		}

		ShapeBodySetup->CollisionTraceFlag = CTF_UseSimpleAsComplex;
		AddShapeToGeomArray<ShapeElemType>();
		ShapeBodySetup->bNeverNeedsCookedCollisionData = true;
		bUseArchetypeBodySetup = false;	//We're making our own body setup, so don't use the archetype's.

		//Update bodyinstance and shapes
		BodyInstance.BodySetup = ShapeBodySetup;
		{
			if(BodyInstance.IsValidBodyInstance())
			{
#if WITH_PHYSX
				SCOPED_SCENE_READ_LOCK(GetPhysXSceneFromIndex(BodyInstance.GetSceneIndex()));
				TArray<PxShape *> PShapes;
				BodyInstance.GetAllShapes_AssumesLocked(PShapes);

				check(PShapes.Num() == 1);	//Shape component should only have 1 shape
				SetShapeToNewGeom<ShapeElemType>(PShapes[0]);
#endif
			}
		}
	}
}
예제 #3
0
bool FPhysScene::GetKinematicTarget(const FBodyInstance* BodyInstance, FTransform& OutTM) const
{
#if WITH_PHYSX
	if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic())
	{
#if WITH_SUBSTEPPING
		uint32 BodySceneType = SceneType(BodyInstance);
		if (IsSubstepping(BodySceneType))
		{
			FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[BodySceneType];
			return PhysSubStepper->GetKinematicTarget(BodyInstance, OutTM);
		}
		else
#endif
		{

			SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
			PxTransform POutTM;
			bool validTM = PRigidDynamic->getKinematicTarget(POutTM);
			if (validTM)
			{
				OutTM = P2UTransform(POutTM);
				return true;
			}
		}
	}
#endif

	return false;
}
예제 #4
0
void GatherPhysXStats(PxScene* PScene, uint32 SceneType)
{
	/** Gather PhysX stats */
	if (SceneType == 0)
	{
		if (PScene)
		{
			SCOPED_SCENE_READ_LOCK(PScene);
			PxSimulationStatistics SimStats;
			PScene->getSimulationStatistics(SimStats);

			SET_DWORD_STAT(STAT_NumActiveConstraints, SimStats.nbActiveConstraints);
			SET_DWORD_STAT(STAT_NumActiveSimulatedBodies, SimStats.nbActiveDynamicBodies);
			SET_DWORD_STAT(STAT_NumActiveKinematicBodies, SimStats.nbActiveKinematicBodies);
			SET_DWORD_STAT(STAT_NumStaticBodies, SimStats.nbStaticBodies);
			SET_DWORD_STAT(STAT_NumMobileBodies, SimStats.nbDynamicBodies);
			
			SET_DWORD_STAT(STAT_NumBroadphaseAdds, SimStats.getNbBroadPhaseAdds(PxSimulationStatistics::VolumeType::eRIGID_BODY));
			SET_DWORD_STAT(STAT_NumBroadphaseRemoves, SimStats.getNbBroadPhaseRemoves(PxSimulationStatistics::VolumeType::eRIGID_BODY));

			uint32 NumShapes = 0;
			for (int32 GeomType = 0; GeomType < PxGeometryType::eGEOMETRY_COUNT; ++GeomType)
			{
				NumShapes += SimStats.nbShapes[GeomType];
			}

			SET_DWORD_STAT(STAT_NumShapes, NumShapes);

		}

	}

#if 0	//this is not reliable right now
	else if (SceneType == 1 & UPhysicsSettings::Get()->bEnableAsyncScene)
	{
		//Having to duplicate because of macros. In theory we can fix this but need to get this quickly
		PxSimulationStatistics SimStats;
		PScene->getSimulationStatistics(SimStats);

		SET_DWORD_STAT(STAT_NumActiveConstraintsAsync, SimStats.nbActiveConstraints);
		SET_DWORD_STAT(STAT_NumActiveSimulatedBodiesAsync, SimStats.nbActiveDynamicBodies);
		SET_DWORD_STAT(STAT_NumActiveKinematicBodiesAsync, SimStats.nbActiveKinematicBodies);
		SET_DWORD_STAT(STAT_NumStaticBodiesAsync, SimStats.nbStaticBodies);
		SET_DWORD_STAT(STAT_NumMobileBodiesAsync, SimStats.nbDynamicBodies);

		SET_DWORD_STAT(STAT_NumBroadphaseAddsAsync, SimStats.getNbBroadPhaseAdds(PxSimulationStatistics::VolumeType::eRIGID_BODY));
		SET_DWORD_STAT(STAT_NumBroadphaseRemovesAsync, SimStats.getNbBroadPhaseRemoves(PxSimulationStatistics::VolumeType::eRIGID_BODY));

		uint32 NumShapes = 0;
		for (int32 GeomType = 0; GeomType < PxGeometryType::eGEOMETRY_COUNT; ++GeomType)
		{
			NumShapes += SimStats.nbShapes[GeomType];
		}

		SET_DWORD_STAT(STAT_NumShapesAsync, NumShapes);
	}
#endif
}
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
}
예제 #6
0
bool FConstraintInstance::ExecuteOnUnbrokenJointReadOnly(TFunctionRef<void(const physx::PxD6Joint*)> Func) const
{
	if(ConstraintData)
	{
		SCOPED_SCENE_READ_LOCK(ConstraintData->getScene());

		if(!(ConstraintData->getConstraintFlags()&PxConstraintFlag::eBROKEN))
		{
			Func(ConstraintData);
			return true;
		}
	}

	return false;
}
예제 #7
0
void FPhysSubstepTask::AddTorque(FBodyInstance * Body, const FVector & Torque)
{
    check(Body);

    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We should only apply torque on non kinematic actors
    if (IsRigidDynamicNonKinematic(PRigidDynamic))
    {
        FTorqueTarget TorqueTarget;
        TorqueTarget.Torque = Torque;

        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.Torques.Add(TorqueTarget);
    }
}
예제 #8
0
void FPhysSubstepTask::AddForce(FBodyInstance * Body, const FVector & Force)
{
    check(Body);
    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We should only apply forces on non kinematic actors
    if (IsRigidDynamicNonKinematic(PRigidDynamic))
    {

        FForceTarget ForceTarget;
        ForceTarget.bPosition = false;
        ForceTarget.Force = Force;

        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.Forces.Add(ForceTarget);
    }
}
예제 #9
0
void FPhysSubstepTask::SetKinematicTarget(FBodyInstance * Body, const FTransform & TM)
{
    check(Body);
    TM.DiagnosticCheckNaN_All();

    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We only interpolate kinematic actors
    if (!IsRigidDynamicNonKinematic(PRigidDynamic))
    {
        FKinematicTarget KinmaticTarget(Body, TM);
        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.bKinematicTarget = true;
        TargetState.KinematicTarget = KinmaticTarget;
    }

}
예제 #10
0
bool FPhysSubstepTask::GetKinematicTarget(const FBodyInstance* Body, FTransform& OutTM) const
{
#if WITH_PHYSX
	const PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
	SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
	if (const FPhysTarget* TargetState = PhysTargetBuffers[External].Find(Body))
	{
		if (TargetState->bKinematicTarget)
		{
			OutTM = TargetState->KinematicTarget.TargetTM;
			return true;
		}
	}
#endif

	return false;
}
예제 #11
0
bool UDestructibleComponent::ExecuteOnPhysicsReadOnly(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_READ_LOCK(PScene);
		Func();

		return true;
	}
#endif

	return false;
}
예제 #12
0
void FPhysScene::SyncComponentsToBodies(uint32 SceneType)
{
	SCOPE_CYCLE_COUNTER(STAT_TotalPhysicsTime);
	SCOPE_CYCLE_COUNTER(STAT_SyncComponentsToBodies);

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

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

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

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

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

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

#if WITH_APEX
	if (ActiveDestructibleActors[SceneType].Num())
	{
		SCOPED_SCENE_READ_LOCK(GetPhysXScene(SceneType));
		UDestructibleComponent::UpdateDestructibleChunkTM(ActiveDestructibleActors[SceneType]);
	}
#endif
}
예제 #13
0
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const
{
	if(GetPhysicsScene() == NULL)
	{
		return false;
	}

	if(PrimComp == NULL)
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : No PrimComp"));
		return false;
	}

	// if target is skeletalmeshcomponent and do not support singlebody physics
	if ( !PrimComp->ShouldTrackOverlaps() )
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName());
		return false;
	}

	ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType();

#if WITH_PHYSX
	// if extent is 0, do line trace
	if (PrimComp->IsZeroExtent())
	{
		return RaycastMulti(this, OutHits, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()));
	}

	PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor();
	if(PRigidActor == NULL)
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName());
		return false;
	}
	PxScene * const PScene = PRigidActor->getScene();

	OutHits.Empty();

	// Get all the shapes from the actor
	TArray<PxShape*, TInlineAllocator<8>> PShapes;
	{
		SCOPED_SCENE_READ_LOCK(PScene);
		PShapes.AddZeroed(PRigidActor->getNbShapes());
		PRigidActor->getShapes(PShapes.GetData(), PShapes.Num());
	}

	// calculate the test global pose of the actor
	PxTransform PGlobalStartPose = U2PTransform(FTransform(Start));
	PxTransform PGlobalEndPose = U2PTransform(FTransform(End));

	bool bHaveBlockingHit = false;
	PxQuat PGeomRot = U2PQuat(Rot.Quaternion());

	// Iterate over each shape
	SCENE_LOCK_READ(PScene);
	for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++)
	{
		PxShape* PShape = PShapes[ShapeIdx];
		check(PShape);

		TArray<struct FHitResult> Hits;

		// Calc shape global pose
		PxTransform PLocalShape = PShape->getLocalPose();
		PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape);
		PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape);
		// consider localshape rotation for shape rotation
		PxQuat PShapeRot = PGeomRot * PLocalShape.q;

		GET_GEOMETRY_FROM_SHAPE(PGeom, PShape);

		if(PGeom != NULL)
		{
			SCENE_UNLOCK_READ(PScene);
			if (GeomSweepMulti(this, *PGeom, PShapeRot, Hits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())))
			{
				bHaveBlockingHit = true;
			}

			OutHits.Append(Hits);
			SCENE_LOCK_READ(PScene);
		}
	}
	SCENE_UNLOCK_READ(PScene);

	return bHaveBlockingHit;
#endif //WITH_PHYSX
	return false;
}