1

I want to create a sample application that allows the user to get information about continents on a globe when they tap on them. In order to do this, I need to figure out the location where a user taps on an SCNSphere object in a scene (SceneKit). I attempted to do it like this:

import UIKit
import SceneKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let scene = SCNScene()

        /* Lighting and camera added (hidden)*/

        let earthNode = SCNSphere(radius: 1)
        /* Added styling to the Earth (hidden)*/
        earthNode.name = "Earth"
        scene.rootNode.addChildNode(earthNode)

        let sceneView = self.view as! SCNView
        sceneView.scene = scene

        sceneView.allowsCameraControl = true

        // add a tap gesture recognizer
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        sceneView.addGestureRecognizer(tapGesture)

    }


    @objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
        // retrieve the SCNView
        let sceneView = self.view as! SCNView

        // check what nodes are tapped
        let p = gestureRecognize.location(in: scnView)
        let hitResults = sceneView.hitTest(p, options: [:])
        // check that we clicked on at least one object
        if hitResults.count > 0 {
            // retrieved the first clicked object
            let result: SCNHitTestResult = hitResults[0]

            print(result.node.name!)
            print("x: \(p.x) y: \(p.y)") // <--- THIS IS WHERE I PRINT THE COORDINATES


        }
    }

}

When I actually run this code however and click on an area on my sphere, it prints out the coordinates of the tap on the screen instead of where I tapped on the sphere. For example, the coordinates are the same when I tap on the center of the sphere, and when I tap it in the center again after rotating the sphere.

I want to know where on the actual sphere I pressed, not just where I click on the screen. What is the best way that I should go about this problem?

4

1 回答 1

4

在 hitResult 中,您可以获得 result.textureCoordinates,它会告诉您地图纹理中的点。从这一点开始,您应该知道地图的位置,因为地图应该具有映射到纹理的坐标。

 @objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
    // retrieve the SCNView
    let sceneView = self.view as! SCNView

    // check what nodes are tapped
    let p = gestureRecognize.location(in: scnView)
    let hitResults = sceneView.hitTest(p, options: [:])
    // check that we clicked on at least one object
    if hitResults.count > 0 {
        // retrieved the first clicked object
        let result: SCNHitTestResult = hitResults[0]

        print(result.node.name!)
        print(result.textureCoordinates(withMappingChannel 0)) // This line is added here. 
        print("x: \(p.x) y: \(p.y)") // <--- THIS IS WHERE I PRINT THE COORDINATES


    }
}
于 2019-01-28T21:26:12.500 回答