使用 ARKit 显示 DAE 文件并跟踪场景中的锚点

Posted

技术标签:

【中文标题】使用 ARKit 显示 DAE 文件并跟踪场景中的锚点【英文标题】:Displaying a DAE file with ARKit and tracking an Anchor in the scene 【发布时间】:2017-11-08 04:49:52 【问题描述】:

我正在试用 ARKit,并使用 this tutorial 设置了一个 ARSCNView

然后用this tutorial.的第二部分设置跟踪水平3D平面

我创建了一个单视图应用程序,然后将 ARSCNView 刷新到根视图,并带有一个到我的 ViewController 的出口。

这是ViewController中的代码:

import UIKit
import ARKit

class ViewController: UIViewController 

    //MARK: Properties
    @IBOutlet weak var arScene: ARSCNView!

    //MARK: ARKit variables
    var realityConfiguration: ARWorldTrackingSessionConfiguration?

    //MARK: Lifecycle
    override func viewDidLoad() 
        super.viewDidLoad()         
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        self.prepare()
    

    //MARK: Actions      

    //MARK: Overrides


extension ViewController 
    func prepare() 
        //Check to see if active reality is supported
        guard ARSessionConfiguration.isSupported else 
            //Custom alert function that just quickly displays a UIAlertController
            AppDelegate.alert(title: "Not Supported", message: "Active Reality is not supported on this device")
            return
        
        //Set up the ARSessionConfiguration
        self.realityConfiguration = ARWorldTrackingSessionConfiguration()
        //Set up the ARSCNView
        guard let config = self.realityConfiguration else 
            return
        
        //Run the ARSCNView and set its delegate
        self.arScene.session.run(config)
        self.arScene.delegate = self
    


extension ViewController: ARSCNViewDelegate 
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 
        return nil
    

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) 
        guard let planAnchor = anchor as? ARPlaneAnchor else 
            return
        

        let plane = SCNPlane(width: CGFloat(planAnchor.extent.x), height: CGFloat(planAnchor.extent.z))
        let planeNode = SCNNode(geometry: plane)
        planeNode.position = SCNVector3Make(planAnchor.center.x, 0, planAnchor.center.z)

        planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)

        node.addChildNode(planeNode)          
    

    func renderer(_ renderer: SCNSceneRenderer, willUpdate node: SCNNode, for anchor: ARAnchor) 
        print("Will updated Node on Anchor: \(anchor.identifier)")
    

    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) 
        print("Did updated Node on Anchor: \(anchor.identifier)")
    

    func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) 
        print("Removed Node on Anchor: \(anchor.identifier)")
    

我下载了 Xcode 9 测试版,按照 Apple 的教程进行操作,发现我的 iPhone 6 没有 ARWorldTrackingSessionConfiguration 对象所需的 A9 芯片。

在我链接的第一个教程中大约一半时,Apple 表示您仍然可以在没有 A9 芯片的情况下创建 AR 体验。但是,它们没有进一步详细说明。有没有其他人找到起点,并愿意提供使用 .dae 文件的代码示例和

选择一个锚点来显示它 跟踪该锚点 实际显示.dae文件

【问题讨论】:

您可以使用增强现实模板创建一个新的 ios 应用程序,然后从 Content Technology 弹出菜单中选择 SceneKit 或 SpriteKit。 【参考方案1】:

使用您的代码并没有什么可看的——只是一个实时摄像头视图。

您在现实中看不到任何增强的主要原因是,您的代码仅在将锚点添加到 ARSession... 时才将 SceneKit 内容添加到场景中,但您没有手动添加任何锚点,并且您尚未启用平面检测,因此 ARKit 不会自动添加锚点。如果您启用平面检测,您将开始到达某个地方......

self.realityConfiguration = ARWorldTrackingSessionConfiguration()
realityConfiguration?.planeDetection = .horizontal

但你仍然什么也看不到。那是因为您的 ARSCNViewDelegate 实现有相互冲突的指令。这部分:

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 
    return nil

...表示不会为您的锚创建任何 SceneKit 节点。因为没有节点,所以您的 renderer(_:didAdd:for:) 函数永远不会被调用,因此您在该方法中的代码永远不会创建任何 SceneKit 内容。

如果您打开平面检测并删除/注释掉renderer(_: nodeFor:) 方法,您的其余代码应该会得到类似这样的结果:

(纯白色区域是你的SCNPlane。我必须在白色桌子上展开我的 iPad 保护套以获得足够的场景细节以进行平面检测以找到任何东西。另外,检查背景......实际上有一段时间今天的 WWDC,商品商店里没有挤满人。)

至于您是否需要 A9,Apple 的消息在这里有点不清楚。当他们说 ARKit 需要 A9 或更高版本时,他们真正的意思是 ARWorldTrackingSessionConfiguration 需要。这就是所有最好的 AR 魔法所在。 (arkit 甚至还有一个 UIRequiredDeviceCapabilities 密钥实际上涵盖了支持世界跟踪的设备,因此您可以将 App Store 上的应用限制为仅提供给这些设备。)

不过,仍有一些 ARKit 没有世界追踪功能。使用基类 ARSessionConfiguration 运行会话,您将获得仅方向跟踪。 (没有位置跟踪,没有平面检测,没有命中测试。)

这对你有什么影响?好吧,如果你玩过当前版本的 Pokémon GO,它的工作原理是这样的:因为它只跟踪设备的方向,而不是位置,所以你无法靠近皮卡丘或在他身后走动——他占据了真实世界的错觉只要您只倾斜或转动设备而不移动它,世界就会保持不变。

您使用 SceneKit 加载 3D 内容并将其放置在 AR 中,就像您将其加载并放置在任何其他 SceneKit 应用程序/游戏中一样。有很多资源可以做到这一点,并且有很多方法可以做到这一点。当您创建一个新的 AR 项目并选择 SceneKit 时,您可以在 Xcode 模板中找到其中之一。加载部分是这样的:

let scene = SCNScene(named: "ship.scn" inDirectory: "assets.scnassets")
let ship = scene.rootNode.childNode(withName: "ship", recursively: true)

然后放置:

ship.simdPosition = float3(0, 0, -0.5) 
// half a meter in front of the *initial* camera position
myARSCNView.scene.rootNode.addChildNode(ship)

在 AR 中放置东西时要记住的主要区别是位置以米为单位(并且您的内容需要设计成合理的以米为单位)。

【讨论】:

谢谢你!希望您在 WWDC 上玩得开心。我现在看到我的委托方法是冲突的。我以为ARWorldTrackingSessionConfiguration.planeDetection默认是打开的,但我再次检查了文档,果然! @JonVogel 我认为默认情况下它是关闭的,所以你必须明确设置它才能让它工作,现在也是ARWorldTrackingConfiguration.PlaneDetection

以上是关于使用 ARKit 显示 DAE 文件并跟踪场景中的锚点的主要内容,如果未能解决你的问题,请参考以下文章

ARKit 和 .dae 文件,对象之间的奇怪空间

如何为 ARKit 将 dae 导入 SceneKit

SceneKit - 如何获取 .dae 模型的动画?

ARKit – 3D 模型的轴心点错误

ios - ARKit 3D模型素材

3d 模型 SceneKit/ARKit 的哪种格式文件更好用