I’m working currently on a project where you can load your usdz file into a Realitiykit. I’m relatively new to this API. What I want,is to have a preview of a usdz object and being able to selct some surface points of this object and to connect those via a line. In order to achive that i have some problems:
- Firstly, how do I load an object in a plane white view (Not added into the real world camera AR)
- Secondly, how am I able to select some points on the 3D object surface via gesture recogintion.
- How do I connect those with a line.
This is my current code:
struct ContentView: View {
var body: some View {
ARViewContainer()
.edgesIgnoringSafeArea(.all)
}
}
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
context.coordinator.arView = arView
// Load the USDZ model
let modelEntity = try! ModelEntity.loadModel(named: "yourModel.usdz")
// Create an anchor to hold the model
let anchorEntity = AnchorEntity(world: [0, 0, 0])
anchorEntity.addChild(modelEntity)
// Add the anchor to the ARView
arView.scene.addAnchor(anchorEntity)
// Configure the background color to white (simulates a plane white view)
arView.environment.background = .color(.white)
// Setup gesture recognizer
context.coordinator.setupGestureRecognition()
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
}
class Coordinator: NSObject {
var arView: ARView?
var selectedPoints: [SIMD3<Float>] = []
override init() {
super.init()
}
func setupGestureRecognition() {
guard let arView = arView else { return }
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
arView.addGestureRecognizer(tapGesture)
}
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
guard let arView = arView else { return }
let location = gesture.location(in: arView)
// Perform a hit test to find where the user tapped on the model
let results = arView.hitTest(location)
if let firstResult = results.first {
let position = firstResult.worldTransform.translation
selectedPoints.append(position)
addSphere(at: position)
if selectedPoints.count > 1 {
drawLine(from: selectedPoints[selectedPoints.count - 2], to: position)
}
}
}
private func addSphere(at position: SIMD3<Float>) {
guard let arView = arView else { return }
let sphere = MeshResource.generateSphere(radius: 0.01)
let material = SimpleMaterial(color: .red, isMetallic: false)
let sphereEntity = ModelEntity(mesh: sphere, materials: [material])
sphereEntity.position = position
let anchorEntity = AnchorEntity(world: position)
anchorEntity.addChild(sphereEntity)
arView.scene.addAnchor(anchorEntity)
}
private func drawLine(from start: SIMD3<Float>, to end: SIMD3<Float>) {
guard let arView = arView else { return }
let vertices: [SIMD3<Float>] = [start, end]
let indices: [UInt32] = [0, 1]
let lineMesh = MeshResource.generate(from: vertices, indices: indices)
let material = SimpleMaterial(color: .blue, isMetallic: false)
let lineEntity = ModelEntity(mesh: lineMesh, materials: [material])
let anchorEntity = AnchorEntity(world: [0, 0, 0])
anchorEntity.addChild(lineEntity)
arView.scene.addAnchor(anchorEntity)
}
}
extension matrix_float4x4 {
/// Extracts the translation vector (position) from the 4x4 matrix
var translation: SIMD3<Float> {
return SIMD3<Float>(columns.3.x, columns.3.y, columns.3.z)
}
}
I appriciate your time!