我在 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
}
使用我的代码中的
separateLettersIn(text:)
和 createBlockOfText()
方法来分隔每个字符串的字母,并为每个字母分配物理体和碰撞形状。
import SwiftUI
import RealityKit
struct ContentView : View {
let arView = ARView(frame: .zero)
var body: some View {
ZStack {
ARViewContainer(arView: arView)
.ignoresSafeArea()
}
}
}
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) { }
}