iOS-ARKit-如何创建旋转对象手势功能? [英] ios - ARKit - How to create rotate object gesture function?

查看:309
本文介绍了iOS-ARKit-如何创建旋转对象手势功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是ARKit的新手.我想创建一个旋转对象的函数.这是我有关拖动和旋转对象的代码:

// Rotate object
@objc func rotateRecognized(sender: UIPanGestureRecognizer) {
    let sceneView = sender.view as! ARSCNView
    let swipeLocation = sender.location(in: sceneView)
    let hitTest = sceneView.hitTest(swipeLocation)
    if !hitTest.isEmpty {
        sender.minimumNumberOfTouches = 2
        let results = hitTest.first!
        let node = results.node
        let xPan = sender.velocity(in: sceneView).x/10000
        node.runAction(SCNAction.rotateBy(x: 0, y: xPan, z: 0, duration: 0.1))
    }
}

// Drag object
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    //1. Get The Current Touch Point
    guard let currentTouchPoint = touches.first?.location(in: self.sceneView),
        //2. Get The Next Feature Point Etc
        let hitTest = 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
    self.sceneView.scene.rootNode.enumerateChildNodes{ (node, _) in
       node.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)
    }

}

当我拖动一个对象时,它可以正常工作.但是,当我用两根手指滑动对象来旋转对象时,除非删除touchesMoves方法,否则对象将无法旋转. 如何解决这个问题?谢谢.

解决方案

我认为最好使用GestureRecognizers而不是将touchesgestures结合在一起使用.

因此,让我们看一下如何解决这个问题.

您已经具有拖动SCNNode的功能,可以很容易地将其转换为UIPanGesture,并且您希望有一个函数可以围绕它的YAxis旋转SCNNode,而我们可以很容易地使用UIRotationGestureRecognizer进行此操作.

在我的示例中,我有一个名为currentNode的SCNNode,尽管您的当然会有所不同.

首先,我们将创建两个变量:

//Store The Rotation Of The CurrentNode
var currentAngleY: Float = 0.0

//Not Really Necessary But Can Use If You Like 
var isRotating = false

然后我们将在viewDidLoad中创建两个gestureRecognizers:

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

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

完成此操作后,我们需要创建函数.

第一个将处理拖动currentNode的操作,例如:

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

    if !isRotating{

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

    //2. Get The Next Feature Point Etc
    guard let hitTest = self.augmentedRealityView.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
    currentNode.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)

    }
}

第二次绕它的YAxis旋转

/// 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
    }
}

这是一个非常粗糙的示例,您需要查看不同的gestureStates等,但是希望它可以为您指明正确的方向...

I'm new in ARKit. I want to create a function to rotate object. This is my code about drag and rotate object:

// Rotate object
@objc func rotateRecognized(sender: UIPanGestureRecognizer) {
    let sceneView = sender.view as! ARSCNView
    let swipeLocation = sender.location(in: sceneView)
    let hitTest = sceneView.hitTest(swipeLocation)
    if !hitTest.isEmpty {
        sender.minimumNumberOfTouches = 2
        let results = hitTest.first!
        let node = results.node
        let xPan = sender.velocity(in: sceneView).x/10000
        node.runAction(SCNAction.rotateBy(x: 0, y: xPan, z: 0, duration: 0.1))
    }
}

// Drag object
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    //1. Get The Current Touch Point
    guard let currentTouchPoint = touches.first?.location(in: self.sceneView),
        //2. Get The Next Feature Point Etc
        let hitTest = 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
    self.sceneView.scene.rootNode.enumerateChildNodes{ (node, _) in
       node.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)
    }

}

When I drag an object, it's work fine. But when I rotate object by swipe with two fingers, the object cannot rotate until I remove the touchesMoves method. How to fix this issue? Thank you.

解决方案

I think it would be best to approach this using GestureRecognizers rather than a combination of both touches and gestures together.

Let's have a look therefore, at how we could tackle this.

You already have the functionality to drag an SCNNode which could quite easily be converted into a UIPanGesture, and you want a function to rotate an SCNNode around it's YAxis which we can quite easily do with a UIRotationGestureRecognizer.

In my example I have an SCNNode called currentNode, although yours will of course be different.

First we will create two variables:

//Store The Rotation Of The CurrentNode
var currentAngleY: Float = 0.0

//Not Really Necessary But Can Use If You Like 
var isRotating = false

Then we will create two gestureRecognizers in viewDidLoad:

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

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

Having done this, we then need to create our functions.

The first will handle dragging the currentNode e.g:

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

    if !isRotating{

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

    //2. Get The Next Feature Point Etc
    guard let hitTest = self.augmentedRealityView.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
    currentNode.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)

    }
}

The second rotating it around it's YAxis:

/// 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
    }
}

This is a very crude example and you would need to look at the different gestureStates etc, but hopefully it should point you in the right direction...

这篇关于iOS-ARKit-如何创建旋转对象手势功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆