Unreal 中的手勢追蹤
手部追蹤系統使用個人的手掌和手指作為輸入。 每個手指的位置和旋轉數據、整個手掌和手勢都可以使用。 從 Unreal 4.26 開始,手部追蹤是以 Unreal HeadMountedDisplay 外掛程式為基礎,並在所有 XR 平臺和裝置上使用通用 API。 Windows Mixed Reality 和 OpenXR 系統的功能都相同。
手部姿勢
手擺姿勢可讓您追蹤並使用使用者的手和手指做為輸入,這可在藍圖和 C++ 中存取。 Unreal API 會將數據當做座標系統傳送,且刻度會與 Unreal 引擎同步。
列舉會 EHandKeypoint
描述階層:
您可以使用取得動作控制器數據函式,從使用者的手中 取得所有這些數據 。 該函式會傳 回 XRMotionControllerData 結構。 以下範例藍圖腳本會剖析 XRMotionControllerData 結構,以取得手部關節位置,並在每個關節的位置繪製偵錯座標系統。
請務必檢查結構是否有效,而且它是一手。 否則,您可能會在存取位置、旋轉和弧度陣列時取得未定義的行為。
列舉 EWMRHandKeypoint
描述 Hand 的骨骼階層。 您可以在藍圖中找到每個手部索引鍵:
完整的 C++ 列舉如下:
enum class EWMRHandKeypoint : uint8
{
Palm,
Wrist,
ThumbMetacarpal,
ThumbProximal,
ThumbDistal,
ThumbTip,
IndexMetacarpal,
IndexProximal,
IndexIntermediate,
IndexDistal,
IndexTip,
MiddleMetacarpal,
MiddleProximal,
MiddleIntermediate,
MiddleDistal,
MiddleTip,
RingMetacarpal,
RingProximal,
RingIntermediate,
RingDistal,
RingTip,
LittleMetacarpal,
LittleProximal,
LittleIntermediate,
LittleDistal,
LittleTip
};
您可以在 Windows.Perception.人員 中找到每個列舉案例的數值。HandJointKind 數據表。
支援手部追蹤
您可以在藍圖中使用手部追蹤,方法是從手部追蹤 Windows 混合實境新增支援手部追蹤>:
如果裝置上支援手部追蹤,且false
手部追蹤無法使用,則此函式會傳回 true
。
C++:
包含 WindowsMixedRealityHandTrackingFunctionLibrary.h
。
static bool UWindowsMixedRealityHandTrackingFunctionLibrary::SupportsHandTracking()
取得手部追蹤
您可以使用 GetHandJointTransform 從手傳回空間數據。 數據會更新每個框架,但如果您位於框架內,則會快取傳回的值。 基於效能考慮,不建議在此函式中具有繁重的邏輯。
C++:
static bool UWindowsMixedRealityHandTrackingFunctionLibrary::GetHandJointTransform(EControllerHand Hand, EWMRHandKeypoint Keypoint, FTransform& OutTransform, float& OutRadius)
以下是 GetHandJointTransform 函式參數的明細:
- Hand – 可以是用戶左側或右手。
- 索引鍵點 – 手部的骨頭。
- 轉換 – 骨骼基底的座標和方向。 您可以要求下一個骨頭的基底,以取得骨頭結尾的轉換數據。 一個特殊的尖骨給遠端。
- **Radius—骨頭基底的半徑。
- **傳回值—如果追蹤此框架的骨頭為 true,則為 false,如果未追蹤骨頭則為 false。
手部即時鏈接動畫
手部姿勢會使用 Live Link 外掛程式公開給動畫。
如果已啟用 Windows Mixed Reality 和 Live Link 外掛程式:
- 選取 [視窗 > 實時連結 ] 以開啟 [即時鏈接編輯器] 視窗。
- 選取 [來源 ],然後啟用 Windows Mixed Reality Hand Tracking Source
啟用來源並開啟動畫資產之後,請展開 [預覽場景] 索引卷標中的 [動畫] 區段,也會看到其他選項。
手部動畫階層與 中的 EWMRHandKeypoint
相同。 動畫可以使用 WindowsMixedRealityHandTrackingLiveLinkRemapAsset 來複位目標:
它也可以在編輯器中子類別化:
手部網格
您必須使用 Microsoft OpenXR 外掛程式,才能從 Unreal Marketplace 或 GitHub 取得。
手網格做為追蹤幾何
重要
在 OpenXR 中以追蹤幾何的形式取得手網格,需要您呼叫 Set Use Hand Mesh with Enabled Tracking Geometry。
若要啟用該模式,您應該呼叫 Set Use Hand Mesh with Enabled Tracking Geometry:
注意
無法同時啟用這兩種模式。 如果您啟用其中一個,則會自動停用另一個。
存取 Hand Mesh 數據
您必須先:才能存取手部網格資料:
- 選取您的ARSessionConfig資產、展開AR設定 -> 世界對應設定,然後核取 [從追蹤幾何產生網格數據]。
以下是預設網格參數:
- 使用網格數據進行遮蔽
- 產生網格數據的衝突
- 產生網格數據的導覽網格
- 在Wireframe中轉譯網格資料 - 顯示產生的網格的偵錯參數
這些參數值會當做空間對應網格和手部網格預設值使用。 您可以隨時在藍圖或任何網格的程式代碼中變更它們。
C++ API 參考
用來 EEARObjectClassification
尋找所有可追蹤物件的手網格值。
enum class EARObjectClassification : uint8
{
// Other types
HandMesh,
};
當系統偵測到任何可追蹤的物件時,會呼叫下列委派,包括手部網格。
class FARSupportInterface
{
public:
// Other params
DECLARE_AR_SI_DELEGATE_FUNCS(OnTrackableAdded)
DECLARE_AR_SI_DELEGATE_FUNCS(OnTrackableUpdated)
DECLARE_AR_SI_DELEGATE_FUNCS(OnTrackableRemoved)
};
請確定您的委派處理程式遵循下列函式簽章:
void UARHandMeshComponent::OnTrackableAdded(UARTrackedGeometry* Added)
您可以透過 UARTrackedGeometry::GetUnderlyingMesh
存取網格資料:
UMRMeshComponent* UARTrackedGeometry::GetUnderlyingMesh()
藍圖 API 參考
若要在藍圖中使用手部網格:
- 將 ARTrackableNotify 元件新增至藍圖動作專案
- 移至 [ 詳細數據] 面板,然後展開 [ 事件 ] 區段。
- 在事件圖形中使用下列節點覆寫 Add/Update/Remove Tracked Geometry:
OpenXR 中的 Hand Mesh 視覺效果
可視化手部網格的建議方式是搭配 Microsoft OpenXR 外掛程式使用 Epic 的 XRVisualization 外掛程式。
然後在藍圖編輯器中,您應該使用 Microsoft OpenXR 外掛程式中的設定 Use Hand Mesh 函式,並將 Enabled XRVisualization 作為參數:
若要管理轉譯程式,您應該使用 XRVisualization 中的轉譯動作控制器 :
結果:
如果您需要更複雜的專案,例如使用自定義著色器繪製手部網格,您需要取得網格做為追蹤幾何。
手部光線
取得手部姿勢適用於近距離互動,例如抓取物件或按下按鈕。 不過,有時候您需要使用遠離使用者的全像投影。 這可以透過手部光線來完成,這可用於 C++ 和藍圖中的指點裝置。 您可以從手部繪製光線到遠點,並從 Unreal 光線追蹤中取得一些協助,選取本來無法觸達的全像投影。
重要
由於所有函式結果都會變更每個畫面,因此它們全都是可呼叫的。 如需純函式和不完善或可呼叫函式的詳細資訊,請參閱函式上的藍圖使用者 GUID。
若要取得手部光線的數據,您應該使用上一節的取得動作控制器數據函式。 傳回的結構包含兩個參數,可用來建立手部光線 – 目標位置和目標旋轉。 這些參數會形成由肘部導向的光線。 您應該採用它們,並尋找所指向的全像投影。
以下是判斷手部光線是否擊中 Widget 並設定自定義命中結果的範例:
若要在藍圖中使用手部光線,請在 Windows Mixed Reality HMD 下搜尋任何動作:
若要在 C++ 中存取它們,請包含在 WindowsMixedRealityFunctionLibrary.h
呼叫程式代碼檔案的頂端。
列舉
您也可以存取 EHMDInputControllerButtons 下的輸入案例,這可用於藍圖:
若要在 C++ 中存取,請使用 EHMDInputControllerButtons
列舉類別:
enum class EHMDInputControllerButtons : uint8
{
Select,
Grasp,
//......
};
以下是兩個適用列舉案例的明細:
- 選取 - 用戶觸發的 Select 事件。
- 在 HoloLens 2 中透過空中點選、注視和認可來觸發,或說出已啟用語音輸入的 「選取」。
- Grasp - 使用者觸發的 Grasp 事件。
- 在 HoloLens 2 中,關閉全像投影上的使用者手指來觸發。
您可以透過 EHMDTrackingStatus
如下所示的列舉,在 C++ 中存取手部網格的追蹤狀態:
enum class EHMDTrackingStatus : uint8
{
NotTracked,
//......
Tracked
};
以下是兩個適用列舉案例的明細:
- NotTracked - 手部看不到
- 追蹤 - 手部已完整追蹤
結構
PointerPoseInfo 結構可以提供下列手部數據的相關信息:
- 原點 – 手部的來源
- 方向 – 手的方向
- 向上 – 手 部向上向量
- 方向 – 方向 四元數
- 追蹤狀態 – 目前的追蹤狀態
您可以透過藍圖存取 PointerPoseInfo 結構,如下所示:
或使用 C++:
struct FPointerPoseInfo
{
FVector Origin;
FVector Direction;
FVector Up;
FQuat Orientation;
EHMDTrackingStatus TrackingStatus;
};
函式
下列所有函式都可以在每個畫面上呼叫,以允許持續監視。
- 取得指標姿勢信息 會傳回目前畫面中手部光線方向的完整資訊。
藍圖:
C++:
static FPointerPoseInfo UWindowsMixedRealityFunctionLibrary::GetPointerPoseInfo(EControllerHand hand);
- 如果手在目前框架中被擷取,則擷 取會傳回 true。
藍圖:
C++:
static bool UWindowsMixedRealityFunctionLibrary::IsGrasped(EControllerHand hand);
- 如果使用者在目前畫面中觸發了 Select,則會傳回 True。
藍圖:
C++:
static bool UWindowsMixedRealityFunctionLibrary::IsSelectPressed(EControllerHand hand);
- 如果事件或按鈕在目前框架中觸發,則 Button Clicked 會傳回 true。
藍圖:
C++:
static bool UWindowsMixedRealityFunctionLibrary::IsButtonClicked(EControllerHand hand, EHMDInputControllerButtons button);
- 取得控制器追蹤狀態 會傳回目前畫面中的追蹤狀態。
藍圖:
C++:
static EHMDTrackingStatus UWindowsMixedRealityFunctionLibrary::GetControllerTrackingStatus(EControllerHand hand);
手勢
HoloLens 2 會追蹤空間手勢,這表示您可以將這些手勢擷取為輸入。 手勢追蹤是以訂用帳戶模型為基礎。 您應該使用 「設定手勢」函式,告訴裝置您想要追蹤的手勢。您可以在 HoloLens 2 基本使用方式檔中找到有關手勢的更多詳細數據。
Windows Mixed Reality
然後,您應該新增程式代碼以訂閱下列事件:
OpenXR
在OpenXR中,手勢事件會透過輸入管線追蹤。 使用手部互動,裝置可以自動辨識點選和按住手勢,但無法辨識其他手勢。 它們的名稱為 OpenXRMsftHandInteraction Select 和 Grip 對應。 您不需要啟用訂用帳戶,您應該在 Project 設定/Engine/Input 中宣告事件,如下所示:
您可以在 Windows Mixed Reality Spatial Input 底下找到 Blueprint 函式,以及在您的呼叫程式代碼檔案中新增 WindowsMixedRealitySpatialInputFunctionLibrary.h
C++ 函式。
列舉
藍圖:
C++:
enum class ESpatialInputAxisGestureType : uint8
{
None = 0,
Manipulation = 1,
Navigation = 2,
NavigationRails = 3
};
函式
您可以使用 函式來啟用和停用手勢擷 CaptureGestures
取。 開啟的手勢引發輸入事件時,函式會在 true
手勢擷取成功時傳回,如果 false
發生錯誤,則傳回 。
藍圖:
C++:
static bool UWindowsMixedRealitySpatialInputFunctionLibrary::CaptureGestures(
bool Tap = false,
bool Hold = false,
ESpatialInputAxisGestureType AxisGesture = ESpatialInputAxisGestureType::None,
bool NavigationAxisX = true,
bool NavigationAxisY = true,
bool NavigationAxisZ = true);
以下是您可以在藍圖和 C++ 中找到的重要事件:
const FKey FSpatialInputKeys::TapGesture(TapGestureName);
const FKey FSpatialInputKeys::DoubleTapGesture(DoubleTapGestureName);
const FKey FSpatialInputKeys::HoldGesture(HoldGestureName);
const FKey FSpatialInputKeys::LeftTapGesture(LeftTapGestureName);
const FKey FSpatialInputKeys::LeftDoubleTapGesture(LeftDoubleTapGestureName);
const FKey FSpatialInputKeys::LeftHoldGesture(LeftHoldGestureName);
const FKey FSpatialInputKeys::RightTapGesture(RightTapGestureName);
const FKey FSpatialInputKeys::RightDoubleTapGesture(RightDoubleTapGestureName);
const FKey FSpatialInputKeys::RightHoldGesture(RightHoldGestureName);
const FKey FSpatialInputKeys::LeftManipulationGesture(LeftManipulationGestureName);
const FKey FSpatialInputKeys::LeftManipulationXGesture(LeftManipulationXGestureName);
const FKey FSpatialInputKeys::LeftManipulationYGesture(LeftManipulationYGestureName);
const FKey FSpatialInputKeys::LeftManipulationZGesture(LeftManipulationZGestureName);
const FKey FSpatialInputKeys::LeftNavigationGesture(LeftNavigationGestureName);
const FKey FSpatialInputKeys::LeftNavigationXGesture(LeftNavigationXGestureName);
const FKey FSpatialInputKeys::LeftNavigationYGesture(LeftNavigationYGestureName);
const FKey FSpatialInputKeys::LeftNavigationZGesture(LeftNavigationZGestureName);
const FKey FSpatialInputKeys::RightManipulationGesture(RightManipulationGestureName);
const FKey FSpatialInputKeys::RightManipulationXGesture(RightManipulationXGestureName);
const FKey FSpatialInputKeys::RightManipulationYGesture(RightManipulationYGestureName);
const FKey FSpatialInputKeys::RightManipulationZGesture(RightManipulationZGestureName);
const FKey FSpatialInputKeys::RightNavigationGesture(RightNavigationGestureName);
const FKey FSpatialInputKeys::RightNavigationXGesture(RightNavigationXGestureName);
const FKey FSpatialInputKeys::RightNavigationYGesture(RightNavigationYGestureName);
const FKey FSpatialInputKeys::RightNavigationZGesture(RightNavigationZGestureName);
下一個開發檢查點
依循我們配置的 Unreal 開發旅程,此時您會探索 MRTK核心建置組塊。 接下來,您可以繼續進行下一個建置組塊:
或者,直接跳到混合實境平台功能和 API 的主題:
您可以隨時回到 Unreal 開發檢查點。