在ARSCNView中平滑地旋转对象

时间:2018-07-06 20:22:47

标签: swift xcode scenekit arkit uipangesturerecognizer

在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或Ikea应用程序。

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

1 个答案:

答案 0 :(得分:0)

看看旋转对象函数,似乎某些逻辑不太正确。

首先,我认为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 }

    }

}

希望有帮助...