创建类似于Apple焦点方块的对象放置指示器

时间:2018-06-18 02:25:30

标签: swift scenekit augmented-reality arkit

处理我的第一个ARKit项目,我使用水平平面检测将3d模型放置在水平面上。

我试图使用焦点方块,但作为一个Swift新手,我无法想象如何使用它。所以我想创建自己的静态指标。

我的方法是创建一个SCNPlane作为指标。但是,我的SCNPlane并不像Apple的焦点广场那样快速移动,所以我需要帮助我的代码。

这是我的代码:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

    // Create a SceneKit plane to visualize the node using its position and extent.
    let plane = SCNPlane(width: CGFloat(0.1), height: CGFloat(0.1))
    let planeNode = SCNNode(geometry: plane)
    let planeMaterial = SCNMaterial()
    planeMaterial.diffuse.contents = UIColor.gray.withAlphaComponent(0.3)
    plane.materials = [planeMaterial]
    planeNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z)

    // SCNPlanes are vertically oriented in their local coordinate space.
    // Rotate it to match the horizontal orientation of the ARPlaneAnchor.
    planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)

    // ARKit owns the node corresponding to the anchor, so make the plane a child node.
    node.addChildNode(planeNode)
}

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard let planeAnchor = anchor as?  ARPlaneAnchor,
        let planeNode = node.childNodes.first,
        let plane = planeNode.geometry as? SCNPlane
        else { return }
    let x = CGFloat(planeAnchor.center.x)
    let y = CGFloat(planeAnchor.center.y)
    let z = CGFloat(planeAnchor.center.z)
    planeNode.position = SCNVector3(x, y, z)
}

不确定这是否是正确的做法?如果你们有正确的方法,请告诉我

2 个答案:

答案 0 :(得分:0)

我想它必须以这种方式大致工作:

class ViewController: UIViewController {

    @IBOutlet var sceneView: ARSCNView!
    var focusSquare = FocusSquare() // custom class instantiation

    // ............................

    var session: ARSession {
        return sceneView.session
    }
    override func viewDidLoad() {
        super.viewDidLoad()   
        sceneView.delegate = self
        sceneView.session.delegate = self

        sceneView.scene.rootNode.addChildNode(focusSquare)
    }    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        resetTracking()
    } 
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        session.pause()
    }
    func resetTracking() {
        virtualObjectInteraction.selectedObject = nil     
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal, .vertical]
        session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
        statusViewController.scheduleMessage("PLEASE, FIND A SURFACE", inSeconds: 5.0, messageType: .planeEstimation)
    }
    func updateFocusSquare(isObjectVisible: Bool) {
        if isObjectVisible {
            focusSquare.hide()
        } else {
            focusSquare.unhide()
            statusViewController.scheduleMessage("MOVE LEFT-RIGHT", inSeconds: 5.0, messageType: .focusSquare)
        }
        if let camera = session.currentFrame?.camera, case .normal = camera.trackingState,
            let result = self.sceneView.smartHitTest(screenCenter) {
            updateQueue.async {
                self.sceneView.scene.rootNode.addChildNode(self.focusSquare)
                self.focusSquare.state = .detecting(hitTestResult: result, camera: camera)
        }
            addObjectButton.isHidden = false
            statusViewController.cancelScheduledMessage(for: .focusSquare)
        } else {
            updateQueue.async {
                self.focusSquare.state = .initializing
                self.sceneView.pointOfView?.addChildNode(self.focusSquare)
            }
            addObjectButton.isHidden = true
        }
    }
}

您可以下载Apple的示例项目here,您可以在其中查看如何创建FocusSquare()课程。

答案 1 :(得分:0)

Apple的焦点方形平滑行为是由于" virtualObjectLoader" class与" updateAtTime"和" didUpdate"渲染器函数的实现

只需看看这三个元素,您就会找到正确的方法

如果有任何问题

,请在添加这些概念后发布您的代码