2016-10-08 10 views
0

SceneKitを使用してビルボードクワッドを作成しました。 cameraNodeはUIDeviceMotionと同期されており、予想通りにビルボードノードが表示されます。 事は、私はそれをタップすると、これらのノードを呼び出すことです。 このため、私はhitTestでUITapGestureRecognizerを使用しました。 ここに私のコードのいくつかがあります。SceneKit:ビルボードのクワッドでヒットテストが動作しない

// ==== in viewDidLoad 

// initialize tap gesture 
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onNodeTapped)) 
    sceneView.addGestureRecognizer(tapGesture) 

// initialize scenekit.scene 
let scene = SCNScene() 
scene.rootNode.addChildNode(cameraNode) 
scene.rootNode.addChildNode(worldNode) 
sceneView.scene = scene 
sceneView.autoenablesDefaultLighting = true 
sceneView.pointOfView = cameraNode 

そして、これは、このコードは非常にrarly作品タップハンドラ

func onNodeTapped(_ gestureRecognize: UIGestureRecognizer) { 
    let location = gestureRecognize.location(in: sceneView) // <---- updated 
    let hitResults = sceneView.hitTest(location, options: nil) 
    for result in hitResults { 
     // FOR_TEST: hit test visualization 
     if let material = result.node.geometry?.materials.first { 
      SCNTransaction.begin() 
      SCNTransaction.animationDuration = 0.5 
      SCNTransaction.completionBlock = { 
       SCNTransaction.begin() 
       SCNTransaction.animationDuration = 0.5 
       material.emission.contents = UIColor.black 
       SCNTransaction.commit() 
      } 
      material.emission.contents = UIColor.red 
      SCNTransaction.commit() 
     } 

     // target tap event handling 
     if let target = (result.node as? TargetNode)?.target { 
      if onTargetTapped(target) { 
       return 
      } 
     } 
    } 
} 

です。私が意味するのは、視覚化部分が20回のうち1回だけに反応し、onTargetTappedが100回のうち1回だけ呼び出されるということです。 微妙なことはターゲット設定が問題です。

SCNHitTestOption.categoryBitMaskに関連するものが見つかりましたが、それはまったく役に立たなかった。

また、このScenviewを開くと、このエラーメッセージがコンソールに表示されます。 「[SceneKit]エラー:_C3DUnProjectPointsでエラーが発生しました」 このメッセージは、hitTestの機能不全に関連している可能性がありますか?このコードは、看板SCNGeometryとSCNNode

override func initializeGeometry() -> SCNGeometry { 
    let geometry = SCNPlane(width: width, height: height) 
    let material = geometry.materials.first 
    material?.diffuse.contents = initializeTexture() 
    material?.writesToDepthBuffer = false 
    material?.readsFromDepthBuffer = false 
    return geometry 
} 

// ====建物ノード

node = SCNNode() 
node.geometry = initializeGeometry() 
node.categoryBitMask = MyConstraints.targetNodeHitTestCategoryBitMask 
node.constraints = [SCNBillboardConstraint()] 
+0

看板を設定するコードは表示できますか? –

答えて

0

を構築するためにあなたが取得しているされて

を更新しました


annotationsDisplayViewのタップ座標ヒットテストルックアップのためにこれらの座標をsceneViewに渡します。これらのビューが正確に互いに重なるのでなければ、不一致が発生します。

私はあなたの代わりに

let location = gestureRecognize.location(in: sceneView) 

をしたいと思います。

ヒットテストでは回転版の広告板を使用するかどうか不思議でした。私はそれがそうであることを確認した。ここには動作中の(Mac)サンプルがあります。

override func mouseDown(with theEvent: NSEvent) { 
    /* Called when a mouse click occurs */ 

    // check what nodes are clicked 
    let p = self.convert(theEvent.locationInWindow, from: nil) 
    let hitResults = self.hitTest(p, options: [:]) 
    // check that we clicked on at least one object 
    if hitResults.count > 0 { 
     Swift.print("hit me") 
    } 
    for result in hitResults { 
     Swift.print(result.node.name) 

     // get its material 
     let material = result.node.geometry!.firstMaterial! 

     // highlight it 
     SCNTransaction.begin() 
     SCNTransaction.animationDuration = 0.5 

     // on completion - unhighlight 
     SCNTransaction.completionBlock = { 
      SCNTransaction.begin() 
      SCNTransaction.animationDuration = 0.5 

      material.emission.contents = NSColor.black 

      SCNTransaction.commit() 
     } 

     material.emission.contents = NSColor.yellow 

     SCNTransaction.commit() 
    } 

    super.mouseDown(with: theEvent) 
} 

とビューコントローラで:SCNViewサブクラスで

override func awakeFromNib(){ 
    super.awakeFromNib() 

    // create a new scene 
    let scene = SCNScene() 

    let side = CGFloat(2.0) 
    let quad1 = SCNNode.init(geometry: SCNPlane(width: side, height: side)) 
    quad1.name = "green" 
    quad1.geometry?.firstMaterial?.diffuse.contents = NSColor.green 

    let quad2 = SCNNode.init(geometry: SCNPlane(width: side, height: side)) 
    quad2.name = "red" 
    quad2.geometry?.firstMaterial?.diffuse.contents = NSColor.red 

    let quad3 = SCNNode.init(geometry: SCNPlane(width: side, height: side)) 
    quad3.name = "blue" 
    quad3.geometry?.firstMaterial?.diffuse.contents = NSColor.blue 

    scene.rootNode.addChildNode(quad1) 
    scene.rootNode.addChildNode(quad2) 
    scene.rootNode.addChildNode(quad3) 

    let rotation = CGFloat(M_PI_2) * 0.9 
    quad1.position.y = side/2 
    quad1.eulerAngles.y = rotation 

    quad2.position.x = side/2 
    quad2.eulerAngles.x = rotation 

    // comment out these constraints to verify that they matter 
    quad1.constraints = [SCNBillboardConstraint()] 
    quad2.constraints = [SCNBillboardConstraint()] 

    // create and add a camera to the scene 
    let cameraNode = SCNNode() 
    cameraNode.camera = SCNCamera() 
    scene.rootNode.addChildNode(cameraNode) 

    // place the camera 
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 15) 

    // create and add a light to the scene 
    let lightNode = SCNNode() 
    lightNode.light = SCNLight() 
    lightNode.light!.type = .omni 
    lightNode.position = SCNVector3(x: 0, y: 10, z: 10) 
    scene.rootNode.addChildNode(lightNode) 

    // create and add an ambient light to the scene 
    let ambientLightNode = SCNNode() 
    ambientLightNode.light = SCNLight() 
    ambientLightNode.light!.type = .ambient 
    ambientLightNode.light!.color = NSColor.darkGray 
    scene.rootNode.addChildNode(ambientLightNode) 

    // set the scene to the view 
    self.gameView!.scene = scene 

    // allows the user to manipulate the camera 
    self.gameView!.allowsCameraControl = true 

    // show statistics such as fps and timing information 
    self.gameView!.showsStatistics = true 

    // configure the view 
    self.gameView!.backgroundColor = NSColor.black 
} 
+0

答えをありがとう、 それはタイプミスでした。変更してもう一度やり直しても、まだ動作しません。 –

0

ヒットテストは、あなたのノードが看板拘束されたかどうか動作するはずです。それは私のためです。

override func viewDidLoad() { 
    self.sceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(_:)))) 
    ... 
} 

@objc func tap(_ recognizer: UITapGestureRecognizer) { 
    let loc = recognizer.location(in: self.sceneView) 
    if let hit = self.sceneView.hitTest(loc) { 
     ... 
    } 
} 
関連する問題