Convert SpatialEventGesture location3D to Entity

In my visionOS app I am attempting to get the location of a finger press (not a tap, but when the user first presses their fingers together). As far as I can tell, the only way to get this event is to use a SpatialEventGesture.

I've currently got a DragGesture and I am able to use the convert functions in the passed in EntityTargetValue to convert the location3D from the DragEvent to my hit tested entity. But as far as I can tell the SpatialEventGesture doesn't use an EntityTargetValue. I've tried using the convert functions in my targeted entity (ie, myEntity.convert(position: from:)) but these do not return valid values.

My questions are:

  1. Is SpatialEventGesture the correct way to get notified of finger presses?
  2. How do I convert the location3D in the SpatialEventGesture to my entity space?
Answered by Vision Pro Engineer in 803759022

Hi @KGraus

You can convert the location of a SpatialEventGesture to the same coordinate space as an entity by using the convert(_:from:to:) method either targetedToEntity(_:) or targetedToAnyEntity() provide you with.

For example, here's how you can use targetedToEntity(_:) with a SpatialTapGesture to convert its location3D to the coordinate space of your target entity:

.gesture(
    SpatialEventGesture()
        .targetedToEntity(targetEntity)
        .onChanged { events in
            for value in events.gestureValue {
                // Convert the location3D to entity space.
                let positionInEntitySpace = events.convert(value.location3D, from: .local, to: targetEntity.parent!)
                print("Position in entity space: \(positionInEntitySpace)")
                
                // You can also get the position of the "input device" (i.e. the fingers) performing the spatial event gesture.
                if let inputPosition = value.inputDevicePose?.pose3D.position {
                    // Convert the position to scene space.
                    let pressPositionInSceneSpace = events.convert(inputPosition, from: .local, to: .scene)
                    
                    // Determine which hand is performing the gesture.
                    if value.chirality == .right {
                        print("Right hand press position: \(pressPositionInSceneSpace)")
                    } else if value.chirality == .left {
                        print("Left hand press position: \(pressPositionInSceneSpace)")
                    }
                }
            }
        }
)

This snippet also demonstrates how to get the actual press position of the fingers in scene space, just in case that is also useful for you!

Accepted Answer

Hi @KGraus

You can convert the location of a SpatialEventGesture to the same coordinate space as an entity by using the convert(_:from:to:) method either targetedToEntity(_:) or targetedToAnyEntity() provide you with.

For example, here's how you can use targetedToEntity(_:) with a SpatialTapGesture to convert its location3D to the coordinate space of your target entity:

.gesture(
    SpatialEventGesture()
        .targetedToEntity(targetEntity)
        .onChanged { events in
            for value in events.gestureValue {
                // Convert the location3D to entity space.
                let positionInEntitySpace = events.convert(value.location3D, from: .local, to: targetEntity.parent!)
                print("Position in entity space: \(positionInEntitySpace)")
                
                // You can also get the position of the "input device" (i.e. the fingers) performing the spatial event gesture.
                if let inputPosition = value.inputDevicePose?.pose3D.position {
                    // Convert the position to scene space.
                    let pressPositionInSceneSpace = events.convert(inputPosition, from: .local, to: .scene)
                    
                    // Determine which hand is performing the gesture.
                    if value.chirality == .right {
                        print("Right hand press position: \(pressPositionInSceneSpace)")
                    } else if value.chirality == .left {
                        print("Left hand press position: \(pressPositionInSceneSpace)")
                    }
                }
            }
        }
)

This snippet also demonstrates how to get the actual press position of the fingers in scene space, just in case that is also useful for you!

Thank you for the reply!

Convert SpatialEventGesture location3D to Entity
 
 
Q