Skip to content

Feature: XR sample viewer #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions xr_sample_project/Config/DefaultEngine.ini
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@


[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/Samples/VRSample/VRSample_lvl.VRSample_lvl
EditorStartupMap=/Game/Samples/VRSample/VRSample_lvl.VRSample_lvl
GameDefaultMap=/Game/SampleViewer/SampleViewer_lvl.SampleViewer_lvl
EditorStartupMap=/Game/SampleViewer/SampleViewer_lvl.SampleViewer_lvl

[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
Expand Down
13 changes: 13 additions & 0 deletions xr_sample_project/Config/DefaultGame.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ MaxChunkSize=0
bBuildHttpChunkInstallData=False
HttpChunkInstallDataDirectory=(Path="")
WriteBackMetadataToAssetRegistry=Disabled
bWritePluginSizeSummaryJsons=False
bCompressed=True
PackageCompressionFormat=Oodle
bForceUseProjectCompressionFormatIgnoreHardwareOverride=False
Expand All @@ -52,10 +53,13 @@ InternationalizationPreset=English
LocalizationTargetCatchAllChunkId=0
bCookAll=False
bCookMapsOnly=False
bTreatWarningsAsErrorsOnCook=False
bSkipEditorContent=False
bSkipMovies=False
-IniKeyDenylist=KeyStorePassword
-IniKeyDenylist=KeyPassword
-IniKeyDenylist=DebugKeyStorePassword
-IniKeyDenylist=DebugKeyPassword
-IniKeyDenylist=rsa.privateexp
-IniKeyDenylist=rsa.modulus
-IniKeyDenylist=rsa.publicexp
Expand All @@ -71,6 +75,8 @@ bSkipMovies=False
-IniKeyDenylist=MobileProvision
-IniKeyDenylist=IniKeyDenylist
-IniKeyDenylist=IniSectionDenylist
+IniKeyDenylist=DebugKeyStorePassword
+IniKeyDenylist=DebugKeyPassword
+IniKeyDenylist=KeyStorePassword
+IniKeyDenylist=KeyPassword
+IniKeyDenylist=rsa.privateexp
Expand All @@ -90,7 +96,14 @@ bSkipMovies=False
+IniKeyDenylist=IniSectionDenylist
-IniSectionDenylist=HordeStorageServers
-IniSectionDenylist=StorageServers
-IniSectionDenylist=/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings
+IniSectionDenylist=/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings
+IniSectionDenylist=HordeStorageServers
+IniSectionDenylist=StorageServers
+MapsToCook=(FilePath="/Game/Samples/VRSample/VRSample_lvl")
+MapsToCook=(FilePath="/Game/Samples/XRTableTop/XRTableTop")
+MapsToCook=(FilePath="/Game/SampleViewer/SampleViewer_lvl")
+DirectoriesToAlwaysCook=(Path="/NNEDenoiser")
bRetainStagedDirectory=False
CustomStageCopyHandler=

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified xr_sample_project/Content/Samples/XRTableTop/XRTableTop.umap
Binary file not shown.
313 changes: 313 additions & 0 deletions xr_sample_project/Source/xr_samplesproject/GenericXR/XRPawn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
// Fill out your copyright notice in the Description page of Project Settings.


#include "XRPawn.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/WidgetInteractionComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
#include "Kismet/KismetMathLibrary.h"
#include "MotionControllerComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "xr_samplesproject/VRSample/VRHandAnimInstance.h"

// Sets default values
AXRPawn::AXRPawn()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
vrOrigin = CreateDefaultSubobject<USceneComponent>(TEXT("VROrigin"));
vrOrigin->SetupAttachment(RootComponent);
vrCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
vrCamera->SetupAttachment(vrOrigin);
vrCamera->SetRelativeLocation(FVector(0.0f, 0.0f, -90.0f));

leftMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("LeftMotionController"));
leftMotionController->SetupAttachment(vrOrigin);
leftMotionController->SetTrackingSource(EControllerHand::Left);
leftHandMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Left Hand Mesh"));
leftHandMesh->SetupAttachment(leftMotionController);

rightMotionController = CreateDefaultSubobject<UMotionControllerComponent>(TEXT("RightMotionController"));
rightMotionController->SetupAttachment(vrOrigin);
rightMotionController->SetTrackingSource(EControllerHand::Right);
rightHandMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Right Hand Mesh"));
rightHandMesh->SetupAttachment(rightMotionController);

leftMotionControllerInteractor = CreateDefaultSubobject<UMotionControllerComponent>(
TEXT("LeftMotionControllerInteractor"));
leftMotionControllerInteractor->SetupAttachment(vrOrigin);
leftMotionControllerInteractor->SetTrackingSource(EControllerHand::Left);
leftInteraction = CreateDefaultSubobject<UWidgetInteractionComponent>(TEXT("Left Interactor"));
leftInteraction->SetupAttachment(leftMotionControllerInteractor);

rightMotionControllerInteractor = CreateDefaultSubobject<UMotionControllerComponent>(
TEXT("RightMotionControllerInteractor"));
rightMotionControllerInteractor->SetupAttachment(vrOrigin);
rightMotionControllerInteractor->SetTrackingSource(EControllerHand::Right);
rightInteraction = CreateDefaultSubobject<UWidgetInteractionComponent>(TEXT("Right Interactor"));
rightInteraction->SetupAttachment(rightMotionControllerInteractor);
}

void AXRPawn::BeginPlay()
{
Super::BeginPlay();

leftHandMesh->SetSkeletalMesh(handMesh);
leftHandMesh->SetAnimationMode(EAnimationMode::AnimationBlueprint);
leftAnimInstanceBase = leftHandMesh->GetAnimInstance();
leftAnimInstance = Cast<UVRHandAnimInstance>(leftAnimInstanceBase);
rightHandMesh->SetSkeletalMesh(handMesh);
rightHandMesh->SetAnimationMode(EAnimationMode::AnimationBlueprint);
rightAnimInstanceBase = rightHandMesh->GetAnimInstance();
rightAnimInstance = Cast<UVRHandAnimInstance>(rightAnimInstanceBase);

GEngine->XRSystem->SetTrackingOrigin(TrackingOrigin);
GetCharacterMovement()->SetMovementMode(MOVE_Walking, 0);
InitializeCapsuleHeight();

if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem
<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(mappingContext, 0);
Subsystem->AddMappingContext(menuMappingContext, 0);
}
}

FTimerHandle UpdateHeight;
GetWorldTimerManager().SetTimer(UpdateHeight, this, &AXRPawn::SetCapsuleHeight, 0.35f, true);
FTimerHandle UpdateCapsuleLocation;
GetWorldTimerManager().SetTimer(UpdateCapsuleLocation, this, &AXRPawn::UpdateRoomScaleMovement, 0.3f, true);

}

void AXRPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);

if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
EnhancedInputComponent->BindAction(move_X, ETriggerEvent::Triggered, this, &AXRPawn::MoveRight);
EnhancedInputComponent->BindAction(move_Y, ETriggerEvent::Triggered, this, &AXRPawn::MoveForward);
//Update Hand Animations
EnhancedInputComponent->BindAction(grip_L, ETriggerEvent::Triggered, this, &AXRPawn::SetLeftGripAxis);
EnhancedInputComponent->BindAction(grip_R, ETriggerEvent::Triggered, this, &AXRPawn::SetRightGripAxis);
EnhancedInputComponent->BindAction(trigger_L, ETriggerEvent::Triggered, this, &AXRPawn::SetLeftTriggerAxis);
EnhancedInputComponent->BindAction(trigger_R, ETriggerEvent::Triggered, this, &AXRPawn::SetRightTriggerAxis);
//Reset Hand Animations on Cancelled Action
EnhancedInputComponent->BindAction(grip_L, ETriggerEvent::Canceled, this, &AXRPawn::ResetLeftGripAxis);
EnhancedInputComponent->BindAction(grip_R, ETriggerEvent::Canceled, this, &AXRPawn::ResetRightGripAxis);
EnhancedInputComponent->BindAction(trigger_L, ETriggerEvent::Canceled, this, &AXRPawn::ResetLeftTriggerAxis);
EnhancedInputComponent->BindAction(trigger_R, ETriggerEvent::Canceled, this, &AXRPawn::ResetRightTriggerAxis);
//Reset Hand Animations on Completed Action
EnhancedInputComponent->BindAction(grip_L, ETriggerEvent::Completed, this, &AXRPawn::ResetLeftGripAxis);
EnhancedInputComponent->BindAction(grip_R, ETriggerEvent::Completed, this, &AXRPawn::ResetRightGripAxis);
EnhancedInputComponent->BindAction(trigger_L, ETriggerEvent::Completed, this, &AXRPawn::ResetLeftTriggerAxis);
EnhancedInputComponent->BindAction(trigger_R, ETriggerEvent::Completed, this, &AXRPawn::ResetRightTriggerAxis);

//Simulate Mouse Click
EnhancedInputComponent->BindAction(clickLeft, ETriggerEvent::Started, this, &AXRPawn::SimulateClickLeft);
EnhancedInputComponent->BindAction(clickLeft, ETriggerEvent::Canceled, this, &AXRPawn::ResetClickLeft);
EnhancedInputComponent->BindAction(clickLeft, ETriggerEvent::Completed, this, &AXRPawn::ResetClickLeft);
EnhancedInputComponent->BindAction(clickRight, ETriggerEvent::Started, this, &AXRPawn::SimulateClickRight);
EnhancedInputComponent->BindAction(clickRight, ETriggerEvent::Canceled, this, &AXRPawn::ResetClickRight);
EnhancedInputComponent->BindAction(clickRight, ETriggerEvent::Completed, this, &AXRPawn::ResetClickRight);

EnhancedInputComponent->BindAction(turn, ETriggerEvent::Triggered, this, &AXRPawn::SmoothTurn);
EnhancedInputComponent->BindAction(turn, ETriggerEvent::Completed, this, &AXRPawn::ResetDoOnce);
}
}

void AXRPawn::MoveForward(const FInputActionValue& value)
{
const auto inputValue = value.Get<float>();

if (abs(inputValue) > MovementDeadzone)
{
if (bMoveInLookDirection)
{
FVector Direction = vrCamera->GetForwardVector();
AddMovementInput(Direction, inputValue * MoveSpeed);
}
else
{
FVector direction = rightMotionController->GetForwardVector();
AddMovementInput(direction, inputValue * MoveSpeed);
}
}
}

void AXRPawn::MoveRight(const FInputActionValue& value)
{
const auto inputValue = value.Get<float>();

if (abs(inputValue) > MovementDeadzone)
{
if (bMoveInLookDirection)
{
FVector Direction = vrCamera->GetRightVector();
AddMovementInput(Direction, inputValue * MoveSpeed);
}
else
{
FVector direction = rightMotionController->GetRightVector();
AddMovementInput(direction, inputValue * MoveSpeed);
}
}
}

void AXRPawn::SmoothTurn(const FInputActionValue& value)
{
auto inputValue = value.Get<float>() * RotationSpeed;

if (bUseSmoothTurn)
{
if (abs(inputValue) > RotationDeadzone)
{
SetActorRotation(FRotator(0.0f, GetActorRotation().Yaw + inputValue, 0.0f));
}
}
else
{
if (bDoOnce && abs(inputValue) > RotationDeadzone)
{
auto RotationAngle = 0.0f;
if (inputValue > 0.0f)
{
RotationAngle = SnapRotationDegrees;
SetActorRotation(FRotator(0.0f, GetActorRotation().Yaw + RotationAngle, 0.0f));
}
else
{
RotationAngle = SnapRotationDegrees * -1.0f;
SetActorRotation(FRotator(0.0f, GetActorRotation().Yaw + RotationAngle, 0.0f));
}
bDoOnce = false;
}
}
}

void AXRPawn::ResetDoOnce()
{
if (!bDoOnce)
{
bDoOnce = true;
}
}

void AXRPawn::InitializeCapsuleHeight()
{
capsuleHalfHeight = GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}

void AXRPawn::SetCapsuleHeight()
{
FVector DevicePosition;
FQuat DeviceRotation;
GEngine->XRSystem->GetCurrentPose(IXRTrackingSystem::HMDDeviceId, DeviceRotation, DevicePosition);
GetCapsuleComponent()->SetCapsuleSize(GetCapsuleComponent()->GetScaledCapsuleRadius(), capsuleHalfHeight, true);
const auto halfHeight = DevicePosition.Z / 2.0f + 10.0f;
vrOrigin->AddRelativeLocation(FVector(0.0f, 0.0f, capsuleHalfHeight - halfHeight));
capsuleHalfHeight = halfHeight;
}

void AXRPawn::SetLeftGripAxis(const FInputActionValue& value)
{
if (leftAnimInstance)
{
leftAnimInstance->GripAxis = value.Get<float>();
}
}

void AXRPawn::SetRightGripAxis(const FInputActionValue& value)
{
if (rightAnimInstance)
{
rightAnimInstance->GripAxis = value.Get<float>();
}
}

void AXRPawn::SetLeftTriggerAxis(const FInputActionValue& value)
{
if (leftAnimInstance)
{
leftAnimInstance->TriggerAxis = value.Get<float>();
}
}

void AXRPawn::SetRightTriggerAxis(const FInputActionValue& value)
{
if (rightAnimInstance)
{
rightAnimInstance->TriggerAxis = value.Get<float>();
}
}

void AXRPawn::ResetLeftGripAxis()
{
if (leftAnimInstance)
{
leftAnimInstance->GripAxis = 0.0f;
}
}

void AXRPawn::ResetRightGripAxis()
{
if (rightAnimInstance)
{
rightAnimInstance->GripAxis = 0.0f;
}
}

void AXRPawn::ResetLeftTriggerAxis()
{
if (leftAnimInstance)
{
leftAnimInstance->TriggerAxis = 0.0f;
}
}

void AXRPawn::ResetRightTriggerAxis()
{
if (rightAnimInstance)
{
rightAnimInstance->TriggerAxis = 0.0f;
}
}

void AXRPawn::SimulateClickLeft()
{
if (leftInteraction->IsOverFocusableWidget())
{
leftInteraction->PressPointerKey(EKeys::LeftMouseButton);
}
}

void AXRPawn::SimulateClickRight()
{
if (rightInteraction->IsOverFocusableWidget())
{
rightInteraction->PressPointerKey(EKeys::LeftMouseButton);
}
}

void AXRPawn::ResetClickLeft()
{
leftInteraction->ReleasePointerKey(EKeys::LeftMouseButton);
}

void AXRPawn::ResetClickRight()
{
rightInteraction->ReleasePointerKey(EKeys::LeftMouseButton);
}

void AXRPawn::UpdateRoomScaleMovement()
{
FVector Offset = vrCamera->GetComponentLocation() - GetActorLocation();
AddActorWorldOffset(FVector(Offset.X, Offset.Y, 0.0f));
vrOrigin->AddWorldOffset(UKismetMathLibrary::NegateVector(FVector(Offset.X, Offset.Y, 0.0f)));
}
Loading