diff --git a/Source/DisplayClusterExtensions/Private/WalkingPawnMovement.cpp b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp similarity index 69% rename from Source/DisplayClusterExtensions/Private/WalkingPawnMovement.cpp rename to Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp index d49ce2e3c6458393808cf131276c2cd0e57c043f..37b75ccf3a9cdd10b80a17a41866d1a20352c0f1 100644 --- a/Source/DisplayClusterExtensions/Private/WalkingPawnMovement.cpp +++ b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp @@ -1,8 +1,8 @@ -#include "WalkingPawnMovement.h" +#include "VRPawnMovement.h" #include "DrawDebugHelpers.h" -UWalkingPawnMovement::UWalkingPawnMovement(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +UVRPawnMovement::UVRPawnMovement(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider")); CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); @@ -11,54 +11,60 @@ UWalkingPawnMovement::UWalkingPawnMovement(const FObjectInitializer& ObjectIniti CapsuleColliderComponent->SetCapsuleSize(40.0f, 96.0f); } -void UWalkingPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){ +void UVRPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){ - Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + SetCapsuleColliderToUserSize(); + + FVector PositionChange = GetPendingInputVector(); + + if (NavigationMode == EVRNavigationModes::Walk) + { + PositionChange.Z = 0.0f; + ConsumeInputVector(); + AddInputVector(PositionChange); + } - if (NavigationMode == EVRNavigationModes::nav_mode_walk) + if(NavigationMode == EVRNavigationModes::Fly || NavigationMode == EVRNavigationModes::Walk) { - SetCapsuleColliderCharacterSizeVR(); MoveByGravityOrStepUp(DeltaTime); CheckForPhysWalkingCollision(); - } - - LastCameraPosition = CameraComponent->GetComponentLocation(); - LastDeltaTime = DeltaTime; -} -void UWalkingPawnMovement::AddInputVector(FVector WorldVector, bool bForce /*= false*/) -{ - if (NavigationMode == EVRNavigationModes::nav_mode_walk) - { - WalkingModeInput(WorldVector, bForce); + if(CheckForVirtualMovCollision(PositionChange, DeltaTime)) + { + ConsumeInputVector(); + } } - else if (NavigationMode == EVRNavigationModes::nav_mode_fly) + + if(NavigationMode == EVRNavigationModes::None) { - Super::AddInputVector(WorldVector, bForce); + ConsumeInputVector(); } + + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + LastCameraPosition = CameraComponent->GetComponentLocation(); } -void UWalkingPawnMovement::WalkingModeInput(FVector WorldDirection, bool bForce) +bool UVRPawnMovement::CheckForVirtualMovCollision(FVector PositionChange, float DeltaTime) { - WorldDirection.Z = 0.0f;//walking - FVector End = WorldDirection.GetSafeNormal() * GetMaxSpeed(); + FVector ProbePosition = PositionChange.GetSafeNormal() * GetMaxSpeed() * DeltaTime; FHitResult FHitResultVR; - CapsuleColliderComponent->AddWorldOffset(End* LastDeltaTime * WorldDirection.Size(), true, &FHitResultVR); - - if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) > CapsuleColliderComponent->GetScaledCapsuleRadius()) + CapsuleColliderComponent->AddWorldOffset(ProbePosition, true, &FHitResultVR); + if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) < CapsuleColliderComponent->GetScaledCapsuleRadius()) { - Super::AddInputVector(WorldDirection, bForce); + return true; } + return false; } -void UWalkingPawnMovement::SetCameraComponent(UCameraComponent* NewCameraComponent) +void UVRPawnMovement::SetCameraComponent(UCameraComponent* NewCameraComponent) { CameraComponent = NewCameraComponent; CapsuleColliderComponent->SetupAttachment(CameraComponent); } -void UWalkingPawnMovement::SetCapsuleColliderCharacterSizeVR() +void UVRPawnMovement::SetCapsuleColliderToUserSize() { float CharachterSize = abs(UpdatedComponent->GetComponentLocation().Z - CameraComponent->GetComponentLocation().Z); @@ -87,7 +93,7 @@ void UWalkingPawnMovement::SetCapsuleColliderCharacterSizeVR() } } -void UWalkingPawnMovement::CheckForPhysWalkingCollision() +void UVRPawnMovement::CheckForPhysWalkingCollision() { FVector CurrentCameraPosition = CameraComponent->GetComponentLocation(); FVector Direction = CurrentCameraPosition - LastCameraPosition; @@ -100,25 +106,25 @@ void UWalkingPawnMovement::CheckForPhysWalkingCollision() } } -void UWalkingPawnMovement::MoveByGravityOrStepUp(float DeltaSeconds) +void UVRPawnMovement::MoveByGravityOrStepUp(float DeltaSeconds) { FVector StartLineTraceUnderCollider = CapsuleColliderComponent->GetComponentLocation(); StartLineTraceUnderCollider.Z -= CapsuleColliderComponent->GetScaledCapsuleHalfHeight(); FHitResult HitDetailsMultiLineTrace = CreateMultiLineTrace(FVector(0, 0, -1), StartLineTraceUnderCollider, CapsuleColliderComponent->GetScaledCapsuleRadius() / 4.0f, false); - float DiffernceDistance = abs(MaxStepHeight - HitDetailsMultiLineTrace.Distance); - //Going up + float DistanceDifference = abs(MaxStepHeight - HitDetailsMultiLineTrace.Distance); + //Going up (in Fly and Walk Mode) if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance < MaxStepHeight)) { - ShiftVertically(DiffernceDistance, UpSteppingAcceleration, DeltaSeconds, 1); + ShiftVertically(DistanceDifference, UpSteppingAcceleration, DeltaSeconds, 1); } - //Falling, Gravity, Going down - else if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f)) + //Gravity (only in Walk Mode) + else if (NavigationMode==EVRNavigationModes::Walk && ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f))) { - ShiftVertically(DiffernceDistance, GravityAcceleration, DeltaSeconds, -1); + ShiftVertically(DistanceDifference, GravityAcceleration, DeltaSeconds, -1); } } -void UWalkingPawnMovement::ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction) +void UVRPawnMovement::ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction) { VerticalSpeed += VerticalAcceleration * DeltaSeconds; if (VerticalSpeed*DeltaSeconds < DiffernceDistance) @@ -132,7 +138,7 @@ void UWalkingPawnMovement::ShiftVertically(float DiffernceDistance, float Vertic } } -FHitResult UWalkingPawnMovement::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility) +FHitResult UVRPawnMovement::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility) { //Re-initialize hit info FHitResult HitDetails = FHitResult(ForceInit); @@ -155,7 +161,7 @@ FHitResult UWalkingPawnMovement::CreateLineTrace(FVector Direction, const FVecto return HitDetails; } -FHitResult UWalkingPawnMovement::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility) +FHitResult UVRPawnMovement::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility) { TArray<FVector> StartVectors; TArray<FHitResult> OutHits; diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp index 3bdf59ed703923fddee28cb068bb3b511575632e..57750819a5c2afac0f930263dd8e720201bed309 100644 --- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp +++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp @@ -27,9 +27,9 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events. - WalkingMovement = CreateDefaultSubobject<UWalkingPawnMovement>(TEXT("WalkingMovement")); - WalkingMovement->SetUpdatedComponent(RootComponent); - WalkingMovement->SetCameraComponent(CameraComponent); + VRMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("WalkingMovement")); + VRMovement->SetUpdatedComponent(RootComponent); + VRMovement->SetCameraComponent(CameraComponent); RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingMovement")); RotatingMovement->UpdatedComponent = RootComponent; @@ -210,10 +210,10 @@ void AVirtualRealityPawn::BeginPlay() if (SettingsActors.Num() > 0) { ADisplayClusterSettings* Settings = Cast<ADisplayClusterSettings>(SettingsActors[0]); - WalkingMovement->MaxSpeed = Settings->MovementMaxSpeed; - WalkingMovement->Acceleration = Settings->MovementAcceleration; - WalkingMovement->Deceleration = Settings->MovementDeceleration; - WalkingMovement->TurningBoost = Settings->MovementTurningBoost; + VRMovement->MaxSpeed = Settings->MovementMaxSpeed; + VRMovement->Acceleration = Settings->MovementAcceleration; + VRMovement->Deceleration = Settings->MovementDeceleration; + VRMovement->TurningBoost = Settings->MovementTurningBoost; BaseTurnRate = Settings->RotationSpeed; } @@ -277,9 +277,6 @@ void AVirtualRealityPawn::BeginPlay() CollisionComponent->SetCollisionProfileName(FName("NoCollision")); CollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); - - //if the navigation mode was changed in the editor, it should be updated in the actual movement component - SetNavigationMode(NavigationMode); } void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -420,7 +417,7 @@ FTwoVectors AVirtualRealityPawn::GetHandRay(float Length) UPawnMovementComponent* AVirtualRealityPawn::GetMovementComponent() const { - return WalkingMovement; + return VRMovement; } void AVirtualRealityPawn::InitRoomMountedComponentReferences() @@ -460,6 +457,5 @@ void AVirtualRealityPawn::InitRoomMountedComponentReferences() void AVirtualRealityPawn::SetNavigationMode(EVRNavigationModes Mode) { - NavigationMode = Mode; - WalkingMovement->NavigationMode = Mode; + VRMovement->NavigationMode = Mode; } diff --git a/Source/DisplayClusterExtensions/Public/VRPawnMovement.h b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h new file mode 100644 index 0000000000000000000000000000000000000000..20a6f4b6707cd7a8ec60116f4fb0386d9fc017a4 --- /dev/null +++ b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h @@ -0,0 +1,70 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/FloatingPawnMovement.h" +#include "Components/CapsuleComponent.h" +#include "Camera/CameraComponent.h" + +#include "VRPawnMovement.generated.h" + +/* + * This Movement component is needed since in VR not only the pawn itself (UpdatedComponent) is moved but also the + * user herself can walk and thereby move the CameraComponent, which can also lead to collisions or e.g. going up steps + * + * The four modes are: + * None: No controller movement is applied and no corrections regarding steps or collisions with walls are done + * Ghost: The same as above but now the Inputs can be used for unconstrained flying (also through objects) + * Fly: The user can fly but not through walls etc. When the user walks against a wall the scene is moved with her to avoid walking through + * The user can also walk up stairs with a maximum step height of MaxStepHeight + * Walk: Additionally to Fly now gravity keeps the user on the floor + */ + +UENUM(BlueprintType) +enum class EVRNavigationModes : uint8 +{ + None UMETA(DisplayName = "None (no controller movement)"), + Ghost UMETA(DisplayName = "Ghost (flying, also through walls)"), + Fly UMETA(DisplayName = "Fly (prohibiting collisions)"), + Walk UMETA(DisplayName = "Walk (gravity and prohibiting collisions)") +}; + +UCLASS() +class DISPLAYCLUSTEREXTENSIONS_API UVRPawnMovement : public UFloatingPawnMovement +{ + GENERATED_UCLASS_BODY() + +public: + + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + + void SetCameraComponent(UCameraComponent* NewCameraComponent); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement") + EVRNavigationModes NavigationMode = EVRNavigationModes::Walk; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement") + float MaxStepHeight = 40.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement") + float GravityAcceleration = 981.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement") + float UpSteppingAcceleration = 500.0f; + +private: + FHitResult CreateLineTrace(FVector Direction, const FVector Start, bool Visibility); + FHitResult CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility); + void SetCapsuleColliderToUserSize(); + void CheckForPhysWalkingCollision(); + bool CheckForVirtualMovCollision(FVector PositionChange, float DeltaTime); + void MoveByGravityOrStepUp(float DeltaSeconds); + void ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction); + //(direction = Down = -1), (direction = Up = 1) + + UPROPERTY() UCapsuleComponent* CapsuleColliderComponent = nullptr; + UPROPERTY() UCameraComponent* CameraComponent = nullptr; + + float VerticalSpeed = 0.0f; + FVector LastCameraPosition; +}; diff --git a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h index 2cf7a590291102c2f5fa14cf2ff417cbf9bae4e7..b02f183320a14b199290438a8f3d4a21f50389ee 100644 --- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h +++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h @@ -6,7 +6,7 @@ #include "DisplayClusterPawn.h" #include "DisplayClusterSceneComponent.h" #include "Components/CapsuleComponent.h" -#include "WalkingPawnMovement.h" +#include "VRPawnMovement.h" #include "GameFramework/RotatingMovementComponent.h" #include "MotionControllerComponent.h" @@ -56,8 +56,6 @@ public: UFUNCTION(Category = "Pawn") USceneComponent* GetTrackingOriginComponent(); UFUNCTION(Category = "Pawn") void SetNavigationMode(EVRNavigationModes Mode); - //we also add this property so the navigation mode can be changed easier in the editor, will get forwarded to the movment comp on BeginPlay - UPROPERTY(Category = "Pawn", EditAnywhere, BlueprintReadOnly) EVRNavigationModes NavigationMode = EVRNavigationModes::nav_mode_fly; private: UFUNCTION(Category = "Pawn") USceneComponent* GetCaveCenterComponent(); @@ -80,7 +78,7 @@ protected: virtual UPawnMovementComponent* GetMovementComponent() const override; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn", meta = (AllowPrivateAccess = "true")) float BaseTurnRate = 45.0f; - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UWalkingPawnMovement* WalkingMovement = nullptr; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UVRPawnMovement* VRMovement = nullptr; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) URotatingMovementComponent* RotatingMovement = nullptr; // Use only when handling cross-device (PC, HMD, CAVE/ROLV) compatibility manually. CAVE/ROLV flystick. diff --git a/Source/DisplayClusterExtensions/Public/WalkingPawnMovement.h b/Source/DisplayClusterExtensions/Public/WalkingPawnMovement.h deleted file mode 100644 index 1fce5e52c144a71e48d6817f597143f16362f784..0000000000000000000000000000000000000000 --- a/Source/DisplayClusterExtensions/Public/WalkingPawnMovement.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/FloatingPawnMovement.h" -#include "Components/CapsuleComponent.h" -#include "Camera/CameraComponent.h" - -#include "WalkingPawnMovement.generated.h" - -UENUM(BlueprintType) -enum class EVRNavigationModes : uint8 -{ - nav_mode_none UMETA(DisplayName = "Navigation Mode None"), - nav_mode_walk UMETA(DisplayName = "Navigation Mode Walk"), - nav_mode_fly UMETA(DisplayName = "Navigation Mode Fly") -}; - -UCLASS() -class DISPLAYCLUSTEREXTENSIONS_API UWalkingPawnMovement : public UFloatingPawnMovement -{ - GENERATED_UCLASS_BODY() - -public: - - virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, - FActorComponentTickFunction* ThisTickFunction) override; - - virtual void AddInputVector(FVector WorldVector, bool bForce = false) override; - - void SetCameraComponent(UCameraComponent* NewCameraComponent); - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "WalkingMovement") - EVRNavigationModes NavigationMode = EVRNavigationModes::nav_mode_fly; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "WalkingMovement") - float MaxStepHeight = 40.0f; - -private: - FHitResult CreateLineTrace(FVector Direction, const FVector Start, bool Visibility); - FHitResult CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility); - void SetCapsuleColliderCharacterSizeVR(); - void CheckForPhysWalkingCollision(); - void WalkingModeInput(FVector WorldDirection, bool bForce); - void MoveByGravityOrStepUp(float DeltaSeconds); - void ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction); - //(direction = Down = -1), (direction = Up = 1) - - UPROPERTY() UCapsuleComponent* CapsuleColliderComponent = nullptr; - UPROPERTY() UCameraComponent* CameraComponent = nullptr; - - float VerticalSpeed = 0.0f; - UPROPERTY() float GravityAcceleration = 981.0f; - UPROPERTY() float UpSteppingAcceleration = 500.0f; - FVector LastCameraPosition; - float LastDeltaTime = 0.0f; -};