LiDAR 和 RealityKit——为扫描模型捕捉真实世界的纹理

LiDAR and RealityKit – Capture a Real World Texture for a Scanned Model

任务

我想 capture 一个真实世界的纹理,并将其应用到在 LiDAR 扫描仪的帮助下生成的重建网格。我想应该为此使用 Projection-View-Model 矩阵。纹理必须从固定的视点制作,例如,从房间的中心。但是,如果我们可以应用 environmentTexturing 数据,在场景中收集为 cube-map 纹理,这将是一个理想的解决方案。

看看3D Scanner App。这是一个参考应用程序,允许我们导出带有纹理的模型。

我需要通过一次迭代捕获纹理。我不需要实时更新它。我意识到改变 PoV 会导致错误的纹理感知,换句话说,纹理失真。我还意识到 RealityKit 中有一个动态细分并且有一个自动纹理 mipmapping(纹理的分辨率取决于它捕获的距离)。

import RealityKit
import ARKit
import Metal
import ModelIO

class ViewController: UIViewController, ARSessionDelegate {
    
    @IBOutlet var arView: ARView!

    override func viewDidLoad() {
        super.viewDidLoad()

        arView.session.delegate = self
        arView.debugOptions.insert(.showSceneUnderstanding)

        let config = ARWorldTrackingConfiguration()
        config.sceneReconstruction = .mesh
        config.environmentTexturing = .automatic
        arView.session.run(config)
    }
}

问题


场景重建

遗憾的是,我仍然无法使用 LiDAR 扫描过程实时捕获模型的纹理。在 WWDC20 和 WWDC21 上,Apple 都没有为此宣布原生 API(因此现在只能使用 third-party APIs 进行纹理捕捉 - 不要问我是哪个 :-))。

不过,有个好消息 – 一种新的方法终于出现了。它将允许开发人员从一系列镜头中创建带纹理的模型。

摄影测量

Object Capture API 在 WWDC 2021 上宣布,为开发者提供 long-awaited photogrammetry 工具。在输出中我们得到具有 UV-mapped hi-rez 纹理的 USDZ 模型。要实施 Object Capture API,您需要 macOS 12 和 Xcode 13。

要从一系列镜头创建 USDZ 模型,请将所有拍摄的图像提交到 RealityKit 的 PhotogrammetrySession

下面是一个代码片段,可以说明这个过程:

import RealityKit
import Combine

let pathToImages = URL(fileURLWithPath: "/path/to/my/images/")

let url = URL(fileURLWithPath: "model.usdz")

var request = PhotogrammetrySession.Request.modelFile(url: url, 
                                                   detail: .medium)

var configuration = PhotogrammetrySession.Configuration()
configuration.sampleOverlap = .normal
configuration.sampleOrdering = .unordered
configuration.featureSensitivity = .normal
configuration.isObjectMaskingEnabled = false

guard let session = try PhotogrammetrySession(input: pathToImages, 
                                      configuration: configuration)
else { return 
} 

var subscriptions = Set<AnyCancellable>()

session.output.receive(on: DispatchQueue.global())
              .sink(receiveCompletion: { _ in
                  // errors
              }, receiveValue: { _ in
                  // output
              }) 
              .store(in: &subscriptions)

session.process(requests: [request])

您可以使用相应的 UV-mapped 纹理重建 USD 和 OBJ 模型。

如何在 Unity 中完成

我想分享一些关于 Unity 的 AR Foundation 工作的有趣信息,其中包含来自 LiDAR 的网格。目前——2020 年 11 月 1 日——情况很荒谬。这与原生 ARKit 开发人员无法使用标准 high-level RealityKit 工具捕获扫描对象的纹理这一事实有关,但是 Unity 的 AR Foundation 用户(创建 ARKit 应用程序)可以使用 ARMeshManager 脚本来执行此操作。我不知道这个脚本是由 AR Foundation 团队开发的,还是只是由一家小型创意初创公司(后来被收购)的开发人员开发的,但事实仍然如此。

要将 ARKit 网格化与 AR Foundation 结合使用,您只需将 ARMeshManager 组件添加到您的场景中。正如您在图片上看到的那样,有 Texture CoordinatesColorMesh Density.

等特征

如果有人有关于必须如何在 Unity 中配置或编写脚本的更多详细信息,请post在此线程中进行讨论。

您可以通过 here

查看答案

这是对这个项目的描述:MetalWorldTextureScan 它演示了如何使用 ARKit 和 Metal 扫描您的环境并创建带纹理的网格。