Как определить, нажимает ли пользователь на объект, показанный на экране, с помощью ARKit - swift - PullRequest
0 голосов
/ 01 июля 2018

Я новое программирование iOS. Я хочу создать приложение, которое позволит пользователю нажимать на конкретный объект, который был показан на экране. Я использую addGestureRecognizer для объекта, который был показан, чтобы определить, был ли пользователь нажал, тогда я просто хочу добавить другой объект на экран.

Вот что я сделал до сих пор

objpizza = make2dNode(image:#imageLiteral(resourceName: "pizza"),width: 0.07,height: 0.07)
    objpizza.position = SCNVector3(0,0,-0.2)
    objpizza.name = "none"

    self.arView.addGestureRecognizer(UIGestureRecognizer(target: self, action: #selector(selectObject)))
    arView.scene.rootNode.addChildNode(objpizza)

Вот make2dNode функция просто настроить объект

func make2dNode(image: UIImage, width: CGFloat = 0.1, height: CGFloat = 0.1) -> SCNNode {
    let plane = SCNPlane(width: width, height: height)
    plane.firstMaterial!.diffuse.contents = image
    let node = SCNNode(geometry: plane)
    node.constraints = [SCNBillboardConstraint()]
    return node
}

Вот функция, которая никогда не вызывалась, когда я реализовал в self.arView.addGestureRecognizer(UIGestureRecognizer(target: self, action: #selector(selectObject)))

@objc func selectObject() {

    print("Image has been selected")
}

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Обнаружение касания на SCNNode требует большего, чем просто добавление UITapGestureRecogniser к вашему виду.

Чтобы определить, к какому SCNNode вы прикоснулись, вам нужно использовать SCNHitTest (в сочетании с вашим gestRecognizer), который:

Процесс поиска элементов сцены, расположенных по указанному точка или вдоль указанного отрезка (или луча).

An SCNHitTest ищет:

SCNGeometry объекты вдоль указанного вами луча. Для каждого пересечения между лучом и геометрией, SceneKit создает результат теста удара предоставить информацию как об объекте SCNNode, содержащем геометрия и расположение пересечения на геометрии поверхность.

Хорошо, вы могли бы подумать, но как это на самом деле работает в моем случае?

Хорошо, давайте начнем с создания узла SCNNode с геометрией SCNSphere и добавления его в нашу сцену.

//1. Create An SCNNode With An SCNSphere Geometry
let nodeOneGeometry = SCNSphere(radius: 0.2)

//2. Set It's Colour To Cyan
nodeOneGeometry.firstMaterial?.diffuse.contents = UIColor.cyan

//3. Assign The Geometry To The Node
nodeOne = SCNNode(geometry: nodeOneGeometry)

//4. Assign A Name For Our Node
nodeOne.name = "Node One"

//5. Position It & Add It To Our ARSCNView
nodeOne.position = SCNVector3(0, 0, -1.5)
augmentedRealityView.scene.rootNode.addChildNode(nodeOne)

Здесь вы заметите, что я назначил имя нашему SCNNode, это значительно облегчает его отслеживание (например, идентификацию с помощью hitTest).

Теперь мы добавили наш SCNNode в иерархию, давайте создадим UITapGestureRecognizer примерно так:

//1. Create A UITapGestureRecognizer & Add It To Our MainView
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(checkNodeHit(_:)))
tapGesture.numberOfTapsRequired = 1
self.view.addGestureRecognizer(tapGesture)

Теперь у нас есть все настройки, необходимые для создания нашей функции checkNodeHit, которая будет определять, к какому узлу подключился пользователь:

/// Runs An SCNHitTest To Check If An SCNNode Has Been Hit
///
/// - Parameter gesture: UITapGestureRecognizer
@objc func checkNodeHit(_ gesture: UITapGestureRecognizer){

    //1. Get The Current Touch Location In The View
    let currentTouchLocation = gesture.location(in: self.augmentedRealityView)

    //2. Perform An SCNHitTest To Determine If We Have Hit An SCNNode
    guard let hitTestNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return }

    if hitTestNode.name == "Node One"{

        print("The User Has Successfuly Tapped On \(hitTestNode.name!)")

    }
}

Теперь, если вы хотите разместить SCNNode там, где нажал пользователь, вы должны использовать вместо этого ARSCNHitTest, который обеспечивает:

Информация о реальной поверхности, найденная путем исследования точки в изображение камеры устройства сеанса AR.

После этого мы можем использовать свойство worldTransform нашего результата для размещения виртуального контента в этом месте.

Для вашей информации, worldTransform:

Положение и ориентация результата теста на удар относительно мировая система координат.

Позиционирование в ARKit можно легко визуализировать так:

enter image description here

Опять давайте посмотрим, как мы могли бы использовать это для размещения виртуального объекта:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location In Our ARSCNView & Perform An ARSCNHitTest For Any Viable Feature Points
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),
          let hitTest = self.augmentedRealityView.hitTest(currentTouchLocation, types: .featurePoint).first else { return }

    //2. Get The World Transform From The HitTest & Get The Positional Data From The Matrix (3rd Column)
    let worldPositionFromTouch = hitTest.worldTransform.columns.3

    //3. Create An SCNNode At The Touch Location
    let boxNode = SCNNode()
    let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
    boxGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
    boxNode.geometry = boxGeometry
    boxNode.position = SCNVector3(worldPositionFromTouch.x, worldPositionFromTouch.y, worldPositionFromTouch.z)

    //4. Add It To The Scene Hierachy
    self.augmentedRealityView.scene.rootNode.addChildNode(boxNode)

}

Надеюсь, это поможет ...

0 голосов
/ 01 июля 2018

Вам нужно реализовать

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(_:)))
arView.addGestureRecognizer(tapGesture)

Для функции идентифицирует, если пользователь нажал

@obj func didTap(_ gesture: UITabGestureRecognizer){ 
  object2 = make2Node(image: nameOfimage, width: 0.07, height: 0.07)
  object2.position = SCNVector(0,0,0.2)
  arView.scene.rootNode.addChildNode(object2)

Наслаждайся кодированием, братан.

...