Перетаскивание SCNNode в ARKit Использование SceneKit

У меня есть простой SCNNode в ARKit, и я пытаюсь перетащить его туда, куда я двигал пальцем по телефону. Вот мой код.

 @objc func pan(recognizer :UIGestureRecognizer) {

        guard let currentFrame = self.sceneView.session.currentFrame else {
            return
        }

        var translation = matrix_identity_float4x4
        translation.columns.3.z = -1.5

        let sceneView = recognizer.view as! ARSCNView
        let touchLocation = recognizer.location(in: sceneView)

        let hitTestResult = sceneView.hitTest(touchLocation, options: [:])

        if !hitTestResult.isEmpty {

            print("hit result")

            guard let hitResult = hitTestResult.first else {
                return
            }

            let node = hitResult.node

            node.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
        }
    }

Проблема в том, что перетаскивание происходит очень медленно и не является гладким.

Ответ 1

Я обрабатываю перевод с помощью PanGesture следующим образом. Деление на 700 состоит в том, чтобы сгладить и настроить скорость движения, я достиг этого значения путем проб или ошибок, вы можете поэкспериментировать с ним.

@objc func onTranslate(_ sender: UIPanGestureRecognizer) {
    let position = sender.location(in: scnView)
    let state = sender.state

    if (state == .failed || state == .cancelled) {
        return
    }

    if (state == .began) {
        // Check it on a virtual object
        if let objectNode = virtualObject(at: position) {
            // virtualObject(at searches for root node if it a subnode
            targetNode = objectNode
            latestTranslatePos = position
        }

    }
    else if let _ = targetNode {

        // Translate virtual object
        let deltaX = Float(position.x - latestTranslatePos!.x)/700
        let deltaY = Float(position.y - latestTranslatePos!.y)/700

        targetNode!.localTranslate(by: SCNVector3Make(deltaX, 0.0, deltaY))

        latestTranslatePos = position

        if (state == .ended) {
            targetNode = nil
        }
    }
}

Ответ 2

У меня была аналогичная проблема. В то время как вы должны использовать совет Джона в комментариях и использовать правильные состояния жесты (Начал, Изменен, Закончен), я думаю, проблема может заключаться в том, что вы захватываете hitResult.node, когда вы должны захватывать родительский элемент node, или даже родительский родитель и т.д. У меня была эта проблема, и я решил ее исправить, перейдя на родительские уровни, пока весь объект не будет выбран, а не его часть.

Ответ 3

Была такая же проблема. Использование SCNTransaction мне.

@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
    [...]

    SCNTransaction.begin()
    SCNTransaction.animationDuration = 0
    imagePlane.position.x = hitTestResult.localCoordinates.x
    imagePlane.position.y = hitTestResult.localCoordinates.y
    SCNTransaction.commit()
}