如何在屏幕中央添加一个立方体,让它永不离开?

How to add a cube in the center of the screen, and so that it never leaves?

下午好! 我是 SceneKit 的新手。而且我也解决不了这个问题。

我需要让立方体一直在屏幕中央并跟随相机直到找到水平线并站在上面。 我让它留在一个地方 这是我现在的简单代码。

        import UIKit
        import SceneKit
        import ARKit

        class ViewController: UIViewController, ARSCNViewDelegate {

            @IBOutlet var sceneView: ARSCNView!

            override func viewDidLoad() {
                super.viewDidLoad()


                let scene = SCNScene()


                let boxGeometry = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)


                let material = SCNMaterial()

                material.diffuse.contents = UIColor.blue
                material.specular.contents = UIColor(white: 0.6, alpha: 1.0)



                let boxNode = SCNNode(geometry: boxGeometry)
                boxNode.geometry?.materials = [material]


                boxNode.position = SCNVector3(0,0,-1.0)


                scene.rootNode.addChildNode(boxNode)

                sceneView.scene = scene


                //------------------------------------
                // Set the view's delegate
                sceneView.delegate = self

                // Show statistics such as fps and timing information
                sceneView.showsStatistics = true


                // Set the scene to the view
                sceneView.scene = scene
            }

            override func viewWillAppear(_ animated: Bool) {
                super.viewWillAppear(animated)

                // Create a session configuration
                let configuration = ARWorldTrackingConfiguration()

                // Run the view's session
                sceneView.session.run(configuration)
            }

            override func viewWillDisappear(_ animated: Bool) {
                super.viewWillDisappear(animated)

                // Pause the view's session
                sceneView.session.pause()
            }

       }

请帮帮我。不要骂)

这里更新了您的代码,以确保该框始终位于屏幕中央。一旦代码检测到平面,它就会将盒子的父级设置为平面锚点。

这一切都很原始,但应该对你有帮助。如果您希望节点浮动在屏幕中央,请取消注释 willRenderScene 回调中的 SCNTransactions。如果希望盒子始终面向用户,可以添加一个lookAtConstraint

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!
    var boxNode: SCNNode? // keep a reference to the cube

    override func viewDidLoad() {
        super.viewDidLoad()


        let scene = SCNScene()


        let boxNode = createBox()
        scene.rootNode.addChildNode(boxNode)
        self.boxNode = boxNode

        sceneView.scene = scene


        //------------------------------------
        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true


        // Set the scene to the view
        sceneView.scene = scene
    }

    func createBox() -> SCNNode {
        let boxGeometry = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)

        let material = SCNMaterial()
        material.diffuse.contents = UIColor.blue
        material.specular.contents = UIColor(white: 0.6, alpha: 1.0)

        let boxNode = SCNNode(geometry: boxGeometry)
        boxNode.geometry?.materials = [material]

        return boxNode;
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal

        // Run the view's session
        sceneView.session.run(configuration)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Pause the view's session
        sceneView.session.pause()
    }

    // on willRender update the cube's position.
    func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
        // get camera translation and rotation
        guard let pointOfView = sceneView.pointOfView else { return }
        let transform = pointOfView.transform // transformation matrix
        let orientation = SCNVector3(-transform.m31, -transform.m32, -transform.m33) // camera rotation
        let location = SCNVector3(transform.m41, transform.m42, transform.m43) // camera translation

        let currentPostionOfCamera = orientation + location
//        SCNTransaction.begin()
        if let boxNode = self.boxNode {
            boxNode.position = currentPostionOfCamera
        }
//        SCNTransaction.commit()
    }


    // detect plances
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        guard anchor is ARPlaneAnchor else { return }
        if let boxNode = self.boxNode {
            let newBoxNode = createBox() // create a new node for the center of the screen
            self.boxNode = newBoxNode
            SCNTransaction.begin()
            boxNode.removeFromParentNode()
            node.addChildNode(boxNode) // set the current box to the plane.
            sceneView.scene.rootNode.addChildNode(newBoxNode) // add the new box node to the scene
            SCNTransaction.commit()
        }

    }
}

extension SCNVector3 {
    static func + (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
        return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
    }
}