Ios 如何通过在屏幕上拖动手指来更改相机位置-Swift

Ios 如何通过在屏幕上拖动手指来更改相机位置-Swift,ios,swift,arkit,Ios,Swift,Arkit,我正在尝试学习ARKIT并制作一个小的演示应用程序来绘制3D。 以下是我编写的代码,到目前为止没有问题: import UIKit import ARKit class ViewController: UIViewController, ARSCNViewDelegate { @IBOutlet weak var sceneView: ARSCNView! @IBOutlet weak var DRAW: UIButton! @IBOutlet weak var D

我正在尝试学习ARKIT并制作一个小的演示应用程序来绘制3D。 以下是我编写的代码,到目前为止没有问题:

import UIKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet weak var sceneView: ARSCNView!

    @IBOutlet weak var DRAW: UIButton!
    @IBOutlet weak var DEL: UIButton!

    let config = ARWorldTrackingConfiguration()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.sceneView.session.run(config)
        self.sceneView.delegate = self
    }

    func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {

        guard let pointOfView = sceneView.pointOfView else {return}
        let transform = pointOfView.transform
        let cameraOrientation = SCNVector3(-transform.m31,-transform.m32,-transform.m33)
        let cameraLocation = SCNVector3(transform.m41,transform.m42,transform.m43)
        let cameraCurrentPosition = cameraOrientation + cameraLocation

        DispatchQueue.main.async {

            if (self.DRAW.isTouchInside){
                let sphereNode  = SCNNode(geometry: SCNSphere(radius: 0.02))
                    sphereNode.position = cameraCurrentPosition
                    self.sceneView.scene.rootNode.addChildNode(sphereNode)
                    sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red
                    print("RED Button is Pressed")
                }else if (self.DEL.isTouchInside){
                    self.sceneView.scene.rootNode.enumerateChildNodes{
                    (node, stop) in
                    node.removeFromParentNode()
                    }
                }else{
                    let pointer = SCNNode(geometry: SCNSphere(radius: 0.01))
                    pointer.name = "pointer"
                    pointer.position = cameraCurrentPosition
                    self.sceneView.scene.rootNode.enumerateChildNodes({(node,_) in
                        if node.name == "pointer"{
                            node.removeFromParentNode()
                        }
                    })
                     self.sceneView.scene.rootNode.addChildNode(pointer)
                    pointer.geometry?.firstMaterial?.diffuse.contents = UIColor.purple
                }
        }
    }
}

func +(left:SCNVector3,right:SCNVector3) -> SCNVector3 {
    return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
}
如您所见,我设置了场景并对其进行了配置, 我创建了一个按下时要绘制的按钮、一个占据场景中心的指针(或取景器)和一个删除插入节点的按钮

现在,我希望能够将cameraCurrentPosition从中心移动到另一个点:如果可能,我希望通过触摸屏幕上的手指位置来移动它。
如果可能,有人能帮我编写代码吗?

一般来说,不能在ARSCN中以编程方式移动摄影机,摄影机变换是设备相对于虚拟场景的物理位置

话虽如此,您可以在视图控制器中使用
touchesMoved
方法将用户触摸绘制到屏幕上

var touchRoots: [SCNNode] = [] // list of root nodes for each set of touches drawn

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    // get the initial touch event
    if let touch = touches.first {
        guard let pointOfView = self.sceneView.pointOfView else { return }
        let transform = pointOfView.transform // transformation matrix
        let orientation = SCNVector3(-transform.m31, -transform.m32, -transform.m33) // camera rotation
        let location = SCNVector3(transform.m41, transform.m42, transform.m43) // location of camera frustum
        let currentPostionOfCamera = orientation + location // center of frustum in world space
        DispatchQueue.main.async {
            let touchRootNode : SCNNode = SCNNode() // create an empty node to serve as our root for the incoming points
            touchRootNode.position = currentPostionOfCamera // place the root node ad the center of the camera's frustum
            touchRootNode.scale = SCNVector3(1.25, 1.25, 1.25)// touches projected in Z will appear smaller than expected - increase scale of root node to compensate
            guard let sceneView = self.sceneView else { return }
            sceneView.scene.rootNode.addChildNode(touchRootNode) // add the root node to the scene
            let constraint = SCNLookAtConstraint(target: self.sceneView.pointOfView) // force root node to always face the camera
            constraint.isGimbalLockEnabled = true // enable gimbal locking to avoid issues with rotations from LookAtConstraint
            touchRootNode.constraints = [constraint] // apply LookAtConstraint

            self.touchRoots.append(touchRootNode)
        }
    }
}

override func func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let translation = touch.location(in: self.view)
        let translationFromCenter = CGPoint(x: translation.x - (0.5 * self.view.frame.width), y: translation.y - (0.5 * self.view.frame.height))

        // add nodes using the main thread
        DispatchQueue.main.async {
            guard let touchRootNode = self.touchRoots.last else { return }
            let sphereNode : SCNNode = SCNNode(geometry: SCNSphere(radius: 0.015))
            sphereNode.position = SCNVector3(-1*Float(translationFromCenter.x/1000), -1*Float(translationFromCenter.y/1000), 0)
            sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.white
            touchRootNode.addChildNode(sphereNode)  // add point to the active root
        }
    }
}
var touchRoots:[SCNNode]=[]//绘制的每组触摸的根节点列表
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
//获取初始触摸事件
如果让触摸=先触摸{
guard let pointOfView=self.sceneView.pointOfView-else{return}
让transform=pointOfView.transform//变换矩阵
让方向=SCConvert3(-transform.m31,-transform.m32,-transform.m33)//摄像机旋转
设location=scinvector3(transform.m41、transform.m42、transform.m43)//摄像机截头台的位置
让CurrentPositionOfcamera=方向+位置//世界空间中截锥体的中心
DispatchQueue.main.async{
让touchRootNode:SCNNode=SCNNode()//创建一个空节点作为传入点的根
touchRootNode.position=CurrentPositionOfcamera//将根节点放置在相机平截头体的中心
touchRootNode.scale=SCNVector3(1.25,1.25,1.25)//投影到Z中的触摸将比预期的小-增加根节点的比例以进行补偿
guard let sceneView=self.sceneView else{return}
sceneView.scene.rootNode.addChildNode(touchRootNode)//将根节点添加到场景中
let constraint=SCNLookAtConstraint(target:self.sceneView.pointOfView)//强制根节点始终面向摄影机
constraint.isGimbalLockEnabled=true//启用万向节锁定以避免LookAtConstraint的旋转问题
touchRootNode.constraints=[constraint]//应用LookAtConstraint
self.touchRoots.append(touchRootNode)
}
}
}
覆盖func func TOUCESMOVED(touchs:Set,带有事件:UIEvent?){
如果让触摸=先触摸{
让translation=touch.location(在:self.view中)
设translationFromCenter=CGPoint(x:translation.x-(0.5*self.view.frame.width),y:translation.y-(0.5*self.view.frame.height))
//使用主线程添加节点
DispatchQueue.main.async{
guard let touchRootNode=self.touchRoots.last else{return}
设球体:SCNNode=SCNNode(几何体:SCNSphere(半径:0.015))
sphereNode.position=SCInvector3(-1*浮点(translationFromCenter.x/1000),-1*浮点(translationFromCenter.y/1000),0)
sphereNode.geometry?.firstMaterial?.diffuse.contents=UIColor.white
touchRootNode.addChildNode(sphereNode)//将点添加到活动根
}
}
}

注意:解决方案只处理一次触摸,但它很简单,可以扩展示例以添加多点触摸支持。

非常感谢,这就是我要找的示例:D从这里我可以安静地继续处理触摸最值得记住的是,UIKit(0,0)位于屏幕的左上角,添加球体时,屏幕中心为(0,0,0)。