Реализуйте поведение типа перекрестия в RealityKit

Чего я хочу добиться: прикрепить сферу к положению камеры (чтобы она всегда оставалась в центре экрана при перемещении устройства) и определять, когда она находится поверх других объектов AR - чтобы запускать другие действия / поведение на объектах AR.

Подход: я создал сферу и прикрепил ее к центру экрана, как показано ниже.

@IBOutlet var arView: ARView!

override func viewDidLoad() {
    super.viewDidLoad()

    let mesh = MeshResource.generateSphere(radius: 0.1)
    let sphere = ModelEntity(mesh: mesh)

    let anchor = AnchorEntity(.camera)

    sphere.setParent(anchor)
    arView.scene.addAnchor(anchor)

    sphere.transform.translation.z = -0.75
}

Следующий шаг: проведите хит-тест или raycast in session(_:didUpdate:)

 let results = arView.hitTest(CGPoint(x: 0.5, y: 0.5), query: .all, mask: .default)
//normalised center ; 2D position of the camera (our sphere) in the view’s coordinate system

Но благодаря такому подходу я постоянно получаю наземный самолет. Есть ли что-то, чего мне не хватает, или есть другой подход к достижению этого?

Примечание. На случай, если что-то не так, я создал свою базовую сцену, так как я хочу отслеживать изображение и добавлять контент поверх маркера изображения в Reality Composer, а использование .rcproject в Xcode также имеет включено свойство столкновения для всех наложенных элементов.


person anahom    schedule 20.01.2021    source источник
comment
Есть ли у ваших объектов CollisionComponent? В документации для hitTest говорится, что он игнорирует объекты, у которых его нет.   -  person EmilioPelaez    schedule 20.01.2021
comment
Я вызвал entity.generateCollisionShapes(recursive: true), а также включил Physics- ›Collision shape в Reality Composer.   -  person anahom    schedule 20.01.2021


Ответы (1)


Попробуйте следующее решение:

import ARKit
import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    var sphere: ModelEntity?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = arView.center
        let results: [CollisionCastHit] = arView.hitTest(touch)
        
        if let result: CollisionCastHit = results.first {
            if result.entity.name == "Cube" && sphere?.isAnchored == true {
                print("BOOM!")
            }
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Crosshair
        let mesh01 = MeshResource.generateSphere(radius: 0.01)
        sphere = ModelEntity(mesh: mesh01)
        sphere?.transform.translation.z = -0.15
        let cameraAnchor = AnchorEntity(.camera)
        sphere?.setParent(cameraAnchor)
        arView.scene.addAnchor(cameraAnchor)
        
        // Model for collision
        let mesh02 = MeshResource.generateBox(size: 0.3)
        let box = ModelEntity(mesh: mesh02, materials: [SimpleMaterial()])
        box.generateCollisionShapes(recursive: true)
        box.name = "Cube"
        let planeAnchor = AnchorEntity(.plane(.any, 
                              classification: .any, 
                               minimumBounds: [0.2, 0.2]))
        box.setParent(planeAnchor)
        arView.scene.addAnchor(planeAnchor)
    }
}
person Andy Fedoroff    schedule 20.01.2021
comment
Привет, Энди, спасибо за быстрый ответ. Но это когда вы хотите проверить, нажали ли вы на куб. Я пытался добиться того, чтобы если в сцене уже есть сфера (размещенная в месте расположения камеры), я хочу проверить, пересекается ли в любой момент времени луч из положения сферы с кубом. Практически в любое время камера находится прямо (смотрит) на одной линии с кубом. Может быть, мой подход неверен, и есть лучший способ получить то, на что смотрит камера, и есть ли какой-либо объект AR на ее прямой проекции. Надеюсь, это проясняет мой вопрос - person anahom; 21.01.2021
comment
Огромное спасибо. Я просто пропустил touch = arView.center в приведенном выше коде, и он отлично работает. Еще раз спасибо! - person anahom; 21.01.2021