diff --git a/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37b75ccf3a9cdd10b80a17a41866d1a20352c0f1 --- /dev/null +++ b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp @@ -0,0 +1,192 @@ + +#include "VRPawnMovement.h" +#include "DrawDebugHelpers.h" + +UVRPawnMovement::UVRPawnMovement(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ + CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider")); + CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); + CapsuleColliderComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); + CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block); + CapsuleColliderComponent->SetCapsuleSize(40.0f, 96.0f); +} + +void UVRPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction){ + + SetCapsuleColliderToUserSize(); + + FVector PositionChange = GetPendingInputVector(); + + if (NavigationMode == EVRNavigationModes::Walk) + { + PositionChange.Z = 0.0f; + ConsumeInputVector(); + AddInputVector(PositionChange); + } + + if(NavigationMode == EVRNavigationModes::Fly || NavigationMode == EVRNavigationModes::Walk) + { + MoveByGravityOrStepUp(DeltaTime); + CheckForPhysWalkingCollision(); + + if(CheckForVirtualMovCollision(PositionChange, DeltaTime)) + { + ConsumeInputVector(); + } + } + + if(NavigationMode == EVRNavigationModes::None) + { + ConsumeInputVector(); + } + + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + LastCameraPosition = CameraComponent->GetComponentLocation(); +} + +bool UVRPawnMovement::CheckForVirtualMovCollision(FVector PositionChange, float DeltaTime) +{ + FVector ProbePosition = PositionChange.GetSafeNormal() * GetMaxSpeed() * DeltaTime; + FHitResult FHitResultVR; + CapsuleColliderComponent->AddWorldOffset(ProbePosition, true, &FHitResultVR); + if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) < CapsuleColliderComponent->GetScaledCapsuleRadius()) + { + return true; + } + return false; +} + +void UVRPawnMovement::SetCameraComponent(UCameraComponent* NewCameraComponent) +{ + CameraComponent = NewCameraComponent; + CapsuleColliderComponent->SetupAttachment(CameraComponent); +} + + +void UVRPawnMovement::SetCapsuleColliderToUserSize() +{ + float CharachterSize = abs(UpdatedComponent->GetComponentLocation().Z - CameraComponent->GetComponentLocation().Z); + + if (CharachterSize > MaxStepHeight) + { + float ColliderHeight = CharachterSize - MaxStepHeight; + float ColliderHalfHeight = ColliderHeight / 2.0f; + float ColliderRadius = 40.0f; + if (ColliderHalfHeight <= ColliderRadius) + {//Make the collider to a Sphere + CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight); + } + else + {//Make the collider to a Capsule + CapsuleColliderComponent->SetCapsuleSize(ColliderRadius, ColliderHalfHeight); + } + + CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation()); + CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight)); + CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1)); + } + else + { + CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation()); + CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1)); + } +} + +void UVRPawnMovement::CheckForPhysWalkingCollision() +{ + FVector CurrentCameraPosition = CameraComponent->GetComponentLocation(); + FVector Direction = CurrentCameraPosition - LastCameraPosition; + FHitResult FHitResultPhys; + CapsuleColliderComponent->AddWorldOffset(Direction, true, &FHitResultPhys); + + if (FHitResultPhys.bBlockingHit) + { + UpdatedComponent->AddLocalOffset(FHitResultPhys.Normal*FHitResultPhys.PenetrationDepth); + } +} + +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 DistanceDifference = abs(MaxStepHeight - HitDetailsMultiLineTrace.Distance); + //Going up (in Fly and Walk Mode) + if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance < MaxStepHeight)) + { + ShiftVertically(DistanceDifference, UpSteppingAcceleration, DeltaSeconds, 1); + } + //Gravity (only in Walk Mode) + else if (NavigationMode==EVRNavigationModes::Walk && ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f))) + { + ShiftVertically(DistanceDifference, GravityAcceleration, DeltaSeconds, -1); + } +} + +void UVRPawnMovement::ShiftVertically(float DiffernceDistance, float VerticalAcceleration, float DeltaSeconds, int Direction) +{ + VerticalSpeed += VerticalAcceleration * DeltaSeconds; + if (VerticalSpeed*DeltaSeconds < DiffernceDistance) + { + UpdatedComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * VerticalSpeed * DeltaSeconds)); + } + else + { + UpdatedComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * DiffernceDistance)); + VerticalSpeed = 0; + } +} + +FHitResult UVRPawnMovement::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility) +{ + //Re-initialize hit info + FHitResult HitDetails = FHitResult(ForceInit); + + FVector End = ((Direction * 1000.f) + Start); + // additional trace parameters + FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, NULL); + TraceParams.bTraceComplex = true; //to use complex collision on whatever we interact with to provide better precision. + TraceParams.bReturnPhysicalMaterial = true; //to provide details about the physical material, if one exists on the thing we hit, to come back in our hit result. + + if (Visibility) + DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1, 0, 1); + + if (GetWorld()->LineTraceSingleByChannel(HitDetails, Start, End, ECC_Visibility, TraceParams)) + { + if (HitDetails.bBlockingHit) + { + } + } + return HitDetails; +} + +FHitResult UVRPawnMovement::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility) +{ + TArray<FVector> StartVectors; + TArray<FHitResult> OutHits; + FHitResult HitDetailsMultiLineTrace; + HitDetailsMultiLineTrace.Distance = -1.0f;//(Distance=-1) not existing, but to know if this Variable not Initialized(when all Traces not compatible) + + StartVectors.Add(Start); //LineTraceCenter + StartVectors.Add(Start + FVector(0, -Radius, 0)); //LineTraceLeft + StartVectors.Add(Start + FVector(0, +Radius, 0)); //LineTraceRight + StartVectors.Add(Start + FVector(+Radius, 0, 0)); //LineTraceFront + StartVectors.Add(Start + FVector(-Radius, 0, 0)); //LineTraceBehind + + bool IsBlockingHitAndSameActor = true; + bool IsAllNothingHiting = true; + // loop through TArray + for (FVector& Vector : StartVectors) + { + FHitResult OutHit = CreateLineTrace(Direction, Vector, Visibility); + OutHits.Add(OutHit); + IsBlockingHitAndSameActor &= (OutHit.Actor == OutHits[0].Actor); //If all Hiting the same Object, then you are (going up/down) or (walking) + IsAllNothingHiting &= (OutHit.Actor == nullptr); //If all Hiting nothing, then you are falling + } + + if (IsBlockingHitAndSameActor || IsAllNothingHiting) + HitDetailsMultiLineTrace = OutHits[0]; + + return HitDetailsMultiLineTrace; +} \ No newline at end of file diff --git a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp index de17d478c5ac6bc9be9124d845fdc3f56b7aa960..57750819a5c2afac0f930263dd8e720201bed309 100644 --- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp +++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp @@ -27,8 +27,9 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events. - Movement = CreateDefaultSubobject<UFloatingPawnMovement>(TEXT("Movement")); - Movement->UpdatedComponent = RootComponent; + VRMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("WalkingMovement")); + VRMovement->SetUpdatedComponent(RootComponent); + VRMovement->SetCameraComponent(CameraComponent); RotatingMovement = CreateDefaultSubobject<URotatingMovementComponent>(TEXT("RotatingMovement")); RotatingMovement->UpdatedComponent = RootComponent; @@ -55,13 +56,6 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial HmdRightMotionController->SetShowDeviceModel(true); HmdRightMotionController->SetVisibility(false); - CapsuleColliderComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleCollider")); - CapsuleColliderComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); - CapsuleColliderComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); - CapsuleColliderComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block); - CapsuleColliderComponent->SetupAttachment(CameraComponent); - CapsuleColliderComponent->SetCapsuleSize(40.0f, 96.0f); - HmdTracker1 = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("HmdTracker1")); HmdTracker1->SetupAttachment(RootComponent); HmdTracker1->SetTrackingSource(EControllerHand::Special_1); @@ -79,7 +73,7 @@ void AVirtualRealityPawn::OnForward_Implementation(float Value) { if (RightHand) { - HandleMovementInput(Value, RightHand->GetForwardVector()); + AddMovementInput(RightHand->GetForwardVector(), Value); } } @@ -87,7 +81,7 @@ void AVirtualRealityPawn::OnRight_Implementation(float Value) { if (RightHand) { - HandleMovementInput(Value, RightHand->GetRightVector()); + AddMovementInput(RightHand->GetRightVector(), Value); } } @@ -118,11 +112,6 @@ void AVirtualRealityPawn::SetBaseTurnRate(float Value) BaseTurnRate = Value; } -UFloatingPawnMovement* AVirtualRealityPawn::GetFloatingPawnMovement() -{ - return Movement; -} - URotatingMovementComponent* AVirtualRealityPawn::GetRotatingMovementComponent() { return RotatingMovement; @@ -221,10 +210,10 @@ void AVirtualRealityPawn::BeginPlay() if (SettingsActors.Num() > 0) { ADisplayClusterSettings* Settings = Cast<ADisplayClusterSettings>(SettingsActors[0]); - Movement->MaxSpeed = Settings->MovementMaxSpeed; - Movement->Acceleration = Settings->MovementAcceleration; - Movement->Deceleration = Settings->MovementDeceleration; - Movement->TurningBoost = Settings->MovementTurningBoost; + VRMovement->MaxSpeed = Settings->MovementMaxSpeed; + VRMovement->Acceleration = Settings->MovementAcceleration; + VRMovement->Deceleration = Settings->MovementDeceleration; + VRMovement->TurningBoost = Settings->MovementTurningBoost; BaseTurnRate = Settings->RotationSpeed; } @@ -288,8 +277,6 @@ void AVirtualRealityPawn::BeginPlay() CollisionComponent->SetCollisionProfileName(FName("NoCollision")); CollisionComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); - - LastCameraPosition = CameraComponent->GetComponentLocation(); } void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -306,14 +293,6 @@ void AVirtualRealityPawn::EndPlay(const EEndPlayReason::Type EndPlayReason) void AVirtualRealityPawn::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); - //if the walking-mode is activated - if (NavigationMode == EVRNavigationModes::nav_mode_walk) - { - DeltaTime = DeltaSeconds; - SetCapsuleColliderCharacterSizeVR(); - MoveByGravityOrStepUp(DeltaSeconds); - CheckForPhysWalkingCollision(); - } // if an actor is grabbed and a behavior is defined move move him accordingly if (GrabbedActor != nullptr) @@ -333,8 +312,6 @@ void AVirtualRealityPawn::Tick(float DeltaSeconds) //Flystick might not be available at start, hence is checked every frame. InitRoomMountedComponentReferences(); - - LastCameraPosition = CameraComponent->GetComponentLocation(); } void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) @@ -440,111 +417,7 @@ FTwoVectors AVirtualRealityPawn::GetHandRay(float Length) UPawnMovementComponent* AVirtualRealityPawn::GetMovementComponent() const { - return Movement; -} - -void AVirtualRealityPawn::SetCapsuleColliderCharacterSizeVR() -{ - float CharachterSize = abs(RootComponent->GetComponentLocation().Z - CameraComponent->GetComponentLocation().Z); - - if (CharachterSize > MaxStepHeight) - { - float ColliderHeight = CharachterSize - MaxStepHeight; - float ColliderHalfHeight = ColliderHeight / 2.0f; - float ColliderRadius = 40.0f; - if (ColliderHalfHeight <= ColliderRadius) - {//Make the collider to a Sphere - CapsuleColliderComponent->SetCapsuleSize(ColliderHalfHeight, ColliderHalfHeight); - } - else - {//Make the collider to a Capsule - CapsuleColliderComponent->SetCapsuleSize(ColliderRadius, ColliderHalfHeight); - } - - CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation()); - CapsuleColliderComponent->AddWorldOffset(FVector(0, 0, -ColliderHalfHeight)); - CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1)); - } - else - { - CapsuleColliderComponent->SetWorldLocation(CameraComponent->GetComponentLocation()); - CapsuleColliderComponent->SetWorldRotation(FRotator(0, 0, 1)); - } -} - -void AVirtualRealityPawn::CheckForPhysWalkingCollision() -{ - FVector CurrentCameraPosition = CameraComponent->GetComponentLocation(); - FVector Direction = CurrentCameraPosition - LastCameraPosition; - FHitResult FHitResultPhys; - CapsuleColliderComponent->AddWorldOffset(Direction, true, &FHitResultPhys); - - if (FHitResultPhys.bBlockingHit) - { - RootComponent->AddLocalOffset(FHitResultPhys.Normal*FHitResultPhys.PenetrationDepth); - } -} - -void AVirtualRealityPawn::HandleMovementInput(float Value, FVector Direction) -{ - if (NavigationMode == EVRNavigationModes::nav_mode_walk) - { - VRWalkingMode(Value, Direction); - } - else if (NavigationMode == EVRNavigationModes::nav_mode_fly) - { - VRFlyingMode(Value, Direction); - } -} - -void AVirtualRealityPawn::VRWalkingMode(float Value, FVector Direction) -{ - Direction.Z = 0.0f;//walking - FVector End = (Direction * GetFloatingPawnMovement()->GetMaxSpeed()); - FHitResult FHitResultVR; - CapsuleColliderComponent->AddWorldOffset(End* DeltaTime*Value, true, &FHitResultVR); - - if (FVector::Distance(FHitResultVR.Location, CapsuleColliderComponent->GetComponentLocation()) > CapsuleColliderComponent->GetScaledCapsuleRadius()) - { - AddMovementInput(Direction, Value); - } -} - -void AVirtualRealityPawn::VRFlyingMode(float Value, FVector Direction) -{ - AddMovementInput(Direction, Value); -} - -void AVirtualRealityPawn::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 - if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance < MaxStepHeight)) - { - ShiftVertically(DiffernceDistance, UpSteppingAcceleration, DeltaSeconds, 1); - } - //Falling, Gravity, Going down - else if ((HitDetailsMultiLineTrace.bBlockingHit && HitDetailsMultiLineTrace.Distance > MaxStepHeight) || (HitDetailsMultiLineTrace.Actor == nullptr && HitDetailsMultiLineTrace.Distance != -1.0f)) - { - ShiftVertically(DiffernceDistance, GravityAcceleration, DeltaSeconds, -1); - } -} - -void AVirtualRealityPawn::ShiftVertically(float DiffernceDistance, float Acceleration, float DeltaSeconds, int Direction) -{ - VerticalSpeed += Acceleration * DeltaSeconds; - if (VerticalSpeed*DeltaSeconds < DiffernceDistance) - { - RootComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * VerticalSpeed * DeltaSeconds)); - } - else - { - RootComponent->AddLocalOffset(FVector(0.f, 0.f, Direction * DiffernceDistance)); - VerticalSpeed = 0; - } + return VRMovement; } void AVirtualRealityPawn::InitRoomMountedComponentReferences() @@ -582,56 +455,7 @@ void AVirtualRealityPawn::InitRoomMountedComponentReferences() } } - -FHitResult AVirtualRealityPawn::CreateLineTrace(FVector Direction, const FVector Start, bool Visibility) -{ - //Re-initialize hit info - FHitResult HitDetails = FHitResult(ForceInit); - - FVector End = ((Direction * 1000.f) + Start); - // additional trace parameters - FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, NULL); - TraceParams.bTraceComplex = true; //to use complex collision on whatever we interact with to provide better precision. - TraceParams.bReturnPhysicalMaterial = true; //to provide details about the physical material, if one exists on the thing we hit, to come back in our hit result. - - if (Visibility) - DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1, 0, 1); - - if (GetWorld()->LineTraceSingleByChannel(HitDetails, Start, End, ECC_Visibility, TraceParams)) - { - if (HitDetails.bBlockingHit) - { - } - } - return HitDetails; -} - -FHitResult AVirtualRealityPawn::CreateMultiLineTrace(FVector Direction, const FVector Start, float Radius, bool Visibility) +void AVirtualRealityPawn::SetNavigationMode(EVRNavigationModes Mode) { - TArray<FVector> StartVectors; - TArray<FHitResult> OutHits; - FHitResult HitDetailsMultiLineTrace; - HitDetailsMultiLineTrace.Distance = -1.0f;//(Distance=-1) not existing, but to know if this Variable not Initialized(when all Traces not compatible) - - StartVectors.Add(Start); //LineTraceCenter - StartVectors.Add(Start + FVector(0, -Radius, 0)); //LineTraceLeft - StartVectors.Add(Start + FVector(0, +Radius, 0)); //LineTraceRight - StartVectors.Add(Start + FVector(+Radius, 0, 0)); //LineTraceFront - StartVectors.Add(Start + FVector(-Radius, 0, 0)); //LineTraceBehind - - bool IsBlockingHitAndSameActor = true; - bool IsAllNothingHiting = true; - // loop through TArray - for (FVector& Vector : StartVectors) - { - FHitResult OutHit = CreateLineTrace(Direction, Vector, Visibility); - OutHits.Add(OutHit); - IsBlockingHitAndSameActor &= (OutHit.Actor == OutHits[0].Actor); //If all Hiting the same Object, then you are (going up/down) or (walking) - IsAllNothingHiting &= (OutHit.Actor == nullptr); //If all Hiting nothing, then you are falling - } - - if (IsBlockingHitAndSameActor || IsAllNothingHiting) - HitDetailsMultiLineTrace = OutHits[0]; - - return HitDetailsMultiLineTrace; + 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 0570e8aa290c2325b927bca9d036108b0df95741..b02f183320a14b199290438a8f3d4a21f50389ee 100644 --- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h +++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h @@ -6,20 +6,13 @@ #include "DisplayClusterPawn.h" #include "DisplayClusterSceneComponent.h" #include "Components/CapsuleComponent.h" -#include "GameFramework/FloatingPawnMovement.h" -#include "GameFramework/PawnMovementComponent.h" +#include "VRPawnMovement.h" #include "GameFramework/RotatingMovementComponent.h" #include "MotionControllerComponent.h" #include "VirtualRealityPawn.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") -}; + UENUM(BlueprintType) enum class EAttachementType : uint8 @@ -44,7 +37,6 @@ public: UFUNCTION(Category = "Pawn") float GetBaseTurnRate() const; UFUNCTION(Category = "Pawn") void SetBaseTurnRate(float Value); - UFUNCTION(Category = "Pawn") UFloatingPawnMovement* GetFloatingPawnMovement(); UFUNCTION(Category = "Pawn") URotatingMovementComponent* GetRotatingMovementComponent(); //Bunch of Getter Functions for components to avoid users having to know the names @@ -63,6 +55,8 @@ public: UFUNCTION(Category = "Pawn") USceneComponent* GetTrackingOriginComponent(); + UFUNCTION(Category = "Pawn") void SetNavigationMode(EVRNavigationModes Mode); + private: UFUNCTION(Category = "Pawn") USceneComponent* GetCaveCenterComponent(); UFUNCTION(Category = "Pawn") USceneComponent* GetShutterGlassesComponent(); @@ -70,9 +64,6 @@ private: UFUNCTION(Category = "Pawn") void HandlePhysicsAndAttachActor(AActor* HitActor); public: - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EVRNavigationModes NavigationMode = EVRNavigationModes::nav_mode_fly; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") float MaxStepHeight = 40.0f; //Execute specified console command on all nDisplayCluster Nodes UFUNCTION(Exec, BlueprintCallable, Category = "DisplayCluster") static void ClusterExecute(const FString& Command); private: @@ -87,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")) UFloatingPawnMovement* Movement = 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. @@ -131,22 +122,6 @@ protected: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EAttachementType AttachRightHandInCAVE = EAttachementType::AT_FLYSTICK; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn") EAttachementType AttachLeftHandInCAVE = EAttachementType::AT_NONE; - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn", meta = (AllowPrivateAccess = "true")) UCapsuleComponent* CapsuleColliderComponent = nullptr; private: - float DeltaTime = 0.0f; - float VerticalSpeed = 0.0f; - UPROPERTY() float GravityAcceleration = 981.0f; - UPROPERTY() float UpSteppingAcceleration = 500.0f; - FVector LastCameraPosition; - - 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 HandleMovementInput(float Value, FVector Direction); - void VRWalkingMode(float Value, FVector Direction); - void VRFlyingMode(float Value, FVector Direction); - void MoveByGravityOrStepUp(float DeltaSeconds); - void ShiftVertically(float DiffernceDistance, float Acceleration, float DeltaSeconds, int Direction);//(direction = Down = -1), (direction = Up = 1) void InitRoomMountedComponentReferences(); };