209 lines
6.4 KiB
C++
209 lines
6.4 KiB
C++
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||
|
|
||
|
#include "OculusXRAnchorComponent.h"
|
||
|
#include "OculusXRAnchors.h"
|
||
|
#include "OculusXRHMD.h"
|
||
|
#include "OculusXRAnchorBPFunctionLibrary.h"
|
||
|
#include "OculusXRAnchorsPrivate.h"
|
||
|
#include "GameFramework/PlayerController.h"
|
||
|
|
||
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||
|
static TAutoConsoleVariable<int32> CVarOculusXRVerboseAnchorDebugXR(
|
||
|
TEXT("ovr.OculusXRVerboseAnchorDebug"),
|
||
|
0,
|
||
|
TEXT("Enables or disables verbose logging for Oculus anchors.\n")
|
||
|
TEXT("<=0: disabled (no printing)\n")
|
||
|
TEXT(" 1: enabled (verbose logging)\n"));
|
||
|
#endif
|
||
|
|
||
|
UOculusXRAnchorComponent::UOculusXRAnchorComponent(const FObjectInitializer& ObjectInitializer)
|
||
|
: Super(ObjectInitializer)
|
||
|
, bUpdateHeadSpaceTransform(true)
|
||
|
, AnchorHandle(0)
|
||
|
, StorageLocations(0)
|
||
|
{
|
||
|
AnchorHandle = 0;
|
||
|
PrimaryComponentTick.bCanEverTick = true;
|
||
|
PrimaryComponentTick.bStartWithTickEnabled = true;
|
||
|
PrimaryComponentTick.TickGroup = TG_PostUpdateWork;
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::BeginPlay()
|
||
|
{
|
||
|
Super::BeginPlay();
|
||
|
|
||
|
UWorld* World = GetWorld();
|
||
|
if (IsValid(World))
|
||
|
{
|
||
|
APlayerController* PlayerController = World->GetFirstPlayerController();
|
||
|
if (IsValid(PlayerController))
|
||
|
{
|
||
|
PlayerCameraManager = PlayerController->PlayerCameraManager;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||
|
{
|
||
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||
|
UpdateAnchorTransform();
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||
|
{
|
||
|
Super::EndPlay(EndPlayReason);
|
||
|
|
||
|
if (HasValidHandle())
|
||
|
{
|
||
|
EOculusXRAnchorResult::Type AnchorResult;
|
||
|
OculusXRAnchors::FOculusXRAnchors::DestroyAnchor(AnchorHandle.GetValue(), AnchorResult);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FOculusXRUInt64 UOculusXRAnchorComponent::GetHandle() const
|
||
|
{
|
||
|
return AnchorHandle;
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::SetHandle(FOculusXRUInt64 Handle)
|
||
|
{
|
||
|
AnchorHandle = Handle;
|
||
|
}
|
||
|
|
||
|
bool UOculusXRAnchorComponent::HasValidHandle() const
|
||
|
{
|
||
|
return AnchorHandle != FOculusXRUInt64(0);
|
||
|
}
|
||
|
|
||
|
FOculusXRUUID UOculusXRAnchorComponent::GetUUID() const
|
||
|
{
|
||
|
return AnchorUUID;
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::SetUUID(FOculusXRUUID NewUUID)
|
||
|
{
|
||
|
if (AnchorUUID.IsValidUUID())
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Anchor component already has valid UUID, cannot re-assign a new UUID. Component: %s -- Space: %llu -- UUID: %s"),
|
||
|
*GetName(), AnchorHandle, *AnchorUUID.ToString());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!NewUUID.IsValidUUID())
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Warning, TEXT("New UUID provided to component is invalid, cannot assign. Component: %s -- Space: %llu"), *GetName(), AnchorHandle);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Assigned new Oculus UUID: %s"), *NewUUID.ToString());
|
||
|
|
||
|
AnchorUUID = NewUUID;
|
||
|
}
|
||
|
|
||
|
bool UOculusXRAnchorComponent::IsStoredAtLocation(EOculusXRSpaceStorageLocation Location) const
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Anchor UUID: %s - Saved Local: %d - Saved Cloud: %d"),
|
||
|
*GetUUID().ToString(),
|
||
|
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Local),
|
||
|
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Cloud));
|
||
|
|
||
|
return (StorageLocations & static_cast<int32>(Location)) > 0;
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::SetStoredLocation(EOculusXRSpaceStorageLocation Location, bool Stored)
|
||
|
{
|
||
|
if (Stored)
|
||
|
{
|
||
|
StorageLocations |= static_cast<int32>(Location);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StorageLocations = StorageLocations & ~static_cast<int32>(Location);
|
||
|
}
|
||
|
|
||
|
UE_LOG(LogOculusXRAnchors, Verbose, TEXT("Anchor UUID: %s - Saved Local: %d - Saved Cloud: %d"),
|
||
|
*GetUUID().ToString(),
|
||
|
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Local),
|
||
|
StorageLocations & static_cast<int32>(EOculusXRSpaceStorageLocation::Cloud));
|
||
|
}
|
||
|
|
||
|
bool UOculusXRAnchorComponent::IsSaved() const
|
||
|
{
|
||
|
return StorageLocations > 0;
|
||
|
}
|
||
|
|
||
|
void UOculusXRAnchorComponent::UpdateAnchorTransform() const
|
||
|
{
|
||
|
if (GetWorld() == nullptr)
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve World Context"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
AActor* Parent = GetOwner();
|
||
|
if (Parent)
|
||
|
{
|
||
|
if (AnchorHandle.Value)
|
||
|
{
|
||
|
FTransform OutTransform;
|
||
|
if (UOculusXRAnchorBPFunctionLibrary::GetAnchorTransformByHandle(AnchorHandle, OutTransform))
|
||
|
{
|
||
|
#if WITH_EDITOR
|
||
|
// Link only head-space transform update
|
||
|
if (bUpdateHeadSpaceTransform && PlayerCameraManager != nullptr)
|
||
|
{
|
||
|
FTransform MainCameraTransform;
|
||
|
MainCameraTransform.SetLocation(PlayerCameraManager->GetCameraLocation());
|
||
|
MainCameraTransform.SetRotation(FQuat(PlayerCameraManager->GetCameraRotation()));
|
||
|
|
||
|
if (!ToWorldSpacePose(MainCameraTransform, OutTransform))
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Display, TEXT("Was not able to transform anchor to world space pose"));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||
|
if (CVarOculusXRVerboseAnchorDebugXR.GetValueOnGameThread() > 0)
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Display, TEXT("UpdateAnchor Pos %s"), *OutTransform.GetLocation().ToString());
|
||
|
UE_LOG(LogOculusXRAnchors, Display, TEXT("UpdateAnchor Rot %s"), *OutTransform.GetRotation().ToString());
|
||
|
}
|
||
|
#endif
|
||
|
Parent->SetActorLocationAndRotation(OutTransform.GetLocation(), OutTransform.GetRotation(), false, 0, ETeleportType::ResetPhysics);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool UOculusXRAnchorComponent::ToWorldSpacePose(FTransform CameraTransform, FTransform& OutTrackingSpaceTransform) const
|
||
|
{
|
||
|
OculusXRHMD::FOculusXRHMD* OculusXRHMD = OculusXRHMD::FOculusXRHMD::GetOculusXRHMD();
|
||
|
if (!OculusXRHMD)
|
||
|
{
|
||
|
UE_LOG(LogOculusXRAnchors, Warning, TEXT("Unable to retrieve OculusXRHMD, cannot calculate anchor world space pose."));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
OculusXRHMD::FPose MainCameraPose(CameraTransform.GetRotation(), CameraTransform.GetLocation());
|
||
|
OculusXRHMD::FPose TrackingSpacePose(OutTrackingSpaceTransform.GetRotation(), OutTrackingSpaceTransform.GetLocation());
|
||
|
|
||
|
FVector OutHeadPosition;
|
||
|
FQuat OutHeadOrientation;
|
||
|
const bool bGetPose = OculusXRHMD->GetCurrentPose(OculusXRHMD->HMDDeviceId, OutHeadOrientation, OutHeadPosition);
|
||
|
if (!bGetPose)
|
||
|
return false;
|
||
|
|
||
|
OculusXRHMD::FPose HeadPose(OutHeadOrientation, OutHeadPosition);
|
||
|
|
||
|
OculusXRHMD::FPose poseInHeadSpace = HeadPose.Inverse() * TrackingSpacePose;
|
||
|
|
||
|
// To world space pose
|
||
|
const OculusXRHMD::FPose WorldTrackingSpacePose = MainCameraPose * poseInHeadSpace;
|
||
|
|
||
|
OutTrackingSpaceTransform.SetLocation(WorldTrackingSpacePose.Position);
|
||
|
OutTrackingSpaceTransform.SetRotation(WorldTrackingSpacePose.Orientation);
|
||
|
|
||
|
return true;
|
||
|
}
|