ARSCNView 中的平滑对象旋转

Smooth object rotation in ARSCNView

在 AR 中旋转 3d 对象时,我试图使我的平移手势与 jigspace 应用程序一样流畅。这是我现在拥有的:

@objc func rotateObject(sender: UIPanGestureRecognizer) {

    let sceneView = sender.view as! ARSCNView
    var currentAngleY: Float = 0.0

    let translation = sender.translation(in: sceneView)
    var newAngleY = Float(translation.x)*Float(Double.pi)/180

    sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in

        if sender.state == .changed {
            newAngleY -= currentAngleY
            node.eulerAngles.y = newAngleY
        } else if sender.state == .ended {
            currentAngleY = newAngleY
            node.removeAllActions()
        }
    }
}

我在使用它时似乎有延迟,我正在尝试弄清楚如何使旋转尽可能平滑,同样,有点像 jigspace 或宜家应用程序。

我还注意到,当我尝试旋转某个角度的对象时,它会变得很尴尬。

查看您的旋转对象函数,似乎有些逻辑不太正确。

首先,我认为 var currentAngleY: Float = 0 应该在函数体之外。

其次,您应该将 currentAngleY 添加到 newAngleY 变量,例如:

/// Rotates The Models On Their YAxis
///
/// - Parameter gesture: UIPanGestureRecognizer
@objc func rotateModels(_ gesture: UIPanGestureRecognizer) {

    let translation = gesture.translation(in: gesture.view!)
    var newAngleY = (Float)(translation.x)*(Float)(Double.pi)/180.0
    newAngleY += currentAngleY

    DispatchQueue.main.async {
        self.sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
            node.eulerAngles.y = newAngleY

        }
    }

    if(gesture.state == .ended) { currentAngleY = newAngleY }

}

因此,在工作环境中的一个例子如下:

 class ViewController: UIViewController {

    @IBOutlet var augmentedRealityView: ARSCNView!

    var currentAngleY: Float = 0

    //-----------------------
    // MARK: - View LifeCycle
    //-----------------------

    override func viewDidLoad() {
        super.viewDidLoad()

        //1. Generate Our Three Box Nodes
        generateBoxNodes()

        //2. Create Our Rotation Gesture
        let rotateGesture = UIPanGestureRecognizer(target: self, action: #selector(rotateModels(_:)))
        self.view.addGestureRecognizer(rotateGesture)

        //3. Run The Session
        let configuration = ARWorldTrackingConfiguration()
        augmentedRealityView.session.run(configuration)
    }


    //------------------------
    // MARK: - Node Generation
    //------------------------

    /// Generates Three SCNNodes With An SCNBox Geometry
    func generateBoxNodes(){

        //1. Create An Array Of Colours For Each Face
        let colours: [UIColor] = [.red, .green, .blue, .purple, .cyan, .black]

        //2. Create An SCNNode Wih An SCNBox Geometry
        let boxNode = SCNNode()
        let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.01)
        boxNode.geometry = boxGeometry

        //3. Create A Different Material For Each Face
        var materials = [SCNMaterial]()

        for i in 0..<5{
            let faceMaterial = SCNMaterial()
            faceMaterial.diffuse.contents = colours[i]
            materials.append(faceMaterial)
        }

        //4. Set The Geometries Materials
        boxNode.geometry?.materials = materials

        //5. Create Two More Nodes By Cloning The First One
        let secondBox = boxNode.flattenedClone()
        let thirdBox = boxNode.flattenedClone()

        //6. Position Them In A Line & Add To The Scene
        boxNode.position = SCNVector3(-0.2, 0, -1.5)
        secondBox.position = SCNVector3(0, 0, -1.5)
        thirdBox.position = SCNVector3(0.2, 0, -1.5)

        self.augmentedRealityView.scene.rootNode.addChildNode(boxNode)
        self.augmentedRealityView.scene.rootNode.addChildNode(secondBox)
        self.augmentedRealityView.scene.rootNode.addChildNode(thirdBox)
    }

    //----------------------
    // MARK: - Node Rotation
    //----------------------

    /// Rotates The Models On Their YAxis
    ///
    /// - Parameter gesture: UIPanGestureRecognizer
    @objc func rotateModels(_ gesture: UIPanGestureRecognizer) {

        let translation = gesture.translation(in: gesture.view!)
        var newAngleY = (Float)(translation.x)*(Float)(Double.pi)/180.0
        newAngleY += currentAngleY

        DispatchQueue.main.async {
            self.augmentedRealityView.scene.rootNode.enumerateChildNodes { (node, _) in
                node.eulerAngles.y = newAngleY

            }
        }

        if(gesture.state == .ended) { currentAngleY = newAngleY }

    }

}

希望对您有所帮助...