언어/iOS
RealityKit - TextField에 입력한 글자를 3D Entity로 출력하기!
안녕도라
2024. 11. 11. 22:13
다음은 textField에 입력된 값을 MeshResource.generateText함수를 사용해 3D모델로 만드는 간단한 예제이다!
import SwiftUI
import ARKit
import RealityKit
import Combine
struct ContentView: View {
@State private var text: String = ""
var body: some View {
VStack {
ARViewContainer(text: $text)
.ignoresSafeArea()
// TextField
VStack(alignment: .trailing, spacing: 6) {
TextField("아무거나 입력해보소!", text: $text)
.padding()
.background(Color.gray.opacity(0.2))
.cornerRadius(8)
.padding()
}
.padding()
}
}
}
struct ARViewContainer: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero, cameraMode: .nonAR, automaticallyConfigureSession: false)
arView.environment.background = .color(.white)
// TextEntity를 붙일 빈 앵커
let emptyEntity = ModelEntity()
let emptyAnchor = AnchorEntity(world: [0, 0, 0])
emptyAnchor.addChild(emptyEntity)
arView.installGestures([.all], for: emptyEntity)
arView.scene.anchors.append(emptyAnchor)
context.coordinator.emptyEntity = emptyEntity
// 카메라
let camera = PerspectiveCamera()
camera.position = [0, 1, 1]
let cameraAnchor = AnchorEntity(world: [0, 0, 0])
cameraAnchor.addChild(camera)
arView.scene.addAnchor(cameraAnchor)
context.coordinator.camera = camera
context.coordinator.cancellable = arView.scene.subscribe(to: SceneEvents.Update.self) { _ in
camera.look(at: emptyEntity.position, from: camera.position, relativeTo: nil)
} as? AnyCancellable
return arView
}
// @binding값으로 호출 업데이트
func updateUIView(_ uiView: ARView, context: Context) {
// 텍스트 입력값에 따라 update
context.coordinator.updateText(text: text)
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
}
class Coordinator: NSObject {
var emptyEntity: ModelEntity?
var camera: PerspectiveCamera?
var textEntity: ModelEntity?
var cancellable: AnyCancellable?
func updateText(text: String) {
guard let emptyEntity = emptyEntity else { return }
// 입력값이 바뀔 때마다 reset해주기 위함
textEntity?.removeFromParent()
let textMesh = MeshResource.generateText(text, extrusionDepth: 0.03, font: .systemFont(ofSize: 0.15), containerFrame: .zero, alignment: .center, lineBreakMode: .byTruncatingTail)
let textMaterial = SimpleMaterial(color: .black, isMetallic: true)
textEntity = ModelEntity(mesh: textMesh, materials: [textMaterial])
if let textEntity = textEntity {
textEntity.position = [-0.7, 0.2, 0]
textEntity.generateCollisionShapes(recursive: true)
emptyEntity.addChild(textEntity)
}
}
}