如何从 3D 文本网格中提取单个字符

问题描述 投票:0回答:1

我在 SwiftUI 中使用 RealityKit 显示 3D 文本。 我正在使用

MeshResource.generateText
生成 3D 文本网格。

如何分离访问单个角色的网格,以将物理/碰撞应用于网格内的每个角色,例如达到爆炸效果?

struct ContentView : View {
    var body: some View {
            ARViewContainer().edgesIgnoringSafeArea(.all)
                .onTapGesture(perform: {
                // explode text
            }
}
struct ARVariables{
  static var arView: ARView!
}

struct ARViewContainer: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        ARVariables.arView = ARView(frame: .zero)

        let modelA  = generateModelFromText(translateY: 0, color: .white)
        let anchor = AnchorEntity(.plane(.horizontal, classification: .any, minimumBounds: SIMD2<Float>(0.2, 0.2)))
        anchor.children.append(modelA)

        ARVariables.arView.scene.anchors.append(anchor)
        ARVariables.arView.installGestures(.all, for: modelA)
        
        return ARVariables.arView        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
    
}
func generateModelFromText(translateY:Float=0.05, color:UIColor = .gray)->ModelEntity {
       
    let font:UIFont = .systemFont(ofSize: 0.3, weight: UIFont.Weight.heavy, width: .condensed)
    let mesh = MeshResource.generateText(
        "That Text",
        extrusionDepth: 0.08,
        font: font
    )
    
    let material = SimpleMaterial(color: color, roughness: 0.3, isMetallic: true)
    let model = ModelEntity(mesh: mesh, materials: [material])
    
    model.transform.translation.y = -0.08
    model.transform.translation.x = -1 * (mesh.bounds.max.x / 2)
    
    model.generateCollisionShapes(recursive: true)
    
    return model
}

ios swift swiftui metal realitykit
1个回答
0
投票

使用我的代码中的

separateLettersIn(text:)
createBlockOfText()
方法来分隔每个字符串的字母,并为每个字母分配物理体和碰撞形状。

import SwiftUI
import RealityKit

struct ContentView : View {
    let arView = ARView(frame: .zero)

    var body: some View {
        ZStack {
            ARViewContainer(arView: arView)
                .ignoresSafeArea()
        }
    }
}

enter image description here

struct ARViewContainer : UIViewRepresentable {
    let arView: ARView
    let plane = ModelEntity(mesh: .generatePlane(width: 10, depth: 10),
                       materials: [UnlitMaterial(color: .black)])
    
    func separateLettersIn(_ text: String) -> [String] {
        var array: [String] = []
        
        for (_, str) in text.enumerated() {
            array += [str.description]
        }
        return array
    }
    
    func createBlockOfText() -> Entity {
        let entity = Entity()
        let blockOfText = separateLettersIn("Apple RealityKit")
        
        for j in 0 ..< blockOfText.count {
            let mesh = MeshResource.generateText(blockOfText[j],
                                   extrusionDepth: 0.02,
                                             font: .monospacedSystemFont(ofSize: 0.4,
                                                                         weight: .black))
            let letter = ModelEntity(mesh: mesh)
            letter.position.x = Float(j) / 4
            letter.generateCollisionShapes(recursive: false)
            
            Task { @MainActor in
                try await Task.sleep(nanoseconds: UInt64(2e9))    // delay
                letter.physicsBody = .init()
                letter.physicsBody?.massProperties = .init(mass: .random(in: 0.01...0.99))
            }
            entity.addChild(letter)
        }
        let entityOffset = entity.visualBounds(relativeTo: nil).boundingRadius
        entity.position.x -= entityOffset
        return entity
    }
    
    func makeUIView(context: Context) -> ARView {
        let blockOfText = createBlockOfText()
        plane.position.y = -0.4
        plane.generateCollisionShapes(recursive: false)
        plane.physicsBody = .init()
        plane.physicsBody?.mode = .static
        plane.orientation = .init(angle: .pi/10, axis: [1,0,0])

        let anchor = AnchorEntity()
        anchor.children.append(blockOfText)
        anchor.children.append(plane)
        arView.scene.anchors.append(anchor)
        return arView
    }
    func updateUIView(_ view: ARView, context: Context) { }
}
© www.soinside.com 2019 - 2024. All rights reserved.