手部追蹤示例
這(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手部追蹤。 |
示例工作原理(lǐ)
當打開示例後,用(yòng)戶将手放在頭顯相機的(de)視野中時(shí),手部追蹤功能将啓動。用(yòng)戶将看到每隻手的(de)網格模型。如果手部追蹤被激活爲輸入模式,場(chǎng)景中的(de)3D對(duì)象将變得(de)可(kě)交互。根據選擇的(de)交互選項,場(chǎng)景中會生成不同的(de)可(kě)交互對(duì)象。
下(xià)圖展示了(le)手部網格模型。
手部追蹤
該示例使用(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)或停止手部追蹤。
手部網格的(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é)旋轉信息。
要獲取手部關節的(de)變換,可(kě)以使用(yòng) GetKeypointStateForAHand 函數。GetKeypointStateForAHand 函數的(de)參數包括 EControllerHand 和(hé) EHandKeypoint,其中 EControllerHand 指定手部(右手或左手),EHandKeypoint 指定關節。該函數會返回一個(gè)布爾值,表示是否找到該手部關節。
手部網格
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)。
可(kě)以使用(yòng) GetObjectClassification 函數來(lái)檢查對(duì)象的(de)分(fēn)類。
警告! 在 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)。 |
警告! 在藍圖節點中,Unreal Engine 會将參數作爲返回值進行引用(yòng)。必須同時(shí)傳遞手部網格表示的(de)演員(yuán)引用(yòng)和(hé)頂點數量的(de)變量,否則可(kě)能會創建多(duō)個(gè)Actor。 |
手勢
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)。
手勢數據包括以下(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)檢測結果。
手勢跟蹤交互
本節解釋了(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)。
警告! 在将此演員(yuán)添加到場(chǎng)景中或生成之前,請務必檢查手勢跟蹤是否可(kě)用(yòng)。 |
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)狀态。
空間手勢交互
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é)捏合手勢。
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)交互狀态。
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)代碼示例)。
此組件的(de)一個(gè)使用(yòng)示例是 BP_SpacesHandInteractableCube 藍圖演員(yuán),位于插件文件夾 SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > HandTracking > Placeable > InteractableObjects 中。
空間捕捉
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à)圖所示。
警告! 在将此組件用(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)捏合手勢與交互箱進行交互。