ARKit 交互(手势)

spo*_*oax 5 xcode ios swift swift4 arkit

我正在尝试使用 ARKit 制作一个 iOS 应用程序。到目前为止,我已经使用了 Apple 的“放置对象”示例并对其进行了扩充,因此它具有我自己的几何形状。这部分都很好用。

我有几个不同的物体可以放在地上。用简单的术语解释物体,它们是前面有门的盒子。

我遇到的问题是我现在想向应用程序添加手势,以便在轻敲门时它会旋转打开。然后当它再次被敲击时,门就会关闭。

我已经寻找了一些关于如何做到这一点的教程,但找不到任何东西。有人可以向我解释如何做到这一点,或者向我指出如何实现这种交互性的教程。

谢谢!:)

Cla*_*lay 4

下面是一个基本的 swift Playground,它在加载时创建一扇门。通过点击门,您可以旋转打开,再次点击将关闭门。我\xe2\x80\x99已将代码分解为不同的函数,以便您可以看到门如何打开和关闭。

\n\n
import ARKit\nimport SceneKit\nimport PlaygroundSupport\n\nclass ViewController: NSObject {\n\nvar doorNode: SCNNode!\nvar doorisOpen: Bool!\n\nvar sceneView: ARSCNView\ninit(sceneView: ARSCNView) {\n    self.sceneView = sceneView\n\n    super.init()\n\n    self.setupWorldTracking()\n    self.sceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(_:))))\n        // place door\n    self.sceneView.scene.rootNode.addChildNode(createDoor(position: SCNVector3(0,0,-1)))\n}\n\nprivate func setupWorldTracking() {\n    if ARWorldTrackingConfiguration.isSupported {\n        let configuration = ARWorldTrackingConfiguration()\n        configuration.planeDetection = .horizontal\n        configuration.isLightEstimationEnabled = true\n        self.sceneView.session.run(configuration, options: [])\n    }\n}\n\n@objc func handleTap(_ gesture: UITapGestureRecognizer) {\n    let results = self.sceneView.hitTest(gesture.location(in: gesture.view), types: ARHitTestResult.ResultType.featurePoint)\n    guard let result: ARHitTestResult = results.first else {\n        return\n    }\n\n    let tappedNode = self.sceneView.hitTest(gesture.location(in: gesture.view), options: [:])\n\n    if !tappedNode.isEmpty {\n        let node = tappedNode[0].node \n        if doorisOpen == true {\n            // rotate door \n            closeDoor()\n        } else {\n            // rotate door  \n            openDoor()\n        }\n\n    } else { \n\n        return\n\n    }\n\n}\n\nfunc createDoor(position: SCNVector3) -> SCNNode {\n\n    let door = SCNBox(width: 0.3, height: 0.7, length: 0.025, chamferRadius: 0)\n    doorNode = SCNNode(geometry: door)\n    door.firstMaterial?.locksAmbientWithDiffuse = true\n    door.firstMaterial?.diffuse.contents = UIColor.brown\n    // place door \n    doorNode.position = position\n    // Pivot door from the end\n    endPivot(for: doorNode)\n\n    return doorNode\n}\n\nfunc openDoor() {\n    let rotate = SCNAction.rotateBy(x: 0, y: CGFloat(degToRadians(degrees: 90)), z: 0, duration: 1)\n    doorNode.runAction(rotate)\n    doorisOpen = true\n}\n\nfunc closeDoor() {\n    let rotate = SCNAction.rotateBy(x: 0, y: CGFloat(degToRadians(degrees: -90)), z: 0, duration: 1)\n    doorNode.runAction(rotate)\n    doorisOpen = false\n}\n\nfunc endPivot(for node: SCNNode) {\n    var min = SCNVector3Zero\n    var max = SCNVector3Zero\n    node.__getBoundingBoxMin(&min, max: &max)\n    node.pivot = SCNMatrix4MakeTranslation(min.x, 0, 0)\n}\n\n\nfunc degToRadians(degrees:Double) -> Double\n{\n    return degrees * (M_PI / 180);\n }\n\n}\n\nlet sceneView = ARSCNView()\n\nlet viewController = ViewController(sceneView: sceneView)\nsceneView.autoenablesDefaultLighting = true\nPlaygroundPage.current.needsIndefiniteExecution = true\nPlaygroundPage.current.liveView = viewController.sceneView \n
Run Code Online (Sandbox Code Playgroud)\n