fix a few wrist tracker issues and introduce SGWristTrackerVisualizationComponent
This commit is contained in:
@@ -50,7 +50,6 @@
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
#include "SGCore/SGHapticGlove.h"
|
||||
#include "SGDebug/SGDebugVirtualHand.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
#include "SGSettings/SGSettings.h"
|
||||
#include "SGTracking/SGGloveTracker.h"
|
||||
|
||||
|
||||
@@ -35,14 +35,9 @@
|
||||
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
|
||||
#include "Animation/Skeleton.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "IXRTrackingSystem.h"
|
||||
#include "UObject/ConstructorHelpers.h"
|
||||
|
||||
#include "SGDebug/SGDebugGizmo.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
#include "SGSettings/SGSettings.h"
|
||||
|
||||
struct USGWristTrackerComponent::FImpl
|
||||
@@ -300,11 +295,9 @@ void USGWristTrackerComponent::FImpl::UpdateWristTrackingData() const
|
||||
void USGWristTrackerComponent::FImpl::DrawDebugGizmo() const
|
||||
{
|
||||
const UWorld* World{Owner->GetWorld()};
|
||||
const FVector& Location{Owner->GetComponentLocation()};
|
||||
const FRotator& Rotation{Owner->GetComponentRotation()};
|
||||
const FSGDebugGizmoSettings& DebugGizmoSettings{Owner->GetWristTrackingSettings().DebugGizmoSettings};
|
||||
|
||||
FSGDebugGizmo::Draw(World, Location, Rotation, DebugGizmoSettings);
|
||||
FSGDebugGizmo::Draw(World, Owner->WristLocation, Owner->WristRotation, DebugGizmoSettings);
|
||||
}
|
||||
|
||||
void USGWristTrackerComponent::FImplDeleter::operator()(const FImpl* P) const
|
||||
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2024 SenseGlove
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Components/SGWristTrackerVisualizationComponent.h"
|
||||
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
struct USGWristTrackerVisualizationComponent::FImpl
|
||||
{
|
||||
/************************
|
||||
* Static methods
|
||||
************************/
|
||||
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
USGWristTrackerVisualizationComponent* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(USGWristTrackerVisualizationComponent* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
|
||||
bool IsEditor() const;
|
||||
|
||||
void UpdateLocationAndRotation() const;
|
||||
};
|
||||
|
||||
USGWristTrackerVisualizationComponent::USGWristTrackerVisualizationComponent(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
PrimaryComponentTick.bTickEvenWhenPaused = false;
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
PrimaryComponentTick.bStartWithTickEnabled = true;
|
||||
bTickInEditor = true;
|
||||
bNeverNeedsRenderUpdate = true;
|
||||
bAllowConcurrentTick = true;
|
||||
|
||||
SetCastShadow(false);
|
||||
SetCastHiddenShadow(false);
|
||||
bCastDynamicShadow = false;
|
||||
SetOnlyOwnerSee(false);
|
||||
SetReceivesDecals(false);
|
||||
SetCanEverAffectNavigation(false);
|
||||
}
|
||||
|
||||
void USGWristTrackerVisualizationComponent::InitializeComponent()
|
||||
{
|
||||
Super::InitializeComponent();
|
||||
|
||||
Pimpl->UpdateLocationAndRotation();
|
||||
}
|
||||
|
||||
void USGWristTrackerVisualizationComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
Pimpl->UpdateLocationAndRotation();
|
||||
}
|
||||
|
||||
void USGWristTrackerVisualizationComponent::TickComponent(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Pimpl->IsEditor())
|
||||
{
|
||||
EditorTick(DeltaTime, TickType, ThisTickFunction);
|
||||
return;
|
||||
}
|
||||
#endif /* WITH_EDITOR */
|
||||
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
Pimpl->UpdateLocationAndRotation();
|
||||
}
|
||||
|
||||
|
||||
void USGWristTrackerVisualizationComponent::EditorTick(
|
||||
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Pimpl->UpdateLocationAndRotation();
|
||||
}
|
||||
|
||||
USGWristTrackerVisualizationComponent::FImpl::FImpl(USGWristTrackerVisualizationComponent* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
USGWristTrackerVisualizationComponent::FImpl::~FImpl() = default;
|
||||
|
||||
bool USGWristTrackerVisualizationComponent::FImpl::IsEditor() const
|
||||
{
|
||||
const UWorld* World{Owner->GetWorld()};
|
||||
if (World && (World->WorldType == EWorldType::Editor || World->WorldType == EWorldType::EditorPreview))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void USGWristTrackerVisualizationComponent::FImpl::UpdateLocationAndRotation() const
|
||||
{
|
||||
USGWristTrackerComponent* ParentComponent{Cast<USGWristTrackerComponent>(Owner->GetAttachParent())};
|
||||
if (!ensureAlwaysMsgf(IsValid(ParentComponent),
|
||||
TEXT("This component should be attached to a SGWristTackerComponent!")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SGLOG(ParentComponent->GetWristRotation(), ParentComponent->GetWristLocation())
|
||||
|
||||
//Owner->MotionSource = FName("Left");
|
||||
// Owner->SetWorldLocation(ParentComponent->GetWristLocation());
|
||||
// Owner->SetWorldRotation(ParentComponent->GetWristRotation());
|
||||
}
|
||||
|
||||
void USGWristTrackerVisualizationComponent::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -39,13 +39,13 @@
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "XRDeviceVisualizationComponent.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
|
||||
#include "SenseGlove/Components/SGGrabComponent.h"
|
||||
#include "SenseGlove/Components/SGTouchComponent.h"
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerVisualizationComponent.h"
|
||||
#include "SGLog/SGLog.h"
|
||||
|
||||
static constexpr float SG_HAND_MESH_YAW_CORRECTION_OFFSET = -90.0f;
|
||||
@@ -190,7 +190,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
|
||||
WristTrackerLeft->SetupAttachment(GetRootComponent());
|
||||
WristTrackerLeft->SetRight(false);
|
||||
|
||||
ControllerVisualizerLeft = ObjectInitializer.CreateDefaultSubobject<UXRDeviceVisualizationComponent>(
|
||||
ControllerVisualizerLeft = ObjectInitializer.CreateDefaultSubobject<USGWristTrackerVisualizationComponent>(
|
||||
this, TEXT("ControllerVisualizerLeft"));
|
||||
ControllerVisualizerLeft->SetupAttachment(WristTrackerLeft);
|
||||
ControllerVisualizerLeft->SetDisplayModelSource(FName("OpenXR"));
|
||||
@@ -349,7 +349,7 @@ ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
|
||||
WristTrackerRight->SetupAttachment(GetRootComponent());
|
||||
WristTrackerRight->SetRight(true);
|
||||
|
||||
ControllerVisualizerRight = ObjectInitializer.CreateDefaultSubobject<UXRDeviceVisualizationComponent>(
|
||||
ControllerVisualizerRight = ObjectInitializer.CreateDefaultSubobject<USGWristTrackerVisualizationComponent>(
|
||||
this, TEXT("ControllerVisualizerRight"));
|
||||
ControllerVisualizerRight->SetupAttachment(WristTrackerRight);
|
||||
ControllerVisualizerRight->SetDisplayModelSource(FName("OpenXR"));
|
||||
@@ -1687,7 +1687,7 @@ void ASGPawn::FImpl::UpdateWristTrackerVisualization(const bool bRight, const EX
|
||||
const bool bIsVisualizationActive = VisualType == EXRVisualType::Controller
|
||||
|| !!Settings.bHandTrackingVisualizationAllowed;
|
||||
|
||||
UXRDeviceVisualizationComponent* ControllerVisualizer{
|
||||
USGWristTrackerVisualizationComponent* ControllerVisualizer{
|
||||
bRight ? Owner->ControllerVisualizerLeft : Owner->ControllerVisualizerRight
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @author Mamadou Babaei <mamadou@senseglove.com>
|
||||
*
|
||||
* @section LICENSE
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Copyright (c) 2020 - 2024 SenseGlove
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* @section DESCRIPTION
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "HeadMountedDisplayTypes.h"
|
||||
#include "Math/Rotator.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "XRDeviceVisualizationComponent.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "SGWristTrackerVisualizationComponent.generated.h"
|
||||
|
||||
UCLASS(Blueprintable, ClassGroup = MotionController, meta = (BlueprintSpawnableComponent))
|
||||
class SENSEGLOVE_API USGWristTrackerVisualizationComponent : public UXRDeviceVisualizationComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
public:
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
protected:
|
||||
virtual void EditorTick(float DeltaTime,
|
||||
enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction);
|
||||
};
|
||||
@@ -48,10 +48,10 @@
|
||||
class UCameraComponent;
|
||||
class UPrimitiveComponent;
|
||||
class USphereComponent;
|
||||
class UXRDeviceVisualizationComponent;
|
||||
|
||||
class USGVirtualHandComponent;
|
||||
class USGWristTrackerComponent;
|
||||
class USGWristTrackerVisualizationComponent;
|
||||
|
||||
UCLASS(Config=Game, BlueprintType, Blueprintable)
|
||||
class SENSEGLOVE_API ASGPawn : public APawn
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
USGWristTrackerComponent* WristTrackerLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
UXRDeviceVisualizationComponent* ControllerVisualizerLeft;
|
||||
USGWristTrackerVisualizationComponent* ControllerVisualizerLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGVirtualHandComponent* HandLeft;
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
USGWristTrackerComponent* WristTrackerRight;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
UXRDeviceVisualizationComponent* ControllerVisualizerRight;
|
||||
USGWristTrackerVisualizationComponent* ControllerVisualizerRight;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
|
||||
USGVirtualHandComponent* HandRight;
|
||||
@@ -251,7 +251,7 @@ public:
|
||||
return WristTrackerLeft;
|
||||
}
|
||||
|
||||
FORCEINLINE UXRDeviceVisualizationComponent* GetControllerVisualizerLeft() const
|
||||
FORCEINLINE USGWristTrackerVisualizationComponent* GetControllerVisualizerLeft() const
|
||||
{
|
||||
return ControllerVisualizerLeft;
|
||||
}
|
||||
@@ -311,7 +311,7 @@ public:
|
||||
return WristTrackerRight;
|
||||
}
|
||||
|
||||
FORCEINLINE UXRDeviceVisualizationComponent* GetControllerVisualizerRight() const
|
||||
FORCEINLINE USGWristTrackerVisualizationComponent* GetControllerVisualizerRight() const
|
||||
{
|
||||
return ControllerVisualizerLeft;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "XRDeviceVisualizationComponent.h"
|
||||
|
||||
#include "SenseGlove/Components/SGVirtualHandComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerComponent.h"
|
||||
#include "SenseGlove/Components/SGWristTrackerVisualizationComponent.h"
|
||||
#include "SenseGlove/GameFramework/SGPawn.h"
|
||||
|
||||
UCameraComponent* UPawnKismetLibrary::GetCamera(const ASGPawn* Pawn)
|
||||
@@ -54,7 +54,7 @@ USGWristTrackerComponent* UPawnKismetLibrary::GetWristTrackerLeft(const ASGPawn*
|
||||
return Pawn->GetWristTrackerLeft();
|
||||
}
|
||||
|
||||
UXRDeviceVisualizationComponent* UPawnKismetLibrary::GetControllerVisualizerLeft(const ASGPawn* Pawn)
|
||||
USGWristTrackerVisualizationComponent* UPawnKismetLibrary::GetControllerVisualizerLeft(const ASGPawn* Pawn)
|
||||
{
|
||||
return Pawn->GetControllerVisualizerLeft();
|
||||
}
|
||||
@@ -114,7 +114,7 @@ USGWristTrackerComponent* UPawnKismetLibrary::GetWristTrackerRight(const ASGPawn
|
||||
return Pawn->GetWristTrackerRight();
|
||||
}
|
||||
|
||||
UXRDeviceVisualizationComponent* UPawnKismetLibrary::GetControllerVisualizerRight(const ASGPawn* Pawn)
|
||||
USGWristTrackerVisualizationComponent* UPawnKismetLibrary::GetControllerVisualizerRight(const ASGPawn* Pawn)
|
||||
{
|
||||
return Pawn->GetControllerVisualizerRight();
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@
|
||||
|
||||
class UCameraComponent;
|
||||
class USphereComponent;
|
||||
class UXRDeviceVisualizationComponent;
|
||||
|
||||
class ASGPawn;
|
||||
class USGVirtualHandComponent;
|
||||
class USGWristTrackerComponent;
|
||||
class USGWristTrackerVisualizationComponent;
|
||||
|
||||
UCLASS(meta=(ScriptName = "SesneGlovePawnKismetLibrary"))
|
||||
class SENSEGLOVEKISMET_API UPawnKismetLibrary final : public USGBlueprintFunctionLibrary
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
static USGWristTrackerComponent* GetWristTrackerLeft(const ASGPawn* Pawn);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Game Framework | Pawn")
|
||||
static UXRDeviceVisualizationComponent* GetControllerVisualizerLeft(const ASGPawn* Pawn);
|
||||
static USGWristTrackerVisualizationComponent* GetControllerVisualizerLeft(const ASGPawn* Pawn);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Game Framework | Pawn")
|
||||
static USGVirtualHandComponent* GetHandLeft(const ASGPawn* Pawn);
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
static USGWristTrackerComponent* GetWristTrackerRight(const ASGPawn* Pawn);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Game Framework | Pawn")
|
||||
static UXRDeviceVisualizationComponent* GetControllerVisualizerRight(const ASGPawn* Pawn);
|
||||
static USGWristTrackerVisualizationComponent* GetControllerVisualizerRight(const ASGPawn* Pawn);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Game Framework | Pawn")
|
||||
static USGVirtualHandComponent* GetHandRight(const ASGPawn* Pawn);
|
||||
|
||||
@@ -139,6 +139,136 @@ struct FSGXRTracker::FImpl
|
||||
return Settings->GetTrackingSettings().WristTrackingSettings;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetDefaultLeftMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("Left"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetDefaultRightMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("Right"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetDefaultMotionSourceName(const EControllerHand Hand)
|
||||
{
|
||||
const FName& Name{
|
||||
Hand == EControllerHand::Right
|
||||
? GetDefaultRightMotionSourceName()
|
||||
: GetDefaultLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetDefaultMotionSourceName(const bool bRight)
|
||||
{
|
||||
const FName& Name{
|
||||
bRight
|
||||
? GetDefaultRightMotionSourceName()
|
||||
: GetDefaultLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetLegacyControllerLeftMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("Left"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetLegacyControllerRightMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("Right"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetLegacyControllerMotionSourceName(const EControllerHand Hand)
|
||||
{
|
||||
const FName& Name{
|
||||
Hand == EControllerHand::Right
|
||||
? GetLegacyControllerRightMotionSourceName()
|
||||
: GetLegacyControllerLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetLegacyControllerMotionSourceName(const bool bRight)
|
||||
{
|
||||
const FName& Name{
|
||||
bRight
|
||||
? GetLegacyControllerRightMotionSourceName()
|
||||
: GetLegacyControllerLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMoreSpecificLeftMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("HandTrackingLeft"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMoreSpecificRightMotionSourceName()
|
||||
{
|
||||
static const FName Name(TEXT("HandTrackingRight"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMoreSpecificMotionSourceName(const EControllerHand Hand)
|
||||
{
|
||||
const FName& Name{
|
||||
Hand == EControllerHand::Right
|
||||
? GetMoreSpecificRightMotionSourceName()
|
||||
: GetMoreSpecificLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMoreSpecificMotionSourceName(const bool bRight)
|
||||
{
|
||||
const FName& Name{
|
||||
bRight
|
||||
? GetMoreSpecificRightMotionSourceName()
|
||||
: GetMoreSpecificLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetLeftMotionSourceName()
|
||||
{
|
||||
const bool bUseMoreSpecificMotionSourceNames = ShouldUseMoreSpecificMotionSourceNames();
|
||||
const FName& Name{
|
||||
bUseMoreSpecificMotionSourceNames
|
||||
? GetMoreSpecificLeftMotionSourceName()
|
||||
: GetDefaultLeftMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetRightMotionSourceName()
|
||||
{
|
||||
const bool bUseMoreSpecificMotionSourceNames = ShouldUseMoreSpecificMotionSourceNames();
|
||||
const FName& Name{
|
||||
bUseMoreSpecificMotionSourceNames
|
||||
? GetMoreSpecificRightMotionSourceName()
|
||||
: GetDefaultRightMotionSourceName()
|
||||
};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMotionSourceName(const EControllerHand Hand)
|
||||
{
|
||||
const FName& Name{Hand == EControllerHand::Right ? GetRightMotionSourceName() : GetLeftMotionSourceName()};
|
||||
return Name;
|
||||
}
|
||||
|
||||
FORCEINLINE static const FName& GetMotionSourceName(const bool bRight)
|
||||
{
|
||||
const FName& Name{bRight ? GetRightMotionSourceName() : GetLeftMotionSourceName()};
|
||||
return Name;
|
||||
}
|
||||
|
||||
static ESGPositionalTrackingHardware GetPositionalTrackingHardware();
|
||||
|
||||
FORCEINLINE static USGHapticGlove* GetGlove(const EControllerHand Hand)
|
||||
@@ -926,19 +1056,24 @@ void FSGXRTracker::UpdateDeviceLocations(
|
||||
LocateInfo.baseSpace = TrackingSpace;
|
||||
LocateInfo.time = DisplayTime;
|
||||
|
||||
const bool bFallbackToHandTrackingIfNoGloveDetected = FImpl::ShouldFallbackToHandTrackingIfNoGloveDetected();
|
||||
|
||||
const bool bLeftGloveConnected = FImpl::IsLeftGloveConnected();
|
||||
if (bLeftGloveConnected)
|
||||
{
|
||||
/// NOTE
|
||||
/// It's necessary to call the UpdateXRHandTrackingData first for the wrist tracking to work properly when the
|
||||
/// motion controllers are not active and we rely on the OpenXRHandTracking data for wrist tracking.
|
||||
/// See the NOTE inside the FSGXRTracker::FImpl::GetWristLocationAndRotation method.
|
||||
/// See the NOTE inside the FSGXRTracker::FImpl::GetWristTransform method.
|
||||
Pimpl->UpdateXRHandTrackingData(Pimpl->HandStates[0], LocateInfo);
|
||||
Pimpl->UpdateSGHandState(EControllerHand::Left, Pimpl->HandStates[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pimpl->UpdateXRHandTrackingData(Pimpl->HandStates[0], LocateInfo);
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
Pimpl->UpdateXRHandTrackingData(Pimpl->HandStates[0], LocateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
const bool bRightGloveConnected = FImpl::IsRightGloveConnected();
|
||||
@@ -953,7 +1088,10 @@ void FSGXRTracker::UpdateDeviceLocations(
|
||||
}
|
||||
else
|
||||
{
|
||||
Pimpl->UpdateXRHandTrackingData(Pimpl->HandStates[1], LocateInfo);
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
Pimpl->UpdateXRHandTrackingData(Pimpl->HandStates[1], LocateInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,36 +1122,40 @@ bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerInd
|
||||
{
|
||||
FTransform ControllerTransform{FTransform::Identity};
|
||||
|
||||
const bool bFallbackToHandTrackingIfNoGloveDetected = FImpl::ShouldFallbackToHandTrackingIfNoGloveDetected();
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
|
||||
const FImpl::FSGMotionSourceInfo* KeyPointInfoPtr{Pimpl->MotionSourceToKeypointMap.Find(MotionSource)};
|
||||
if (KeyPointInfoPtr)
|
||||
const FImpl::FSGMotionSourceInfo* KeyPointInfoPtr{Pimpl->MotionSourceToKeypointMap.Find(MotionSource)};
|
||||
if (KeyPointInfoPtr)
|
||||
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
if (GetControllerTrackingStatus(ControllerIndex, DeviceHand) != ETrackingStatus::NotTracked)
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
{
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
|
||||
const EHandKeypoint KeyPoint = KeyPointInfoPtr->Key;
|
||||
const bool bIsLeft = KeyPointInfoPtr->Value;
|
||||
const EHandKeypoint KeyPoint = KeyPointInfoPtr->Key;
|
||||
const bool bIsLeft = KeyPointInfoPtr->Value;
|
||||
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
const bool bIsLeft = DeviceHand == EControllerHand::Left;
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
if (bIsLeft)
|
||||
{
|
||||
if (bIsLeft)
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
|
||||
ControllerTransform = GetLeftHandState().GetTransform(KeyPoint);
|
||||
ControllerTransform = GetLeftHandState().GetTransform(KeyPoint);
|
||||
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
ControllerTransform = GetLeftHandState().GetTransform(EHandKeypoint::Wrist);
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
bTracked = !!GetLeftHandState().bReceivedJointPoses;
|
||||
}
|
||||
else
|
||||
{
|
||||
bTracked = !!GetLeftHandState().bReceivedJointPoses;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
|
||||
ControllerTransform = GetRightHandState().GetTransform(KeyPoint);
|
||||
ControllerTransform = GetRightHandState().GetTransform(KeyPoint);
|
||||
#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
ControllerTransform = GetRightHandState().GetTransform(EHandKeypoint::Wrist);
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
bTracked = !!GetRightHandState().bReceivedJointPoses;
|
||||
bTracked = !!GetRightHandState().bReceivedJointPoses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1026,24 +1168,10 @@ bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerInd
|
||||
{
|
||||
static const FName OpenXRName{TEXT("OpenXR")};
|
||||
|
||||
static constexpr int32 CurrentPlayerControllerIndex = 0;
|
||||
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2
|
||||
const bool bUseMoreSpecificMotionSourceNames = FImpl::ShouldUseMoreSpecificMotionSourceNames();
|
||||
|
||||
static const FName
|
||||
LeftName(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingLeft") : TEXT("Left"));
|
||||
static const FName RightName(bUseMoreSpecificMotionSourceNames
|
||||
? TEXT("HandTrackingRight")
|
||||
: TEXT("Right"));
|
||||
|
||||
FName MotionSource;
|
||||
if (DeviceHand == EControllerHand::Left)
|
||||
{
|
||||
MotionSource = LeftName;
|
||||
}
|
||||
else if (DeviceHand == EControllerHand::Right)
|
||||
{
|
||||
MotionSource = RightName;
|
||||
}
|
||||
const FName& MotionSource{FImpl::GetDefaultMotionSourceName(DeviceHand)};
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 2 */
|
||||
|
||||
const TArray<IMotionController*> MotionControllers{
|
||||
@@ -1064,8 +1192,9 @@ bool FSGXRTracker::GetControllerOrientationAndPosition(const int32 ControllerInd
|
||||
continue;
|
||||
}
|
||||
|
||||
const ETrackingStatus TrackingStatus = MotionController->GetControllerTrackingStatus(0, MotionSource);
|
||||
if (TrackingStatus != ETrackingStatus::Tracked)
|
||||
const ETrackingStatus TrackingStatus = MotionController->GetControllerTrackingStatus(
|
||||
CurrentPlayerControllerIndex, MotionSource);
|
||||
if (TrackingStatus == ETrackingStatus::NotTracked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1110,8 +1239,12 @@ ETrackingStatus FSGXRTracker::GetControllerTrackingStatus(const int32 Controller
|
||||
return ETrackingStatus::Tracked;
|
||||
}
|
||||
|
||||
const FSGXRHandState& HandState{bIsLeft ? GetLeftHandState() : GetRightHandState()};
|
||||
return !!HandState.bReceivedJointPoses ? ETrackingStatus::Tracked : ETrackingStatus::NotTracked;
|
||||
const bool bFallbackToHandTrackingIfNoGloveDetected = FImpl::ShouldFallbackToHandTrackingIfNoGloveDetected();
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
const FSGXRHandState& HandState{bIsLeft ? GetLeftHandState() : GetRightHandState()};
|
||||
return !!HandState.bReceivedJointPoses ? ETrackingStatus::Tracked : ETrackingStatus::NotTracked;
|
||||
}
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3
|
||||
}
|
||||
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 */
|
||||
@@ -1129,8 +1262,6 @@ void FSGXRTracker::EnumerateSources(TArray<FMotionControllerSource>& SourcesOut)
|
||||
{
|
||||
ensureAlwaysMsgf(IsInGameThread(), TEXT("Is not in the game thread!"));
|
||||
|
||||
const bool bUseMoreSpecificMotionSourceNames = FImpl::ShouldUseMoreSpecificMotionSourceNames();
|
||||
|
||||
SourcesOut.Reserve(SourcesOut.Num() + (EHandKeypointCount * 2));
|
||||
|
||||
const UEnum* EnumPtr{
|
||||
@@ -1138,14 +1269,14 @@ void FSGXRTracker::EnumerateSources(TArray<FMotionControllerSource>& SourcesOut)
|
||||
};
|
||||
ensureAlwaysMsgf(EnumPtr, TEXT("Failed to find the HMD hand keypoint!"));
|
||||
|
||||
const FString Left(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingLeft") : TEXT("Left"));
|
||||
const FString Right(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingRight") : TEXT("Right"));
|
||||
const FName& Left(FImpl::GetLeftMotionSourceName());
|
||||
const FName& Right(FImpl::GetRightMotionSourceName());
|
||||
|
||||
for (int32 Keypoint = 0; Keypoint < EHandKeypointCount; Keypoint++)
|
||||
{
|
||||
const FString EnumString{ParseEOpenXRHandKeypointEnumName(EnumPtr->GetNameByValue(Keypoint)).ToString()};
|
||||
const FString StringLeft{FString::Printf(TEXT("%s%s"), *Left, *EnumString)};
|
||||
const FString StringRight{FString::Printf(TEXT("%s%s"), *Right, *EnumString)};
|
||||
const FString StringLeft{FString::Printf(TEXT("%s%s"), *Left.ToString(), *EnumString)};
|
||||
const FString StringRight{FString::Printf(TEXT("%s%s"), *Right.ToString(), *EnumString)};
|
||||
FName SourceL(*(StringLeft));
|
||||
FName SourceR(*(StringRight));
|
||||
SourcesOut.Add(MoveTemp(SourceL));
|
||||
@@ -1345,7 +1476,6 @@ void FSGXRTracker::FImpl::BuildMotionSourceToKeypointMap()
|
||||
return;
|
||||
}
|
||||
|
||||
const bool bUseMoreSpecificMotionSourceNames = ShouldUseMoreSpecificMotionSourceNames();
|
||||
const bool bSupportLegacyControllerMotionSources = ShouldSupportLegacyControllerMotionSources();
|
||||
|
||||
// There is a motion source that corresponds to each hand keypoint of the form [Left|Right][Keypoint].
|
||||
@@ -1360,24 +1490,28 @@ void FSGXRTracker::FImpl::BuildMotionSourceToKeypointMap()
|
||||
|
||||
ensureAlwaysMsgf(IsInGameThread(), TEXT("Is not in the game thread!"));
|
||||
|
||||
const FString Left(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingLeft") : TEXT("Left"));
|
||||
const FString Right(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingRight") : TEXT("Right"));
|
||||
const FName& Left(GetLeftMotionSourceName());
|
||||
const FName& Right(GetRightMotionSourceName());
|
||||
|
||||
for (int64 e = 0; e < EHandKeypointCount; ++e)
|
||||
{
|
||||
const EHandKeypoint EnumValue = static_cast<EHandKeypoint>(e);
|
||||
const FString EnumName{EnumPtr->GetNameStringByValue(e)};
|
||||
|
||||
FName LeftName(Left + EnumName);
|
||||
FName RightName(Right + EnumName);
|
||||
FName LeftName(Left.ToString() + EnumName);
|
||||
FName RightName(Right.ToString() + EnumName);
|
||||
MotionSourceToKeypointMap.Add(MoveTemp(LeftName), FSGMotionSourceInfo(EnumValue, true));
|
||||
MotionSourceToKeypointMap.Add(MoveTemp(RightName), FSGMotionSourceInfo(EnumValue, false));
|
||||
}
|
||||
|
||||
if (bSupportLegacyControllerMotionSources)
|
||||
{
|
||||
MotionSourceToKeypointMap.Add(FName("Left"), FSGMotionSourceInfo(EHandKeypoint::Wrist, true));
|
||||
MotionSourceToKeypointMap.Add(FName("Right"), FSGMotionSourceInfo(EHandKeypoint::Wrist, false));
|
||||
const FName& LeftLegacyControllerMotionSourceName{GetLegacyControllerLeftMotionSourceName()};
|
||||
const FName& RightLegacyControllerMotionSourceName{GetLegacyControllerRightMotionSourceName()};
|
||||
MotionSourceToKeypointMap.Add(
|
||||
LeftLegacyControllerMotionSourceName, FSGMotionSourceInfo(EHandKeypoint::Wrist, true));
|
||||
MotionSourceToKeypointMap.Add(
|
||||
RightLegacyControllerMotionSourceName, FSGMotionSourceInfo(EHandKeypoint::Wrist, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1526,23 +1660,11 @@ bool FSGXRTracker::FImpl::GetWristTransform(
|
||||
static const FName OpenXRName{TEXT("OpenXR")};
|
||||
static const FName OpenXRHandTrackingName{TEXT("OpenXRHandTracking")};
|
||||
|
||||
const bool bUseMoreSpecificMotionSourceNames = ShouldUseMoreSpecificMotionSourceNames();
|
||||
|
||||
static const FName LeftName(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingLeft") : TEXT("Left"));
|
||||
static const FName RightName(bUseMoreSpecificMotionSourceNames ? TEXT("HandTrackingRight") : TEXT("Right"));
|
||||
|
||||
FName MotionSource;
|
||||
if (DeviceHand == EControllerHand::Left)
|
||||
{
|
||||
MotionSource = LeftName;
|
||||
}
|
||||
else if (DeviceHand == EControllerHand::Right)
|
||||
{
|
||||
MotionSource = RightName;
|
||||
}
|
||||
|
||||
const FName& MotionSource{GetMotionSourceName(DeviceHand)};
|
||||
static constexpr int32 CurrentPlayerControllerIndex = 0;
|
||||
|
||||
const bool bFallbackToHandTrackingIfNoGloveDetected = ShouldFallbackToHandTrackingIfNoGloveDetected();
|
||||
|
||||
const TArray<IMotionController*> MotionControllers{IModularFeatures::Get().GetModularFeatureImplementations<
|
||||
IMotionController>(IMotionController::GetModularFeatureName())};
|
||||
|
||||
@@ -1553,25 +1675,28 @@ bool FSGXRTracker::FImpl::GetWristTransform(
|
||||
continue;
|
||||
}
|
||||
|
||||
ETrackingStatus TrackingStatus = MotionController->GetControllerTrackingStatus(
|
||||
const ETrackingStatus TrackingStatus = MotionController->GetControllerTrackingStatus(
|
||||
CurrentPlayerControllerIndex, MotionSource);
|
||||
if (TrackingStatus != ETrackingStatus::Tracked)
|
||||
if (TrackingStatus == ETrackingStatus::NotTracked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()};
|
||||
const FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()};
|
||||
|
||||
/// NOTE
|
||||
/// We have to always check the wrist tracking data from the OpenXRHandTracking system instead of OpenXR,
|
||||
/// otherwise even if the motion controllers become deactivated their tracking status sometimes mysteriously
|
||||
/// reported as Tracked.
|
||||
// We have to always check the wrist tracking data from the OpenXRHandTracking system instead of OpenXR,
|
||||
// otherwise even if the motion controllers become deactivated their tracking status sometimes mysteriously
|
||||
// reported as Tracked.
|
||||
|
||||
if (DeviceTypeName == OpenXRHandTrackingName)
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
bOutMotionSourceHandTracking = true;
|
||||
const bool bResult = GetOpenXRHandTrackingWristTransform(DeviceHand, OutTransform);
|
||||
return bResult;
|
||||
if (DeviceTypeName == OpenXRHandTrackingName)
|
||||
{
|
||||
bOutMotionSourceHandTracking = true;
|
||||
const bool bResult = GetOpenXRHandTrackingWristTransform(DeviceHand, OutTransform);
|
||||
return bResult;
|
||||
}
|
||||
}
|
||||
|
||||
if (DeviceTypeName == OpenXRName)
|
||||
@@ -1582,6 +1707,20 @@ bool FSGXRTracker::FImpl::GetWristTransform(
|
||||
}
|
||||
}
|
||||
|
||||
/// WORKAROUND
|
||||
// Sometimes the motion controller array does not contain a OpenXRHandTracking though it's being tracked! So, as a
|
||||
// last resort we always attempt at retrieving the OpenXRHandTracking wrist transform in case all other measures we
|
||||
// have taken has already failed!
|
||||
if (bFallbackToHandTrackingIfNoGloveDetected)
|
||||
{
|
||||
const bool bResult = GetOpenXRHandTrackingWristTransform(DeviceHand, OutTransform);
|
||||
if (bResult)
|
||||
{
|
||||
bOutMotionSourceHandTracking = true;
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2039,10 +2178,13 @@ bool FSGXRTracker::FImpl::UpdateSGHandState(const EControllerHand DeviceHand, FS
|
||||
|
||||
FTransform WristTransform;
|
||||
bool bMotionSourceHandTracking = false;
|
||||
if (!GetWristTransform(DeviceHand, WristTransform, bMotionSourceHandTracking))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const bool bGotWristTransform = GetWristTransform(DeviceHand, WristTransform, bMotionSourceHandTracking);
|
||||
|
||||
/// NOTE
|
||||
// Even if we fail to get the wrist transform, the SenseGlove data needs to make it to the FXRMotionControllerData!
|
||||
// So, we just ignore the bGotWristTransform results! Otherwise, even if bFallbackToHandTrackingIfNoGloveDetected
|
||||
// is disabled it will output the hand-tracking data.
|
||||
(void) bGotWristTransform;
|
||||
|
||||
if (!UpdateSGWristJointData(OutHandState, WristTransform, bMotionSourceHandTracking))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user