diff --git a/Content/VirtualRealityCPP/Blueprints/MotionControllerHand.uasset b/Content/VirtualRealityCPP/Blueprints/MotionControllerHand.uasset index 1346c25..950385b 100644 Binary files a/Content/VirtualRealityCPP/Blueprints/MotionControllerHand.uasset and b/Content/VirtualRealityCPP/Blueprints/MotionControllerHand.uasset differ diff --git a/Source/VRCode/VRCode.Build.cs b/Source/VRCode/VRCode.Build.cs index b084bef..7ea7f44 100644 --- a/Source/VRCode/VRCode.Build.cs +++ b/Source/VRCode/VRCode.Build.cs @@ -10,7 +10,15 @@ public class VRCode : ModuleRules { public VRCode(ReadOnlyTargetRules ROTargetRules) : base(ROTargetRules) { - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" }); + PublicDependencyModuleNames.AddRange(new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "HeadMountedDisplay", + "SteamVR" + }); PrivateDependencyModuleNames.AddRange(new string[] { }); diff --git a/Source/VRCode/VRHand.cpp b/Source/VRCode/VRHand.cpp index 024a991..110538e 100644 --- a/Source/VRCode/VRHand.cpp +++ b/Source/VRCode/VRHand.cpp @@ -19,6 +19,7 @@ #include "Runtime/Engine/Classes/Kismet/KismetMathLibrary.h" #include "Runtime/Engine/Classes/Kismet/HeadMountedDisplayFunctionLibrary.h" #include "Runtime/Engine/Classes/Components/SplineMeshComponent.h" +#include "SteamVRChaperoneComponent.h" // Sets default values AVRHand::AVRHand() : @@ -64,7 +65,12 @@ AVRHand::AVRHand() : TeleportArrow = CreateDefaultSubobject( TEXT( "TeleportArrow" ) ); TeleportArrow->SetupAttachment( TeleportCylinder ); - + + RoomScaleMesh = CreateDefaultSubobject(TEXT("RoomScaleMesh")); + RoomScaleMesh->SetupAttachment( TeleportArrow ); + + SteamVRChaperone = CreateDefaultSubobject(TEXT("SteamVRChaperone")); + } void AVRHand::OnConstruction(const FTransform & Transform) @@ -105,6 +111,8 @@ void AVRHand::BeginPlay() { Super::BeginPlay(); + SetupRoomScaleOutline(); + MotionController->Hand = Hand; if ( Hand == EControllerHand::Left ) { @@ -229,7 +237,7 @@ void AVRHand::Tick( float DeltaTime ) FVector HitLocation; bool IsValidTeleportDestination = TraceTeleportDestination( TracePoints, NavLocation, HitLocation ); - TeleportCylinder->SetVisibility( IsValidTeleportDestination, true ); + UpdateRoomScaleOutline(); if ( IsValidTeleportDestination ) { @@ -331,7 +339,11 @@ void AVRHand::ActivateTeleporter() // if ( GEngine ) GEngine->AddOnScreenDebugMessage( -1, 0.16f, FColor::White, FString::Printf( TEXT( "Activating Teleporter " ) ) ); IsTeleporterActive = true; - if ( MotionController ) + TeleportCylinder->SetVisibility(true, true); + + TeleportCylinder->SetVisibility(IsRoomScale, false); + + if (MotionController) InitialControllerRotation = MotionController->GetComponentRotation(); } @@ -413,4 +425,49 @@ FRotator AVRHand::GetControllerRelativeRotation() const FTransform RelativeTransform = CurrentTransform.GetRelativeTransform( InitialTransform ); return RelativeTransform.GetRotation().Rotator(); -} \ No newline at end of file +} + +void AVRHand::SetupRoomScaleOutline() +{ + auto Vertices = SteamVRChaperone->GetBounds(); + auto Normal = FVector(0.0f, 0.0f, 1.0f); + + FVector RectCenter; + FRotator RectRotation; + float SideLengthX, SideLengthY; + + UKismetMathLibrary::MinimumAreaRectangle(GetWorld(), Vertices, Normal, RectCenter, RectRotation, SideLengthX, SideLengthY); + + if (FMath::IsNearlyEqual(SideLengthX, 100.0f, 0.01f) || FMath::IsNearlyEqual(SideLengthY, 100.0f, 0.01f)) + { + IsRoomScale = false; + return; // Measure Chaperone (Defaults to 100x100 if roomscale isn't used) + } + + IsRoomScale = true; + + // Setup Room-scale mesh (1x1x1 units in size by default) to the size of the room-scale dimensions + RoomScaleMesh->SetWorldScale3D(FVector(SideLengthX, SideLengthY, ChaperoneMeshHeight)); + RoomScaleMesh->SetRelativeRotation(RectRotation); +} + +void AVRHand::UpdateRoomScaleOutline() +{ + if (RoomScaleMesh->IsVisible()) + { + FRotator DeviceRotation; + FVector DevicePosition; + UHeadMountedDisplayFunctionLibrary::GetOrientationAndPosition(DeviceRotation, DevicePosition); + + DeviceRotation.Pitch = 0; + DeviceRotation.Roll = 0; + + DevicePosition.X = -DevicePosition.X; + DevicePosition.Y = -DevicePosition.Y; + DevicePosition.Z = 0; + + FVector NewLocation = DeviceRotation.UnrotateVector(DevicePosition); + + RoomScaleMesh->SetRelativeLocation(NewLocation, false, nullptr, ETeleportType::None); + } +} diff --git a/Source/VRCode/VRHand.h b/Source/VRCode/VRHand.h index cd055c8..baa073f 100644 --- a/Source/VRCode/VRHand.h +++ b/Source/VRCode/VRHand.h @@ -10,6 +10,8 @@ #include "VRHand.generated.h" +class USteamVRChaperoneComponent; + UENUM(BlueprintType) enum class EGripState : uint8 { @@ -54,6 +56,12 @@ class VRCODE_API AVRHand : public AActor class UStaticMeshComponent *TeleportArrow; + UPROPERTY( VisibleAnywhere, BlueprintReadOnly, Category = "Code Components", meta = ( AllowPrivateAccess = "true" ) ) + class UStaticMeshComponent *RoomScaleMesh; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Code Components", meta = (AllowPrivateAccess = "true")) + class USteamVRChaperoneComponent *SteamVRChaperone; + FRotator InitialControllerRotation; TArray SplineMeshes; public: @@ -83,6 +91,12 @@ class VRCODE_API AVRHand : public AActor UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Code Variables" ) bool IsTeleporterActive; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Code Variables") + bool IsRoomScale = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Code Variables") + float ChaperoneMeshHeight = 70; + UPROPERTY( EditAnywhere, BlueprintReadWrite, Category = "Code Variables" ) EGripState Grip; @@ -127,4 +141,6 @@ class VRCODE_API AVRHand : public AActor FRotator GetControllerRelativeRotation(); + void SetupRoomScaleOutline(); + void UpdateRoomScaleOutline(); };