ios - 如何使用手势旋转和缩放ARKit模型?

标签 ios swift augmented-reality scenekit arkit

我正在尝试像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
        }
    }
}

但这是行不通的。我究竟做错了什么?

最佳答案

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

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帖子。

关于ios - 如何使用手势旋转和缩放ARKit模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62363876/

相关文章:

java - 在网络摄像头流上读取和写入

swift - 如何从 SCNText iOS 获取浮点值?

ios - 是什么导致 AVMutableComposition 大幅增加视频的大小? - iOS、 swift 、AVFoundation

ios - 核心数据错误 : Unsupported expression type (11, SIZE)

cocoa-touch - 您是否必须桥接到 ObjectiveC 才能快速 float ?

ios - 如何在 iOS swift 中使用 AVPlayer 访问 iOS 文件应用程序中存在的视频文件?

ios - 为什么声明为需要参数的 swift 函数可以在没有参数的情况下传递?

animation - 将动画 3D 模型转换为 Quake 2 的模型

ios - WKInerfaceLabel 放置在 WKInerfaceTable 之上,但不希望它与 WKInterfaceTable 一起滚动

ios - 在后台模式下从 Alamofire 获取数据