In my app i’m including a usdz object in AR World. I wish to make it in order that the article follows the motion of the digital camera and all the time stays within the centre of the display screen. I’m unable to do it please Assist.
I’ve tried including the article and updating it is place within the renderer did replace operate but it surely didn’t work. Right here is my code
//
// ARViewController.swift
// KubeStar
//
// Created by Coder Crew on 10/26/22.
//
import UIKit
import ARKit
import SceneKit
import simd
class ARViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var arView: ARSCNView!
var sceneView: ARSCNView!
var cameraNode: SCNNode!
let place = SCNVector3(x: 0, y: 5, z: 10)
var scnView: SCNView!
var scnScene: SCNScene!
var popupView = CustomViewAR()
var latitude = CLLocationDegrees()
var longitude = CLLocationDegrees()
var isShow : Bool?
let popupPlane = SCNPlane()
var popupNode = SCNNode()
var tapgest = UITapGestureRecognizer()
override func viewDidLoad() {
tremendous.viewDidLoad()
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
config.environmentTexturing = .computerized
arView.delegate = self
arView.session.run(config)
DispatchQueue.most important.asyncAfter(deadline: .now() + 0.5) {
self.addObject()
}
addTapGesture()
setUpPopUpView()
}
override func viewWillAppear(_ animated: Bool) {
tremendous.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
arView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
tremendous.viewWillDisappear(animated)
arView.session.pause()
}
func addObject(){
let scene = SCNScene()
let usdzNode = SCNNode()
//
let usdzScene = SCNScene(named: "dice.usdz")!
let usdzChildNodes = usdzScene.rootNode.childNodes
for node in usdzChildNodes {
usdzNode.addChildNode(node)
}
usdzNode.place = SCNVector3(0, 0, -2) // set the place of the article
scene.rootNode.addChildNode(usdzNode)
// scene!.rootNode.place = SCNVector3(0, 0, -1)
let ambientLightNode = SCNNode()
ambientLightNode.gentle = SCNLight()
ambientLightNode.gentle?.kind = .ambient
ambientLightNode.gentle?.colour = UIColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
// scene.rootNode.place = SCNVector3(0, 0, -1)
let cameraNode = SCNNode()
cameraNode.digital camera = SCNCamera()
// 3: Place digital camera
cameraNode.place = SCNVector3(x: 0, y: 0, z: -2)
// 4: Set digital camera on scene
scene.rootNode.addChildNode(cameraNode)
// arView.allowsCameraControl = true
let simdVector = SIMD3<Float>(x: 100, y: 100, z: 100)
let vector = SCNVector3(simdVector)
scene.rootNode.scale = vector
arView.scene = scene
let panGesture = UIPanGestureRecognizer(goal: self, motion: #selector(handlePanGesture(_:)))
arView.addGestureRecognizer(panGesture)
let pinchGesture = UIPinchGestureRecognizer(goal: self, motion: #selector(handlePinchGesture(_:)))
arView.addGestureRecognizer(pinchGesture)
let rotateGesture = UIRotationGestureRecognizer(goal: self, motion: #selector(handleRotateGesture(_:)))
arView.addGestureRecognizer(rotateGesture)
}
@objc func handleRotateGesture(_ gesture: UIRotationGestureRecognizer) {
guard let currentFrame = arView.session.currentFrame else {
return
}
let rotation = Float(gesture.rotation)
let rotationDelta = simd_quatf(angle: rotation, axis: simd_float3(1, 1, 1))
let usdzNode = arView.scene.rootNode.childNodes.first!
let usdzTransform = usdzNode.simdTransform
let newTransform = simd_mul(usdzTransform, simd_float4x4(rotationDelta))
usdzNode.simdTransform = newTransform
gesture.rotation = 0
}
@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
guard let currentFrame = arView.session.currentFrame else {
return
}
let translation = gesture.translation(in: arView)
let deltaX = Float(translation.x) / Float(arView.bounds.width)
let deltaY = Float(translation.y) / Float(arView.bounds.peak)
let usdzNode = arView.scene.rootNode.childNodes.first!
var usdzTransform = usdzNode.simdTransform
// Get the digital camera's orientation in world area
let digital camera = currentFrame.digital camera
let cameraTransform = digital camera.remodel.inverse
// let cameraForward = cameraTransform.ahead
let rotationFactor: Float = 10.0
// Rotate the USDZ object all over the world Y and X axes based mostly on gesture translation
usdzTransform *= simd_float4x4(simd_quatf(angle: -deltaX * rotationFactor, axis: simd_float3(0, 1, 0)))
usdzTransform *= simd_float4x4(simd_quatf(angle: deltaY * rotationFactor, axis: simd_float3(1, 0, 0)))
usdzNode.simdTransform = usdzTransform
gesture.setTranslation(CGPoint.zero, in: arView)
}
@objc func handlePinchGesture(_ gesture: UIPinchGestureRecognizer) {
guard let currentFrame = arView.session.currentFrame else {
return
}
let usdzNode = arView.scene.rootNode.childNodes.first!
let usdzTransform = usdzNode.simdTransform
var scaleMatrix = matrix_identity_float4x4
let scale = Float(gesture.scale)
scaleMatrix.columns.0.x = scale
scaleMatrix.columns.1.y = scale
scaleMatrix.columns.2.z = scale
let newTransform = simd_mul(usdzTransform, scaleMatrix)
usdzNode.simdTransform = newTransform
gesture.scale = 1
}
func addTapGesture()
{
let faucet = UITapGestureRecognizer(goal: self, motion: #selector(handleTap(_:)))
arView.addGestureRecognizer(faucet)
}
@objc func handleTap(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: arView)
let hitResults = arView.hitTest(location, choices: nil)
if let hitNode = hitResults.first?.node {
showPopup(nextTo: hitNode)
tapgest = UITapGestureRecognizer(goal: self, motion: #selector(closePopup))
arView.addGestureRecognizer(tapgest)
isShow = true
}
}
@objc func dismissPopupView() {
// popupView.alpha = 0
}
func setUpPopUpView(){
popupView = CustomViewAR().loadNib() as! CustomViewAR
let geocoder = CLGeocoder()
let location = CLLocation(latitude: latitude, longitude: longitude)
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
guard error == nil else {
print("Error: (error!)")
return
}
guard let placemark = placemarks!.first else {
print("Error: placemark is nil")
return
}
let handle = "(placemark.identify ?? "Couldn't discover information"), ( placemark.locality ?? "No Metropolis"), ( placemark.administrativeArea ?? "No Administrative Space"), ( placemark.nation ?? "No Nation")"
self.popupView.setValues(labelName: placemark.identify!, placeAddress: handle)
}
}
func showPopup(nextTo node: SCNNode) {
popupView.isHidden = false
setUpPopUpView()
popupView.bringSubviewToFront(popupView.lblAddress)
popupView.bringSubviewToFront(popupView.lblPlaceName)
popupView.lblAddress.textColor = UIColor.black
let worldPosition = node.simdWorldPosition - 30
let x = worldPosition.x + 30 // modify as wanted
let y = worldPosition.y + 30// modify as wanted
popupView.body = CGRect(x: Int(x), y: Int(y), width: 250, peak: 250)
popupPlane.width = 60 // modify as wanted
popupPlane.peak = 60 // modify as wanted
popupPlane.cornerRadius = 10
popupPlane.firstMaterial?.diffuse.contents = popupView
popupNode = SCNNode(geometry: popupPlane)
// popupNode.place = SCNVector3(0, 0, -1000)
popupNode.opacity = 0.8
popupNode.simdWorldPosition = worldPosition // set place utilizing simdWorldPosition
let constraint = SCNBillboardConstraint()
constraint.freeAxes = [.Y]
popupNode.constraints = [constraint]
arView.scene.rootNode.addChildNode(popupNode)
// Animate the popup to look
SCNTransaction.start()
SCNTransaction.animationDuration = 0.5
SCNTransaction.commit()
}
@objc func closePopup() {
if isShow == true {
SCNTransaction.start()
SCNTransaction.animationDuration = 0.5
popupView.alpha = 0
SCNTransaction.commit()
popupView.isHidden = true
let configuration = ARWorldTrackingConfiguration()
arView.session.run(configuration, choices: [.resetTracking, .removeExistingAnchors])
arView.setNeedsDisplay()
popupNode.isHidden = true
isShow = false
arView.removeGestureRecognizer(tapgest)
setUpPopUpView()
} else {
}
}
func addAnimation(node: SCNNode) {
let rotateOne = SCNAction.rotateBy(x: 0, y: CGFloat(Float.pi), z: 0, period: 5.0)
let hoverUp = SCNAction.moveBy(x: 0, y: 0.2, z: 0, period: 2.5)
let hoverDown = SCNAction.moveBy(x: 0, y: -0.2, z: 0, period: 2.5)
let hoverSequence = SCNAction.sequence([hoverUp, hoverDown])
let rotateAndHover = SCNAction.group([rotateOne, hoverSequence])
let repeatForever = SCNAction.repeatForever(rotateAndHover)
node.runAction(repeatForever)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive contact: UITouch) -> Bool {
if contact.view == popupView || contact.view?.isDescendant(of: popupView) == true {
return false
}else{
popupView.alpha = 0
return true
}
}
@IBAction func backBtnTapped(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
}
extension ARViewController: ARSCNViewDelegate, SCNSceneRendererDelegate {
func session(_ session: ARSession,
didFailWithError error: Error) {
print("Session Failed - most likely as a result of lack of digital camera entry")
}
func sessionWasInterrupted(_ session: ARSession) {
print("Session interrupted")
}
func sessionInterruptionEnded(_ session: ARSession) {
print("Session resumed")
}
}
extension UIView {
/** Masses occasion from nib with the identical identify. */
func loadNib() -> UIView {
let bundle = Bundle(for: kind(of: self))
let nibName = "CustomViewAR"
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, choices: nil).first as! UIView
}
}