无法旋转我的3D对象

时间:2018-04-20 06:02:39

标签: rotation uigesturerecognizer scenekit arkit

我使用ARKit和SceneKit框架创建了一个项目。我正在使用文件扩展名.dae,文件在我的项目中是本地可用的,如下面的屏幕截图所示。

enter image description here

在这里,我在这个虚拟对象上应用了许多手势,例如Tap Gesture(当我点击相机屏幕时,它将虚拟对象放在那里),与Pinch Gesture和Pan Gesture相同。所有这些手势都完美无缺。现在我想应用旋转手势,为此我不知道如何做到这一点,我也没有得到任何这样的可用来源来实现这一点。

以下是我目前的工作代码,

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    private var movedObject: SCNNode?
    private var hud :MBProgressHUD!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.sceneView.autoenablesDefaultLighting = true
        sceneView.delegate = self
        sceneView.showsStatistics = true
        let scene = SCNScene()
        sceneView.scene = scene

        registerGestureRecognizers()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal

        // Run the view's session
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    }

    private func registerGestureRecognizers() {

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped(recognizer:)))
        tapGestureRecognizer.numberOfTapsRequired = 1
        self.sceneView.addGestureRecognizer(tapGestureRecognizer)

        let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(pinched(recognizer:)))
        self.sceneView.addGestureRecognizer(pinchGestureRecognizer)

        let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(moveObject(recognizer:)))
        panGestureRecognizer.maximumNumberOfTouches = 1
        panGestureRecognizer.minimumNumberOfTouches = 1
        self.sceneView.addGestureRecognizer(panGestureRecognizer)

        let rotationGestureRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(rotateObject(recognizer:)))
        self.sceneView.addGestureRecognizer(rotationGestureRecognizer)
    }

    @objc func pinched(recognizer :UIPinchGestureRecognizer) {

        if recognizer.state == .changed {

            guard let sceneView = recognizer.view as? ARSCNView else {
                return
            }
            let touch = recognizer.location(in: sceneView)
            let hitTestResults = self.sceneView.hitTest(touch, options: nil)
            if let hitTest = hitTestResults.first {
                let chairNode = hitTest.node
                let pinchScaleX = Float(recognizer.scale) * chairNode.scale.x
                let pinchScaleY = Float(recognizer.scale) * chairNode.scale.y
                let pinchScaleZ = Float(recognizer.scale) * chairNode.scale.z
                chairNode.scale = SCNVector3(pinchScaleX,pinchScaleY,pinchScaleZ)
                recognizer.scale = 1
            }
        }
    }

    @objc func moveObject(recognizer: UIPanGestureRecognizer) {
        print("Move object")
        if recognizer.state == .began {
            print("Pan state began")
            let tapPoint: CGPoint? = recognizer.location(in: sceneView)
            let result = sceneView.hitTest(tapPoint ?? CGPoint.zero, options: nil)
            if result.count == 0 {
                return
            }
            let hitResult: SCNHitTestResult? = result.first
            if (hitResult?.node.name == "free_car_1") {
                movedObject = hitResult?.node
            } else if (hitResult?.node.parent?.name == "free_car_1") {
                movedObject = hitResult?.node.parent
            }
            if (movedObject != nil) {
                print("Holding an Object")
            }
        }
        if recognizer.state == .changed {
            print("Pan State Changed")
            if (movedObject != nil) {
                let tapPoint: CGPoint? = recognizer.location(in: sceneView)
                let hitResults = sceneView.hitTest(tapPoint ?? CGPoint.zero, types: .featurePoint)
                let result: ARHitTestResult? = hitResults.last
                let matrix: SCNMatrix4 = SCNMatrix4((result?.worldTransform)!)
                //SCNMatrix4FromMat4((result?.worldTransform)!)
                let vector: SCNVector3 = SCNVector3Make(matrix.m41, matrix.m42, matrix.m43)
                movedObject?.position = vector
                print("Moving object position")
            }
        }
        if recognizer.state == .ended {
            print("Done moving object homeie")
            movedObject = nil
        }
    }

    @objc func tapped(recognizer :UITapGestureRecognizer) {

        guard let sceneView = recognizer.view as? ARSCNView else {
            return
        }
        let touch = recognizer.location(in: sceneView)
        let hitTestResults = sceneView.hitTest(touch)
        guard let hitTest = hitTestResults.first?.node else {
            let hitTestResultsWithExistingPlane = sceneView.hitTest(touch, types: .existingPlane)
            let chairScene = SCNScene(named: "ShelbyWD.dae")!
            guard let chairNode = chairScene.rootNode.childNode(withName:       "ShelbyWD", recursively: true) else {
                return
            }
            if let hitTestAvailable = hitTestResultsWithExistingPlane.first {
                chairNode.position = SCNVector3(hitTestAvailable.worldTransform.columns.3.x,hitTestAvailable.worldTransform.columns.3.y,hitTestAvailable.worldTransform.columns.3.z)
                self.sceneView.scene.rootNode.addChildNode(chairNode)
                return
            }
            return
        }
        hitTest.removeFromParentNode()
    }

    @objc func rotateObject(recognizer :UIRotationGestureRecognizer) 
    {

    }
}

有人可以帮助我在我的物体上应用旋转手势吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

为了旋转SCNNode,您需要做的第一件事就是创建一个变量来将rotationAngle存储在YAxis或您希望执行旋转的任何其他周围,例如:

var currentAngleY: Float = 0.0

然后有一些方法可以检测到你希望旋转的节点,在我的例子中我称之为currentNode,例如。

var currentNode: SCNNode!

在我的例子中,我将围绕YAxis旋转。

您可以像UIPanGestureRecognizer那样使用:

/// Rotates An Object On It's YAxis
///
/// - Parameter gesture: UIPanGestureRecognizer
@objc func rotateObject(_ gesture: UIPanGestureRecognizer) {

    guard let nodeToRotate = currentNode else { return }

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

    nodeToRotate.eulerAngles.y = newAngleY

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

    print(nodeToRotate.eulerAngles)
}

或者如果你想使用UIRotationGesture,你可以这样做:

/// Rotates An SCNNode Around It's YAxis
///
/// - Parameter gesture: UIRotationGestureRecognizer
@objc func rotateNode(_ gesture: UIRotationGestureRecognizer){

//1. Get The Current Rotation From The Gesture
let rotation = Float(gesture.rotation)

//2. If The Gesture State Has Changed Set The Nodes EulerAngles.y
if gesture.state == .changed{
    isRotating = true
    currentNode.eulerAngles.y = currentAngleY + rotation
}

//3. If The Gesture Has Ended Store The Last Angle Of The Cube
if(gesture.state == .ended) {
    currentAngleY = currentNode.eulerAngles.y
    isRotating = false
 }
}

希望它有所帮助...