手部追蹤示例
這個示例演示了如何啓用(yòng)手部追蹤功能(néng),如何使用(yòng)SpacesHandTracking特性返回的數據,以及如何啓用(yòng)手部交互。要使用(yòng)這個功能(néng),必須在Snapdragon Spaces插件設置中(zhōng)啓用(yòng),路徑為(wèi):Project Settings > Snapdragon Spaces plugin.
警告! 請确保禁用(yòng)OpenXRHandTracking插件,以防标準的手部追蹤功能(néng)覆蓋Spaces手部追蹤。 |
示例工(gōng)作(zuò)原理(lǐ)
當打開示例後,用(yòng)戶将手放在頭顯相機的視野中(zhōng)時,手部追蹤功能(néng)将啓動。用(yòng)戶将看到每隻手的網格模型。如果手部追蹤被激活為(wèi)輸入模式,場景中(zhōng)的3D對象将變得可(kě)交互。根據選擇的交互選項,場景中(zhōng)會生成不同的可(kě)交互對象。
下圖展示了手部網格模型。
手部追蹤
該示例使用(yòng)了 BP_HandTrackingManager 藍圖資源(位于 SnapdragonSpacesSamples 内容 > SnapdragonSpaces > Samples > HandTracking > Placeable),用(yòng)于控制場景中(zhōng)不同的交互選項,包括遠(yuǎn)程交互和近程交互。
要啓用(yòng)或禁用(yòng)手部追蹤,必須使用(yòng) Toggle Spaces Feature 方法,并選擇手部追蹤作(zuò)為(wèi)要啓用(yòng)的功能(néng)。通過這種方法,可(kě)以在項目的某些部分(fēn)按需啓用(yòng)或停止手部追蹤。
手部網格的啓用(yòng)可(kě)以通過 Toggle AR Capture 方法,将捕獲類型設置為(wèi) Hand Meshing 來實現,也可(kě)以通過 Toggle Spaces Feature 方法來啓用(yòng)。
警告! 在 Snapdragon Spaces 版本 0.12.1 之前,手部網格的啓用(yòng)是通過 Set Hand Mesh Status 實現的,網格的可(kě)見性通過 Get Hand Mesh Status 方法來檢查狀态進行管理(lǐ)。 |
兩個手部以運動控制器的形式表示,數據可(kě)以通過 Get Motion Controller Data 方法來獲取,從而訪問手部關節的位置和旋轉信息。
要獲取手部關節的變換,可(kě)以使用(yòng) GetKeypointStateForAHand 函數。GetKeypointStateForAHand 函數的參數包括 EControllerHand 和 EHandKeypoint,其中(zhōng) EControllerHand 指定手部(右手或左手),EHandKeypoint 指定關節。該函數會返回一個布爾值,表示是否找到該手部關節。
手部網格
BP_HandMeshingViewer,位于 SnapdragonSpacesSamples 内容 > SnapdragonSpaces > Samples > HandTracking > Placeable,綁定了來自 AR Trackable Notify 組件的事件,以響應 AR 可(kě)追蹤幾何體(tǐ)的變化,并用(yòng)于渲染手部網格,它觸發 On Add/Update Tracked Geometry 事件,并且由于不同類型的對象可(kě)以被注冊為(wèi) UARTrackedGeometry,要驗證追蹤的幾何體(tǐ)是否是手部網格,必須檢查對象分(fēn)類是否為(wèi) EARObjectClassification::HandMesh,如果手部追蹤是輸入模式,BP_HandMeshingViewer 會在 BP_HandTrackingControllerComponent 中(zhōng)生成,并作(zuò)為(wèi)手部網格的渲染器使用(yòng)。
可(kě)以使用(yòng) GetObjectClassification 函數來檢查對象的分(fēn)類。
警告! 在 Snapdragon Spaces 0.13.0 版本之前,BP_HandMeshingViewer 并不存在,這項功能(néng)在 BP_HandTrackingManager 中(zhōng)實現。在 Snapdragon Spaces 0.12.1 版本之前,渲染手部網格的方法是使用(yòng) HGestures Blueprint Library 中(zhōng)的 Render Hand Mesh,該方法在 Snapdragon Spaces 0.13.0 版本中(zhōng)已被棄用(yòng)。 |
警告! 在藍圖節點中(zhōng),Unreal Engine 會将參數作(zuò)為(wèi)返回值進行引用(yòng)。必須同時傳遞手部網格表示的演員引用(yòng)和頂點數量的變量,否則可(kě)能(néng)會創建多(duō)個Actor。 |
手勢
WBP_HandTrackingSample(位于 SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > HandTracking > UI)曾用(yòng)于在手部網格和手部關節可(kě)視化之間切換,并顯示每幀識别的手勢。為(wèi)此,使用(yòng)了 HGestures Blueprint Library 類中(zhōng)的函數,每一幀中(zhōng)都會檢查雙手是否被跟蹤,以及正在執行的手勢,這是通過使用(yòng) Get XRHand Gesture Data 和 Is Hand Tracked 方法完成的。
手勢數據包括以下參數:
● Type: 枚舉值,表示檢測到的手勢類型。可(kě)能(néng)的手勢有(yǒu):{UNKNOWN, OPEN_HAND, GRAB, PINCH, ERROR}
● GestureRatio: 浮點值,範圍從 0 到 1,表示手勢的執行程度。
● FlipRatio: 浮點值,範圍從 -1 到 1,表示手勢是從背面(-1)、正面(1)還是介于兩者之間的位置檢測到的。
下圖展示了 UI 上顯示的左手手勢類型和比例的檢測結果。
手勢跟蹤交互
本節解釋了使用(yòng)手勢跟蹤交互所需的各種演員和組件。
警告! 手勢跟蹤交互不僅在手勢跟蹤示例中(zhōng)使用(yòng),還在項目中(zhōng)的所有(yǒu)示例中(zhōng)使用(yòng)。這使得用(yòng)戶能(néng)夠與支持手勢跟蹤的 UI 元素和 3D 元素進行交互。 |
Spaces 手勢輸入管理(lǐ)器
要使用(yòng)手勢跟蹤交互,這個演員是最關鍵的。為(wèi)了将手勢跟蹤設置為(wèi)輸入模式,需要将這個演員添加到場景中(zhōng),建議使用(yòng)“Spawn Actor of Class”節點來生成這個演員。
警告! 在将此演員添加到場景中(zhōng)或生成之前,請務(wù)必檢查手勢跟蹤是否可(kě)用(yòng)。 |
Spaces Hand Gesture Input Manager 演員負責實時監聽手勢,并通過委托報告基于這些手勢的動作(zuò)。它生成并擁有(yǒu)兩個 ASpacesHandInteraction 類的演員,每隻手一個,這些演員用(yòng)于執行交互。以下是該類中(zhōng)可(kě)用(yòng)的變量和函數:
變量
● FOnSpacesHandPinch OnSpacesHandPinchLeft 和 FOnSpacesHandPinch OnSpacesHandPinchRight:用(yòng)于通知捏合手勢狀态的委托。
● FOnSpacesHandOpen OnSpacesHandOpenLeft 和 FOnSpacesHandOpen OnSpacesHandOpenRight:用(yòng)于通知張開手勢狀态的委托。
● FOnSpacesHandGrab OnSpacesHandGrabLeft 和 FOnSpacesHandGrab OnSpacesHandGrabRight:用(yòng)于通知抓取手勢狀态的委托。
● FOnSpacesHandInteractionStatusUpdated OnSpacesHandInteractionStatusUpdated:用(yòng)于通知手部交互狀态更新(xīn)的委托,報告布爾值形式的狀态。
● TSubclassOf<ASpacesHandInteraction> HandInteractionClass:用(yòng)于生成手部交互演員的 Spaces Hand Interaction Actor 的子類。
● FVector LeftRayPositionOffset 和 FVector RightRayPositionOffset:兩個手部交互演員的射線(xiàn)偏移量。
● float RayDistance:兩個手部交互演員的射線(xiàn)距離。
函數
● ASpacesHandInteraction* GetHandLeftInteraction() const 和 ASpacesHandInteraction* GetHandRightInteraction() const:用(yòng)于獲取左手和右手的交互演員。
● void SetHandInteractionState(bool active):用(yòng)于啓用(yòng)或禁用(yòng)手部交互,該函數會影響整個手部交互系統。手部交互默認為(wèi)禁用(yòng)狀态。
● void GetHandInteractionState() const:返回手部交互系統的狀态。
空間手勢交互
Spaces Hand Interaction 演員負責與關卡中(zhōng)不同的可(kě)手部交互元素進行交互,例如 3D 小(xiǎo)部件和其他(tā)類型的演員。該演員支持遠(yuǎn)程手部交互(通過射線(xiàn)投射到場景元素上)和近程手部交互(當用(yòng)手觸摸可(kě)交互演員時激活)。Spaces Hand Interaction 演員會用(yòng)從用(yòng)戶指定的手部開始的射線(xiàn)來表示。射線(xiàn)在使用(yòng)近程交互時會變得不可(kě)見。射線(xiàn)有(yǒu)兩種交互模式:激活(當射線(xiàn)投射到場景中(zhōng)的任何可(kě)手部交互演員上時)和未激活。射線(xiàn)的顔色和長(cháng)度會根據這兩種模式發生變化。要與 UI 進行交互,請使用(yòng)遠(yuǎn)程交互和捏合手勢。
Spaces Hand Interaction actor 可(kě)以通過以下變量和函數進行自定義:
變量
● EControllerHand HandType:指定手是右手還是左手。
● FVector RayPositionOffset:調整射線(xiàn)的位置,它是從肩部位置的偏移量。
● float RayDistance:射線(xiàn)投射的距離(單位為(wèi)厘米)。
● float SnappingDistanceTolerance:在 Spaces Snapping Volume 組件上停止捕捉效果的距離。
● float DistalRayThresholdDistance:與聚焦的可(kě)交互對象的距離,這個距離決定了射線(xiàn)的可(kě)見性,從而切換近端和遠(yuǎn)端交互模式。
● float RayRepresentationLength:在使用(yòng)遠(yuǎn)端交互且未擊中(zhōng)任何可(kě)交互對象時射線(xiàn)的長(cháng)度。
● UStaticMesh* RayMesh:用(yòng)于視覺上表示手部射線(xiàn)的網格,這個網格将用(yòng)于 Unreal Engine Spline Mesh 組件。
● UMaterialInterface* RayMaterial:射線(xiàn)網格的材質(zhì),需要與 Unreal Engine Spline Mesh 組件兼容。
● FLinearColor HitRayColor:射線(xiàn)擊中(zhōng)可(kě)交互對象時的顔色。
● FLinearColor NoHitRayColor:射線(xiàn)未擊中(zhōng)可(kě)交互對象時的顔色。
● TSubclassOf<ASpacesHandJointCollider> HandJointColliderActorClass:用(yòng)于近端交互的 ASpacesHandJointCollider 的子類。建議使用(yòng)插件文(wén)件夾 SnapdragonSpaces > Content > HandTracking > Actors 中(zhōng)的 ASpacesHandJointCollider Blueprint 子類。
提示! 對于 Unreal Engine 的 Spline Mesh 組件,建議使用(yòng)中(zhōng)間幾何體(tǐ)足夠豐富的網格,這樣在有(yǒu)足夠的樣條點時可(kě)以實現彎曲效果。 要使材質(zhì)與 Spline Mesh 組件兼容,請确保材質(zhì)中(zhōng)的“用(yòng)于樣條網格”選項設置為(wèi)啓用(yòng)(可(kě)以在 Details > Usage 中(zhōng)找到該選項)。 |
函數
● FTransform GetGrabPointTransform() const:返回抓取點的變換。對于遠(yuǎn)端交互,将返回射線(xiàn)的端點;對于近端交互,将返回手部的變換。
● FTransform GetOffsetTransform() const:返回可(kě)交互對象與抓取變換之間的偏移變換。
● void SetHandInteractionState(bool active):啓用(yòng)或禁用(yòng)此演員的交互狀态。
Spaces手部交互
将此組件添加到參與物(wù)将使其可(kě)以與手部交互兼容,可(kě)以通過捏合和抓取手勢來抓取帶有(yǒu)此組件的參與物(wù),在遠(yuǎn)端交互模式下,僅支持平移操作(zuò);在近端交互模式下,支持平移、旋轉和縮放操作(zuò),其中(zhōng)縮放需要使用(yòng)雙手完成,可(kě)以調整以下變量來自定義其行為(wèi)。
變量
● float LerpFactor:調節演員的平移和旋轉速度。
● float ScaleLerpFactor:調節演員的縮放速度。
● float MinimumScaleFactor:演員可(kě)以應用(yòng)的最小(xiǎo)縮放因子。
● float MaximumScaleFactor:演員可(kě)以應用(yòng)的最大縮放因子。
● bool bApplyTranslation:指示是否對演員進行平移。
● bool bApplyRotation:指示是否對演員進行旋轉。
● bool bApplyScale:指示是否對演員進行縮放。
● FOnSpacesHandInteractableStateChanged OnSpacesHandInteractableStateChanged:委托/分(fēn)發器,用(yòng)于傳達手部交互在演員上的狀态,使用(yòng) ESpacesHandInteractableState 枚舉返回狀态(有(yǒu)關此枚舉的使用(yòng)方法,請參見下面的代碼示例)。
此組件的一個使用(yòng)示例是 BP_SpacesHandInteractableCube 藍圖演員,位于插件文(wén)件夾 SnapdragonSpacesSamples Content > SnapdragonSpaces > Samples > HandTracking > Placeable > InteractableObjects 中(zhōng)。
空間捕捉
Spaces Snapping Volume 組件繼承自 Unreal Engine 的 Box Component,它主要用(yòng)于将 SpacesHandInteraction 演員的射線(xiàn)端點捕捉到另一個演員的指定位置。這對于交互式 3D 小(xiǎo)部件(如按鈕、複選框或滑塊)特别有(yǒu)用(yòng),但也适用(yòng)于任何類型的 3D 演員。該組件可(kě)以添加到演員中(zhōng),并需要手動放置在所需位置,例如在 3D 小(xiǎo)部件的按鈕上,如下圖所示。
警告! 在将此組件用(yòng)于 UI 時,必須遵循以下指南: ● 盒子的定位和大小(xiǎo)必須與 3D 小(xiǎo)部件組件的形狀一緻,否則可(kě)能(néng)會出現不期望的效果,例如射線(xiàn)投射到 3D 小(xiǎo)部件演員之外時出現閃爍。 ● 組件的 X 軸方向必須與 3D 小(xiǎo)部件組件的方向對齊,以确保能(néng)正确與小(xiǎo)部件組件進行交互。 |
要自定義此組件的行為(wèi),可(kě)以使用(yòng)不同的變量和函數。
變量
● bool bSnap:決定組件是否用(yòng)于捕捉。如果不啓用(yòng)捕捉,組件仍可(kě)以用(yòng)于其他(tā)用(yòng)途,例如 3D 小(xiǎo)部件的滑塊,在這種情況下,雖然無法将射線(xiàn)的端點捕捉到滑塊手柄上,但仍然需要可(kě)視化手部射線(xiàn)以提升用(yòng)戶體(tǐ)驗。
● bool bIsUI:當組件用(yòng)于 3D 小(xiǎo)部件 UI 組件的交互時,必須啓用(yòng)此選項。對于其他(tā)演員,可(kě)以禁用(yòng)此選項。
● bool bIsDisabled:決定組件的碰撞是否從一開始就處于激活狀态,默認情況下為(wèi) false。
函數
● void SetCollisionDisabledState(bool disabled):設置 bIsDisabled 的值。
● void UpdateCollisionStatus(bool active):更新(xīn)組件的碰撞狀态。如果 bIsDisabled 為(wèi) true,無論函數的輸入值如何,碰撞都會被禁用(yòng)。
空間遠(yuǎn)端交互盒
BP_SpacesDistalInteractionBox 允許通過遠(yuǎn)端交互來旋轉和縮放參與物(wù),要使用(yòng)它,必須将其作(zuò)為(wèi)子參與物(wù)組件添加到要操作(zuò)的參與物(wù)中(zhōng)。可(kě)以在 SnapdragonSpaces Content > Hand Tracking > Actors 下找到 BP_SpacesDistalInteractionBox。有(yǒu)關如何将 BP_SpacesDistalInteractionBox 添加到另一個演員的示例,請查看 BP_PandaInteractable ,位于 SnapdragonSpacesSamples Content > Snapdragon Spaces > Samples > HandTracking > Placeable > InteractableObjects 中(zhōng)。遠(yuǎn)端交互箱由多(duō)個 Spaces Distal Manipulator Actor 實例組成,每個實例被稱為(wèi)“操作(zuò)點”。Spaces Distal Manipulator Actor 有(yǒu)兩種類型:Spaces Distal Scale Point 和 Spaces Distal Rotation Point。不同的操作(zuò)點在箱體(tǐ)中(zhōng)的位置不同,具(jù)有(yǒu)不同的行為(wèi),位于箱體(tǐ)邊緣的操作(zuò)點用(yòng)于調整演員的縮放,其餘操作(zuò)點用(yòng)于執行不同的旋轉操作(zuò),具(jù)體(tǐ)旋轉軸(X、Y 或 Z 平面)取決于操作(zuò)點在箱體(tǐ)中(zhōng)的位置。請使用(yòng)捏合手勢與交互箱進行交互。