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(); }
void UPaperFlipbookComponent::FlipbookChangedPhysicsState() { // If the frame has changed and we're using animated collision, we need to recreate that state as well RecreatePhysicsState(); // We just totally changed the physics setup so update overlaps too UpdateOverlaps(); }
void UPrimitiveComponent::OnComponentCollisionSettingsChanged() { if (!IsTemplate() && IsRegistered()) // not for CDOs { // changing collision settings could affect touching status, need to update UpdateOverlaps(); // update navigation data if needed const bool bNewNavRelevant = IsNavigationRelevant(); if (bNavigationRelevant != bNewNavRelevant) { bNavigationRelevant = bNewNavRelevant; UNavigationSystem::UpdateNavOctree(this); } } }
void UBoxComponent::SetBoxExtent(FVector NewBoxExtent, bool bUpdateOverlaps) { BoxExtent = NewBoxExtent; MarkRenderStateDirty(); // do this if already created // otherwise, it hasn't been really created yet if (bPhysicsStateCreated) { DestroyPhysicsState(); UpdateBodySetup(); CreatePhysicsState(); if ( bUpdateOverlaps && IsCollisionEnabled() && GetOwner() ) { UpdateOverlaps(); } } }
void UCapsuleComponent::SetCapsuleSize(float NewRadius, float NewHalfHeight, bool bUpdateOverlaps) { CapsuleHalfHeight = FMath::Max(NewHalfHeight, NewRadius); CapsuleRadius = NewRadius; MarkRenderStateDirty(); // do this if already created // otherwise, it hasn't been really created yet if (bPhysicsStateCreated) { DestroyPhysicsState(); UpdateBodySetup(); CreatePhysicsState(); if ( bUpdateOverlaps && IsCollisionEnabled() && GetOwner() ) { UpdateOverlaps(); } } }
void USkeletalMeshComponent::CompleteParallelBlendPhysics() { Exchange(AnimEvaluationContext.LocalAtoms, AnimEvaluationContext.bDoInterpolation ? CachedLocalAtoms : LocalAtoms); FlipEditableSpaceBases(); // Update Child Transform - The above function changes bone transform, so will need to update child transform UpdateChildTransforms(); // animation often change overlap. UpdateOverlaps(); // New bone positions need to be sent to render thread MarkRenderDynamicDataDirty(); FinalizeBoneTransform(); ParallelAnimationEvaluationTask.SafeRelease(); ParallelBlendPhysicsCompletionTask.SafeRelease(); }
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(); }