ARKit – 海报作为虚拟房间的 window

ARKit – Poster as a window to a virtual room

我正在使用 ARKit 开发 iOS 应用程序。

在现实世界中,墙上有一张海报。海报是固定的东西,所以可以应用任何需要的预处理。

目标是将这张海报 window 变成一个虚拟房间。这样当用户接近海报时,他可以在某个虚拟 3D 环境(房间)中查看 "through" 海报。当然,用户不能通过 "window" 然后在那个 3D 环境中徘徊。他只能观察一个虚拟房间,看着 "through" 海报。

我知道可以让 ARKit 检测到这张海报,并在它周围播放一些视觉效果,甚至在上面放一部电影。

但是我没有找到资料如何把它变成一个window虚拟的3D世界。

非常感谢任何想法和示例项目的链接。

查看 Augmented Images 网页上发布的 this video(使用 Chrome 浏览器观看此视频)。

It's easy to create that type of a virtual cube. All you need is a 3D model of simple cube primitive without a front polygon (in order to see its inner surface). Also you need a plane with a square hole. Assign an out-of-the-box RealityKit occlusion material or a hand-made for this plane and it will hide all the outer walls of cube behind it (look at a picture below).

在 Autodesk Maya 中 Occlusion material 是 Render Stats 中的一个 Hold-Out 选项(仅适用于 Viewport 2.0):

当您跟踪墙上的海报时(启用 detectionImages 选项),您的应用程序必须识别图片和 "load" 3D 立方体及其带有遮挡着色器的遮蔽平面。因此,如果海报上的 ARImageAnchor 和 3D 立方体的 pivot point 必须相交,则立方体的轴心点必须位于立方体的前边缘(与墙面处于同一水平面)。

如果您想下载包含图像检测体验的 Apple 示例代码 – 只需在包含 detectionImages 的同一网页上单击蓝色按钮即可。

这是我的代码的一个简短示例:

@IBOutlet var sceneView: ARSCNView!

override func viewDidLoad() {
    super.viewDidLoad()

    sceneView.delegate = self  // for using renderer() methods of ARSCNViewDelegate
    sceneView.scene = SCNScene()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    resetTrackingConfiguration()
}


func resetTrackingConfiguration() {

    guard let refImage = ARReferenceImage.referenceImages(inGroupNamed: "Poster", 
                                                                bundle: nil) 
    else { return }

    let config = ARWorldTrackingConfiguration()
    config.detectionImages = refImage
    config.maximumNumberOfTrackedImages = 1

    let options = [ARSession.RunOptions.removeExistingAnchors,
                   ARSession.RunOptions.resetTracking]

    sceneView.session.run(config, options: ARSession.RunOptions(options))
}

...当然还有 SceneKit 的 renderer() 实例方法:

func renderer(_ renderer: SCNSceneRenderer,
             didAdd node: SCNNode,
              for anchor: ARAnchor) {

    guard let imageAnchor = anchor as? ARImageAnchor,
          let _ = imageAnchor.referenceImage.name 

    else { return }

    anchorsArray.append(imageAnchor)

    if anchorsArray.first != nil {
        node.addChildNode(portalNode)
    }
}