The right way to repair the place of a 3D usdz object within the centre of the display screen. ios Swift

0
754


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
    }
}