VRTowerDef/Plugins/MetaXR/Source/OculusXRAnchors/Private/OculusXRAnchorComponent.cpp

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;
}