Update to 5.6, lots of Cleanup
This commit is contained in:
parent
f036c2a1fb
commit
d29dbbbe45
141 changed files with 859 additions and 505 deletions
|
@ -10,6 +10,10 @@ namespace UnrealBuildTool.Rules
|
|||
public OpenXRExpansionPlugin(ReadOnlyTargetRules Target)
|
||||
: base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
DefaultBuildSettings = BuildSettingsVersion.Latest;
|
||||
IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
|
||||
|
||||
SetupIrisSupport(Target);
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
|
|
|
@ -373,6 +373,11 @@ bool FVRCharacterNetworkMoveData::Serialize(UCharacterMovementComponent& Charact
|
|||
{
|
||||
bRepRollAndPitch = (Roll != 0 || Pitch != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bCanRepRollAndPitch = (CharacterOwner && (CharacterOwner->bUseControllerRotationRoll || CharacterOwner->bUseControllerRotationPitch));
|
||||
bRepRollAndPitch = bCanRepRollAndPitch && (Roll != 0 || Pitch != 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "UObject/UObjectGlobals.h" // for FindObject<>
|
||||
#include "IXRTrackingSystem.h"
|
||||
#include "IXRSystemAssets.h"
|
||||
#include "SceneView.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
#include "TimerManager.h"
|
||||
#include "VRBaseCharacter.h"
|
||||
|
@ -249,7 +250,7 @@ void UGripMotionControllerComponent::RegisterEndPhysicsTick(bool bRegister)
|
|||
void UGripMotionControllerComponent::EndPhysicsTickComponent(FGripComponentEndPhysicsTickFunction& ThisTickFunction)
|
||||
{
|
||||
|
||||
if (!IsValid(this))
|
||||
if (!IsValidChecked(this))
|
||||
return;
|
||||
|
||||
// Now check if we should turn off any post physics ticking
|
||||
|
@ -4310,7 +4311,7 @@ bool UGripMotionControllerComponent::TeleportMoveGrippedActor(AActor * GrippedAc
|
|||
|
||||
FBPActorGripInformation * GripInfo = LocallyGrippedObjects.FindByKey(GrippedActorToMove);
|
||||
if (!GripInfo)
|
||||
GrippedObjects.FindByKey(GrippedActorToMove);
|
||||
GripInfo = GrippedObjects.FindByKey(GrippedActorToMove);
|
||||
|
||||
if (GripInfo)
|
||||
{
|
||||
|
@ -4327,7 +4328,7 @@ bool UGripMotionControllerComponent::TeleportMoveGrippedComponent(UPrimitiveComp
|
|||
|
||||
FBPActorGripInformation * GripInfo = LocallyGrippedObjects.FindByKey(ComponentToMove);
|
||||
if (!GripInfo)
|
||||
GrippedObjects.FindByKey(ComponentToMove);
|
||||
GripInfo = GrippedObjects.FindByKey(ComponentToMove);
|
||||
|
||||
if (GripInfo)
|
||||
{
|
||||
|
@ -6017,7 +6018,7 @@ void UGripMotionControllerComponent::CleanUpBadPhysicsHandles()
|
|||
{
|
||||
FBPActorGripInformation * GripInfo = LocallyGrippedObjects.FindByKey(PhysicsGrips[g].GripID);
|
||||
if(!GripInfo)
|
||||
GrippedObjects.FindByKey(PhysicsGrips[g].GripID);
|
||||
GripInfo = GrippedObjects.FindByKey(PhysicsGrips[g].GripID);
|
||||
|
||||
if (!GripInfo)
|
||||
{
|
||||
|
@ -6156,44 +6157,48 @@ bool UGripMotionControllerComponent::DestroyPhysicsHandle(const FBPActorGripInfo
|
|||
return true;
|
||||
}
|
||||
|
||||
UPrimitiveComponent *root = Grip.GetGrippedComponent();
|
||||
AActor * pActor = Grip.GetGrippedActor();
|
||||
|
||||
if (!root && pActor)
|
||||
root = Cast<UPrimitiveComponent>(pActor->GetRootComponent());
|
||||
|
||||
if (root)
|
||||
if (IsValid(Grip.GrippedObject))
|
||||
{
|
||||
if (FBodyInstance * rBodyInstance = root->GetBodyInstance(Grip.GrippedBoneName))
|
||||
|
||||
UPrimitiveComponent* root = Grip.GetGrippedComponent();
|
||||
AActor* pActor = Grip.GetGrippedActor();
|
||||
|
||||
if (!root && pActor)
|
||||
root = Cast<UPrimitiveComponent>(pActor->GetRootComponent());
|
||||
|
||||
if (root)
|
||||
{
|
||||
// #TODO: Should this be done on drop instead?
|
||||
// Remove event registration
|
||||
if (!bSkipUnregistering)
|
||||
if (FBodyInstance* rBodyInstance = root->GetBodyInstance(Grip.GrippedBoneName))
|
||||
{
|
||||
if (rBodyInstance->OnRecalculatedMassProperties().IsBoundToObject(this))
|
||||
// #TODO: Should this be done on drop instead?
|
||||
// Remove event registration
|
||||
if (!bSkipUnregistering)
|
||||
{
|
||||
rBodyInstance->OnRecalculatedMassProperties().RemoveAll(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (HandleInfo->bSetCOM)
|
||||
{
|
||||
// Reset center of mass to zero
|
||||
// Get our original values
|
||||
FVector vel = rBodyInstance->GetUnrealWorldVelocity();
|
||||
FVector aVel = rBodyInstance->GetUnrealWorldAngularVelocityInRadians();
|
||||
FVector originalCOM = rBodyInstance->GetCOMPosition();
|
||||
|
||||
if (rBodyInstance->IsValidBodyInstance() && rBodyInstance->BodySetup.IsValid())
|
||||
{
|
||||
rBodyInstance->UpdateMassProperties();
|
||||
if (rBodyInstance->OnRecalculatedMassProperties().IsBoundToObject(this))
|
||||
{
|
||||
rBodyInstance->OnRecalculatedMassProperties().RemoveAll(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (rBodyInstance->IsInstanceSimulatingPhysics())
|
||||
if (HandleInfo->bSetCOM)
|
||||
{
|
||||
// Offset the linear velocity by the new COM position and set it
|
||||
vel += FVector::CrossProduct(aVel, rBodyInstance->GetCOMPosition() - originalCOM);
|
||||
rBodyInstance->SetLinearVelocity(vel, false);
|
||||
// Reset center of mass to zero
|
||||
// Get our original values
|
||||
FVector vel = rBodyInstance->GetUnrealWorldVelocity();
|
||||
FVector aVel = rBodyInstance->GetUnrealWorldAngularVelocityInRadians();
|
||||
FVector originalCOM = rBodyInstance->GetCOMPosition();
|
||||
|
||||
if (rBodyInstance->IsValidBodyInstance() && rBodyInstance->BodySetup.IsValid())
|
||||
{
|
||||
rBodyInstance->UpdateMassProperties();
|
||||
}
|
||||
|
||||
if (rBodyInstance->IsInstanceSimulatingPhysics())
|
||||
{
|
||||
// Offset the linear velocity by the new COM position and set it
|
||||
vel += FVector::CrossProduct(aVel, rBodyInstance->GetCOMPosition() - originalCOM);
|
||||
rBodyInstance->SetLinearVelocity(vel, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7224,8 +7229,15 @@ void UGripMotionControllerComponent::ApplyTrackingParameters(FVector& OriginalPo
|
|||
|
||||
if (IsValid(AttachChar) && !AttachChar->bRetainRoomscale)
|
||||
{
|
||||
FRotator StoredCameraRotOffset = UVRExpansionFunctionLibrary::GetHMDPureYaw_I(curRot.Rotator());
|
||||
LastLocationForLateUpdate += StoredCameraRotOffset.RotateVector(FVector(AttachChar->VRRootReference->VRCapsuleOffset.X, AttachChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FRotator StoredCameraRotOffset = UVRExpansionFunctionLibrary::GetHMDPureYaw_I(curRot.Rotator());
|
||||
LastLocationForLateUpdate += StoredCameraRotOffset.RotateVector(FVector(AttachChar->VRRootReference->VRCapsuleOffset.X, AttachChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7238,8 +7250,15 @@ void UGripMotionControllerComponent::ApplyTrackingParameters(FVector& OriginalPo
|
|||
|
||||
if (!AttachChar->bRetainRoomscale && IsLocallyControlled())
|
||||
{
|
||||
FRotator StoredCameraRotOffset = UVRExpansionFunctionLibrary::GetHMDPureYaw_I(AttachChar->VRReplicatedCamera->GetRelativeRotation());
|
||||
LastLocationForLateUpdate += StoredCameraRotOffset.RotateVector(FVector(AttachChar->VRRootReference->VRCapsuleOffset.X, AttachChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FRotator StoredCameraRotOffset = UVRExpansionFunctionLibrary::GetHMDPureYaw_I(AttachChar->VRReplicatedCamera->GetRelativeRotation());
|
||||
LastLocationForLateUpdate += StoredCameraRotOffset.RotateVector(FVector(AttachChar->VRRootReference->VRCapsuleOffset.X, AttachChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "PhysicsEngine/BodyInstance.h"
|
||||
#include "PhysicsReplicationLOD.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
@ -43,6 +44,12 @@ namespace VRPhysicsReplicationStatics
|
|||
|
||||
// Hacky work around for them not exporting these....
|
||||
#if WITH_EDITOR
|
||||
|
||||
namespace RenderInterpolationCVars
|
||||
{
|
||||
bool bRenderInterpDebugDrawResimTrigger = false;
|
||||
}
|
||||
|
||||
namespace PhysicsReplicationCVars
|
||||
{
|
||||
int32 SkipSkeletalRepOptimization = 1;
|
||||
|
@ -51,6 +58,9 @@ namespace PhysicsReplicationCVars
|
|||
#endif
|
||||
|
||||
int32 EnableDefaultReplication = 0;
|
||||
int32 DebugDrawShowRepMode = 0;
|
||||
float DebugDrawLifeTime = 3.0f;
|
||||
|
||||
|
||||
namespace DefaultReplicationCVars
|
||||
{
|
||||
|
@ -61,6 +71,8 @@ namespace PhysicsReplicationCVars
|
|||
|
||||
namespace ResimulationCVars
|
||||
{
|
||||
//extern bool bApplyPredictiveInterpolationWhenBehindServer;
|
||||
|
||||
bool bRuntimeCorrectionEnabled = false;
|
||||
bool bRuntimeVelocityCorrection = false;
|
||||
bool bRuntimeCorrectConnectedBodies = true;
|
||||
|
@ -72,15 +84,20 @@ namespace PhysicsReplicationCVars
|
|||
|
||||
// Inside of NetworkPhysicsComponent - UPDATE AS CHANGE
|
||||
int32 RedundantInputs = 2;
|
||||
int32 RedundantRemoteInputs = 1;
|
||||
int32 RedundantStates = 0;
|
||||
bool bAllowRewindToClosestState = true;
|
||||
bool bCompareStateToTriggerRewind = false;
|
||||
bool bCompareStateToTriggerRewindIncludeSimProxies = false;
|
||||
bool bCompareInputToTriggerRewind = false;
|
||||
bool bEnableUnreliableFlow = true;
|
||||
bool bEnableReliableFlow = false;
|
||||
bool bApplyDataInsteadOfMergeData = false;
|
||||
bool bAllowInputExtrapolation = true;
|
||||
bool bValidateDataOnGameThread = false;
|
||||
bool bApplySimProxyStateAtRuntime = false;
|
||||
bool bApplySimProxyInputAtRuntime = true;
|
||||
bool bApplyPredictiveInterpolationWhenBehindServer = true;
|
||||
}
|
||||
|
||||
namespace PredictiveInterpolationCVars
|
||||
|
@ -129,6 +146,9 @@ namespace PhysicsReplicationCVars
|
|||
float DrawDebugZOffset = 50.0f;
|
||||
float SleepSecondsClearTarget = 15.0f;
|
||||
int32 TargetTickAlignmentClampMultiplier = 2;
|
||||
int32 TeleportDetectionEnabled = 1;
|
||||
float TeleportDetectionMinDistance = 200.0f;
|
||||
float TeleportDetectionVelocityMultiplier = 1.3f;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -373,13 +393,13 @@ void FPhysicsReplicationVR::RemoveReplicatedTarget(UPrimitiveComponent* Componen
|
|||
{
|
||||
|
||||
// Skip all of the custom logic if we aren't the server
|
||||
if (const UWorld* World = GetOwningWorld())
|
||||
/*if (const UWorld* World = GetOwningWorld())
|
||||
{
|
||||
if (World->GetNetMode() == ENetMode::NM_Client)
|
||||
{
|
||||
return FPhysicsReplication::RemoveReplicatedTarget(Component);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (Component == nullptr)
|
||||
{
|
||||
|
@ -659,7 +679,7 @@ bool FPhysicsReplicationVR::ApplyRigidBodyState(float DeltaSeconds, FBodyInstanc
|
|||
{
|
||||
if (bHardsnapLegacyInPT)
|
||||
{
|
||||
if (Chaos::FSingleParticlePhysicsProxy* Proxy = static_cast<Chaos::FSingleParticlePhysicsProxy*>(BI->GetPhysicsActorHandle()))
|
||||
if (Chaos::FSingleParticlePhysicsProxy* Proxy = static_cast<Chaos::FSingleParticlePhysicsProxy*>(BI->GetPhysicsActor()))
|
||||
{
|
||||
if (Chaos::FPBDRigidsSolver* Solver = Proxy->GetSolver<Chaos::FPBDRigidsSolver>())
|
||||
{
|
||||
|
@ -715,7 +735,7 @@ bool FPhysicsReplicationVR::ApplyRigidBodyState(float DeltaSeconds, FBodyInstanc
|
|||
AsyncInputData.TargetState = NewState;
|
||||
AsyncInputData.TargetState.Position = IdealWorldTM.GetLocation();
|
||||
AsyncInputData.TargetState.Quaternion = IdealWorldTM.GetRotation();
|
||||
AsyncInputData.Proxy = static_cast<Chaos::FSingleParticlePhysicsProxy*>(BI->GetPhysicsActorHandle());
|
||||
AsyncInputData.Proxy = static_cast<Chaos::FSingleParticlePhysicsProxy*>(BI->GetPhysicsActor());
|
||||
AsyncInputData.ErrorCorrection = { ErrorCorrection.LinearVelocityCoefficient, ErrorCorrection.AngularVelocityCoefficient, ErrorCorrection.PositionLerp, ErrorCorrection.AngleLerp };
|
||||
|
||||
AsyncInputData.LatencyOneWay = PingSeconds;
|
||||
|
@ -746,7 +766,7 @@ bool FPhysicsReplicationVR::ApplyRigidBodyState(float DeltaSeconds, FBodyInstanc
|
|||
{
|
||||
FColor Color = FColor::White;
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
DrawDebugDirectionalArrow(OwningWorld, CurrentState.Position, TargetPos, 5.0f, Color, true, CVarNetCorrectionLifetime->GetFloat(), 0, 1.5f);
|
||||
DrawDebugDirectionalArrow(OwningWorld, CurrentState.Position, TargetPos, 5.0f, Color, false, CVarNetCorrectionLifetime->GetFloat(), 0, 1.5f);
|
||||
#if 0
|
||||
//todo: do we show this in async mode?
|
||||
DrawDebugFloatHistory(*OwningWorld, PhysicsTarget.ErrorHistory, NewPos + FVector(0.0f, 0.0f, 100.0f), FVector2D(100.0f, 50.0f), FColor::White);
|
||||
|
@ -791,6 +811,12 @@ void FPhysicsReplicationVR::OnTick(float DeltaSeconds, TMap<TWeakObjectPtr<UPrim
|
|||
return;
|
||||
}
|
||||
|
||||
// Don't tick unless we have data to process
|
||||
if (ComponentsToTargets.Num() == 0 && ReplicatedTargetsQueueVR.Num() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace Chaos;
|
||||
|
||||
|
||||
|
@ -1033,13 +1059,15 @@ void FPhysicsReplicationAsyncVR::FetchObjectSettings(Chaos::FConstPhysicsObjectH
|
|||
|
||||
void FPhysicsReplicationAsyncVR::OnPostInitialize_Internal()
|
||||
{
|
||||
Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
Chaos::FPBDRigidsSolver& RigidsSolver = GetSolver()->CastChecked();
|
||||
RigidsSolver.SetPhysicsReplication_Internal(this);
|
||||
//Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
|
||||
if (ensure(RigidsSolver))
|
||||
/*if (ensure(RigidsSolver))
|
||||
{
|
||||
// This doesn't even do anything currently, nothing gets it #TODO: CHECK BACK ON THIS
|
||||
//RigidsSolver->SetPhysicsReplication(this);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void FPhysicsReplicationAsyncVR::OnPreSimulate_Internal()
|
||||
|
@ -1049,35 +1077,34 @@ void FPhysicsReplicationAsyncVR::OnPreSimulate_Internal()
|
|||
return;
|
||||
}
|
||||
|
||||
if (const FPhysicsReplicationAsyncInput* AsyncInput = GetConsumerInput_Internal())
|
||||
Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
check(RigidsSolver);
|
||||
|
||||
// Early out if this is a resim frame
|
||||
Chaos::FRewindData* RewindData = RigidsSolver->GetRewindData();
|
||||
const bool bRewindDataExist = RewindData != nullptr;
|
||||
if (bRewindDataExist && RewindData->IsResim())
|
||||
{
|
||||
Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
check(RigidsSolver);
|
||||
|
||||
// Early out if this is a resim frame
|
||||
Chaos::FRewindData* RewindData = RigidsSolver->GetRewindData();
|
||||
const bool bRewindDataExist = RewindData != nullptr;
|
||||
if (bRewindDataExist && RewindData->IsResim())
|
||||
//static const auto CVarPostResimWaitForUpdate = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.PostResimWaitForUpdate"));
|
||||
// TODO, Handle the transition from post-resim to interpolation better (disabled by default, resim vs replication interaction is handled via FPhysicsReplicationAsync::CacheResimInteractions)
|
||||
if (SettingsCurrent.PredictiveInterpolationSettings.GetPostResimWaitForUpdate() && RewindData->IsFinalResim())
|
||||
{
|
||||
// TODO, Handle the transition from post-resim to interpolation better (disabled by default, resim vs replication interaction is handled via FPhysicsReplicationAsync::CacheResimInteractions)
|
||||
static const auto CVarPostResimWaitForUpdate = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.PostResimWaitForUpdate"));
|
||||
if (CVarPostResimWaitForUpdate->GetBool() && RewindData->IsFinalResim())
|
||||
for (auto Itr = ObjectToTarget.CreateIterator(); Itr; ++Itr)
|
||||
{
|
||||
for (auto Itr = ObjectToTarget.CreateIterator(); Itr; ++Itr)
|
||||
{
|
||||
FReplicatedPhysicsTargetAsync& Target = Itr.Value();
|
||||
FReplicatedPhysicsTargetAsync& Target = Itr.Value();
|
||||
|
||||
// If final resim frame, mark interpolated targets as waiting for up to date data from the server.
|
||||
if (Target.RepMode == EPhysicsReplicationMode::PredictiveInterpolation)
|
||||
{
|
||||
Target.SetWaiting(RigidsSolver->GetCurrentFrame() + Target.FrameOffset, Target.RepModeOverride);
|
||||
}
|
||||
// If final resim frame, mark interpolated targets as waiting for up to date data from the server.
|
||||
if (Target.RepMode == EPhysicsReplicationMode::PredictiveInterpolation)
|
||||
{
|
||||
Target.SetWaiting(RigidsSolver->GetCurrentFrame() + Target.FrameOffset, Target.RepModeOverride);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (const FPhysicsReplicationAsyncInput* AsyncInput = GetConsumerInput_Internal())
|
||||
{
|
||||
// Update async targets with target input
|
||||
for (const FPhysicsRepAsyncInputData& Input : AsyncInput->InputData)
|
||||
{
|
||||
|
@ -1100,15 +1127,27 @@ void FPhysicsReplicationAsyncVR::OnPreSimulate_Internal()
|
|||
|
||||
UpdateRewindDataTarget(Input);
|
||||
UpdateAsyncTarget(Input, RigidsSolver);
|
||||
}
|
||||
|
||||
if (Chaos::FPBDRigidsSolver::IsNetworkPhysicsPredictionEnabled())
|
||||
{
|
||||
CacheResimInteractions();
|
||||
}
|
||||
DebugDrawReplicationMode(Input);
|
||||
|
||||
ApplyTargetStatesAsync(GetDeltaTime_Internal(), AsyncInput->ErrorCorrection, AsyncInput->InputData);
|
||||
// Deprecated, legacy BodyInstance flow for Default Replication
|
||||
if (Input.Proxy != nullptr)
|
||||
{
|
||||
Chaos::FSingleParticlePhysicsProxy* Proxy = Input.Proxy;
|
||||
Chaos::FRigidBodyHandle_Internal* Handle = Proxy->GetPhysicsThreadAPI();
|
||||
|
||||
const FPhysicsRepErrorCorrectionData& UsedErrorCorrection = Input.ErrorCorrection.IsSet() ? Input.ErrorCorrection.GetValue() : AsyncInput->ErrorCorrection;
|
||||
DefaultReplication_DEPRECATED(Handle, Input, GetDeltaTime_Internal(), UsedErrorCorrection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Chaos::FPBDRigidsSolver::IsNetworkPhysicsPredictionEnabled())
|
||||
{
|
||||
CacheResimInteractions();
|
||||
}
|
||||
|
||||
ApplyTargetStatesAsync(GetDeltaTime_Internal());
|
||||
}
|
||||
|
||||
FReplicatedPhysicsTargetAsync* FPhysicsReplicationAsyncVR::AddObjectToReplication(Chaos::FConstPhysicsObjectHandle PhysicsObject)
|
||||
|
@ -1201,6 +1240,7 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
Target->PrevLinVel = Input.TargetState.LinVel;
|
||||
Target->RepModeOverride = Input.RepMode;
|
||||
}
|
||||
check(Target);
|
||||
|
||||
/** Target Update Description
|
||||
* @param Input = incoming state target for replication.
|
||||
|
@ -1247,6 +1287,9 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
// Set if the target is allowed to be altered after this update
|
||||
Target->bAllowTargetAltering = !(Target->TargetState.Flags & ERigidBodyFlags::Sleeping) && !(Input.TargetState.Flags & ERigidBodyFlags::Sleeping);
|
||||
|
||||
// Cache previous linear velocity
|
||||
const FVector PrevLinVel = Target->TargetState.LinVel;
|
||||
|
||||
// Set Target->ReceiveInterval from either SendInterval or the number of physics ticks between receiving input states
|
||||
if (SendInterval > 0)
|
||||
{
|
||||
|
@ -1259,11 +1302,7 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
}
|
||||
|
||||
// Update target from input and reset properties
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
Target->PrevServerFrame = Target->bWaiting ? Input.ServerFrame : Target->ServerFrame; // DEPRECATED UE5.4
|
||||
Target->PrevReceiveFrame = (Target->ReceiveFrame == INDEX_NONE) ? (RigidsSolver->GetCurrentFrame() - 1) : Target->ReceiveFrame; // DEPRECATED UE5.4
|
||||
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||
Target->ServerFrame = Input.ServerFrame;
|
||||
Target->ServerFrame = Input.ServerFrame;
|
||||
Target->ReceiveFrame = CurrentFrame;
|
||||
Target->TargetState = Input.TargetState;
|
||||
Target->RepMode = Input.RepMode;
|
||||
|
@ -1274,7 +1313,13 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
// Update waiting state
|
||||
Target->UpdateWaiting(Input.ServerFrame);
|
||||
|
||||
if (Input.RepMode == EPhysicsReplicationMode::PredictiveInterpolation)
|
||||
// Apply full Replication LOD on received target
|
||||
ApplyPhysicsReplicationLOD(Input.PhysicsObject, *Target, EPhysicsReplicationLODFlags::LODFlag_All);
|
||||
|
||||
// Check if target is valid to use for resimulation and perform actions if not
|
||||
CheckTargetResimValidity(*Target);
|
||||
|
||||
if (Target->RepMode == EPhysicsReplicationMode::PredictiveInterpolation)
|
||||
{
|
||||
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
|
@ -1284,16 +1329,13 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
const FVector Offset = FVector(0.0f, 0.0f, 50.0f);
|
||||
// Port this?
|
||||
//const FVector Offset = FVector(0.0f, 0.0f, PhysicsReplicationCVars::PredictiveInterpolationCVars::DrawDebugZOffset);
|
||||
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Input.TargetState.Position + Offset, FVector(15.0f, 15.0f, 15.0f), Input.TargetState.Quaternion, FColor::MakeRandomSeededColor(Input.ServerFrame), false, CVarNetCorrectionLifetime->GetFloat(), 0, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Cache the position we received this target at, Predictive Interpolation will alter the target state but use this as the source position for reconciliation.
|
||||
Target->PrevPosTarget = Input.TargetState.Position;
|
||||
Target->PrevRotTarget = Input.TargetState.Quaternion;
|
||||
|
||||
// TickCount is 0 by default at this point and when LOD is used, TickCount will be 0 if no LOD alignment was performed, in this case perform the normal target alignment
|
||||
if (Target->TickCount == 0)
|
||||
{
|
||||
/** Target Alignment Feature
|
||||
* With variable network conditions state inputs from the server can arrive both later or earlier than expected.
|
||||
|
@ -1331,6 +1373,34 @@ void FPhysicsReplicationAsyncVR::UpdateAsyncTarget(const FPhysicsRepAsyncInputDa
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const auto CVarTeleportDetectionEnabled = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.TeleportDetection.Enabled"));
|
||||
// Teleport detection, we don't have specific data that tells us a teleport has happened on the server, so try to detect it by examining the previous and next state
|
||||
if (CVarTeleportDetectionEnabled->GetBool() == 1 && !bFirstTarget && SendInterval > 0 && RigidsSolver->IsUsingFixedDt())
|
||||
{
|
||||
const FVector PosOffset = (Input.TargetState.Position - Target->PrevPosTarget);
|
||||
static const auto CVarTeleportDetectionMinDistance = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.TeleportDetection.MinDistance"));
|
||||
if (PosOffset.SizeSquared() > (CVarTeleportDetectionMinDistance->GetFloat() * CVarTeleportDetectionMinDistance->GetFloat()))
|
||||
{
|
||||
const FVector Velocity = Input.TargetState.LinVel.SizeSquared() > PrevLinVel.SizeSquared() ? Input.TargetState.LinVel : PrevLinVel;
|
||||
const float DeltaSeconds = (SendInterval * RigidsSolver->GetAsyncDeltaTime());
|
||||
static const auto CVarTeleportDetectionVelocityMultiplier = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.TeleportDetection.VelocityMultiplier"));
|
||||
const float PossibleDistanceSquared = (Velocity * (DeltaSeconds * CVarTeleportDetectionVelocityMultiplier->GetFloat())).SizeSquared();
|
||||
|
||||
if (PossibleDistanceSquared < PosOffset.SizeSquared())
|
||||
{
|
||||
// A teleport has most likely happened, set accumulated error seconds to above limit for hard snapping
|
||||
// TODO: Don't piggyback on AccumulatedErrorSeconds (potentially implement ERigidBodyFlags::Teleported)
|
||||
|
||||
static const auto CVarErrorAcumulationSeconds = IConsoleManager::Get().FindConsoleVariable(TEXT("p.ErrorAccumulationSeconds"));
|
||||
Target->AccumulatedErrorSeconds = CVarErrorAcumulationSeconds->GetFloat() + 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the position we received this target at, Predictive Interpolation will alter the target state but use this as the source position for reconciliation.
|
||||
Target->PrevPosTarget = Input.TargetState.Position;
|
||||
Target->PrevRotTarget = Input.TargetState.Quaternion;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1344,6 +1414,14 @@ void FPhysicsReplicationAsyncVR::CacheResimInteractions()
|
|||
static const auto CVarResimDisableReplicationOnInteraction = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.Resim.DisableReplicationOnInteraction"));
|
||||
if (!CVarResimDisableReplicationOnInteraction->GetBool())
|
||||
{
|
||||
ParticlesInResimIslands.Empty();
|
||||
return;
|
||||
}
|
||||
|
||||
if (UsePhysicsReplicationLOD())
|
||||
{
|
||||
// This will be handled by the LOD system
|
||||
ParticlesInResimIslands.Empty();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1353,9 +1431,12 @@ void FPhysicsReplicationAsyncVR::CacheResimInteractions()
|
|||
return;
|
||||
}
|
||||
|
||||
ParticlesInResimIslands.Empty(FMath::CeilToInt(static_cast<float>(ParticlesInResimIslands.Num()) * 0.9f));
|
||||
ResimIslands.Reset();
|
||||
ResimIslandsParticles.Reset();
|
||||
ParticlesInResimIslands.Reset();
|
||||
|
||||
Chaos::Private::FPBDIslandManager& IslandManager = RigidsSolver->GetEvolution()->GetIslandManager();
|
||||
Chaos::FWritePhysicsObjectInterface_Internal Interface = Chaos::FPhysicsObjectInternalInterface::GetWrite();
|
||||
Chaos::FReadPhysicsObjectInterface_Internal Interface = Chaos::FPhysicsObjectInternalInterface::GetRead();
|
||||
for (auto Itr = ObjectToTarget.CreateIterator(); Itr; ++Itr)
|
||||
{
|
||||
FReplicatedPhysicsTargetAsync& Target = Itr.Value();
|
||||
|
@ -1365,7 +1446,9 @@ void FPhysicsReplicationAsyncVR::CacheResimInteractions()
|
|||
if (Chaos::FGeometryParticleHandle* Handle = Interface.GetParticle(POHandle))
|
||||
{
|
||||
// Get a list of particles from the same island as a resim particle is in, i.e. particles interacting with a resim particle
|
||||
for (const Chaos::FGeometryParticleHandle* InteractParticle : IslandManager.FindParticlesInIslands(IslandManager.FindParticleIslands(Handle)))
|
||||
IslandManager.FindParticleIslands(Handle, OUT ResimIslands);
|
||||
IslandManager.FindParticlesInIslands(ResimIslands, OUT ResimIslandsParticles);
|
||||
for (const Chaos::FGeometryParticleHandle* InteractParticle : ResimIslandsParticles)
|
||||
{
|
||||
ParticlesInResimIslands.Add(InteractParticle->GetHandleIdx());
|
||||
}
|
||||
|
@ -1374,66 +1457,152 @@ void FPhysicsReplicationAsyncVR::CacheResimInteractions()
|
|||
}
|
||||
}
|
||||
|
||||
void FPhysicsReplicationAsyncVR::ApplyTargetStatesAsync(const float DeltaSeconds, const FPhysicsRepErrorCorrectionData& ErrorCorrection, const TArray<FPhysicsRepAsyncInputData>& InputData)
|
||||
void FPhysicsReplicationAsyncVR::ApplyTargetStatesAsync(const float DeltaSeconds)
|
||||
{
|
||||
using namespace Chaos;
|
||||
|
||||
// Deprecated, legacy BodyInstance flow
|
||||
for (const FPhysicsRepAsyncInputData& Input : InputData)
|
||||
{
|
||||
if (Input.Proxy != nullptr)
|
||||
/** Helper function to remove replicated target*/
|
||||
auto RemoveTargetHelper = [this](TMap<Chaos::FConstPhysicsObjectHandle, FReplicatedPhysicsTargetAsync>::TIterator Itr, FGeometryParticleHandle* Handle)
|
||||
{
|
||||
Chaos::FSingleParticlePhysicsProxy* Proxy = Input.Proxy;
|
||||
Chaos::FRigidBodyHandle_Internal* Handle = Proxy->GetPhysicsThreadAPI();
|
||||
|
||||
const FPhysicsRepErrorCorrectionData& UsedErrorCorrection = Input.ErrorCorrection.IsSet() ? Input.ErrorCorrection.GetValue() : ErrorCorrection;
|
||||
DefaultReplication_DEPRECATED(Handle, Input, DeltaSeconds, UsedErrorCorrection);
|
||||
}
|
||||
}
|
||||
if (Handle)
|
||||
{
|
||||
ReplicatedParticleIDs.Remove(Handle->ParticleID());
|
||||
}
|
||||
Itr.RemoveCurrent();
|
||||
};
|
||||
|
||||
// PhysicsObject flow
|
||||
Chaos::FWritePhysicsObjectInterface_Internal Interface = Chaos::FPhysicsObjectInternalInterface::GetWrite();
|
||||
for (auto Itr = ObjectToTarget.CreateIterator(); Itr; ++Itr)
|
||||
for (TMap<Chaos::FConstPhysicsObjectHandle, FReplicatedPhysicsTargetAsync>::TIterator Itr = ObjectToTarget.CreateIterator(); Itr; ++Itr)
|
||||
{
|
||||
bool bRemoveItr = true; // Remove current cached replication target unless replication logic tells us to store it for next tick
|
||||
FParticleID ParticleID;
|
||||
|
||||
Chaos::FConstPhysicsObjectHandle& POHandle = Itr.Key();
|
||||
if (FGeometryParticleHandle* Handle = Interface.GetParticle(POHandle))
|
||||
FGeometryParticleHandle* Handle = Interface.GetParticle(POHandle);
|
||||
if (!Handle)
|
||||
{
|
||||
FReplicatedPhysicsTargetAsync& Target = Itr.Value();
|
||||
|
||||
|
||||
if (FPBDRigidParticleHandle* RigidHandle = Handle->CastToRigidParticle())
|
||||
{
|
||||
ParticleID = RigidHandle->ParticleID();
|
||||
|
||||
// Cache custom settings for this object if there are any
|
||||
FetchObjectSettings(POHandle);
|
||||
|
||||
const EPhysicsReplicationMode RepMode = Target.IsWaiting() ? Target.RepModeOverride : Target.RepMode;
|
||||
switch (RepMode)
|
||||
{
|
||||
case EPhysicsReplicationMode::Default:
|
||||
bRemoveItr = DefaultReplication(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
|
||||
case EPhysicsReplicationMode::PredictiveInterpolation:
|
||||
bRemoveItr = PredictiveInterpolation(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
|
||||
case EPhysicsReplicationMode::Resimulation:
|
||||
bRemoveItr = ResimulationReplication(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
}
|
||||
Target.TickCount++;
|
||||
}
|
||||
RemoveTargetHelper(Itr, nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
FPBDRigidParticleHandle* RigidHandle = Handle->CastToRigidParticle();
|
||||
if (!RigidHandle)
|
||||
{
|
||||
RemoveTargetHelper(Itr, Handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
FReplicatedPhysicsTargetAsync& Target = Itr.Value();
|
||||
|
||||
// Cache custom settings for this object if there are any
|
||||
FetchObjectSettings(POHandle);
|
||||
|
||||
// Apply limited Replication LOD
|
||||
ApplyPhysicsReplicationLOD(POHandle, Target, EPhysicsReplicationLODFlags::LODFlag_IslandCheck);
|
||||
|
||||
const EPhysicsReplicationMode RepMode = Target.IsWaiting() ? Target.RepModeOverride : Target.RepMode;
|
||||
switch (RepMode)
|
||||
{
|
||||
case EPhysicsReplicationMode::Default:
|
||||
bRemoveItr = DefaultReplication(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
|
||||
case EPhysicsReplicationMode::PredictiveInterpolation:
|
||||
bRemoveItr = PredictiveInterpolation(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
|
||||
case EPhysicsReplicationMode::Resimulation:
|
||||
bRemoveItr = ResimulationReplication(RigidHandle, Target, DeltaSeconds);
|
||||
break;
|
||||
}
|
||||
Target.TickCount++;
|
||||
|
||||
if (bRemoveItr)
|
||||
{
|
||||
ReplicatedParticleIDs.Remove(ParticleID);
|
||||
Itr.RemoveCurrent();
|
||||
RemoveTargetHelper(Itr, RigidHandle);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FPhysicsReplicationAsyncVR::CheckTargetResimValidity(FReplicatedPhysicsTargetAsync& Target)
|
||||
{
|
||||
if (Target.RepMode != EPhysicsReplicationMode::Resimulation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
if (RigidsSolver == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Chaos::FRewindData* RewindData = RigidsSolver->GetRewindData();
|
||||
if (RewindData == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int32 LocalFrame = Target.ServerFrame - Target.FrameOffset;
|
||||
if (!RewindData->IsFrameWithinRewindHistory(LocalFrame))
|
||||
{
|
||||
|
||||
static const auto CVarResimApplyPredictiveInterpolationWhenBehindServer = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.Resim.ApplyPredictiveInterpolationWhenBehindServer"));
|
||||
|
||||
if (LocalFrame < RewindData->GetEarliestFrame_Internal())
|
||||
{
|
||||
// Client is far ahead of the server, switch over to Predictive Interpolation since it can't use incoming target states from the server to perform resimulations with
|
||||
|
||||
Target.RepMode = EPhysicsReplicationMode::PredictiveInterpolation;
|
||||
}
|
||||
else if (CVarResimApplyPredictiveInterpolationWhenBehindServer->GetBool())
|
||||
{
|
||||
/** NOTE: If the server is ahead of the client we receive target states for frames we have not yet simulated on the client, target states are stored in FRewindData still though.
|
||||
* If PhysicsReplicationCVars::ResimulationCVars::bApplyPredictiveInterpolationWhenBehindServer is true switch over to using PredictiveInterpolation temporarily.
|
||||
* else FRewindData::CompareTargetsToLastFrame will check for already cached targets to resim with when the server has simulated the corresponding frame */
|
||||
|
||||
Target.RepMode = EPhysicsReplicationMode::PredictiveInterpolation;
|
||||
}
|
||||
|
||||
UE_LOG(LogPhysics, Warning, TEXT("FPhysicsReplication received target frame (%d) out of rewind data bounds (%d, %d) - %s - Target will use EPhysicsReplicationMode: %s"),
|
||||
LocalFrame, RewindData->GetEarliestFrame_Internal(), RewindData->CurrentFrame(), (LocalFrame < RewindData->GetEarliestFrame_Internal()) ? TEXT("Client is far ahead of the server, server might be dropping frames.") : TEXT("Client is behind the server, client might be dropping frames."), *UEnum::GetValueAsString(Target.RepMode));
|
||||
}
|
||||
}
|
||||
|
||||
void FPhysicsReplicationAsyncVR::ApplyPhysicsReplicationLOD(Chaos::FConstPhysicsObjectHandle PhysicsObjectHandle, FReplicatedPhysicsTargetAsync& Target, const uint32 LODFLags)
|
||||
{
|
||||
Chaos::FPBDRigidsSolver& RigidsSolver = GetSolver()->CastChecked();
|
||||
|
||||
IPhysicsReplicationLODAsync* PhysRepLod = RigidsSolver.GetPhysicsReplicationLOD_Internal();
|
||||
if (!PhysRepLod || !PhysRepLod->IsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FPhysicsRepLodData* LodData = PhysRepLod->GetLODData_Internal(PhysicsObjectHandle, LODFLags);
|
||||
if (LodData && LodData->DataAssigned)
|
||||
{
|
||||
// Apply recommended replication mode
|
||||
Target.RepMode = LodData->ReplicationMode;
|
||||
|
||||
if (Target.RepMode == EPhysicsReplicationMode::PredictiveInterpolation)
|
||||
{
|
||||
const bool bShouldSleep = (Target.TargetState.Flags & ERigidBodyFlags::Sleeping) != 0;
|
||||
int32 TargetClientFrame = (Target.ServerFrame - Target.FrameOffset);
|
||||
|
||||
// If we use Predicitve Interpolation and we should not sleep and the aligned frame from LOD is ahead of the target, perform LOD aligment extrapolation
|
||||
if (!bShouldSleep && LodData->AlignedFrame > TargetClientFrame)
|
||||
{
|
||||
// Calculate how far to forward predict and extrapolate target by that amount
|
||||
const int32 FullPredictionFrames = RigidsSolver.GetCurrentFrame() - TargetClientFrame;
|
||||
const float FullPredictionTime = (FullPredictionFrames * GetDeltaTime_Internal());
|
||||
const float AlignedPredictionTime = FullPredictionTime - LodData->AlignedTime;
|
||||
FPhysicsReplicationAsyncVR::ExtrapolateTarget(Target, AlignedPredictionTime);
|
||||
|
||||
// Update tick count based on LOD alignment
|
||||
Target.TickCount = LodData->AlignedFrame - TargetClientFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1775,11 +1944,6 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
return true;
|
||||
}
|
||||
|
||||
if (Target.IsWaiting())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Chaos::FPBDRigidsSolver* RigidsSolver = static_cast<Chaos::FPBDRigidsSolver*>(GetSolver());
|
||||
if (RigidsSolver == nullptr)
|
||||
{
|
||||
|
@ -1803,8 +1967,8 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
const FVector Offset = FVector(0.0f, 0.0f, 50.0f);
|
||||
const FVector StartPos = Target.TargetState.Position + Offset;
|
||||
const int32 SizeMultiplier = FMath::Clamp(Target.TickCount, -4, 30);
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(StartPos, FVector(5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f), Target.TargetState.Quaternion, FColor::MakeRandomSeededColor(Target.ServerFrame), false, CVarNetCorrectionLifetime->GetFloat(), 0, 1.0f);
|
||||
static const auto CVarDebugdrawLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(StartPos, FVector(5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f, 5.0f + SizeMultiplier * 0.75f), Target.TargetState.Quaternion, FColor::MakeRandomSeededColor(Target.ServerFrame), false, CVarDebugdrawLifetime->GetFloat(), 0, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1864,6 +2028,11 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
return bClearTarget;
|
||||
};
|
||||
|
||||
// If waiting on an up to date state, early out but allow target clearing since we might not receive a new state if target is already set to sleep for example
|
||||
if (Target.IsWaiting())
|
||||
{
|
||||
return EndReplicationHelper(Target, true);
|
||||
}
|
||||
|
||||
static const auto CVarEarlyOutWithVelocity = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.EarlyOutWithVelocity"));
|
||||
static const auto CVarEarlyOutDistanceSqr = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.EarlyOutDistanceSqr"));
|
||||
|
@ -1909,8 +2078,41 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
const FVector TargetLinVel = FVector(Target.TargetState.LinVel);
|
||||
const FVector TargetAngVel = FVector(FMath::DegreesToRadians(Target.TargetState.AngVel)); // Radians
|
||||
|
||||
/** --- Reconciliation ---
|
||||
* If target velocities are low enough, check the traveled direction and distance from previous frame and compare with replicated linear velocity.
|
||||
/** --- Reconciliation --- */
|
||||
static const auto CVarKinematicHardSnap = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.KinematicHardSnap"));
|
||||
static const auto CVarErrorAccumulationSeconds = IConsoleManager::Get().FindConsoleVariable(TEXT("p.ErrorAccumulationSeconds"));
|
||||
static const auto CVarAlwaysHardSnap = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.AlwaysHardSnap"));
|
||||
const bool bHardSnap = (!bCanSimulate && CVarKinematicHardSnap->GetBool())
|
||||
|| Target.AccumulatedErrorSeconds > CVarErrorAccumulationSeconds->GetFloat()
|
||||
|| CVarAlwaysHardSnap->GetBool();
|
||||
|
||||
if (bHardSnap)
|
||||
{
|
||||
Target.AccumulatedErrorSeconds = 0.0f;
|
||||
|
||||
if (Handle->IsKinematic())
|
||||
{
|
||||
// Set a FKinematicTarget to hard snap kinematic object
|
||||
const Chaos::FKinematicTarget KinTarget = Chaos::FKinematicTarget::MakePositionTarget(Target.PrevPosTarget, Target.PrevRotTarget); // Uses EKinematicTargetMode::Position
|
||||
RigidsSolver->GetEvolution()->SetParticleKinematicTarget(Handle, KinTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set XRVW to hard snap dynamic object and force recalculation of friction
|
||||
const bool bCorrectConnectedBodies = SettingsCurrent.PredictiveInterpolationSettings.GetCorrectConnectedBodies();
|
||||
RigidsSolver->GetEvolution()->ApplyParticleTransformCorrection(Handle, Target.PrevPosTarget, Target.PrevRotTarget, bCorrectConnectedBodies, /*bInRecalculateFrictionOnConnectedBodies*/ true, ReplicatedParticleIDs);
|
||||
Handle->SetV(TargetLinVel);
|
||||
Handle->SetW(TargetAngVel);
|
||||
}
|
||||
|
||||
// Cache data for next replication
|
||||
Target.PrevLinVel = FVector(Target.TargetState.LinVel);
|
||||
|
||||
// End replication and go to sleep if that's requested
|
||||
return EndReplicationHelper(Target, true);
|
||||
}
|
||||
|
||||
/** If target velocities are low enough, check the traveled direction and distance from previous frame and compare with replicated linear velocity.
|
||||
* If the object isn't moving enough along the replicated velocity it's considered stuck and needs reconciliation.
|
||||
* SoftSnap is performed each tick while there is a registered error, if enough time pass HardSnap forces the object into the correct state. */
|
||||
static const auto CVarVelocityBased = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.VelocityBased"));
|
||||
|
@ -1919,7 +2121,7 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
static const auto CVarDisableErrorVelocityLimits = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.DisableErrorVelocityLimits"));
|
||||
static const auto CVarErrorAccLinVelMaxLimit = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.ErrorAccLinVelMaxLimit"));
|
||||
static const auto CVarErrorAccAngVelMaxLimit = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.ErrorAccAngVelMaxLimit"));
|
||||
if (CVarDisableErrorVelocityLimits->GetBool() ||
|
||||
if ( CVarDisableErrorVelocityLimits->GetBool() ||
|
||||
(TargetLinVel.Size() < CVarErrorAccLinVelMaxLimit->GetFloat() && TargetAngVel.Size() < CVarErrorAccAngVelMaxLimit->GetFloat()))
|
||||
{
|
||||
const FVector PrevDiff = CurrentState.Position - Target.PrevPos;
|
||||
|
@ -1952,43 +2154,8 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
{
|
||||
bSoftSnap = false;
|
||||
}
|
||||
|
||||
static const auto CVarErrorAccumulationSeconds = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.ErrorAccumulationSeconds"));
|
||||
static const auto CVarAlwaysHardSnap = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.AlwaysHardSnap"));
|
||||
static const auto CVarKinematicHardSnap = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.KinematicHardSnap"));
|
||||
|
||||
const bool bHardSnap = (!bCanSimulate && CVarKinematicHardSnap->GetBool())
|
||||
|| Target.AccumulatedErrorSeconds > CVarErrorAccumulationSeconds->GetFloat()
|
||||
|| CVarAlwaysHardSnap->GetBool();
|
||||
|
||||
if (bHardSnap)
|
||||
{
|
||||
Target.AccumulatedErrorSeconds = 0.0f;
|
||||
|
||||
if (Handle->IsKinematic())
|
||||
{
|
||||
// Set a FKinematicTarget to hard snap kinematic object
|
||||
const Chaos::FKinematicTarget KinTarget = Chaos::FKinematicTarget::MakePositionTarget(Target.PrevPosTarget, Target.PrevRotTarget); // Uses EKinematicTargetMode::Position
|
||||
RigidsSolver->GetEvolution()->SetParticleKinematicTarget(Handle, KinTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set XRVW to hard snap dynamic object and force recalculation of friction
|
||||
const bool bCorrectConnectedBodies = SettingsCurrent.PredictiveInterpolationSettings.GetCorrectConnectedBodies();
|
||||
RigidsSolver->GetEvolution()->ApplyParticleTransformCorrection(Handle, Target.PrevPosTarget, Target.PrevRotTarget, bCorrectConnectedBodies, /*bInRecalculateFrictionOnConnectedBodies*/ true, ReplicatedParticleIDs);
|
||||
|
||||
|
||||
Handle->SetV(TargetLinVel);
|
||||
Handle->SetW(TargetAngVel);
|
||||
}
|
||||
|
||||
// Cache data for next replication
|
||||
Target.PrevLinVel = FVector(Target.TargetState.LinVel);
|
||||
|
||||
// End replication and go to sleep if that's requested
|
||||
return EndReplicationHelper(Target, true);
|
||||
}
|
||||
else if (Handle->IsKinematic()) // Smooth Kinematic Replication
|
||||
|
||||
if (Handle->IsKinematic()) // Smooth Kinematic Replication
|
||||
{
|
||||
static const auto CVarKinematicPrediction = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.PredictiveInterpolation.KinematicPrediction"));
|
||||
const bool bKinematicPrediction = CVarKinematicPrediction->GetBool();
|
||||
|
@ -2035,8 +2202,8 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
const FVector Offset = FVector(0.0f, 0.0f, CVarDrawDebugZOffset->GetFloat());
|
||||
const FVector Pos = KinTargetPos + Offset;
|
||||
const int32 SizeMultiplier = FMath::Clamp(Target.TickCount, -4, 30);
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugSphere(Pos, 3.0f + SizeMultiplier * 0.75f, 8, FColor::MakeRandomSeededColor(Target.ServerFrame), false, CVarNetCorrectionLifetime->GetFloat(), 0, 1.0f);
|
||||
static const auto CVarDebugdrawLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugSphere(Pos, 3.0f + SizeMultiplier * 0.75f, 8, FColor::MakeRandomSeededColor(Target.ServerFrame), false, CVarDebugdrawLifetime->GetFloat(), 0, 1.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2214,7 +2381,12 @@ bool FPhysicsReplicationAsyncVR::PredictiveInterpolation(Chaos::FPBDRigidParticl
|
|||
void FPhysicsReplicationAsyncVR::ExtrapolateTarget(FReplicatedPhysicsTargetAsync& Target, const int32 ExtrapolateFrames, const float DeltaSeconds)
|
||||
{
|
||||
const float ExtrapolationTime = DeltaSeconds * static_cast<float>(ExtrapolateFrames);
|
||||
FPhysicsReplicationAsyncVR::ExtrapolateTarget(Target, ExtrapolationTime);
|
||||
}
|
||||
|
||||
/** Static function to extrapolate a target for N Seconds */
|
||||
void FPhysicsReplicationAsyncVR::ExtrapolateTarget(FReplicatedPhysicsTargetAsync& Target, const float ExtrapolationTime)
|
||||
{
|
||||
// Extrapolate target position
|
||||
Target.TargetState.Position = Target.TargetState.Position + Target.TargetState.LinVel * ExtrapolationTime;
|
||||
|
||||
|
@ -2242,15 +2414,15 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
return true;
|
||||
}
|
||||
|
||||
if (Target.ServerFrame <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const int32 LocalFrame = Target.ServerFrame - Target.FrameOffset;
|
||||
|
||||
if (LocalFrame >= RewindData->CurrentFrame() || LocalFrame < RewindData->GetEarliestFrame_Internal())
|
||||
if (!RewindData->IsFrameWithinRewindHistory(LocalFrame))
|
||||
{
|
||||
if (LocalFrame > 0 && (RewindData->CurrentFrame() - RewindData->GetEarliestFrame_Internal()) == RewindData->Capacity())
|
||||
{
|
||||
UE_LOG(LogPhysics, Warning, TEXT("FPhysicsReplication::ResimulationReplication target frame (%d) out of rewind data bounds (%d,%d)"),
|
||||
LocalFrame, RewindData->GetEarliestFrame_Internal(), RewindData->CurrentFrame());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2269,11 +2441,24 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
const bool bCompareW = Chaos::FPhysicsSolverBase::GetResimulationErrorAngularVelocityThresholdEnabled() || SettingsCurrent.ResimulationSettings.bOverrideResimulationErrorAngularVelocityThreshold;
|
||||
bool bShouldTriggerResim = false;
|
||||
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
// Debugging
|
||||
FColor DebugColor = FColor::Black;
|
||||
bool bResimV = false;
|
||||
bool bResimW = false;
|
||||
#endif
|
||||
|
||||
// Check for positional discrepancy in Distance between client and server
|
||||
if (bCompareX)
|
||||
{
|
||||
const float ResimPositionErrorThreshold = SettingsCurrent.ResimulationSettings.GetResimulationErrorPositionThreshold(Chaos::FPhysicsSolverBase::GetResimulationErrorPositionThreshold());
|
||||
bShouldTriggerResim = Chaos::FRewindData::CheckVectorThreshold(Target.TargetState.Position, PastState.GetX(), ResimPositionErrorThreshold);
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
if (bShouldTriggerResim)
|
||||
{
|
||||
DebugColor = FColor::Orange;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check for linear velocity discrepancy in Distance / s between client and server
|
||||
|
@ -2281,13 +2466,25 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
{
|
||||
const float ResimLinVelocityErrorThreshold = SettingsCurrent.ResimulationSettings.GetResimulationErrorLinearVelocityThreshold(Chaos::FPhysicsSolverBase::GetResimulationErrorLinearVelocityThreshold());
|
||||
bShouldTriggerResim = Chaos::FRewindData::CheckVectorThreshold(Target.TargetState.LinVel, PastState.GetV(), ResimLinVelocityErrorThreshold);
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
if (bShouldTriggerResim)
|
||||
{
|
||||
bResimV = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check for angular velocity discrepancy in Degrees / s between client and server
|
||||
if (!bShouldTriggerResim && bCompareW)
|
||||
{
|
||||
const float ResimAngVelocityErrorThreshold = SettingsCurrent.ResimulationSettings.GetResimulationErrorAngularVelocityThreshold(Chaos::FPhysicsSolverBase::GetResimulationErrorAngularVelocityThreshold());
|
||||
bShouldTriggerResim = Chaos::FRewindData::CheckVectorThreshold(FMath::DegreesToRadians(Target.TargetState.AngVel), PastState.GetW(), ResimAngVelocityErrorThreshold);
|
||||
bShouldTriggerResim = Chaos::FRewindData::CheckVectorThreshold(Target.TargetState.AngVel, FMath::RadiansToDegrees(PastState.GetW()), ResimAngVelocityErrorThreshold);
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
if (bShouldTriggerResim)
|
||||
{
|
||||
bResimW = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check for rotational discrepancy in Degrees between client and server
|
||||
|
@ -2295,6 +2492,12 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
{
|
||||
const float ResimRotationErrorThreshold = SettingsCurrent.ResimulationSettings.GetResimulationErrorRotationThreshold(Chaos::FPhysicsSolverBase::GetResimulationErrorRotationThreshold());
|
||||
bShouldTriggerResim = Chaos::FRewindData::CheckQuaternionThreshold(Target.TargetState.Quaternion, PastState.GetR(), ResimRotationErrorThreshold);
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
if (bShouldTriggerResim)
|
||||
{
|
||||
DebugColor = FColor::Magenta;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2311,16 +2514,51 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
}
|
||||
|
||||
static const auto CVarResimDrawDebug = IConsoleManager::Get().FindConsoleVariable(TEXT("np2.Resim.DrawDebug"));
|
||||
if (CVarResimDrawDebug->GetBool())
|
||||
static const auto CVarRenderInterpDebugDrawResimTrigger = IConsoleManager::Get().FindConsoleVariable(TEXT("p.RenderInterp.DebugDraw.ResimTrigger"));
|
||||
if (CVarResimDrawDebug->GetBool() || CVarRenderInterpDebugDrawResimTrigger->GetBool())
|
||||
{
|
||||
static constexpr float BoxSize = 5.0f;
|
||||
const float ColorLerp = bShouldTriggerResim ? 1.0f : 0.0f;
|
||||
const FColor DebugColor = FLinearColor::LerpUsingHSV(FLinearColor::Green, FLinearColor::Red, ColorLerp).ToFColor(false);
|
||||
if (bShouldTriggerResim)
|
||||
{
|
||||
FVector Box = CVarRenderInterpDebugDrawResimTrigger->GetBool() ? FVector(6, 3, 2) : FVector(40, 20, 10);
|
||||
const float DrawThickness = CVarRenderInterpDebugDrawResimTrigger->GetBool() ? 0.5f : 1.5f;
|
||||
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Target.TargetState.Position, FVector(BoxSize, BoxSize, BoxSize), Target.TargetState.Quaternion, FColor::Orange, true, CVarNetCorrectionLifetime->GetFloat(), 0, 1.0f);
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(PastState.GetX(), FVector(6, 6, 6), PastState.GetR(), DebugColor, true, CVarNetCorrectionLifetime->GetFloat(), 0, 1.0f);
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(PastState.GetX(), Target.TargetState.Position, 5.0f, FColor::MakeRandomSeededColor(LocalFrame), true, CVarNetCorrectionLifetime->GetFloat(), 0, 0.5f);
|
||||
static const auto CVarDebugdrawLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
if (CVarRenderInterpDebugDrawResimTrigger->GetBool()) // Resim debug draw extension for render interpolation
|
||||
{
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(PastState.GetX(), Box, PastState.GetR(), FColor::White, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Target.TargetState.Position, Box, Target.TargetState.Quaternion, DebugColor, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX(), PastState.GetX(), 5.0f, FColor::White, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(PastState.GetX(), Target.TargetState.Position, 5.0f, FColor::Black, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
|
||||
if (bResimV)
|
||||
{
|
||||
const FVector DiffV = Target.TargetState.LinVel - PastState.GetV();
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Target.TargetState.Position, Target.TargetState.Position + DiffV, 5.0f, FColor::Orange, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
}
|
||||
if (bResimW)
|
||||
{
|
||||
const FVector DiffW = Target.TargetState.AngVel - FMath::RadiansToDegrees(PastState.GetW());
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Target.TargetState.Position + DiffW, Target.TargetState.Position, 5.0f, FColor::Magenta, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
}
|
||||
}
|
||||
else // Resim trigger debug draw
|
||||
{
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Handle->GetX(), Box, PastState.GetR(), FColor::White, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Handle->GetX() + (Target.TargetState.Position - PastState.GetX()), Box, Target.TargetState.Quaternion, DebugColor, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
|
||||
if (bResimV)
|
||||
{
|
||||
const FVector DiffV = Target.TargetState.LinVel - PastState.GetV();
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX(), Handle->GetX() + DiffV, 5.0f, FColor::Orange, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
}
|
||||
if (bResimW)
|
||||
{
|
||||
const FVector DiffW = Target.TargetState.AngVel - FMath::RadiansToDegrees(PastState.GetW());
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX() + DiffW, Handle->GetX(), 5.0f, FColor::Magenta, false, CVarDebugdrawLifetime->GetFloat(), 0, DrawThickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2332,12 +2570,8 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
|
||||
if (bShouldTriggerResim && Target.TickCount == 0 && LocalFrame > RewindData->GetBlockedResimFrame())
|
||||
{
|
||||
// Trigger resimulation
|
||||
RigidsSolver->GetEvolution()->GetIslandManager().SetParticleResimFrame(Handle, LocalFrame);
|
||||
|
||||
int32 ResimFrame = RewindData->GetResimFrame();
|
||||
ResimFrame = (ResimFrame == INDEX_NONE) ? LocalFrame : FMath::Min(ResimFrame, LocalFrame);
|
||||
RewindData->SetResimFrame(ResimFrame);
|
||||
// Request resimulation
|
||||
RewindData->RequestResimulation(LocalFrame, Handle);
|
||||
}
|
||||
else if (SettingsCurrent.ResimulationSettings.GetRuntimeCorrectionEnabled())
|
||||
{
|
||||
|
@ -2381,8 +2615,8 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
if (CVarResimDrawDebug->GetBool())
|
||||
{
|
||||
static const auto CVarNetCorrectionLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetCorrectionLifetime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX(), CorrectedX, 5.0f, FColor::MakeRandomSeededColor(LocalFrame), true, CVarNetCorrectionLifetime->GetFloat(), 0, 0.5f);
|
||||
static const auto CVarDebugdrawLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(Handle->GetX(), CorrectedX, 5.0f, FColor::MakeRandomSeededColor(LocalFrame), true, CVarDebugdrawLifetime->GetFloat(), 0, 0.5f);
|
||||
}
|
||||
#endif
|
||||
// Apply correction to position and rotation
|
||||
|
@ -2406,14 +2640,90 @@ bool FPhysicsReplicationAsyncVR::ResimulationReplication(Chaos::FPBDRigidParticl
|
|||
RigidsSolver->GetEvolution()->ApplySleepOnConnectedParticles(Handle);
|
||||
}
|
||||
}
|
||||
else if (Target.IsWaiting())
|
||||
{
|
||||
// Don't clear the target if we are waiting for a specific target frame and not sleeping
|
||||
bClearTarget = false;
|
||||
}
|
||||
|
||||
|
||||
return bClearTarget;
|
||||
}
|
||||
|
||||
void FPhysicsReplicationAsyncVR::DebugDrawReplicationMode(const FPhysicsRepAsyncInputData& Input)
|
||||
{
|
||||
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
|
||||
static const auto CVarDebugDrawShowRepMode = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.ShowRepMode"));
|
||||
if (!CVarDebugDrawShowRepMode->GetBool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input.PhysicsObject == nullptr && Input.Proxy == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FColor DebugColor = FColor::White;
|
||||
FVector BoxExtent = FVector(10.0f, 10.0f, 10.0f);
|
||||
FQuat Rotation = FQuat::Identity;
|
||||
|
||||
if (Input.PhysicsObject)
|
||||
{
|
||||
if (FReplicatedPhysicsTargetAsync* Target = ObjectToTarget.Find(Input.PhysicsObject))
|
||||
{
|
||||
Chaos::FReadPhysicsObjectInterface_Internal Interface = Chaos::FPhysicsObjectInternalInterface::GetRead();
|
||||
if (Chaos::FGeometryParticleHandle* Handle = Interface.GetParticle(Input.PhysicsObject))
|
||||
{
|
||||
BoxExtent = Handle->LocalBounds().Extents() * 0.5f;
|
||||
Rotation = Handle->GetR();
|
||||
}
|
||||
|
||||
const EPhysicsReplicationMode RepMode = Target->IsWaiting() ? Target->RepModeOverride : Target->RepMode;
|
||||
switch (RepMode)
|
||||
{
|
||||
case EPhysicsReplicationMode::PredictiveInterpolation:
|
||||
DebugColor = FColor::Yellow;
|
||||
break;
|
||||
case EPhysicsReplicationMode::Resimulation:
|
||||
DebugColor = FColor::Red;
|
||||
break;
|
||||
case EPhysicsReplicationMode::Default:
|
||||
default:
|
||||
DebugColor = FColor::Cyan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Input.Proxy != nullptr)
|
||||
{
|
||||
// Legacy Default physics replication
|
||||
|
||||
Chaos::FSingleParticlePhysicsProxy* Proxy = Input.Proxy;
|
||||
Chaos::FRigidBodyHandle_Internal* Handle = Proxy->GetPhysicsThreadAPI();
|
||||
|
||||
Rotation = Handle->GetR();
|
||||
DebugColor = FColor::Green;
|
||||
}
|
||||
|
||||
static const auto CVarDebugdrawLifetime = IConsoleManager::Get().FindConsoleVariable(TEXT("p.Net.DebugDraw.LifeTime"));
|
||||
Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Input.TargetState.Position, BoxExtent, Rotation, DebugColor, false, CVarDebugdrawLifetime->GetFloat(), 0, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FName FPhysicsReplicationAsyncVR::GetFNameForStatId() const
|
||||
{
|
||||
const static FLazyName StaticName("FPhysicsReplicationAsyncCallback");
|
||||
return StaticName;
|
||||
}
|
||||
|
||||
bool FPhysicsReplicationAsyncVR::UsePhysicsReplicationLOD()
|
||||
{
|
||||
Chaos::FPBDRigidsSolver& RigidsSolver = GetSolver()->CastChecked();
|
||||
|
||||
IPhysicsReplicationLODAsync* PhysRepLod = RigidsSolver.GetPhysicsReplicationLOD_Internal();
|
||||
return PhysRepLod && PhysRepLod->IsEnabled();
|
||||
}
|
||||
|
||||
#pragma endregion // FPhysicsReplicationAsync
|
|
@ -725,11 +725,11 @@ void AGrippableStaticMeshActor::OnRep_ReplicatedMovement()
|
|||
return;
|
||||
}
|
||||
|
||||
if (VRGripInterfaceSettings.HoldingControllers.Num() > 0)
|
||||
/*if (VRGripInterfaceSettings.HoldingControllers.Num() > 0)
|
||||
{
|
||||
ShouldWeSkipAttachmentReplication();
|
||||
int gg = 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
Super::OnRep_ReplicatedMovement();
|
||||
}
|
||||
|
|
|
@ -206,7 +206,8 @@ bool UHandSocketComponent::GetAnimationSequenceAsPoseSnapShot(UAnimSequence* InA
|
|||
const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->GetSkinnedAsset()->GetRefSkeleton() : InAnimationSequence->GetSkeleton()->GetReferenceSkeleton();
|
||||
FTransform LocalTransform;
|
||||
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = InAnimationSequence->GetCompressedTrackToSkeletonMapTable();
|
||||
//const TArray<FTrackToSkeletonMap>& TrackMap = InAnimationSequence->GetCompressedTrackToSkeletonMapTable();
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = InAnimationSequence->GetCompressedData().Get().CompressedTrackToSkeletonMapTable;
|
||||
int32 TrackIndex = INDEX_NONE;
|
||||
|
||||
OutPoseSnapShot.LocalTransforms.Reserve(OutPoseSnapShot.BoneNames.Num());
|
||||
|
@ -237,8 +238,9 @@ bool UHandSocketComponent::GetAnimationSequenceAsPoseSnapShot(UAnimSequence* InA
|
|||
|
||||
if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
|
||||
{
|
||||
double TrackLocation = 0.0f;
|
||||
InAnimationSequence->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), TrackLocation, false);
|
||||
//double TrackLocation = 0.0f;
|
||||
// FAnimExtraContext default is fine, its a zero track location
|
||||
InAnimationSequence->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), FAnimExtractContext(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -317,7 +319,7 @@ bool UHandSocketComponent::GetBlendedPoseSnapShot(FPoseSnapshot& PoseSnapShot, U
|
|||
const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->GetSkinnedAsset()->GetRefSkeleton() : HandTargetAnimation->GetSkeleton()->GetReferenceSkeleton();
|
||||
FTransform LocalTransform;
|
||||
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = HandTargetAnimation->GetCompressedTrackToSkeletonMapTable();
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = HandTargetAnimation->GetCompressedData().Get().CompressedTrackToSkeletonMapTable;
|
||||
int32 TrackIndex = INDEX_NONE;
|
||||
|
||||
for (int32 BoneNameIndex = 0; BoneNameIndex < PoseSnapShot.BoneNames.Num(); ++BoneNameIndex)
|
||||
|
@ -345,8 +347,9 @@ bool UHandSocketComponent::GetBlendedPoseSnapShot(FPoseSnapshot& PoseSnapShot, U
|
|||
|
||||
if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
|
||||
{
|
||||
double TrackLocation = 0.0f;
|
||||
HandTargetAnimation->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), TrackLocation, false);
|
||||
//double TrackLocation = 0.0f;
|
||||
// FAnimExtraContext default is fine, its a zero track location
|
||||
HandTargetAnimation->GetBoneTransform(LocalTransform, FSkeletonPoseBoneIndex(TrackMap[TrackIndex].BoneTreeIndex), FAnimExtractContext(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -609,7 +612,7 @@ FTransform UHandSocketComponent::GetBoneTransformAtTime(UAnimSequence* MyAnimSeq
|
|||
|
||||
if (const IAnimationDataModel* AnimModel = AnimController.GetModel())
|
||||
{
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = MyAnimSequence->GetCompressedTrackToSkeletonMapTable();
|
||||
const TArray<FTrackToSkeletonMap>& TrackMap = MyAnimSequence->GetCompressedData().Get().CompressedTrackToSkeletonMapTable;
|
||||
|
||||
int32 TrackIndex = INDEX_NONE;
|
||||
if (BoneIdx != INDEX_NONE && BoneIdx < TrackMap.Num() && TrackMap[BoneIdx].BoneTreeIndex == BoneIdx)
|
||||
|
@ -635,7 +638,9 @@ FTransform UHandSocketComponent::GetBoneTransformAtTime(UAnimSequence* MyAnimSeq
|
|||
FSkeletonPoseBoneIndex BoneIndex(TrackMap[TrackIndex].BoneTreeIndex);
|
||||
if (BoneIndex.IsValid())
|
||||
{
|
||||
MyAnimSequence->GetBoneTransform(BoneTransform, BoneIndex, /*AnimTime*/ tracklen, bUseRawDataOnly);
|
||||
FAnimExtractContext NewContext;
|
||||
NewContext.CurrentTime = tracklen;
|
||||
MyAnimSequence->GetBoneTransform(BoneTransform, BoneIndex, /*AnimTime*/ NewContext, bUseRawDataOnly);
|
||||
return BoneTransform;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -561,6 +561,7 @@ void UInversePhysicsSkeletalMeshComponent::RegisterEndPhysicsTick(bool bRegister
|
|||
// For testing if the engine fix is live yet or not
|
||||
//return Super::RegisterEndPhysicsTick(bRegister);
|
||||
|
||||
|
||||
if (bRegister != EndPhysicsTickFunctionVR.IsTickFunctionRegistered())
|
||||
{
|
||||
if (bRegister)
|
||||
|
|
|
@ -1117,7 +1117,7 @@ void UAISense_Sight_VR::RemoveAllQueriesByListener(const FPerceptionListener& Li
|
|||
SCOPE_CYCLE_COUNTER(STAT_AI_Sense_Sight_RemoveByListener);
|
||||
UE_MT_SCOPED_WRITE_ACCESS(QueriesListAccessDetector);
|
||||
|
||||
const uint32 ListenerId = Listener.GetListenerID();
|
||||
const FPerceptionListenerID ListenerId = Listener.GetListenerID();
|
||||
|
||||
auto RemoveQuery = [&ListenerId, &OnRemoveFunc](TArray<FAISightQueryVR>& SightQueries, const int32 QueryIndex)->EReverseForEachResult
|
||||
{
|
||||
|
@ -1185,7 +1185,7 @@ void UAISense_Sight_VR::RemoveAllQueriesToTarget_Internal(const FAISightTargetVR
|
|||
|
||||
void UAISense_Sight_VR::OnListenerForgetsActor(const FPerceptionListener& Listener, AActor& ActorToForget)
|
||||
{
|
||||
const uint32 ListenerId = Listener.GetListenerID();
|
||||
const FPerceptionListenerID ListenerId = Listener.GetListenerID();
|
||||
const uint32 TargetId = ActorToForget.GetUniqueID();
|
||||
|
||||
auto ForgetPreviousResult = [&ListenerId, &TargetId](FAISightQueryVR& SightQuery)->EForEachResult
|
||||
|
@ -1212,7 +1212,7 @@ void UAISense_Sight_VR::OnListenerForgetsAll(const FPerceptionListener& Listener
|
|||
{
|
||||
UE_MT_SCOPED_WRITE_ACCESS(QueriesListAccessDetector);
|
||||
|
||||
const uint32 ListenerId = Listener.GetListenerID();
|
||||
const FPerceptionListenerID ListenerId = Listener.GetListenerID();
|
||||
|
||||
auto ForgetPreviousResult = [&ListenerId](FAISightQueryVR& SightQuery)->EForEachResult
|
||||
{
|
||||
|
|
|
@ -103,7 +103,7 @@ bool UVRGameViewportClient::InputKey(const FInputKeyEventArgs& EventArgs)
|
|||
}
|
||||
}
|
||||
|
||||
bool UVRGameViewportClient::InputAxis(FViewport* tViewport, FInputDeviceId InputDevice, FKey Key, float Delta, float DeltaTime, int32 NumSamples, bool bGamepad)
|
||||
bool UVRGameViewportClient::InputAxis(const FInputKeyEventArgs& Args)
|
||||
{
|
||||
// Remap the old int32 ControllerId value to the new InputDeviceId
|
||||
IPlatformInputDeviceMapper& DeviceMapper = IPlatformInputDeviceMapper::Get();
|
||||
|
@ -111,8 +111,8 @@ bool UVRGameViewportClient::InputAxis(FViewport* tViewport, FInputDeviceId Input
|
|||
const int32 NumLocalPlayers = World->GetGameInstance()->GetNumLocalPlayers();
|
||||
|
||||
// Early out if a gamepad or not a mouse event (vr controller) or ignoring input or is default setup / no GEngine
|
||||
if (((!Key.IsMouseButton() && !bGamepad) || (bGamepad && !IsValidGamePadKey(Key))) || NumLocalPlayers < 2 || GameInputMethod == EVRGameInputMethod::GameInput_Default || IgnoreInput())
|
||||
return Super::InputAxis(tViewport, InputDevice, Key, Delta, DeltaTime, NumSamples, bGamepad);
|
||||
if (((!Args.Key.IsMouseButton() && !Args.IsGamepad()) || (Args.IsGamepad() && !IsValidGamePadKey(Args.Key))) || NumLocalPlayers < 2 || GameInputMethod == EVRGameInputMethod::GameInput_Default || IgnoreInput())
|
||||
return Super::InputAxis(Args);
|
||||
|
||||
if (GameInputMethod == EVRGameInputMethod::GameInput_KeyboardAndMouseToPlayer2)
|
||||
{
|
||||
|
@ -123,7 +123,9 @@ bool UVRGameViewportClient::InputAxis(FViewport* tViewport, FInputDeviceId Input
|
|||
FInputDeviceId DeviceId = INPUTDEVICEID_NONE;
|
||||
DeviceMapper.RemapControllerIdToPlatformUserAndDevice(ControllerId, UserId, DeviceId);
|
||||
|
||||
return Super::InputAxis(tViewport, DeviceId, Key, Delta, DeltaTime, NumSamples, bGamepad);
|
||||
FInputKeyEventArgs NewArgs = Args;
|
||||
NewArgs.InputDevice = DeviceId;
|
||||
return Super::InputAxis(NewArgs);
|
||||
}
|
||||
else // Shared keyboard and mouse
|
||||
{
|
||||
|
@ -134,7 +136,9 @@ bool UVRGameViewportClient::InputAxis(FViewport* tViewport, FInputDeviceId Input
|
|||
FInputDeviceId DeviceId = INPUTDEVICEID_NONE;
|
||||
DeviceMapper.RemapControllerIdToPlatformUserAndDevice(i, UserId, DeviceId);
|
||||
|
||||
bRetVal = Super::InputAxis(tViewport, DeviceId, Key, Delta, DeltaTime, NumSamples, bGamepad) || bRetVal;
|
||||
FInputKeyEventArgs NewArgs = Args;
|
||||
NewArgs.InputDevice = DeviceId;
|
||||
bRetVal = Super::InputAxis(NewArgs) || bRetVal;
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
|
|
|
@ -449,7 +449,7 @@ void ARenderTargetReplicationProxy::SendInitMessage()
|
|||
|
||||
void ARenderTargetReplicationProxy::SendNextDataBlob()
|
||||
{
|
||||
if (!IsValid(this) || !this->GetOwner() || !IsValid(this->GetOwner()))
|
||||
if (!IsValidChecked(this) || !this->GetOwner() || !IsValid(this->GetOwner()))
|
||||
{
|
||||
TextureStore.Reset();
|
||||
TextureStore.PackedData.Empty();
|
||||
|
|
|
@ -210,7 +210,7 @@ void UReplicatedVRCameraComponent::UpdateTracking(float DeltaTime)
|
|||
FRotator StoredCameraRotOffset = FRotator::ZeroRotator;
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
//StoredCameraRotOffset = AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -250,7 +250,7 @@ void UReplicatedVRCameraComponent::RunNetworkedSmoothing(float DeltaTime)
|
|||
FRotator StoredCameraRotOffset = FRotator::ZeroRotator;
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
//StoredCameraRotOffset = AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -480,12 +480,12 @@ void UReplicatedVRCameraComponent::HandleXRCamera(float DeltaTime)
|
|||
//FRotator OffsetRotator =
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() != EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
//AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
|
||||
FRotator StoredCameraRotOffset = FRotator::ZeroRotator;
|
||||
if (AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
//StoredCameraRotOffset = AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -536,7 +536,7 @@ void UReplicatedVRCameraComponent::OnRep_ReplicatedCameraTransform()
|
|||
FRotator StoredCameraRotOffset = FRotator::ZeroRotator;
|
||||
if (AttachChar->VRMovementReference && AttachChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
//StoredCameraRotOffset = AttachChar->SeatInformation.InitialRelCameraTransform.Rotator();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -185,7 +185,7 @@ void AVRBaseCharacter::PostInitializeComponents()
|
|||
|
||||
Super::PostInitializeComponents();
|
||||
|
||||
if (IsValid(this))
|
||||
if (IsValidChecked(this))
|
||||
{
|
||||
if (NetSmoother)
|
||||
{
|
||||
|
|
|
@ -1721,6 +1721,17 @@ void UVRBaseCharacterMovementComponent::SimulatedTick(float DeltaSeconds)
|
|||
const FQuat NewCapsuleRotation = UpdatedComponent->GetComponentQuat();
|
||||
if (Mesh == CharacterOwner->GetMesh() && !NewCapsuleRotation.Equals(OldRotationQuat, 1e-6f) && ClientPredictionData)
|
||||
{
|
||||
// #TODO: The below is new in 5.6, i don't have saved capsule rotation, don't think i need this change for base char
|
||||
/*
|
||||
// Add delta rotation to the target rotation and original offset. Otherwise this object will move back toward the old rotation.
|
||||
const FQuat RotationDelta = NewCapsuleRotation - SavedCapsuleRotation;
|
||||
ClientPredictionData->MeshRotationTarget += RotationDelta;
|
||||
ClientPredictionData->OriginalMeshRotationOffset += RotationDelta;
|
||||
|
||||
// Update the MeshRotationOffset to match the capsule rotation.
|
||||
ClientPredictionData->MeshRotationOffset = NewCapsuleRotation;
|
||||
*/
|
||||
|
||||
// Smoothing should lerp toward this new rotation target, otherwise it will just try to go back toward the old rotation.
|
||||
ClientPredictionData->MeshRotationTarget = NewCapsuleRotation;
|
||||
Mesh->SetRelativeLocationAndRotation(SavedMeshRelativeLocation, CharacterOwner->GetBaseRotationOffset());
|
||||
|
@ -1941,13 +1952,18 @@ void UVRBaseCharacterMovementComponent::MoveAutonomous(
|
|||
static const auto CVarEnableQueuedAnimEventsOnServer = IConsoleManager::Get().FindConsoleVariable(TEXT("a.EnableQueuedAnimEventsOnServer"));
|
||||
if (CVarEnableQueuedAnimEventsOnServer->GetInt())
|
||||
{
|
||||
if (const UAnimInstance* AnimInstance = OwnerMesh->GetAnimInstance())
|
||||
if (UAnimInstance* AnimInstance = OwnerMesh->GetAnimInstance())
|
||||
{
|
||||
if (OwnerMesh->VisibilityBasedAnimTickOption <= EVisibilityBasedAnimTickOption::AlwaysTickPose && AnimInstance->NeedsUpdate())
|
||||
{
|
||||
// If we are doing a full graph update on the server but its doing a parallel update,
|
||||
// trigger events right away since these are notifies queued from the montage update and we could be receiving multiple ServerMoves per frame.
|
||||
// trigger events right away since these are notifies queued from the montage update, and we could be receiving multiple ServerMoves per frame.
|
||||
OwnerMesh->ConditionallyDispatchQueuedAnimEvents();
|
||||
|
||||
// We need to manually clear the anim notify queue (since normally its only is cleared in PreUpdateAnimation()) otherwise if animation ticks, the notifies queued from the ServerMove would fire twice.
|
||||
AnimInstance->ClearQueuedAnimEvents(false);
|
||||
|
||||
// When animation ticks, we want its queued events to be triggered.
|
||||
OwnerMesh->AllowQueuedAnimEventsNextDispatch();
|
||||
}
|
||||
}
|
||||
|
@ -1955,7 +1971,7 @@ void UVRBaseCharacterMovementComponent::MoveAutonomous(
|
|||
else
|
||||
{
|
||||
// Revert back to old behavior if wanted/needed.
|
||||
if (OwnerMesh->ShouldOnlyTickMontages(DeltaTime))
|
||||
if (OwnerMesh->ShouldOnlyTickMontages(DeltaTime) || OwnerMesh->ShouldOnlyTickMontagesAndRefreshBones(DeltaTime))
|
||||
{
|
||||
OwnerMesh->ConditionallyDispatchQueuedAnimEvents();
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ void UVRCharacterMovementComponent::Crouch(bool bClientSimulation)
|
|||
{
|
||||
if (!bClientSimulation)
|
||||
{
|
||||
CharacterOwner->bIsCrouched = true;
|
||||
CharacterOwner->SetIsCrouched(true);
|
||||
}
|
||||
CharacterOwner->OnStartCrouch(0.f, 0.f);
|
||||
return;
|
||||
|
@ -195,7 +195,7 @@ void UVRCharacterMovementComponent::Crouch(bool bClientSimulation)
|
|||
//UpdatedComponent->MoveComponent(ScaledHalfHeightAdjust * GetGravityDirection(), UpdatedComponent->GetComponentQuat(), true, nullptr, EMoveComponentFlags::MOVECOMP_NoFlags, ETeleportType::TeleportPhysics);
|
||||
}
|
||||
|
||||
CharacterOwner->bIsCrouched = true;
|
||||
CharacterOwner->SetIsCrouched(true);
|
||||
}
|
||||
|
||||
bForceNextFloorCheck = true;
|
||||
|
@ -240,7 +240,7 @@ void UVRCharacterMovementComponent::UnCrouch(bool bClientSimulation)
|
|||
{
|
||||
if (!bClientSimulation)
|
||||
{
|
||||
CharacterOwner->bIsCrouched = false;
|
||||
CharacterOwner->SetIsCrouched(false);
|
||||
}
|
||||
CharacterOwner->OnEndCrouch(0.f, 0.f);
|
||||
return;
|
||||
|
@ -341,7 +341,11 @@ void UVRCharacterMovementComponent::UnCrouch(bool bClientSimulation)
|
|||
if (!bEncroached)
|
||||
{
|
||||
// Commit the change in location.
|
||||
//UpdatedComponent->MoveComponent(StandingLocation - PawnLocation, UpdatedComponent->GetComponentQuat(), false, nullptr, EMoveComponentFlags::MOVECOMP_NoFlags, ETeleportType::TeleportPhysics);
|
||||
if (!BaseVRCharacterOwner || !BaseVRCharacterOwner->bRetainRoomscale)
|
||||
{
|
||||
// we actually move this when not using retained roomscale
|
||||
//UpdatedComponent->MoveComponent(StandingLocation - PawnLocation, UpdatedComponent->GetComponentQuat(), false, nullptr, EMoveComponentFlags::MOVECOMP_NoFlags, ETeleportType::TeleportPhysics);
|
||||
}
|
||||
bForceNextFloorCheck = true;
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +356,7 @@ void UVRCharacterMovementComponent::UnCrouch(bool bClientSimulation)
|
|||
return;
|
||||
}
|
||||
|
||||
CharacterOwner->bIsCrouched = false;
|
||||
CharacterOwner->SetIsCrouched(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -881,7 +885,7 @@ void UVRCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iteration
|
|||
return;
|
||||
}
|
||||
|
||||
if (!CharacterOwner || (!CharacterOwner->Controller && !bRunPhysicsWithNoController && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity() && (CharacterOwner->GetLocalRole() != ROLE_SimulatedProxy)))
|
||||
if (!CharacterOwner || (!CharacterOwner->GetController() && !bRunPhysicsWithNoController && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity() && (CharacterOwner->GetLocalRole() != ROLE_SimulatedProxy)))
|
||||
{
|
||||
Acceleration = FVector::ZeroVector;
|
||||
Velocity = FVector::ZeroVector;
|
||||
|
@ -908,7 +912,7 @@ void UVRCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iteration
|
|||
RewindVRRelativeMovement();
|
||||
|
||||
// Perform the move
|
||||
while ((remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) && CharacterOwner && (CharacterOwner->Controller || bRunPhysicsWithNoController || HasAnimRootMotion() || CurrentRootMotion.HasOverrideVelocity() || (CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)))
|
||||
while ((remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) && CharacterOwner && (CharacterOwner->GetController() || bRunPhysicsWithNoController || HasAnimRootMotion() || CurrentRootMotion.HasOverrideVelocity() || (CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)))
|
||||
{
|
||||
Iterations++;
|
||||
bJustTeleported = false;
|
||||
|
@ -1085,7 +1089,7 @@ void UVRCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iteration
|
|||
}
|
||||
|
||||
AdjustFloorHeight();
|
||||
SetBase(CurrentFloor.HitResult.Component.Get(), CurrentFloor.HitResult.BoneName);
|
||||
SetBaseFromFloor(CurrentFloor);
|
||||
}
|
||||
else if (CurrentFloor.HitResult.bStartPenetrating && remainingTime <= 0.f)
|
||||
{
|
||||
|
@ -2275,7 +2279,7 @@ void UVRCharacterMovementComponent::UpdateBasedMovement(float DeltaSeconds)
|
|||
{
|
||||
// Nothing changed. This means we probably are using another rotation mechanism (bOrientToMovement etc). We should still follow the base object.
|
||||
// @todo: This assumes only Yaw is used, currently a valid assumption. This is the only reason FaceRotation() is used above really, aside from being a virtual hook.
|
||||
if (bOrientRotationToMovement || (bUseControllerDesiredRotation && CharacterOwner->Controller))
|
||||
if (bOrientRotationToMovement || (bUseControllerDesiredRotation && CharacterOwner->GetController()))
|
||||
{
|
||||
// Custom gravity automatically aligns the character to the gravity direction, so we shouldn't zero out pitch and roll.
|
||||
if (!HasCustomGravity())
|
||||
|
@ -2289,7 +2293,7 @@ void UVRCharacterMovementComponent::UpdateBasedMovement(float DeltaSeconds)
|
|||
}
|
||||
|
||||
// Pipe through ControlRotation, to affect camera.
|
||||
if (CharacterOwner->Controller)
|
||||
if (CharacterOwner->GetController())
|
||||
{
|
||||
const FQuat PawnDeltaRotation = FinalQuat * PawnOldQuat.Inverse();
|
||||
FRotator FinalRotation = FinalQuat.Rotator();
|
||||
|
@ -3195,7 +3199,7 @@ void UVRCharacterMovementComponent::PhysNavWalking(float deltaTime, int32 Iterat
|
|||
}
|
||||
|
||||
// Root motion not for VR
|
||||
if ((!CharacterOwner || !CharacterOwner->Controller) && !bRunPhysicsWithNoController && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity())
|
||||
if ((!CharacterOwner || !CharacterOwner->GetController()) && !bRunPhysicsWithNoController && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity())
|
||||
{
|
||||
Acceleration = FVector::ZeroVector;
|
||||
Velocity = FVector::ZeroVector;
|
||||
|
@ -3814,7 +3818,7 @@ void UVRCharacterMovementComponent::SimulateMovement(float DeltaSeconds)
|
|||
if (IsMovingOnGround())
|
||||
{
|
||||
AdjustFloorHeight();
|
||||
SetBase(CurrentFloor.HitResult.Component.Get(), CurrentFloor.HitResult.BoneName);
|
||||
SetBaseFromFloor(CurrentFloor);
|
||||
}
|
||||
else if (MovementMode == MOVE_Falling)
|
||||
{
|
||||
|
|
|
@ -544,7 +544,7 @@ void UVRGestureComponent::DrawDebugGesture(UObject* WorldContextObject, FTransfo
|
|||
FVector MirrorVector = FVector(1.f, -1.f, 1.f); // Only mirroring on Y axis to flip Left/Right
|
||||
|
||||
// this means foreground lines can't be persistent
|
||||
ULineBatchComponent* const LineBatcher = (InWorld ? ((DepthPriority == SDPG_Foreground) ? InWorld->ForegroundLineBatcher : ((bPersistentLines || (LifeTime > 0.f)) ? InWorld->PersistentLineBatcher : InWorld->LineBatcher)) : NULL);
|
||||
ULineBatchComponent* const LineBatcher = (InWorld ? ((DepthPriority == SDPG_Foreground) ? InWorld->GetLineBatcher(UWorld::ELineBatcherType::Foreground) : ((bPersistentLines || (LifeTime > 0.f)) ? InWorld->GetLineBatcher(UWorld::ELineBatcherType::WorldPersistent) : InWorld->GetLineBatcher(UWorld::ELineBatcherType::World))) : NULL);
|
||||
|
||||
if (LineBatcher != NULL)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ void UVRPathFollowingComponent::GetDebugStringTokens(TArray<FString>& Tokens, TA
|
|||
Tokens.Add(GetStatusDesc());
|
||||
Flags.Add(EPathFollowingDebugTokens::Description);
|
||||
|
||||
if (Status != EPathFollowingStatus::Moving)
|
||||
if (GetStatus() != EPathFollowingStatus::Moving)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Engine/ScopedMovementUpdate.h"
|
||||
#include "SceneManagement.h"
|
||||
#include "PrimitiveSceneProxy.h"
|
||||
#include "SceneView.h"
|
||||
//#include "DrawDebugHelpers.h"
|
||||
#include "IHeadMountedDisplay.h"
|
||||
#include "IXRTrackingSystem.h"
|
||||
|
@ -962,7 +963,7 @@ bool UVRRootComponent::MoveComponentImpl(const FVector& Delta, const FQuat& NewR
|
|||
//CSV_SCOPED_TIMING_STAT(PrimitiveComponent, MoveComponentTime);
|
||||
|
||||
// static things can move before they are registered (e.g. immediately after streaming), but not after.
|
||||
if (!IsValid(this) || (this->Mobility == EComponentMobility::Static && IsRegistered()))//|| CheckStaticMobilityAndWarn(PrimitiveComponentStatics::MobilityWarnText))
|
||||
if (!IsValidChecked(this) || (this->Mobility == EComponentMobility::Static && IsRegistered()))//|| CheckStaticMobilityAndWarn(PrimitiveComponentStatics::MobilityWarnText))
|
||||
{
|
||||
if (OutHit)
|
||||
{
|
||||
|
@ -1233,7 +1234,7 @@ bool UVRRootComponent::MoveComponentImpl(const FVector& Delta, const FQuat& NewR
|
|||
|
||||
// Handle blocking hit notifications. Avoid if pending kill (which could happen after overlaps).
|
||||
const bool bAllowHitDispatch = !BlockingHit.bStartPenetrating || !(MoveFlags & MOVECOMP_DisableBlockingOverlapDispatch);
|
||||
if (BlockingHit.bBlockingHit && bAllowHitDispatch && IsValid(this))
|
||||
if (BlockingHit.bBlockingHit && bAllowHitDispatch && IsValidChecked(this))
|
||||
{
|
||||
check(bFilledHitResult);
|
||||
if (IsDeferringMovementUpdates())
|
||||
|
@ -1329,7 +1330,7 @@ bool UVRRootComponent::UpdateOverlapsImpl(const TOverlapArrayView* NewPendingOve
|
|||
TInlineOverlapPointerArray NewOverlappingComponentPtrs;
|
||||
|
||||
// If pending kill, we should not generate any new overlaps. Also not if overlaps were just disabled during BeginComponentOverlap.
|
||||
if (IsValid(this) && GetGenerateOverlapEvents())
|
||||
if (IsValidChecked(this) && GetGenerateOverlapEvents())
|
||||
{
|
||||
// 4.17 converted to auto cvar
|
||||
static const auto CVarAllowCachedOverlaps = IConsoleManager::Get().FindConsoleVariable(TEXT("p.AllowCachedOverlaps"));
|
||||
|
@ -1553,7 +1554,7 @@ bool UVRRootComponent::IsLocallyControlled() const
|
|||
// Simulated proxies should already have the new height from the server
|
||||
if (!owningVRChar->bRetainRoomscale && (owningVRChar->GetNetMode() < ENetMode::NM_Client || IsLocallyControlled()))
|
||||
{
|
||||
MoveComponent(this->GetComponentQuat().GetUpVector() * (Offset * this->GetComponentScale().Z), GetComponentQuat(), true, nullptr, EMoveComponentFlags::MOVECOMP_NoFlags, ETeleportType::TeleportPhysics);
|
||||
MoveComponent(this->GetComponentQuat().GetUpVector() * (Offset * this->GetComponentScale().Z), GetComponentQuat(), false, nullptr, EMoveComponentFlags::MOVECOMP_NoFlags, ETeleportType::TeleportPhysics);
|
||||
}
|
||||
/*else
|
||||
{
|
||||
|
@ -1581,7 +1582,7 @@ bool UVRRootComponent::IsLocallyControlled() const
|
|||
|
||||
void UVRRootComponent::UpdatePhysicsVolume(bool bTriggerNotifiers)
|
||||
{
|
||||
if (GetShouldUpdatePhysicsVolume() && IsValid(this))
|
||||
if (GetShouldUpdatePhysicsVolume() && IsValidChecked(this))
|
||||
{
|
||||
// SCOPE_CYCLE_COUNTER(STAT_UpdatePhysicsVolume);
|
||||
if (UWorld * MyWorld = GetWorld())
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "VRRootComponent.h"
|
||||
#include "TextureResource.h"
|
||||
#include "Engine/Texture.h"
|
||||
#include "Engine/Texture2D.h"
|
||||
#include "SceneView.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "SceneManagement.h"
|
||||
#include "Materials/Material.h"
|
||||
|
@ -27,6 +29,8 @@
|
|||
#include "Engine/Engine.h"
|
||||
#include "Engine/GameViewportClient.h"
|
||||
#include "Engine/TextureRenderTarget2D.h"
|
||||
#include "ImageUtils.h"
|
||||
#include "ImageCoreUtils.h"
|
||||
//#include "Widgets/SWindow.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Kismet/KismetSystemLibrary.h"
|
||||
|
@ -415,6 +419,8 @@ UVRStereoWidgetComponent::~UVRStereoWidgetComponent()
|
|||
|
||||
void UVRStereoWidgetComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
Super::EndPlay(EndPlayReason);
|
||||
|
||||
if (EndPlayReason == EEndPlayReason::EndPlayInEditor || EndPlayReason == EEndPlayReason::Quit)
|
||||
{
|
||||
//FStereoLayerAdditionalFlagsManager::Destroy();
|
||||
|
@ -431,6 +437,12 @@ void UVRStereoWidgetComponent::BeginDestroy()
|
|||
LayerId = IStereoLayers::FLayerDesc::INVALID_LAYER_ID;
|
||||
}
|
||||
|
||||
if (IsValid(TextureRef))
|
||||
{
|
||||
TextureRef->RemoveFromRoot();
|
||||
TextureRef = nullptr;
|
||||
}
|
||||
|
||||
Super::BeginDestroy();
|
||||
}
|
||||
|
||||
|
@ -601,7 +613,14 @@ void UVRStereoWidgetComponent::TickComponent(float DeltaTime, enum ELevelTick Ti
|
|||
|
||||
if (AVRCharacter* VRChar = Cast<AVRCharacter>(mpawn))
|
||||
{
|
||||
HMDLoc += UVRExpansionFunctionLibrary::GetHMDPureYaw_I(HMDRot.Rotator()).RotateVector(FVector(VRChar->VRRootReference->VRCapsuleOffset.X, VRChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
if (VRChar->VRMovementReference && VRChar->VRMovementReference->GetReplicatedMovementMode() == EVRConjoinedMovementModes::C_VRMOVE_Seated)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HMDLoc += UVRExpansionFunctionLibrary::GetHMDPureYaw_I(HMDRot.Rotator()).RotateVector(FVector(VRChar->VRRootReference->VRCapsuleOffset.X, VRChar->VRRootReference->VRCapsuleOffset.Y, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
DeltaTrans = FTransform(FQuat::Identity, HMDLoc, FVector(1.0f));
|
||||
|
@ -711,8 +730,12 @@ void UVRStereoWidgetComponent::TickComponent(float DeltaTime, enum ELevelTick Ti
|
|||
|
||||
if (RenderTarget)
|
||||
{
|
||||
LayerDsec.Texture = RenderTarget->GetResource()->TextureRHI;
|
||||
// TODO 5.7 need to figure out how to replace this in some way that isn't so fing slow
|
||||
//PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
//LayerDsec.Texture = RenderTarget->GetResource()->TextureRHI;
|
||||
LayerDsec.TextureObj = RenderTarget;
|
||||
LayerDsec.Flags |= (RenderTarget->GetMaterialType() == MCT_TextureExternal) ? IStereoLayers::LAYER_FLAG_TEX_EXTERNAL : 0;
|
||||
//PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
// Forget the left texture implementation
|
||||
//if (LeftTexture)
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
|
||||
#pragma region FPhysicsReplicationAsync
|
||||
|
||||
class FPhysicsReplicationAsyncVR : public Chaos::TSimCallbackObject<
|
||||
class FPhysicsReplicationAsyncVR : public IPhysicsReplicationAsync,
|
||||
public Chaos::TSimCallbackObject<
|
||||
FPhysicsReplicationAsyncInput,
|
||||
Chaos::FSimCallbackNoOutput,
|
||||
Chaos::ESimCallbackOptions::Presimulate | Chaos::ESimCallbackOptions::PhysicsObjectUnregister>
|
||||
|
@ -45,7 +46,9 @@ class FPhysicsReplicationAsyncVR : public Chaos::TSimCallbackObject<
|
|||
virtual void OnPreSimulate_Internal() override;
|
||||
virtual void OnPhysicsObjectUnregistered_Internal(Chaos::FConstPhysicsObjectHandle PhysicsObject) override;
|
||||
|
||||
virtual void ApplyTargetStatesAsync(const float DeltaSeconds, const FPhysicsRepErrorCorrectionData& ErrorCorrection, const TArray<FPhysicsRepAsyncInputData>& TargetStates);
|
||||
virtual void ApplyTargetStatesAsync(const float DeltaSeconds);
|
||||
UE_DEPRECATED(5.6, "Deprecated, call the function with just @param DeltaSeconds instead.")
|
||||
virtual void ApplyTargetStatesAsync(const float DeltaSeconds, const FPhysicsRepErrorCorrectionData& ErrorCorrection, const TArray<FPhysicsRepAsyncInputData>& TargetStates) { ApplyTargetStatesAsync(DeltaSeconds); };
|
||||
|
||||
// Replication functions
|
||||
virtual void DefaultReplication_DEPRECATED(Chaos::FRigidBodyHandle_Internal* Handle, const FPhysicsRepAsyncInputData& State, const float DeltaSeconds, const FPhysicsRepErrorCorrectionData& ErrorCorrection);
|
||||
|
@ -54,7 +57,7 @@ class FPhysicsReplicationAsyncVR : public Chaos::TSimCallbackObject<
|
|||
virtual bool ResimulationReplication(Chaos::FPBDRigidParticleHandle* Handle, FReplicatedPhysicsTargetAsync& Target, const float DeltaSeconds);
|
||||
|
||||
public:
|
||||
virtual void RegisterSettings(Chaos::FConstPhysicsObjectHandle PhysicsObject, FNetworkPhysicsSettingsAsync InSettings);
|
||||
virtual void RegisterSettings(Chaos::FConstPhysicsObjectHandle PhysicsObject, FNetworkPhysicsSettingsAsync InSettings) override;
|
||||
|
||||
private:
|
||||
float LatencyOneWay;
|
||||
|
@ -63,6 +66,8 @@ private:
|
|||
FNetworkPhysicsSettingsAsync SettingsDefault;
|
||||
TMap<Chaos::FConstPhysicsObjectHandle, FReplicatedPhysicsTargetAsync> ObjectToTarget;
|
||||
TMap<Chaos::FConstPhysicsObjectHandle, FNetworkPhysicsSettingsAsync> ObjectToSettings;
|
||||
TArray<const Chaos::Private::FPBDIsland*> ResimIslands;
|
||||
TArray<const Chaos::FGeometryParticleHandle*> ResimIslandsParticles;
|
||||
TArray<int32> ParticlesInResimIslands;
|
||||
TArray<Chaos::FParticleID> ReplicatedParticleIDs;
|
||||
|
||||
|
@ -74,7 +79,15 @@ private:
|
|||
void CacheResimInteractions();
|
||||
// Sets SettingsCurrent to either the objects custom settings or to the default settings
|
||||
void FetchObjectSettings(Chaos::FConstPhysicsObjectHandle PhysicsObject);
|
||||
bool UsePhysicsReplicationLOD();
|
||||
void CheckTargetResimValidity(FReplicatedPhysicsTargetAsync& Target);
|
||||
void ApplyPhysicsReplicationLOD(Chaos::FConstPhysicsObjectHandle PhysicsObjectHandle, FReplicatedPhysicsTargetAsync& Target, const uint32 LODFlags);
|
||||
void DebugDrawReplicationMode(const FPhysicsRepAsyncInputData& Input);
|
||||
|
||||
/** Static function to extrapolate a target for N ticks using X DeltaSeconds */
|
||||
static void ExtrapolateTarget(FReplicatedPhysicsTargetAsync& Target, const int32 ExtrapolateFrames, const float DeltaSeconds);
|
||||
/** Static function to extrapolate a target for N Seconds */
|
||||
static void ExtrapolateTarget(FReplicatedPhysicsTargetAsync& Target, const float ExtrapolationTime);
|
||||
|
||||
public:
|
||||
void Setup(FRigidBodyErrorCorrection ErrorCorrection)
|
||||
|
|
|
@ -61,5 +61,5 @@ public:
|
|||
|
||||
virtual void PostInitProperties() override;
|
||||
virtual bool InputKey(const FInputKeyEventArgs& EventArgs) override;
|
||||
virtual bool InputAxis(FViewport* tViewport, FInputDeviceId InputDevice, FKey Key, float Delta, float DeltaTime, int32 NumSamples = 1, bool bGamepad = false) override;
|
||||
virtual bool InputAxis(const FInputKeyEventArgs& Args) override;
|
||||
};
|
|
@ -93,11 +93,11 @@ public:
|
|||
SetupPlayerInputComponent(InputComponent);
|
||||
InputComponent->RegisterComponent();
|
||||
|
||||
if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
|
||||
{
|
||||
//if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
|
||||
//{
|
||||
InputComponent->bBlockInput = bBlockInput;
|
||||
UInputDelegateBinding::BindInputDelegates(GetClass(), InputComponent);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,11 +108,11 @@ public:
|
|||
SetupPlayerInputComponent(InputComponent);
|
||||
InputComponent->RegisterComponent();
|
||||
|
||||
if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
|
||||
{
|
||||
//if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
|
||||
//{
|
||||
InputComponent->bBlockInput = bBlockInput;
|
||||
UInputDelegateBinding::BindInputDelegates(GetClass(), InputComponent);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,9 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "StereoLayer", Meta = (GetOptions = "EditorFlagCollector.GetFlagNames"))
|
||||
TArray<FName> AdditionalFlags;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<class UTexture2D> TextureRef = nullptr;
|
||||
|
||||
protected:
|
||||
/** Texture displayed on the stereo layer (is stereocopic textures are supported on the platfrom and more than one texture is provided, this will be the right eye) **/
|
||||
//UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "StereoLayer")
|
||||
|
|
|
@ -11,6 +11,8 @@ public class VRExpansionPlugin : ModuleRules
|
|||
|
||||
public VRExpansionPlugin(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
DefaultBuildSettings = BuildSettingsVersion.Latest;
|
||||
IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
//bEnforceIWYU = true;
|
||||
|
||||
|
@ -83,6 +85,7 @@ public class VRExpansionPlugin : ModuleRules
|
|||
// "CoreUObject",
|
||||
//"Engine",
|
||||
"InputCore",
|
||||
"ImageCore", // For new stereo layer stuff
|
||||
//"FLEX", remove comment if building in the NVIDIA flex branch - NOTE when put in place FLEX only listed win32 and win64 at compatible platforms
|
||||
//"HeadMountedDisplay",
|
||||
"RHI",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue