动态更改RealityKit实体的文本

时间:2019-10-11 22:13:39

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

我使用Reality Composer创建了一个非常简单的场景(“ SpeechScene”),其中一个语音标注对象(“ Speech Bubble”)被固定在Face锚点上。

我已通过以下方式将此场景加载到了代码中:

let speechAnchor = try! Experience.loadSpeechScene()
arView.scene.anchors.append(speechAnchor)

let bubble = (arView.scene as? Experience.SpeechScene)?.speechBubble

它呈现预期的效果。但是,我想动态更改此现有实体的文本。

我发现了类似的问题here,但我不清楚如何引用香草meshResource对象的RealityKit.Entity属性。

这可能吗?谢谢!

3 个答案:

答案 0 :(得分:1)

找到您的模型实体(可能是通过放置一个断点并首先查看子代),找到符合HasModel协议的实体,然后使用generatetext将其模型替换为另一个模型:

https://developer.apple.com/documentation/realitykit/meshresource/3244422-generatetext

答案 1 :(得分:0)

  

这种情况下最简单的方法是在Reality Composer中创建多个场景,每个场景必须包含不同的speech-object。我为两个对象编写了代码。您可以使用下面发布的代码在iOS Simulator中对其进行测试。

enter image description here

  

考虑一下,该代码不是用于跟踪的,它只是使用Tap Gesture动态切换两个对象的测试。然后,您需要修改此代码以跟踪人脸。

import RealityKit

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!
    var counter = 0
    var bonjourObject: FaceExperience.Bonjour? = nil
    var holaObject: FaceExperience.Hola? = nil

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

        // Reality Composer Scene named "Bonjour"
        // Model name – "french"
        bonjourObject = try! FaceExperience.loadBonjour()
        bonjourObject?.french?.scale = SIMD3(x: 2, y: 2, z: 2)
        bonjourObject?.french?.position.y = 0.25

        // Reality Composer Scene named "Hola"
        // Model name – "spanish"
        holaObject = try! FaceExperience.loadHola()
        holaObject?.spanish?.scale = SIMD3(x: 2, y: 2, z: 2)
        holaObject?.spanish?.position.z = 0.3
    }
    @IBAction func tapped(_ sender: UITapGestureRecognizer) {            
        if (counter % 2) == 0 {
            arView.scene.anchors.removeAll()
            arView.scene.anchors.append(holaObject!)
        } else {
            arView.scene.anchors.removeAll()
            arView.scene.anchors.append(bonjourObject!)
        }
        counter += 1
    }
}

enter image description here

P.S。

如果要将文本部分放在同一位置–只需将对象从一个场景复制粘贴到另一个场景即可。

答案 2 :(得分:0)

@maxxfrazer的断言是正确的,当前动态更改文本的唯一方法是替换ModelComponent中的Entity,当然前提是它确实遵守HasModel Protocol

我写了一个简单的扩展程序,可以帮助解决这个问题:

//-------------------------
//MARK: - Entity Extensions
//-------------------------

extension Entity{

  /// Changes The Text Of An Entity
  /// - Parameters:
  ///   - content: String
  func setText(_ content: String){ self.components[ModelComponent] = self.generatedModelComponent(text: content) }

  /// Generates A Model Component With The Specified Text
  /// - Parameter text: String
  func generatedModelComponent(text: String) -> ModelComponent{

    let modelComponent: ModelComponent = ModelComponent(

      mesh: .generateText(text, extrusionDepth: TextElements().extrusionDepth, font: TextElements().font,
                          containerFrame: .zero, alignment: .center, lineBreakMode: .byTruncatingTail),

      materials: [SimpleMaterial(color: TextElements().colour, isMetallic: true)]

    )

    return modelComponent
  }

}

//--------------------
//MARK:- Text Elements
//--------------------

/// The Base Setup Of The MeshResource
struct TextElements{

  let initialText = "Cube"
  let extrusionDepth: Float = 0.01
  let font: MeshResource.Font = MeshResource.Font.systemFont(ofSize: 0.05, weight: .bold)
  let colour: UIColor = .white

}

要使用它,可以说您创建了一个名为Entity的{​​{1}}:

textEntity

然后,您可以通过替换 var textEntity = Entity() 并通过随时调用以下方法来随时设置ModelComponent来设置动态更改文本:

MeshResource

当然,关于居中或对齐文本,您需要做一些简单的计算(在此我省略了)。

希望有帮助。