How to convert a Point3D value obtained by a SpatialTapGesture to an Entity coordinate?

I have a visionOS app that displays a ModelEntity in a RealityView. This entity can be tapped by a SpatialTapGesture, and this gesture calls

	.onEnded { event in
		let point3D = event.location3D
		// …
	}

I am unable to convert point3D to the local coordinate of the entity.

I wrote a little test project to investigate the situation (below). The RealityView shows a box, I can tap the visible faces, and I get point3D values that don't make much sense to me. These values are presented here.

So, the main question is: How can I get the coordinate of the point tapped on the shown entity?

I used for SpatialTapGesture all 3 options for the coordinateSpace, .local, .global, and .immersive, without success. Here is my code:

struct ImmersiveView: View {

    var body: some View {
        RealityView { content in
            let mesh = MeshResource.generateBox(width: 1, height: 0.5, depth: 0.25, splitFaces: true)
            
            var frontMaterial = UnlitMaterial()
            frontMaterial.color.tint = .green
            var topMaterial = UnlitMaterial()
            topMaterial.color.tint = .red
            
            let boxEntity = ModelEntity(mesh: mesh, materials: [frontMaterial, topMaterial])
            boxEntity.components.set(InputTargetComponent(allowedInputTypes: .all))
            boxEntity.components[CollisionComponent.self] = CollisionComponent(shapes: [ShapeResource.generateConvex(from: mesh)])
            boxEntity.transform.translation = [0, 0, -3]
            
            content.add(boxEntity)
         }
        .gesture(tapGesture)
   }

    var tapGesture: some Gesture {
        SpatialTapGesture(coordinateSpace: .local)
            .targetedToAnyEntity()
            .onEnded { event in
                let point3D = event.location3D
                print(point3D)
            }
    }

}
Answered by DTS Engineer in 798447022

Hello @Reinhard_Maenner,

Your tap gesture's values are relative to the local coordinate space of the View, not the entity that was tapped. To get there, use convert(_:from:to:), for example:

let entity = value.entity

// Converts from the local space of the View this gesture is attached to the local coordinate space of the Entity that was tapped.
value.convert(value.location3D, from: .local, to: entity)

Best regards,

Greg

Hello @Reinhard_Maenner,

Your tap gesture's values are relative to the local coordinate space of the View, not the entity that was tapped. To get there, use convert(_:from:to:), for example:

let entity = value.entity

// Converts from the local space of the View this gesture is attached to the local coordinate space of the Entity that was tapped.
value.convert(value.location3D, from: .local, to: entity)

Best regards,

Greg

Thanks, Greg. Can you please say, how the parameter coordinateSpace in SpatialTapGesture influences the values obtained? I tried your solution with .local, .global, and .immersiveSpace, and obtained each time different coordinate values.

Hey @Reinhard_Maenner,

The coordinateSpace parameter of the gesture defines the coordinate space that the original value is delivered to you in. For example:

let entity = value.entity

// Converts from the local space of the View this gesture is attached to the local coordinate space of the Entity that was tapped.
value.convert(value.location3D, from: .local, to: entity)

Saying "from" .local here states that value.location3D is in the local coordinate space of the View, but that is only true if .local was used as the coordinateSpace of the gesture.

If the gesture returns values in .local space, then you convert from .local space. If gesture values are in .global space, then you convert from .global space.

How to convert a Point3D value obtained by a SpatialTapGesture to an Entity coordinate?
 
 
Q