void UNiagaraComponent::TickComponent(float DeltaSeconds, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { // EmitterAge += DeltaSeconds; if (EffectInstance) { static FNiagaraVariableInfo Const_Zero(TEXT("ZERO"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_DeltaTime(TEXT("Delta Time"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterPos(TEXT("Emitter Position"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterAge(TEXT("Emitter Age"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterX(TEXT("Emitter X Axis"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterY(TEXT("Emitter Y Axis"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterZ(TEXT("Emitter Z Axis"), ENiagaraDataType::Vector); static FNiagaraVariableInfo Const_EmitterTransform(TEXT("Emitter Transform"), ENiagaraDataType::Matrix); //Todo, open this up to the UI and setting via code and BPs. EffectInstance->SetConstant(Const_Zero, FVector4(0.0f, 0.0f, 0.0f, 0.0f)); // zero constant EffectInstance->SetConstant(Const_DeltaTime, FVector4(DeltaSeconds, DeltaSeconds, DeltaSeconds, DeltaSeconds)); EffectInstance->SetConstant(Const_EmitterPos, FVector4(ComponentToWorld.GetTranslation())); EffectInstance->SetConstant(Const_EmitterX, FVector4(ComponentToWorld.GetUnitAxis(EAxis::X))); EffectInstance->SetConstant(Const_EmitterY, FVector4(ComponentToWorld.GetUnitAxis(EAxis::Y))); EffectInstance->SetConstant(Const_EmitterZ, FVector4(ComponentToWorld.GetUnitAxis(EAxis::Z))); EffectInstance->SetConstant(Const_EmitterTransform, ComponentToWorld.ToMatrixWithScale()); EffectInstance->Tick(DeltaSeconds); } UpdateComponentToWorld(); MarkRenderDynamicDataDirty(); }
void USkeletalMeshComponent::InitAnim(bool bForceReinit) { // a lot of places just call InitAnim without checking Mesh, so // I'm moving the check here if ( SkeletalMesh != NULL && IsRegistered() ) { bool bBlueprintMismatch = (AnimBlueprintGeneratedClass != NULL) && (AnimScriptInstance != NULL) && (AnimScriptInstance->GetClass() != AnimBlueprintGeneratedClass); bool bSkeletonMismatch = AnimScriptInstance && AnimScriptInstance->CurrentSkeleton && (AnimScriptInstance->CurrentSkeleton!=SkeletalMesh->Skeleton); if (bBlueprintMismatch || bSkeletonMismatch ) { ClearAnimScriptInstance(); } // this has to be called before Initialize Animation because it will required RequiredBones list when InitializeAnimScript RecalcRequiredBones(0); InitializeAnimScriptInstance(bForceReinit); TickAnimation(0.f); RefreshBoneTransforms(); UpdateComponentToWorld(); } }
void USceneCaptureComponentCube::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (bCaptureEveryFrame) { UpdateComponentToWorld(false); } }
void UActorComponent::OnRegister() { checkf(!HasAnyFlags(RF_Unreachable), TEXT("%s"), *GetDetailedInfo()); checkf(!GetOuter()->IsTemplate(), TEXT("'%s' (%s)"), *GetOuter()->GetFullName(), *GetDetailedInfo()); checkf(!IsTemplate(), TEXT("'%s' (%s)"), *GetOuter()->GetFullName(), *GetDetailedInfo() ); checkf(World, TEXT("OnRegister: %s to %s"), *GetDetailedInfo(), GetOwner() ? *GetOwner()->GetFullName() : TEXT("*** No Owner ***") ); checkf(!bRegistered, TEXT("OnRegister: %s to %s"), *GetDetailedInfo(), GetOwner() ? *GetOwner()->GetFullName() : TEXT("*** No Owner ***") ); checkf(!IsPendingKill(), TEXT("OnRegister: %s to %s"), *GetDetailedInfo(), GetOwner() ? *GetOwner()->GetFullName() : TEXT("*** No Owner ***") ); bRegistered = true; UpdateComponentToWorld(); if (bAutoActivate) { Activate(true); } }
FTransform USkeletalMeshComponent::ConvertLocalRootMotionToWorld(const FTransform & InTransform) { // Make sure component to world is up to date if (!bWorldToComponentUpdated) { UpdateComponentToWorld(); } const FTransform NewWorldTransform = InTransform * ComponentToWorld; const FVector DeltaWorldTranslation = NewWorldTransform.GetTranslation() - ComponentToWorld.GetTranslation(); const FQuat DeltaWorldRotation = ComponentToWorld.GetRotation().Inverse() * NewWorldTransform.GetRotation(); const FTransform DeltaWorldTransform(DeltaWorldRotation, DeltaWorldTranslation); UE_LOG(LogRootMotion, Log, TEXT("ConvertLocalRootMotionToWorld LocalT: %s, LocalR: %s, WorldT: %s, WorldR: %s."), *InTransform.GetTranslation().ToCompactString(), *InTransform.GetRotation().Rotator().ToCompactString(), *DeltaWorldTransform.GetTranslation().ToCompactString(), *DeltaWorldTransform.GetRotation().Rotator().ToCompactString() ); return DeltaWorldTransform; }
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(); }