From 10a6ed64721a041eb0492f806fc2ced879ee7862 Mon Sep 17 00:00:00 2001 From: Sebastian Pape <pape@vr.rwth-aachen.de> Date: Mon, 1 Feb 2021 13:01:50 +0100 Subject: [PATCH] After first tests seems to now work on Desktop --- .../Private/VRPawnMovement.cpp | 382 +++++++++--------- .../Private/VirtualRealityPawn.cpp | 230 +++++------ .../Public/VRPawnMovement.h | 138 +++---- .../Public/VirtualRealityPawn.h | 103 ++--- 4 files changed, 425 insertions(+), 428 deletions(-) diff --git a/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp index 34464add..b6c5b9d1 100644 --- a/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp +++ b/Source/DisplayClusterExtensions/Private/VRPawnMovement.cpp @@ -1,188 +1,194 @@ - -#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); - - CameraComponent = GetOwner()->FindComponentByClass<UCameraComponent>(); - CapsuleColliderComponent->SetupAttachment(CameraComponent); -} - -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::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; -} + +#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 2c6a729d..4d77d493 100644 --- a/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp +++ b/Source/DisplayClusterExtensions/Private/VirtualRealityPawn.cpp @@ -1,121 +1,109 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "VirtualRealityPawn.h" - - - -#include "GameFramework/InputSettings.h" -#include "GameFramework/PlayerInput.h" -#include "UniversalTrackedComponent.h" -#include "VirtualRealityUtilities.h" -#include "VRPawnMovement.h" - -AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ - bUseControllerRotationYaw = true; - bUseControllerRotationPitch = true; - bUseControllerRotationRoll = true; - BaseEyeHeight = 160.0f; - - AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events. - - PawnMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("Pawn Movement")); - PawnMovement->SetUpdatedComponent(RootComponent); - - Head = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Head")); - Head->ProxyType = ETrackedComponentType::TCT_HEAD; - Head->SetupAttachment(RootComponent); - - RightHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Right Hand")); - RightHand->ProxyType = ETrackedComponentType::TCT_RIGHT_HAND; - RightHand->AttachementType = EAttachementType::AT_FLYSTICK; - RightHand->SetupAttachment(RootComponent); - - LeftHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Left Hand")); - LeftHand->ProxyType = ETrackedComponentType::TCT_LEFT_HAND; - LeftHand->AttachementType = EAttachementType::AT_HANDTARGET; - LeftHand->SetupAttachment(RootComponent); - - Tracker1 = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Vive Tracker 1")); - Tracker1->ProxyType = ETrackedComponentType::TCT_TRACKER_1; - Tracker1->SetupAttachment(RootComponent); - - Tracker2 = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Vive Tracker 2")); - Tracker2->ProxyType = ETrackedComponentType::TCT_TRACKER_2; - Tracker2->SetupAttachment(RootComponent); - - BasicVRInteraction = CreateDefaultSubobject<UBasicVRInteractionComponent>(TEXT("Basic VR Interaction")); - BasicVRInteraction->Initialize(RightHand); -} - -void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) -{ - Super::SetupPlayerInputComponent(PlayerInputComponent); - if (PlayerInputComponent) - { - PlayerInputComponent->BindAxis("MoveForward", this, &AVirtualRealityPawn::OnForward); - PlayerInputComponent->BindAxis("MoveRight", this, &AVirtualRealityPawn::OnRight); - PlayerInputComponent->BindAxis("TurnRate", this, &AVirtualRealityPawn::OnTurnRate); - PlayerInputComponent->BindAxis("LookUpRate", this, &AVirtualRealityPawn::OnLookUpRate); - - // function bindings for grabbing and releasing - PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AVirtualRealityPawn::OnBeginFire); - PlayerInputComponent->BindAction("Fire", IE_Released, this, &AVirtualRealityPawn::OnEndFire); - } -} - -void AVirtualRealityPawn::BeginPlay() -{ - if(!UVirtualRealityUtilities::IsDesktopMode()) /* Disable to not get cyber sick as fast */ - { - UInputSettings::GetInputSettings()->RemoveAxisMapping(FInputAxisKeyMapping("TurnRate", EKeys::MouseX)); - UInputSettings::GetInputSettings()->RemoveAxisMapping(FInputAxisKeyMapping("LookUpRate", EKeys::MouseY)); - } -} - -void AVirtualRealityPawn::OnForward_Implementation(float Value) -{ - if (RightHand) - { - AddMovementInput(RightHand->GetForwardVector(), Value); - } -} - -void AVirtualRealityPawn::OnRight_Implementation(float Value) -{ - if (RightHand) - { - AddMovementInput(RightHand->GetRightVector(), Value); - } -} - -void AVirtualRealityPawn::OnTurnRate_Implementation(float Rate) -{ - AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); -} - -void AVirtualRealityPawn::OnLookUpRate_Implementation(float Rate) -{ - // User-centered projection causes simulation sickness on look up interaction hence not implemented. - if (!UVirtualRealityUtilities::IsRoomMountedMode()) - { - AddControllerPitchInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); - } -} - -void AVirtualRealityPawn::OnBeginFire_Implementation() -{ - BasicVRInteraction->BeginInteraction(); -} - -void AVirtualRealityPawn::OnEndFire_Implementation() -{ - BasicVRInteraction->EndInteraction(); -} - -UPawnMovementComponent* AVirtualRealityPawn::GetMovementComponent() const -{ - return PawnMovement; -} +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "VirtualRealityPawn.h" + + + +#include "GameFramework/InputSettings.h" +#include "GameFramework/PlayerInput.h" +#include "UniversalTrackedComponent.h" +#include "VirtualRealityUtilities.h" +#include "VRPawnMovement.h" + +AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bUseControllerRotationYaw = true; + bUseControllerRotationPitch = true; + bUseControllerRotationRoll = true; + BaseEyeHeight = 160.0f; + + AutoPossessPlayer = EAutoReceiveInput::Player0; // Necessary for receiving motion controller events. + + SetRootComponent(CreateDefaultSubobject<USceneComponent>(TEXT("Root"))); + + CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera")); + CameraComponent->SetupAttachment(RootComponent); + CameraComponent->SetAbsolute(); + + PawnMovement = CreateDefaultSubobject<UVRPawnMovement>(TEXT("Pawn Movement")); + PawnMovement->SetUpdatedComponent(RootComponent); + PawnMovement->SetCameraComponent(CameraComponent); + + Head = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Head")); + Head->ProxyType = ETrackedComponentType::TCT_HEAD; + Head->SetupAttachment(RootComponent); + + RightHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Right Hand")); + RightHand->ProxyType = ETrackedComponentType::TCT_RIGHT_HAND; + RightHand->AttachementType = EAttachementType::AT_FLYSTICK; + RightHand->SetupAttachment(RootComponent); + + LeftHand = CreateDefaultSubobject<UUniversalTrackedComponent>(TEXT("Left Hand")); + LeftHand->ProxyType = ETrackedComponentType::TCT_LEFT_HAND; + LeftHand->AttachementType = EAttachementType::AT_HANDTARGET; + LeftHand->SetupAttachment(RootComponent); + + BasicVRInteraction = CreateDefaultSubobject<UBasicVRInteractionComponent>(TEXT("Basic VR Interaction")); + BasicVRInteraction->Initialize(RightHand); +} + +void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); + if (!PlayerInputComponent) return; + + PlayerInputComponent->BindAxis("MoveForward", this, &AVirtualRealityPawn::OnForward); + PlayerInputComponent->BindAxis("MoveRight", this, &AVirtualRealityPawn::OnRight); + PlayerInputComponent->BindAxis("TurnRate", this, &AVirtualRealityPawn::OnTurnRate); + PlayerInputComponent->BindAxis("LookUpRate", this, &AVirtualRealityPawn::OnLookUpRate); + + // function bindings for grabbing and releasing + PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AVirtualRealityPawn::OnBeginFire); + PlayerInputComponent->BindAction("Fire", IE_Released, this, &AVirtualRealityPawn::OnEndFire); +} + +void AVirtualRealityPawn::OnForward_Implementation(float Value) +{ + if (RightHand) + { + AddMovementInput(RightHand->GetForwardVector(), Value); + } +} + +void AVirtualRealityPawn::OnRight_Implementation(float Value) +{ + if (RightHand) + { + AddMovementInput(RightHand->GetRightVector(), Value); + } +} + +void AVirtualRealityPawn::OnTurnRate_Implementation(float Rate) +{ + /* Turning the user externally will make them sick */ + if (UVirtualRealityUtilities::IsDesktopMode()) + { + AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); + } +} + +void AVirtualRealityPawn::OnLookUpRate_Implementation(float Rate) +{ + /* Turning the user externally will make them sick */ + if (UVirtualRealityUtilities::IsDesktopMode()) + { + AddControllerPitchInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds() * CustomTimeDilation); + } +} + +void AVirtualRealityPawn::OnBeginFire_Implementation() +{ + BasicVRInteraction->BeginInteraction(); +} + +void AVirtualRealityPawn::OnEndFire_Implementation() +{ + BasicVRInteraction->EndInteraction(); +} diff --git a/Source/DisplayClusterExtensions/Public/VRPawnMovement.h b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h index 094b02d3..e0ce022b 100644 --- a/Source/DisplayClusterExtensions/Public/VRPawnMovement.h +++ b/Source/DisplayClusterExtensions/Public/VRPawnMovement.h @@ -1,68 +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; - - 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; -}; +#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 5fc1b5f7..d23192d5 100644 --- a/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h +++ b/Source/DisplayClusterExtensions/Public/VirtualRealityPawn.h @@ -1,51 +1,52 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "BasicVRInteractionComponent.h" -#include "CoreMinimal.h" -#include "GameFramework/DefaultPawn.h" -#include "GameFramework/RotatingMovementComponent.h" -#include "UniversalTrackedComponent.h" -#include "VRPawnMovement.h" -#include "VirtualRealityPawn.generated.h" - -/** - * - */ -UCLASS() -class DISPLAYCLUSTEREXTENSIONS_API AVirtualRealityPawn : public APawn -{ - GENERATED_BODY() -public: - AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer); - - /* Proxy Components */ - UPROPERTY() UUniversalTrackedComponent* Head; - UPROPERTY() UUniversalTrackedComponent* RightHand; - UPROPERTY() UUniversalTrackedComponent* LeftHand; - UPROPERTY() UUniversalTrackedComponent* Tracker1; - UPROPERTY() UUniversalTrackedComponent* Tracker2; - UPROPERTY() UBasicVRInteractionComponent* BasicVRInteraction; - - /* Movement */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement") UVRPawnMovement* PawnMovement; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement") float BaseTurnRate = 45.0f; - -protected: - virtual void BeginPlay() override; - virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; - - /* Movement */ - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnForward(float Value); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnRight(float Value); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnTurnRate(float Rate); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnLookUpRate(float Rate); - - /* Interaction */ - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnBeginFire(); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnEndFire(); - - /* APawn Interface to be able to use AddMovementInput() */ - virtual UPawnMovementComponent* GetMovementComponent() const override; -}; +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "BasicVRInteractionComponent.h" +#include "CoreMinimal.h" +#include "GameFramework/DefaultPawn.h" +#include "GameFramework/RotatingMovementComponent.h" +#include "UniversalTrackedComponent.h" +#include "VRPawnMovement.h" +#include "VirtualRealityPawn.generated.h" + +/** + * + */ +UCLASS() +class DISPLAYCLUSTEREXTENSIONS_API AVirtualRealityPawn : public APawn +{ + GENERATED_BODY() +public: + AVirtualRealityPawn(const FObjectInitializer& ObjectInitializer); + + /* Proxy */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* Head; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* RightHand; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* LeftHand; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* Tracker1; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Proxy Objects") UUniversalTrackedComponent* Tracker2; + + /* Interaction */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Interaction") UBasicVRInteractionComponent* BasicVRInteraction; + + /* Movement */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement") UVRPawnMovement* PawnMovement; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Movement") float BaseTurnRate = 45.0f; + + /* CameraComponent */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pawn|Camera") UCameraComponent* CameraComponent; + +protected: + virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; + + /* Movement */ + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnForward(float Value); + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnRight(float Value); + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnTurnRate(float Rate); + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Movement") void OnLookUpRate(float Rate); + + /* Interaction */ + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnBeginFire(); + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Pawn|Interaction") void OnEndFire(); +}; -- GitLab