void USkeletalMeshComponent::PostPhysicsTick(FPrimitiveComponentPostPhysicsTickFunction &ThisTickFunction)
{
	Super::PostPhysicsTick(ThisTickFunction);

	// if physics is disabled on dedicated server, no reason to be here. 
	if ( !bEnablePhysicsOnDedicatedServer && IsRunningDedicatedServer() )
	{
		return;
	}

	if (IsRegistered() && IsSimulatingPhysics())
	{
		SyncComponentToRBPhysics();
	}

	// this used to not run if not rendered, but that causes issues such as bounds not updated
	// causing it to not rendered, at the end, I think we should blend body positions
	// for example if you're only simulating, this has to happen all the time
	// whether looking at it or not, otherwise
	// @todo better solution is to check if it has moved by changing SyncComponentToRBPhysics to return true if anything modified
	// and run this if that is true or rendered
	// that will at least reduce the chance of mismatch
	// generally if you move your actor position, this has to happen to approximately match their bounds
	if( Bodies.Num() > 0 && IsRegistered() )
	{
		BlendInPhysics();
	}
}
FVector UPrimitiveComponent::GetComponentVelocity() const
{
	if (IsSimulatingPhysics())
	{
		FBodyInstance* BodyInst = GetBodyInstance();
		if(BodyInst != NULL)
		{
			return BodyInst->GetUnrealWorldVelocity();
		}
	}

	return Super::GetComponentVelocity();
}
bool USkeletalMeshComponent::IsAnySimulatingPhysics() const
{
	if( bUseSingleBodyPhysics )
	{
		return IsSimulatingPhysics();
	}

	for ( int32 BodyIndex=0; BodyIndex<Bodies.Num(); ++BodyIndex )
	{
		if (Bodies[BodyIndex]->IsInstanceSimulatingPhysics())
		{
			return true;
		}
	}

	return false;
}
void UPrimitiveComponent::SyncComponentToRBPhysics()
{
	if(!IsRegistered())
	{
		UE_LOG(LogPhysics, Log, TEXT("SyncComponentToRBPhysics : Component not registered (%s)"), *GetPathName());
		return;
	}

	 // BodyInstance we are going to sync the component to
	FBodyInstance* UseBI = GetBodyInstance();
	if(UseBI == NULL || !UseBI->IsValidBodyInstance())
	{
		UE_LOG(LogPhysics, Log, TEXT("SyncComponentToRBPhysics : Missing or invalid BodyInstance (%s)"), *GetPathName());
		return;
	}

	AActor* Owner = GetOwner();
	if(Owner != NULL)
	{
		if (Owner->IsPendingKill() || !Owner->CheckStillInWorld())
		{
			return;
		}
	}

	if (IsPendingKill() || !IsSimulatingPhysics())
	{
		return;
	}

	// See if the transform is actually different, and if so, move the component to match physics
	const FTransform NewTransform = GetComponentTransformFromBodyInstance(UseBI);	
	if(!NewTransform.EqualsNoScale(ComponentToWorld))
	{
		const FVector MoveBy = NewTransform.GetLocation() - ComponentToWorld.GetLocation();
		const FQuat NewRotation = NewTransform.GetRotation();

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

	// Can't do anything without a SkeletalMesh
	// Do nothing more if no bones in skeleton.
	if( !SkeletalMesh || SpaceBases.Num() == 0 )
	{
		return;
	}
	
	AActor * Owner = GetOwner();
	const FAnimUpdateRateParameters  & UpdateRateParams = Owner ? Owner->AnimUpdateRateParams : FAnimUpdateRateParameters();

	{
		FScopeLockPhysXWriter LockPhysXForWriting;

		// Recalculate the RequiredBones array, if necessary
		if( !bRequiredBonesUpToDate )
		{
			RecalcRequiredBones(PredictedLODLevel);
		}

		// Update rate turned off, evaluate every frame.
		if( !bEnableUpdateRateOptimizations || (UpdateRateParams.GetEvaluationRate() <= 1) )
		{
			// evaluate pure animations, and fill up LocalAtoms
			EvaluateAnimation();
			// We need the mesh space bone transforms now for renderer to get delta from ref pose:
			FillSpaceBases();
			// Invalidate cached bones.
			CachedLocalAtoms.Empty();
			CachedSpaceBases.Empty();
		}
		else
		{
			// figure out if our cache is invalid.
			const bool bInvalidCachedBones = (LocalAtoms.Num() != SkeletalMesh->RefSkeleton.GetNum()) 
				|| (LocalAtoms.Num() != CachedLocalAtoms.Num())
				|| (SpaceBases.Num() != CachedSpaceBases.Num());

			// If cache is invalid, we need to rebuild it. And we can't interpolate.
			// (same path if we're not interpolating and not skipping a frame).
			if( bInvalidCachedBones || (!UpdateRateParams.ShouldInterpolateSkippedFrames() && !UpdateRateParams.ShouldSkipEvaluation()) )
			{
				// evaluate pure animations, and fill up LocalAtoms
				EvaluateAnimation();
				// Fill SpaceBases from LocalAtoms
				FillSpaceBases();

				// Cache bones
				CachedLocalAtoms = LocalAtoms;
				CachedSpaceBases = SpaceBases;
			}
			else
			{
				// No interpolation, just copy
				// @todo: if we don't blend any physics, we could even skip the copy.
				if( !UpdateRateParams.ShouldInterpolateSkippedFrames() )
				{
					LocalAtoms = CachedLocalAtoms;
					SpaceBases = CachedSpaceBases;
				}
				else
				{
					// If we are not skipping evaluation this frame, refresh cache.
					if( !UpdateRateParams.ShouldSkipEvaluation() )
					{
						// Preserve LocalAtoms and SpaceBases, so we can keep interpolation.
						Exchange(LocalAtoms, CachedLocalAtoms);
						Exchange(SpaceBases, CachedSpaceBases);

						// evaluate pure animations, and fill up LocalAtoms
						EvaluateAnimation();
						// Fill SpaceBases from LocalAtoms
						FillSpaceBases();

						Exchange(LocalAtoms, CachedLocalAtoms);
						Exchange(SpaceBases, CachedSpaceBases);
					}

					// Interpolate
					{
						SCOPE_CYCLE_COUNTER(STAT_InterpolateSkippedFrames);
						const float Alpha = 0.25f + (1.f / float(FMath::Max(UpdateRateParams.GetEvaluationRate(), 2) * 2));
						FAnimationRuntime::LerpBoneTransforms(LocalAtoms, CachedLocalAtoms, Alpha, RequiredBones);
						FAnimationRuntime::LerpBoneTransforms(SpaceBases, CachedSpaceBases, Alpha, RequiredBones);
					}
				}
			}
		}

		// Transforms updated, cached local bounds are now out of date.
		InvalidateCachedBounds();

		// update physics data from animated data
		UpdateKinematicBonesToPhysics(false);
		UpdateRBJointMotors();
	}

	// @todo anim : hack TTP 224385	ANIM: Skeletalmesh double buffer
	// this is problem because intermediate buffer changes physics position as well
	// this causes issue where a half of frame, physics position is fixed with anim pose, and the other half is real simulated position
	// if you enable physics in tick, since that's before physics update, you'll get animation pose dominating physics pose, which isn't what you want. (Or what you'll see)
	// so do not update transform if physics is on. This problem will be solved by double buffer, when we keep one buffer for intermediate, and the other buffer for result query
	{
		FScopeLockPhysXReader LockPhysXForReading;

		if( !IsSimulatingPhysics() )
		{
			SCOPE_CYCLE_COUNTER(STAT_UpdateLocalToWorldAndOverlaps);
			
			// New bone positions need to be sent to render thread
			UpdateComponentToWorld();	

			// animation often change overlap. 
			UpdateOverlaps();
		}
	}

	MarkRenderDynamicDataDirty();
}