Unreal 中的手勢追蹤
手部追蹤系統使用人員的手掌和手指做為輸入。 每個手指的位置和旋轉資料、整個手掌和手部手勢皆可供使用。 從 Unreal 4.26 開始,手部追蹤是以 Unreal HeadMountedDisplay 外掛程式為基礎,並在所有 XR 平臺和裝置上使用通用 API。 Windows Mixed Reality和 OpenXR 系統的功能都相同。
手部姿勢
手部姿勢可讓您追蹤並使用使用者的手和手指做為輸入,這可在藍圖和 C++ 中存取。 Unreal API 會將資料當做座標系統傳送,並具有與 Unreal Engine 同步處理的刻度。
階層是由 EHandKeypoint
列舉所描述:
您可以使用 取得動作控制器資料 函式,從使用者的手上取得所有資料。 該函式會傳回 XRMotionControllerData 結構。 以下範例藍圖腳本會剖析 XRMotionControllerData 結構,以取得手部聯合位置,並在每個聯合的位置繪製偵錯座標系統。
請務必檢查結構是否有效,而且它是否為手部。 否則,您可能會在存取位置、旋轉和弧度陣列時取得未定義的行為。
列舉 EWMRHandKeypoint
描述手部的骨式階層。 您可以在藍圖中找到每個手部索引鍵:
完整的 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 Mixed Reality:
如果裝置上支援手部追蹤,而且 false
手部追蹤無法使用,則此函式會傳回 true
。
C++:
包含 WindowsMixedRealityHandTrackingFunctionLibrary.h
。
static bool UWindowsMixedRealityHandTrackingFunctionLibrary::SupportsHandTracking()
取得手部追蹤
您可以使用 GetHandJointTransform 從手部傳回空間資料。 資料會更新每個框架,但如果您位於框架內,則會快取傳回的值。 基於效能考慮,不建議在此函式中具有大量邏輯。
C++:
static bool UWindowsMixedRealityHandTrackingFunctionLibrary::GetHandJointTransform(EControllerHand Hand, EWMRHandKeypoint Keypoint, FTransform& OutTransform, float& OutRadius)
以下是 GetHandJointTransform 函式參數的明細:
- 手 – 可以是左側或右手的使用者。
- 索引鍵點 – 手部的骨頭。
- 轉換 – 骨基底的座標和方向。 您可以要求下一個骨頭的基底,以取得骨頭的轉換資料。 特殊的小費骨會提供一端的分離。
- **Radius— 根底的半徑。
- **傳回值—如果追蹤此框架的骨,則為 true,如果未追蹤骨狀,則為 false。
手部即時連結動畫
手部姿勢會使用 Live Link 外掛程式向動畫公開。
如果已啟用Windows Mixed Reality和 Live Link 外掛程式:
- 選取 [視窗 > 即時連結 ] 以開啟 [即時連結編輯器] 視窗。
- 選取[來源],然後啟用Windows Mixed Reality手部追蹤來源
啟用來源並開啟動畫資產之後,請展開[預覽場景] 索引標籤中的 [動畫] 區段,也會看到其他選項。
手部動畫階層與 中的 EWMRHandKeypoint
相同。 動畫可以使用 WindowsMixedRealityHandTrackingLiveLinkRemapAsset來重新設定目標:
它也可以在編輯器中子類別化:
手部網格
您必須使用 Microsoft OpenXR 外掛程式,才能從 Unreal Marketplace 或 GitHub取得。
手部網格做為追蹤幾何
重要
在 OpenXR 中以追蹤幾何的形式取得手網格需要您呼叫 設定使用手部網格 搭配 已啟用追蹤幾何。
若要啟用該模式,您應該呼叫 [設定使用手部網格 搭配 已啟用追蹤幾何]:
注意
這兩種模式都無法同時啟用。 如果您啟用其中一個,則會自動停用另一個。
存取手部網格資料
在您可以存取手部網格資料之前,您必須:
- 選取您的 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 元件新增至藍圖動作專案
- 移至 [詳細資料] 面板,然後展開 [ 事件] 區段。
- 在 [新增/更新/移除追蹤幾何] 上覆寫事件圖形中的下列節點:
OpenXR 中的手部網格視覺效果
視覺化手網格的建議方式是搭配 Microsoft OpenXR 外掛程式使用 Epic 的 XRVisualization 外掛程式。
然後在藍圖編輯器中,您應該使用 Microsoft OpenXR 外掛程式中的Set Use Hand Mesh函式搭配Enabled XRVisualization做為參數:
若要管理轉譯程式,您應該使用 XRVisualization 的 轉譯動作控制器 :
結果:
如果您需要更複雜的專案,例如使用自訂著色器繪製手部網格,您需要取得網格做為追蹤幾何。
手部光線 (Hand Ray)
取得手部姿勢適用于關閉互動,例如抓取物件或按下按鈕。 不過,有時候您需要使用離使用者遠的全像投影。 這可以使用手部光線來完成,這可用於 C++ 和藍圖中的指向裝置。 您可以從手部繪製光線到遠點,並透過 Unreal 光線追蹤的一些協助,選取不達的全像投影。
重要
由於所有函式都會變更每個畫面格,因此所有函式都會變成可呼叫。 如需純函式和不精確或可呼叫函式的詳細資訊,請參閱藍圖使用者 guid on 函式。
若要取得手部光線的資料,您應該使用上一節的取得動作控制器資料函式。 傳回的結構包含兩個參數,可用來建立手部光線 – Aim Position 和 Aim Rotation。 這些參數會形成由您的手部導向的光線。 您應該加以擷取,並找出所指向的全像投影。
以下是判斷手部光線是否叫用小工具,以及設定自訂點擊結果的範例:
若要在藍圖中使用手部光線,請在[Windows Mixed Reality HMD] 底下搜尋任何動作:
若要以 C++ 存取它們,請包含在 WindowsMixedRealityFunctionLibrary.h
呼叫程式碼檔案的頂端。
列舉
您也可以存取 EHMDInputControllerButtons下的輸入案例,其可用於藍圖:
若要在 C++ 中存取,請使用 EHMDInputControllerButtons
列舉類別:
enum class EHMDInputControllerButtons : uint8
{
Select,
Grasp,
//......
};
以下是兩個適用列舉案例的明細:
- 選取 - 使用者觸發的 Select 事件。
- 透過空中點選、注視和認可,或在啟用語音輸入時說出「選取」,以在HoloLens 2中觸發。
- 擷取 - 使用者觸發了「擷取」事件。
- 關閉全像投影上的使用者手指,以在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,則會傳回Select Pressed。
藍圖:
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 對應。 您不需要啟用訂用帳戶,您應該在 [專案設定]/[引擎/輸入] 中宣告事件,如下所示:
您可以在[Windows Mixed Reality空間輸入] 底下找到 [藍圖] 函式,以及在您的呼叫程式碼檔案中新增 WindowsMixedRealitySpatialInputFunctionLibrary.h
C++ 函式。
列舉
藍圖:
C++:
enum class ESpatialInputAxisGestureType : uint8
{
None = 0,
Manipulation = 1,
Navigation = 2,
NavigationRails = 3
};
函式
您可以使用 函式來啟用和停用手勢擷 CaptureGestures
取。 當啟用的手勢引發輸入事件時,如果手勢擷取成功,則函式會傳回 ,如果 false
發生錯誤,則傳回 true
。
藍圖:
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 開發檢查點。