【问题标题】:How do I load my own Reality Composer scene into RealityKit?如何将我自己的 Reality Composer 场景加载到 RealityKit 中?
【发布时间】:2020-10-30 15:48:38
【问题描述】:

我在 Experience.rcproject 文件中创建了 3 个“场景”,它们是在您使用 xcode 启动新的增强现实项目时创建的。

经常为 3D 工作,我会说这些是场景中的 3 个对象,但在 Experience.rcproject 中我添加了 3 个“场景”。在每个内部,相同的 3D 模型。第一个连接到水平平面,第二个连接到垂直平面,第三个连接到图像。

我是第一次使用 Reality Kit 并一路学习。

我这样做的想法是,当我想将它附加到水平、垂直或图像时加载正确的对象。

我就是这样完成的。

我已修改 Apple 提供的 Experience.swift 文件以接受场景名称,如下所示:

public static func loadBox(namedFile:String) throws -> Experience.Box {
    guard let realityFileURL = Foundation.Bundle(for: Experience.Box.self).url(forResource: "Experience", withExtension: "reality") else {
      throw Experience.LoadRealityFileError.fileNotFound("Experience.reality")
    }
    
    let realityFileSceneURL = realityFileURL.appendingPathComponent(namedFile, isDirectory: false)
    let anchorEntity = try Experience.Box.loadAnchor(contentsOf: realityFileSceneURL)
    return createBox(from: anchorEntity)
  }

我叫这条线

let entity = try! Experience.loadBox(namedFile:sceneName)

任何我想要的,但我必须使用这个代码:

// I have to keep a reference to the entity so I can remove it from its parent and nil
currentEntity?.removeFromParent()
currentEntity = nil

// I have to load the entity again, now with another name
let entity = try! Experience.loadBox(namedFile:sceneName)

// store a reference to it, so I can remove it in the future
currentEntity = entity

// remove the old one from the scene
arView.scene.anchors.removeAll()

// add the new one
arView.scene.anchors.append(entity)

这段代码很愚蠢,我相信有更好的方法。

有什么想法吗?

【问题讨论】:

    标签: swift augmented-reality arkit realitykit reality-composer


    【解决方案1】:

    RealityKit/Reality Composer 中的层次结构

    我认为这是一个“理论”问题,而不是实际问题。首先我应该说编辑包含带有锚点和实体的场景的Experience 文件不是一个好主意。

    在 RealityKit 和 Reality Composer 中,如果您在默认场景中创建单个对象,则有相当明确的层次结构:

    Scene –> AnchorEntity -> ModelEntity 
                                  |
                               Physics
                                  |
                              Animation
                                  |
                                Audio
                              
    

    如果您在一个场景中放置两个 3D 模型,它们共享同一个锚点:

    Scene –> AnchorEntity – – – -> – – – – – – – – ->
                                 |                  |
                           ModelEntity01      ModelEntity02
                                 |                  |
                              Physics            Physics
                                 |                  |
                             Animation          Animation
                                 |                  |
                               Audio              Audio
    

    RealityKit 中的AnchorEntity 定义了World Tracking 配置在当前ARSession 中运行的属性:horizontal/vertical 平面检测和/或image detection,和/或body detection,等等。

    让我们看看这些参数:

    AnchorEntity(.plane(.horizontal, classification: .floor, minimumBounds: [1, 1]))
    
    AnchorEntity(.plane(.vertical, classification: .wall, minimumBounds: [0.5, 0.5]))
    
    AnchorEntity(.image(group: "Group", name: "model"))
    

    在这里您可以阅读有关Entity-Component-System 范式的信息。


    结合来自 Reality Composer 的两个场景

    对于这篇文章,我在 Reality Composer 中准备了两个场景——第一个场景 (ConeAndBox) 带有水平平面检测,第二个场景 (Sphere) 带有垂直平面检测。如果您将 RealityKit 中的这些场景组合成一个更大的场景,您将获得两种类型的平面检测——水平和垂直。

    在这个场景中,两个圆锥和盒子固定在一个锚点上。

    在 RealityKit 中,我可以将这些场景组合成一个场景。

    // Plane Detection with a Horizontal anchor
    let coneAndBoxAnchor = try! Experience.loadConeAndBox()
    coneAndBoxAnchor.children[0].anchor?.scale = [7, 7, 7]
    coneAndBoxAnchor.goldenCone!.position.y = -0.1  //.children[0].children[0].children[0]
    arView.scene.anchors.append(coneAndBoxAnchor)
    
    coneAndBoxAnchor.name = "mySCENE"
    coneAndBoxAnchor.children[0].name = "myANCHOR"
    coneAndBoxAnchor.children[0].children[0].name = "myENTITIES"
    
    print(coneAndBoxAnchor)
         
    // Plane Detection with a Vertical anchor
    let sphereAnchor = try! Experience.loadSphere()
    sphereAnchor.steelSphere!.scale = [7, 7, 7]
    arView.scene.anchors.append(sphereAnchor)
    
    print(sphereAnchor)
    

    在 Xcode 的控制台中,您可以看到 ConeAndBox 场景层次结构,其名称在 RealityKit 中给出:

    您可以看到Sphere 没有给出名称的场景层次结构:

    重要的是要注意,我们的组合场景现在在一个数组中包含两个场景。使用以下命令打印此数组:

    print(arView.scene.anchors)
    

    打印出来:

    [ 'mySCENE' : ConeAndBox, '' : Sphere ]
    


    您可以通过AnchoringComponent 重新分配跟踪类型(您可以分配图像检测而不是平面检测):

    coneAndBoxAnchor.children[0].anchor!.anchoring = AnchoringComponent(.image(group: "AR Resources", 
                                                                                name: "planets"))
    


    检索实体并将它们连接到新的 AnchorEntity

    为了分解/重组场景的层次结构,您需要检索所有实体并将它们固定到单个锚点。考虑到 - 跟踪一个锚点比跟踪多个锚点要少。而且,就场景模型的相对位置而言,一个锚点比例如 20 个锚点要稳定得多。

    let coneEntity = coneAndBoxAnchor.goldenCone!
    coneEntity.position.x = -0.2
        
    let boxEntity = coneAndBoxAnchor.plasticBox!
    boxEntity.position.x = 0.01
        
    let sphereEntity = sphereAnchor.steelSphere!
    sphereEntity.position.x = 0.2
        
    let anchor = AnchorEntity(.image(group: "AR Resources", name: "planets")
    anchor.addChild(coneEntity)
    anchor.addChild(boxEntity)
    anchor.addChild(sphereEntity)
        
    arView.scene.anchors.append(anchor)
    


    有用的链接

    现在您对如何构建场景并从这些场景中检索实体有了更深入的了解。如果您需要其他示例,请查看 THIS POSTTHIS POST


    附言

    显示如何从ExperienceX.rcproject 上传场景的附加代码:

    import ARKit
    import RealityKit
    
    class ViewController: UIViewController {
        
        @IBOutlet var arView: ARView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
                        
            // RC generated "loadGround()" method automatically
            let groundArrowAnchor = try! ExperienceX.loadGround()
            groundArrowAnchor.arrowFloor!.scale = [2,2,2]
            arView.scene.anchors.append(groundArrowAnchor)
    
            print(groundArrowAnchor)
        }
    }
    

    【讨论】:

    • 你的回答太棒了。谢谢。只有一个问题:我看到您有两种不同的方法,loadConeAndBox()loadSphere()。这些会是原始 Apple 的loadBox() 的副本吗?请原谅我的愚蠢,但你能把这部分代码贴出来吗?
    • 是的,我修改了一个默认的 Reality Composer 的“盒子”场景,只放了圆锥模型。
    • 我问这个是因为我认为场景名称会以一种可以在加载方法中使用的方式暴露在代码中。无论如何,请参阅上面的loadBox:namedFile。我猜你是这个意思。
    • 请给我你的 Reality Composer 项目。
    • @swiftlearneer - 谢谢。我必须问一切,因为苹果写的文档是不屑一顾的。
    猜你喜欢
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    相关资源
    最近更新 更多