【问题标题】:How can I rotate and scale an ARKit model using gestures?如何使用手势旋转和缩放 ARKit 模型?
【发布时间】:2020-10-03 10:16:15
【问题描述】:

我正在尝试像this video 一样旋转和缩放 ARKit 模型:

这是我的代码:

添加手势:

let tapGesure = UITapGestureRecognizer(target: self, action: #selector(handleTap))
sceneView.addGestureRecognizer(tapGesure)

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(moveNode(_:)))
self.view.addGestureRecognizer(panGesture)

let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotateNode(_:)))
self.view.addGestureRecognizer(rotateGesture)

下面是对应的方法:

点击手势:

// MARK: - Gesture Recognizers
@objc func handleTap(gesture: UITapGestureRecognizer) {

    let location = gesture.location(in: sceneView)
    guard let hitTestResult = sceneView.hitTest(location, types: .existingPlane).first else { return }
    let position = SCNVector3Make(hitTestResult.worldTransform.columns.3.x,
                                  hitTestResult.worldTransform.columns.3.y,
                                  hitTestResult.worldTransform.columns.3.z)
    addFoodModelTo(position: position)
}

UIPanGestureRecognizer平移手势:

@objc func moveNode(_ gesture: UIPanGestureRecognizer) {

    if !isRotating {

        //1. Get The Current Touch Point
        let currentTouchPoint = gesture.location(in: self.sceneView)

        //2. Get The Next Feature Point Etc
        guard let hitTest = self.sceneView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }

        //3. Convert To World Coordinates
        let worldTransform = hitTest.worldTransform

        //4. Set The New Position
        let newPosition = SCNVector3(worldTransform.columns.3.x, worldTransform.columns.3.y, worldTransform.columns.3.z)

        //5. Apply To The Node
        baseNode.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)  
    }
}

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
            baseNode.eulerAngles.y = currentAngleY + rotation
        }

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

但它不起作用。我做错了什么?

【问题讨论】:

    标签: ios swift augmented-reality scenekit arkit


    【解决方案1】:

    对于旋转手势,请执行以下方法:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let rotationGesture = UIRotationGestureRecognizer(target: self, 
                                                          action: #selector(rotation))
    
        self.sceneView.addGestureRecognizer(rotationGesture)
    }
    

    然后:

    let myScene = SCNScene(named: "scene.scn")!
    let modelNode: SCNNode = myScene.rootNode
    
    var originalRotation: SCNVector3? = nil
    

    你也可以检查任何重要的条件:

    private func nodeMethod(at position: CGPoint) -> SCNNode? {
    
        let n = self.sceneView.hitTest(position, options: nil).first(where: { 
            $0.node !== modelNode 
        })?.node
    
        return n
    }
    

    然后:

    @objc func rotation(_ gesture: UIRotationGestureRecognizer) {
    
        let location = gesture.location(in: self.sceneView)
    
        guard let node = nodeMethod(at: location) 
        else { 
            return 
        }
    
        switch gesture.state {
            case .began:
                originalRotation = node.eulerAngles
            case .changed:
                guard var originalRotation = originalRotation 
                else { 
                    return 
                }
                originalRotation.y -= Float(gesture.rotation)
                node.eulerAngles = originalRotation
            default:
                originalRotation = nil
        }
    }
    

    附言

    检查模型的轴心点在哪里。如果它在模型的容器之外,您的模型将不可预测地旋转和缩放。使用以下代码控制枢轴点的位置:

    modelNode.simdPivot.columns.3.z = 0.25
    

    另请阅读 QuaternionEuler 旋转 herehere

    如果您需要锁定任何轴进行旋转,请阅读this 帖子。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多