import ARKit
import RealityKit
import SwiftUI
import CoreLocation
import Mix
class CustomARView: ARView, ARSessionDelegate, CLLocationManagerDelegate {
non-public var cancellables: Set<AnyCancellable> = []
non-public let locationManager = CLLocationManager()
non-public var utility: Utility
non-public var currentEntity: Entity?
required init(body frameRect: CGRect, utility: Utility) {
self.utility = utility
tremendous.init(body: frameRect)
setupARView()
subscribeToActionStream()
setupLocationManager()
}
required init(body frameRect: CGRect) {
self.utility = .sdge // Default worth or you may deal with it in another way
tremendous.init(body: frameRect)
self.automaticallyConfigureSession = false
setupARView()
subscribeToActionStream()
setupLocationManager()
}
@objc required dynamic init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been applied")
}
non-public func setupARView() {
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]
configuration.environmentTexturing = .computerized
session.run(configuration, choices: [.resetTracking, .removeExistingAnchors])
session.delegate = self
print("AR session began with configuration: (configuration)")
let debugOptions: ARView.DebugOptions = [.showFeaturePoints, .showWorldOrigin, .showAnchorOrigins, .showAnchorGeometry]
self.debugOptions = debugOptions
let tapGesture = UITapGestureRecognizer(goal: self, motion: #selector(handleTap(_:)))
addGestureRecognizer(tapGesture)
let pinchGesture = UIPinchGestureRecognizer(goal: self, motion: #selector(handlePinch(_:)))
addGestureRecognizer(pinchGesture)
let panGesture = UIPanGestureRecognizer(goal: self, motion: #selector(handlePan(_:)))
addGestureRecognizer(panGesture)
let rotationGesture = UIRotationGestureRecognizer(goal: self, motion: #selector(handleRotation(_:)))
addGestureRecognizer(rotationGesture)
}
non-public func setupLocationManager() {
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
print("Location supervisor began.")
}
@objc non-public func handleTap(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: self)
print("Faucet detected at location: (location)")
// Examine if the faucet hit an current entity
let hitTestResults = hitTest(location, question: .all)
if let firstHit = hitTestResults.first(the place: { $0.entity is ModelEntity }) {
// If it hit, take away the entity
if let entity = firstHit.entity as? ModelEntity {
print("Present entity hit: (entity.title), eradicating it.")
entity.removeFromParent()
currentEntity = nil
}
} else {
// If it did not hit, place a brand new entity
if let raycastResult = raycast(from: location, permitting: .existingPlaneGeometry, alignment: .horizontal).first {
print("Raycast succeeded, putting mannequin.")
placeModel(at: raycastResult.worldTransform)
} else {
print("Raycast failed. No surfaces detected.")
}
}
}
@objc non-public func handlePinch(_ gesture: UIPinchGestureRecognizer) {
guard let entity = currentEntity else {
print("No present entity to scale.")
return
}
let scale = Float(gesture.scale)
entity.scale *= SIMD3<Float>(repeating: scale)
gesture.scale = 1.0
print("Scaled entity: (entity.title) to scale: (entity.scale)")
}
@objc non-public func handlePan(_ gesture: UIPanGestureRecognizer) {
guard let entity = currentEntity else {
print("No present entity to maneuver.")
return
}
let translation = gesture.translation(in: self)
let xTranslation = Float(translation.x / body.width)
let yTranslation = Float(translation.y / body.top)
entity.place.x += xTranslation
entity.place.z += yTranslation
gesture.setTranslation(.zero, in: self)
print("Moved entity: (entity.title) to place: (entity.place)")
}
@objc non-public func handleRotation(_ gesture: UIRotationGestureRecognizer) {
guard let entity = currentEntity else {
print("No present entity to rotate.")
return
}
let rotation = Float(gesture.rotation)
entity.rework.rotation *= simd_quatf(angle: rotation, axis: SIMD3<Float>(0, 1, 0))
gesture.rotation = 0
print("Rotated entity: (entity.title) to rotation: (entity.rework.rotation)")
}
non-public func placeModel(at rework: simd_float4x4, modelName: String? = nil) {
let modelToPlace = modelName ?? {
swap utility {
case .sdge:
return "Cell.256"
case .sce:
return "Cell.1024"
case .pge:
return "Cell.2048"
}
}()
guard let modelEntity = attempt? Entity.load(named: modelToPlace) else {
print("Error loading USDZ mannequin: (modelToPlace)")
return
}
// Right the orientation and scaling
var rework = rework
// Rotate mannequin counterclockwise by 90 levels across the z-axis
let rotation = simd_float4x4(SCNMatrix4MakeRotation(.pi / 2, 0, 0, 1)) // Rotate round z-axis
rework = simd_mul(rework, rotation)
// Set preliminary scale to make sure it isn't too zoomed in
modelEntity.scale = SIMD3<Float>(repeating: 0.01) // Modify scale as wanted
let anchor = AnchorEntity(world: rework)
anchor.addChild(modelEntity)
scene.addAnchor(anchor)
currentEntity = modelEntity
print("Positioned mannequin: (modelToPlace) at rework: (rework)")
}
non-public func subscribeToActionStream() {
ARManager.shared.actionStream
.sink { [weak self] motion in
print("Acquired AR motion: (motion)")
swap motion {
case .removeAllAnchors:
self?.scene.anchors.removeAll()
print("All anchors eliminated.")
case .addARObject1:
self?.addARObject(named: "Cell.256")
case .addARObject2:
self?.addARObject(named: "Cell.1024")
case .addARObject3:
self?.addARObject(named: "Cell.2048")
}
}
.retailer(in: &cancellables)
}
non-public func addARObject(named modelName: String) {
if let cameraTransform = session.currentFrame?.digital camera.rework {
let distance: Float = 1.0 // 1 meter in entrance of the digital camera
var translation = matrix_identity_float4x4
translation.columns.3.z = -distance
let finalTransform = simd_mul(cameraTransform, translation)
placeModel(at: finalTransform, modelName: modelName)
print("Added AR object: (modelName) at distance: (distance) meters in entrance of digital camera.")
} else {
print("Error: Unable to get digital camera rework.")
}
}
func locationManager(_ supervisor: CLLocationManager, didUpdateLocations places: [CLLocation]) {
guard let location = places.final else {
print("Error: No location information obtainable.")
return
}
print("Location up to date: (location)")
// Deal with location updates
}
}
extension Entity {
func findEntity<T: Entity>(ofType kind: T.Kind) -> T? {
if let match = self as? T {
return match
}
for baby in youngsters {
if let match = baby.findEntity(ofType: kind) {
return match
}
}
return nil
}
}
i’ve been manipulating the objc capabilities to deal with rotation and pan however sliding finger up and down simply makes it develop whereas pinching and twisting it nonetheless would not rotate the item. it strikes left and proper high-quality, and it grows and shrinks high-quality however cannot get it to rotate or acknowledge the aircraft/ floor it ought to sit on.
UPDATE: appears like i can rotate it horizontally simply not the opposite approach, which i gues i am unable to rotate across the z axis? and the sliding up and down nonetheless simply makes it develop and shrink.