void USkeletalMeshComponent::PostBlendPhysics()
{
	SCOPE_CYCLE_COUNTER(STAT_UpdateLocalToWorldAndOverlaps);
	
	// Flip bone buffer and send 'post anim' notification
	FinalizeBoneTransform();

	// Update Child Transform - The above function changes bone transform, so will need to update child transform
	UpdateChildTransforms();

	// animation often change overlap. 
	UpdateOverlaps();

	// Cached local bounds are now out of date
	InvalidateCachedBounds();

	// update bounds
	UpdateBounds();

	// Need to send new bounds to 
	MarkRenderTransformDirty();

	// New bone positions need to be sent to render thread
	MarkRenderDynamicDataDirty();
}
示例#2
0
void UDestructibleComponent::SetChunksWorldTM(const TArray<FUpdateChunksInfo>& UpdateInfos)
{
	const FQuat InvRotation = ComponentToWorld.GetRotation().Inverse();

	for (const FUpdateChunksInfo& UpdateInfo : UpdateInfos)
	{
		// Bone 0 is a dummy root bone
		const int32 BoneIndex = ChunkIdxToBoneIdx(UpdateInfo.ChunkIndex);
		const FVector WorldTranslation	= UpdateInfo.WorldTM.GetLocation();
		const FQuat WorldRotation		= UpdateInfo.WorldTM.GetRotation();

		const FQuat BoneRotation = InvRotation*WorldRotation;
		const FVector BoneTranslation = InvRotation.RotateVector(WorldTranslation - ComponentToWorld.GetTranslation()) / ComponentToWorld.GetScale3D();

		GetEditableSpaceBases()[BoneIndex] = FTransform(BoneRotation, BoneTranslation);
	}

	// Mark the transform as dirty, so the bounds are updated and sent to the render thread
	MarkRenderTransformDirty();

	// New bone positions need to be sent to render thread
	MarkRenderDynamicDataDirty();

	//Update bone visibilty and flip the editable space base buffer
	FlipEditableSpaceBases();
}
示例#3
0
void UDestructibleComponent::SetChunkVisible( int32 ChunkIndex, bool bVisible )
{
#if WITH_APEX
	// Bone 0 is a dummy root bone
	const int32 BoneIndex = ChunkIdxToBoneIdx(ChunkIndex);

	if( bVisible )
	{
		UnHideBone(BoneIndex);

		if (NULL != ApexDestructibleActor)
		{
			physx::PxShape** PShapes;
			const physx::PxU32 PShapeCount = ApexDestructibleActor->getChunkPhysXShapes(PShapes, ChunkIndex);
			if (PShapeCount > 0)
			{
				const physx::PxMat44 ChunkPoseRT = ApexDestructibleActor->getChunkPose(ChunkIndex);	// Unscaled
				const physx::PxTransform Transform(ChunkPoseRT);
				SetChunkWorldRT(ChunkIndex, P2UQuat(Transform.q), P2UVector(Transform.p));
			}
		}
	}
	else
	{
		HideBone(BoneIndex, PBO_None);
	}

	// Mark the transform as dirty, so the bounds are updated and sent to the render thread
	MarkRenderTransformDirty();

	// New bone positions need to be sent to render thread
	MarkRenderDynamicDataDirty();
#endif
}
void UDestructibleComponent::SetChunkWorldRT( int32 ChunkIndex, const FQuat& WorldRotation, const FVector& WorldTranslation )
{
	// Bone 0 is a dummy root bone
	const int32 BoneIndex = ChunkIdxToBoneIdx(ChunkIndex);

	// Mark the transform as dirty, so the bounds are updated and sent to the render thread
	MarkRenderTransformDirty();

#if 0
	// Scale is already applied to the ComponentToWorld transform, and is carried into the bones _locally_.
	// So there is no need to set scale in the bone local transforms
	const FTransform WorldRT(WorldRotation, WorldTranslation, ComponentToWorld.GetScale3D());
	SpaceBases(BoneIndex) = WorldRT*ComponentToWorld.Inverse();
#elif 1
	// More optimal form of the above
	const FQuat BoneRotation = ComponentToWorld.GetRotation().Inverse()*WorldRotation;
	const FVector BoneTranslation = ComponentToWorld.GetRotation().Inverse().RotateVector(WorldTranslation - ComponentToWorld.GetTranslation())/ComponentToWorld.GetScale3D();
	SpaceBases[BoneIndex] = FTransform(BoneRotation, BoneTranslation);
#endif
}
void UGeometryCacheComponent::UpdateTrackSectionMatrixData(int32 SectionIndex, const FMatrix& WorldMatrix)
{
	check(SectionIndex < TrackSections.Num() && "Invalid SectionIndex");
	// Reset this section (in case it already existed)
	FTrackRenderData& UpdateSection = TrackSections[SectionIndex];

	// Update the WorldMatrix only
	UpdateSection.WorldMatrix = WorldMatrix;

	if (!IsRenderStateDirty() && SceneProxy != nullptr)
	{
		// Update it within the scene proxy
		SceneProxy->UpdateSectionWorldMatrix(SectionIndex, WorldMatrix);
	}

	// Update local bounds
	UpdateLocalBounds();

	// Mark transform Dirty
	MarkRenderTransformDirty();
}
void UDestructibleComponent::SetChunkVisible( int32 ChunkIndex, bool bVisible )
{
	// Bone 0 is a dummy root bone
	const int32 BoneIndex = ChunkIdxToBoneIdx(ChunkIndex);
	bool bClearActorFromChunkInfo = false;

	if( bVisible )
	{
		UnHideBone(BoneIndex);
#if WITH_APEX
		PxRigidDynamic* PActor = ApexDestructibleActor != NULL ? ApexDestructibleActor->getChunkPhysXActor(ChunkIndex) : NULL;

		UDestructibleMesh* DMesh = GetDestructibleMesh();

		if (PActor != NULL)
		{
			// If actor has already a chunk info and userdata, we just make sure it is valid and update the 
			// physx actor if needed. We do NOT do this for FormExtended structures, as in this case, the shapes/actors
			// are moved to the 1st structure object internally by APEX.
			if(PActor->userData != NULL && !DMesh->DefaultDestructibleParameters.Flags.bFormExtendedStructures)
			{
				FDestructibleChunkInfo* CI = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData);
				checkf(CI, TEXT("If a chunk actor has user data and it is not a DestructibleChunkInfo, something is messed up."));
				//check(CI->OwningComponent == this);

				if (CI->ChunkIndex != ChunkIndex)
				{
					// grab the old actor and clear its user data, as we steal the ChunkInfo here
					if (CI->Actor && CI->Actor != PActor)
					{
						CI->Actor->userData = NULL;
					}
					CI->ChunkIndex = ChunkIndex;
				}

				CI->OwningComponent = this;
				CI->Actor = PActor;
			}
			else if (PActor->userData == NULL)
			{
				// Setup the user data to have a proper chunk - actor mapping 
				int32 InfoIndex = ChunkInfos.AddUninitialized();

				FDestructibleChunkInfo* CI = &ChunkInfos[InfoIndex];
				CI->Index = InfoIndex;
				CI->ChunkIndex = ChunkIndex;
				CI->OwningComponent = this;
				CI->Actor = PActor;

				int32 UserDataIdx = PhysxChunkUserData.Add(FPhysxUserData(CI));
				check(InfoIndex == UserDataIdx);

				PActor->userData = &PhysxChunkUserData[UserDataIdx];

				// Set collision response to non-root chunks
				if (GetDestructibleMesh()->ApexDestructibleAsset->getChunkParentIndex(ChunkIndex) >= 0)
				{
					SetCollisionResponseForActor(ChunkCollisionResponse, PActor, ChunkIndex);
				}
			}
		}
		else
		{
			bClearActorFromChunkInfo = true;
		}
#endif // WITH_APEX
	}
	else
	{
		HideBone(BoneIndex, PBO_None);
		bClearActorFromChunkInfo = true;
	}

#if WITH_APEX
	if (bClearActorFromChunkInfo)
	{
		// Make sure we clear the physx actor pointer of the chunk info as it might (and probably will) be
		// invalid from now on
		for (int32 i=0; i < ChunkInfos.Num(); ++i)
		{
			if (ChunkInfos[i].ChunkIndex == ChunkIndex)
			{
				ChunkInfos[i].Actor = NULL;
				break;
			}
		}
	}
#endif // WITH_APEX

	// Mark the transform as dirty, so the bounds are updated and sent to the render thread
	MarkRenderTransformDirty();

	// New bone positions need to be sent to render thread
	MarkRenderDynamicDataDirty();
}