手部追蹤

手部追蹤示例

這(zhè)個(gè)示例演示了(le)如何啓用(yòng)手部追蹤功能,如何使用(yòng)SpacesHandTracking特性返回的(de)數據,以及如何啓用(yòng)手部交互。要使用(yòng)這(zhè)個(gè)功能,必須在Snapdragon Spaces插件設置中啓用(yòng),路徑爲:Project Settings > Snapdragon Spaces plugin.



警告!

請确保禁用(yòng)OpenXRHandTracking插件,以防标準的(de)手部追蹤功能覆蓋Spaces手部追蹤。

圖片6.png


示例工作原理(lǐ)

當打開示例後,用(yòng)戶将手放在頭顯相機的(de)視野中時(shí),手部追蹤功能将啓動。用(yòng)戶将看到每隻手的(de)網格模型。如果手部追蹤被激活爲輸入模式,場(chǎng)景中的(de)3D對(duì)象将變得(de)可(kě)交互。根據選擇的(de)交互選項,場(chǎng)景中會生成不同的(de)可(kě)交互對(duì)象。

 

下(xià)圖展示了(le)手部網格模型。


圖片7.png

 

手部追蹤

該示例使用(yòng)了(le) BP_HandTrackingManager 藍圖資源(位于 SnapdragonSpacesSamples 内容 > SnapdragonSpaces > Samples > HandTracking > Placeable),用(yòng)于控制場(chǎng)景中不同的(de)交互選項,包括遠(yuǎn)程交互和(hé)近程交互。

 

要啓用(yòng)或禁用(yòng)手部追蹤,必須使用(yòng) Toggle Spaces Feature 方法,并選擇手部追蹤作爲要啓用(yòng)的(de)功能。通(tōng)過這(zhè)種方法,可(kě)以在項目的(de)某些部分(fēn)按需啓用(yòng)或停止手部追蹤


圖片8.png


手部網格的(de)啓用(yòng)可(kě)以通(tōng)過 Toggle AR Capture 方法,将捕獲類型設置爲 Hand Meshing 來(lái)實現,也(yě)可(kě)以通(tōng)過 Toggle Spaces Feature 方法來(lái)啓用(yòng)。


警告!

在 Snapdragon Spaces 版本 0.12.1 之前,手部網格的(de)啓用(yòng)是通(tōng)過 Set Hand Mesh Status 實現的(de),網格的(de)可(kě)見性通(tōng)過 Get Hand Mesh Status 方法來(lái)檢查狀态進行管理(lǐ)。



兩個(gè)手部以運動控制器的(de)形式表示,數據可(kě)以通(tōng)過 Get Motion Controller Data 方法來(lái)獲取,從而訪問手部關節的(de)位置和(hé)旋轉信息。

 

圖片9.png

 

要獲取手部關節的(de)變換,可(kě)以使用(yòng) GetKeypointStateForAHand 函數。GetKeypointStateForAHand 函數的(de)參數包括 EControllerHand 和(hé) EHandKeypoint,其中 EControllerHand 指定手部(右手或左手),EHandKeypoint 指定關節。該函數會返回一個(gè)布爾值,表示是否找到該手部關節。

 

圖片10.png


手部網格

BP_HandMeshingViewer,位于 SnapdragonSpacesSamples 内容 > SnapdragonSpaces > Samples > HandTracking > Placeable,綁定了(le)來(lái)自 AR Trackable Notify 組件的(de)事件,以響應 AR 可(kě)追蹤幾何體的(de)變化(huà),并用(yòng)于渲染手部網格,它觸發 On Add/Update Tracked Geometry 事件,并且由于不同類型的(de)對(duì)象可(kě)以被注冊爲 UARTrackedGeometry,要驗證追蹤的(de)幾何體是否是手部網格,必須檢查對(duì)象分(fēn)類是否爲 EARObjectClassification::HandMesh,如果手部追蹤是輸入模式,BP_HandMeshingViewer 會在 BP_HandTrackingControllerComponent 中生成,并作爲手部網格的(de)渲染器使用(yòng)。

 

 圖片11.png


可(kě)以使用(yòng) GetObjectClassification 函數來(lái)檢查對(duì)象的(de)分(fēn)類。

 

圖片12.png


警告!

在 Snapdragon Spaces 0.13.0 版本之前,BP_HandMeshingViewer 并不存在,這(zhè)項功能在 BP_HandTrackingManager 中實現。在 Snapdragon Spaces 0.12.1 版本之前,渲染手部網格的(de)方法是使用(yòng) HGestures Blueprint Library 中的(de) Render Hand Mesh,該方法在 Snapdragon Spaces 0.13.0 版本中已被棄用(yòng)。

圖片13.png



警告!

在藍圖節點中,Unreal Engine 會将參數作爲返回值進行引用(yòng)。必須同時(shí)傳遞手部網格表示的(de)演員(yuán)引用(yòng)和(hé)頂點數量的(de)變量,否則可(kě)能會創建多(duō)個(gè)Actor。

   


圖片14.png


手勢

 

圖片15.png


WBP_HandTrackingSample(位于 SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > HandTracking > UI)曾用(yòng)于在手部網格和(hé)手部關節可(kě)視化(huà)之間切換,并顯示每幀識别的(de)手勢。爲此,使用(yòng)了(le) HGestures Blueprint Library 類中的(de)函數,每一幀中都會檢查雙手是否被跟蹤,以及正在執行的(de)手勢,這(zhè)是通(tōng)過使用(yòng) Get XRHand Gesture Data 和(hé) Is Hand Tracked 方法完成的(de)。

 

圖片16.png


手勢數據包括以下(xià)參數:

● Type: 枚舉值,表示檢測到的(de)手勢類型。可(kě)能的(de)手勢有:{UNKNOWN, OPEN_HAND, GRAB, PINCH, ERROR}

● GestureRatio: 浮點值,範圍從 0 到 1,表示手勢的(de)執行程度。

● FlipRatio: 浮點值,範圍從 -1 到 1,表示手勢是從背面(-1)、正面(1)還(hái)是介于兩者之間的(de)位置檢測到的(de)。

下(xià)圖展示了(le) UI 上顯示的(de)左手手勢類型和(hé)比例的(de)檢測結果。

 

圖片17.png

 

手勢跟蹤交互

本節解釋了(le)使用(yòng)手勢跟蹤交互所需的(de)各種演員(yuán)和(hé)組件。



警告!

手勢跟蹤交互不僅在手勢跟蹤示例中使用(yòng),還(hái)在項目中的(de)所有示例中使用(yòng)。這(zhè)使得(de)用(yòng)戶能夠與支持手勢跟蹤的(de) UI 元素和(hé) 3D 元素進行交互。



Spaces 手勢輸入管理(lǐ)器

要使用(yòng)手勢跟蹤交互,這(zhè)個(gè)演員(yuán)是最關鍵的(de)。爲了(le)将手勢跟蹤設置爲輸入模式,需要将這(zhè)個(gè)演員(yuán)添加到場(chǎng)景中,建議(yì)使用(yòng)“Spawn Actor of Class”節點來(lái)生成這(zhè)個(gè)演員(yuán)。

 

圖片28.png

 

警告!

在将此演員(yuán)添加到場(chǎng)景中或生成之前,請務必檢查手勢跟蹤是否可(kě)用(yòng)。

圖片19.png


Spaces Hand Gesture Input Manager 演員(yuán)負責實時(shí)監聽(tīng)手勢,并通(tōng)過委托報告基于這(zhè)些手勢的(de)動作。它生成并擁有兩個(gè) ASpacesHandInteraction 類的(de)演員(yuán),每隻手一個(gè),這(zhè)些演員(yuán)用(yòng)于執行交互。以下(xià)是該類中可(kě)用(yòng)的(de)變量和(hé)函數:

 

變量

● FOnSpacesHandPinch OnSpacesHandPinchLeft 和(hé) FOnSpacesHandPinch OnSpacesHandPinchRight:用(yòng)于通(tōng)知捏合手勢狀态的(de)委托。

● FOnSpacesHandOpen OnSpacesHandOpenLeft 和(hé) FOnSpacesHandOpen OnSpacesHandOpenRight:用(yòng)于通(tōng)知張開手勢狀态的(de)委托。

● FOnSpacesHandGrab OnSpacesHandGrabLeft 和(hé) FOnSpacesHandGrab OnSpacesHandGrabRight:用(yòng)于通(tōng)知抓取手勢狀态的(de)委托。

● FOnSpacesHandInteractionStatusUpdated OnSpacesHandInteractionStatusUpdated:用(yòng)于通(tōng)知手部交互狀态更新的(de)委托,報告布爾值形式的(de)狀态。

● TSubclassOf<ASpacesHandInteraction> HandInteractionClass:用(yòng)于生成手部交互演員(yuán)的(de) Spaces Hand Interaction Actor 的(de)子類。

● FVector LeftRayPositionOffset 和(hé) FVector RightRayPositionOffset:兩個(gè)手部交互演員(yuán)的(de)射線偏移量。

● float RayDistance:兩個(gè)手部交互演員(yuán)的(de)射線距離。


函數

● ASpacesHandInteraction* GetHandLeftInteraction() const 和(hé) ASpacesHandInteraction* GetHandRightInteraction() const:用(yòng)于獲取左手和(hé)右手的(de)交互演員(yuán)。

● void SetHandInteractionState(bool active):用(yòng)于啓用(yòng)或禁用(yòng)手部交互,該函數會影(yǐng)響整個(gè)手部交互系統。手部交互默認爲禁用(yòng)狀态。

● void GetHandInteractionState() const:返回手部交互系統的(de)狀态。

 

圖片20.png

 

空間手勢交互

Spaces Hand Interaction 演員(yuán)負責與關卡中不同的(de)可(kě)手部交互元素進行交互,例如 3D 小部件和(hé)其他(tā)類型的(de)演員(yuán)。該演員(yuán)支持遠(yuǎn)程手部交互(通(tōng)過射線投射到場(chǎng)景元素上)和(hé)近程手部交互(當用(yòng)手觸摸可(kě)交互演員(yuán)時(shí)激活)。Spaces Hand Interaction 演員(yuán)會用(yòng)從用(yòng)戶指定的(de)手部開始的(de)射線來(lái)表示。射線在使用(yòng)近程交互時(shí)會變得(de)不可(kě)見。射線有兩種交互模式:激活(當射線投射到場(chǎng)景中的(de)任何可(kě)手部交互演員(yuán)上時(shí))和(hé)未激活。射線的(de)顔色和(hé)長(cháng)度會根據這(zhè)兩種模式發生變化(huà)。要與 UI 進行交互,請使用(yòng)遠(yuǎn)程交互和(hé)捏合手勢。


圖片21.png


圖片22.png

 

Spaces Hand Interaction actor 可(kě)以通(tōng)過以下(xià)變量和(hé)函數進行自定義:


變量

●  EControllerHand HandType:指定手是右手還(hái)是左手。

●  FVector RayPositionOffset:調整射線的(de)位置,它是從肩部位置的(de)偏移量。

● float RayDistance:射線投射的(de)距離(單位爲厘米)。

● float SnappingDistanceTolerance:在 Spaces Snapping Volume 組件上停止捕捉效果的(de)距離。

● float DistalRayThresholdDistance:與聚焦的(de)可(kě)交互對(duì)象的(de)距離,這(zhè)個(gè)距離決定了(le)射線的(de)可(kě)見性,從而切換近端和(hé)遠(yuǎn)端交互模式。

● float RayRepresentationLength:在使用(yòng)遠(yuǎn)端交互且未擊中任何可(kě)交互對(duì)象時(shí)射線的(de)長(cháng)度。

● UStaticMesh* RayMesh:用(yòng)于視覺上表示手部射線的(de)網格,這(zhè)個(gè)網格将用(yòng)于 Unreal Engine Spline Mesh 組件

●  UMaterialInterface* RayMaterial:射線網格的(de)材質,需要與 Unreal Engine Spline Mesh 組件兼容

● FLinearColor HitRayColor:射線擊中可(kě)交互對(duì)象時(shí)的(de)顔色。

● FLinearColor NoHitRayColor:射線未擊中可(kě)交互對(duì)象時(shí)的(de)顔色。

● TSubclassOf<ASpacesHandJointCollider> HandJointColliderActorClass:用(yòng)于近端交互的(de) ASpacesHandJointCollider 的(de)子類。建議(yì)使用(yòng)插件文件夾 SnapdragonSpaces > Content > HandTracking > Actors 中的(de) ASpacesHandJointCollider Blueprint 子類。


提示!

對(duì)于 Unreal Engine 的(de) Spline Mesh 組件,建議(yì)使用(yòng)中間幾何體足夠豐富的(de)網格,這(zhè)樣在有足夠的(de)樣條點時(shí)可(kě)以實現彎曲效果。

要使材質與 Spline Mesh 組件兼容,請确保材質中的(de)“用(yòng)于樣條網格”選項設置爲啓用(yòng)(可(kě)以在 Details > Usage 中找到該選項)。

 

函數

●  FTransform GetGrabPointTransform() const:返回抓取點的(de)變換。對(duì)于遠(yuǎn)端交互,将返回射線的(de)端點;對(duì)于近端交互,将返回手部的(de)變換。

●  FTransform GetOffsetTransform() const:返回可(kě)交互對(duì)象與抓取變換之間的(de)偏移變換。

●  void SetHandInteractionState(bool active):啓用(yòng)或禁用(yòng)此演員(yuán)的(de)交互狀态。

 

圖片23.png

 

Spaces手部交互

将此組件添加到參與物(wù)将使其可(kě)以與手部交互兼容,可(kě)以通(tōng)過捏合和(hé)抓取手勢來(lái)抓取帶有此組件的(de)參與物(wù),在遠(yuǎn)端交互模式下(xià),僅支持平移操作;在近端交互模式下(xià),支持平移、旋轉和(hé)縮放操作,其中縮放需要使用(yòng)雙手完成,可(kě)以調整以下(xià)變量來(lái)自定義其行爲。


變量

●  float LerpFactor:調節演員(yuán)的(de)平移和(hé)旋轉速度。

●  float ScaleLerpFactor:調節演員(yuán)的(de)縮放速度。

●  float MinimumScaleFactor:演員(yuán)可(kě)以應用(yòng)的(de)最小縮放因子。

●  float MaximumScaleFactor:演員(yuán)可(kě)以應用(yòng)的(de)最大(dà)縮放因子。

●  bool bApplyTranslation:指示是否對(duì)演員(yuán)進行平移。

●  bool bApplyRotation:指示是否對(duì)演員(yuán)進行旋轉。

●  bool bApplyScale:指示是否對(duì)演員(yuán)進行縮放。

●  FOnSpacesHandInteractableStateChanged OnSpacesHandInteractableStateChanged:委托/分(fēn)發器,用(yòng)于傳達手部交互在演員(yuán)上的(de)狀态,使用(yòng) ESpacesHandInteractableState 枚舉返回狀态(有關此枚舉的(de)使用(yòng)方法,請參見下(xià)面的(de)代碼示例)。


圖片24.png

 

此組件的(de)一個(gè)使用(yòng)示例是 BP_SpacesHandInteractableCube 藍圖演員(yuán),位于插件文件夾 SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > HandTracking > Placeable > InteractableObjects 中。

 

圖片25.png

 

空間捕捉

Spaces Snapping Volume 組件繼承自 Unreal Engine 的(de) Box Component,它主要用(yòng)于将 SpacesHandInteraction 演員(yuán)的(de)射線端點捕捉到另一個(gè)演員(yuán)的(de)指定位置。這(zhè)對(duì)于交互式 3D 小部件(如按鈕、複選框或滑塊)特别有用(yòng),但也(yě)适用(yòng)于任何類型的(de) 3D 演員(yuán)。該組件可(kě)以添加到演員(yuán)中,并需要手動放置在所需位置,例如在 3D 小部件的(de)按鈕上,如下(xià)圖所示。

 

圖片26.png


警告!

在将此組件用(yòng)于 UI 時(shí),必須遵循以下(xià)指南(nán):

● 盒子的(de)定位和(hé)大(dà)小必須與 3D 小部件組件的(de)形狀一緻,否則可(kě)能會出現不期望的(de)效果,例如射線投射到 3D 小部件演員(yuán)之外時(shí)出現閃爍。

● 組件的(de) X 軸方向必須與 3D 小部件組件的(de)方向對(duì)齊,以确保能正确與小部件組件進行交互。

   

要自定義此組件的(de)行爲,可(kě)以使用(yòng)不同的(de)變量和(hé)函數。

 

變量

● bool bSnap:決定組件是否用(yòng)于捕捉。如果不啓用(yòng)捕捉,組件仍可(kě)以用(yòng)于其他(tā)用(yòng)途,例如 3D 小部件的(de)滑塊,在這(zhè)種情況下(xià),雖然無法将射線的(de)端點捕捉到滑塊手柄上,但仍然需要可(kě)視化(huà)手部射線以提升用(yòng)戶體驗。

● bool bIsUI:當組件用(yòng)于 3D 小部件 UI 組件的(de)交互時(shí),必須啓用(yòng)此選項。對(duì)于其他(tā)演員(yuán),可(kě)以禁用(yòng)此選項。

● bool bIsDisabled:決定組件的(de)碰撞是否從一開始就處于激活狀态,默認情況下(xià)爲 false。

 

函數

● void SetCollisionDisabledState(bool disabled):設置 bIsDisabled 的(de)值。

● void UpdateCollisionStatus(bool active):更新組件的(de)碰撞狀态。如果 bIsDisabled 爲 true,無論函數的(de)輸入值如何,碰撞都會被禁用(yòng)。

 

空間遠(yuǎn)端交互盒

BP_SpacesDistalInteractionBox 允許通(tōng)過遠(yuǎn)端交互來(lái)旋轉和(hé)縮放參與物(wù),要使用(yòng)它,必須将其作爲子參與物(wù)組件添加到要操作的(de)參與物(wù)中。可(kě)以在 SnapdragonSpaces Content > Hand Tracking > Actors 下(xià)找到 BP_SpacesDistalInteractionBox。有關如何将 BP_SpacesDistalInteractionBox 添加到另一個(gè)演員(yuán)的(de)示例,請查看 BP_PandaInteractable ,位于 SnapdragonSpacesSamples Content > Snapdragon Spaces > Samples > HandTracking > Placeable > InteractableObjects 中。遠(yuǎn)端交互箱由多(duō)個(gè) Spaces Distal Manipulator Actor 實例組成,每個(gè)實例被稱爲“操作點”。Spaces Distal Manipulator Actor 有兩種類型:Spaces Distal Scale Point 和(hé) Spaces Distal Rotation Point。不同的(de)操作點在箱體中的(de)位置不同,具有不同的(de)行爲,位于箱體邊緣的(de)操作點用(yòng)于調整演員(yuán)的(de)縮放,其餘操作點用(yòng)于執行不同的(de)旋轉操作,具體旋轉軸(X、Y 或 Z 平面)取決于操作點在箱體中的(de)位置。請使用(yòng)捏合手勢與交互箱進行交互。

 

圖片27.png