お馴染みのViewContainerを作りARViewを描画する
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let boxAnchor = try! Experience.loadBox()
arView.scene.anchors.append(boxAnchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
tapGestureを付与する
extension ARView {
func enableToGesture() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapGesture))
self.addGestureRecognizer(tapGesture)
}
}
タップした位置にARオブジェクトがあるかないかで処理を分ける。
@objc private func didTapGesture(recognizer: UITapGestureRecognizer) {
let tapLocation = recognizer.location(in: self)
guard let rayResult = self.ray(through: tapLocation) else { return }
let results = self.scene.raycast(origin: rayResult.origin, direction: rayResult.direction)
//中身があったらARObjectをタップしたことになる。なかったらその位置にARobjectを配置する。
if let firstResult = results.first {
} else {
//
}
オブジェクトを置くメソッドを作成
private func placeCube(at position: simd_float3) {
let mesh = MeshResource.generateBox(size: 0.3)
let material = SimpleMaterial(color: .blue,
roughness: 0.3,
isMetallic: true)
let modelEntity = ModelEntity(mesh: mesh,materials: [material])
modelEntity.generateCollisionShapes(recursive: true)
let anchorEntity = AnchorEntity(world: position)
anchorEntity.addChild(modelEntity)
self.scene.addAnchor(anchorEntity)
}
処理を分けた中身を書く
if let firstResult = results.first {
// ARオブジェクトをタップした場合 positionで値を取ってきて
var position = firstResult.position
// その上に乗っける。
position.y += 0.3 / 2
placeCube(at: position)
} else {
// ARオブジェクトがない場所をタップした場合。
// 新しいオブジェクトを置く。
let results = self.raycast(from: tapLocation, allowing: .estimatedPlane, alignment: .any)
if let firstResult = results.first {
let position = simd_make_float3(firstResult.worldTransform.columns.3) // SIMD3<Float>
placeCube(at: position)
}
}