ios - ARKit 交互(手势)

标签 ios swift xcode swift4 arkit

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

我有几个不同的物体可以放在地上。简单来说,它们就是前面有门的盒子。

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

我已经查找了一些有关如何执行此操作的教程,但找不到任何内容。有人可以向我解释如何执行此操作,或者向我介绍显示如何实现这种交互性的教程。

谢谢! :)

最佳答案

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

import ARKit
import SceneKit
import PlaygroundSupport

class ViewController: NSObject {

var doorNode: SCNNode!
var doorisOpen: Bool!

var sceneView: ARSCNView
init(sceneView: ARSCNView) {
    self.sceneView = sceneView

    super.init()

    self.setupWorldTracking()
    self.sceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(_:))))
        // place door
    self.sceneView.scene.rootNode.addChildNode(createDoor(position: SCNVector3(0,0,-1)))
}

private func setupWorldTracking() {
    if ARWorldTrackingConfiguration.isSupported {
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal
        configuration.isLightEstimationEnabled = true
        self.sceneView.session.run(configuration, options: [])
    }
}

@objc func handleTap(_ gesture: UITapGestureRecognizer) {
    let results = self.sceneView.hitTest(gesture.location(in: gesture.view), types: ARHitTestResult.ResultType.featurePoint)
    guard let result: ARHitTestResult = results.first else {
        return
    }

    let tappedNode = self.sceneView.hitTest(gesture.location(in: gesture.view), options: [:])

    if !tappedNode.isEmpty {
        let node = tappedNode[0].node 
        if doorisOpen == true {
            // rotate door 
            closeDoor()
        } else {
            // rotate door  
            openDoor()
        }

    } else { 

        return

    }

}

func createDoor(position: SCNVector3) -> SCNNode {

    let door = SCNBox(width: 0.3, height: 0.7, length: 0.025, chamferRadius: 0)
    doorNode = SCNNode(geometry: door)
    door.firstMaterial?.locksAmbientWithDiffuse = true
    door.firstMaterial?.diffuse.contents = UIColor.brown
    // place door 
    doorNode.position = position
    // Pivot door from the end
    endPivot(for: doorNode)

    return doorNode
}

func openDoor() {
    let rotate = SCNAction.rotateBy(x: 0, y: CGFloat(degToRadians(degrees: 90)), z: 0, duration: 1)
    doorNode.runAction(rotate)
    doorisOpen = true
}

func closeDoor() {
    let rotate = SCNAction.rotateBy(x: 0, y: CGFloat(degToRadians(degrees: -90)), z: 0, duration: 1)
    doorNode.runAction(rotate)
    doorisOpen = false
}

func endPivot(for node: SCNNode) {
    var min = SCNVector3Zero
    var max = SCNVector3Zero
    node.__getBoundingBoxMin(&min, max: &max)
    node.pivot = SCNMatrix4MakeTranslation(min.x, 0, 0)
}


func degToRadians(degrees:Double) -> Double
{
    return degrees * (M_PI / 180);
 }

}

let sceneView = ARSCNView()

let viewController = ViewController(sceneView: sceneView)
sceneView.autoenablesDefaultLighting = true
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = viewController.sceneView 

关于ios - ARKit 交互(手势),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48172003/

相关文章:

ios - 是否可以更改搜索栏中取消按钮的垂直位置?

IOS越狱如何拦截短信/短信

ios - 如何在iOS中基于String动态调整UITextview高度

ios - 防止在 UIImagePickerController 中选择同一张照片两次

swift - Swift 中的多个 For 循环条件

xcode - 为现有项目创建 git 存储库?

iOS : Scroll view works only after keyboard appears

swift - 在 Swift 中创建线程安全读取时,为什么在并发队列之外创建一个变量?

ios - 所有 View 上的页面 View Controller 按钮

ios - 在 Swift 中使用 UIActivityIndi​​cator-for-SDWebImage