Как добавить куб в центр экрана, чтобы он никогда не уходил? - PullRequest
1 голос
/ 24 марта 2020

Добрый день! Я новичок в 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()
            }

       }

Помогите мне, пожалуйста. Не ругайтесь)

1 Ответ

1 голос
/ 26 марта 2020

Вот обновление вашего кода, которое гарантирует, что поле всегда находится в центре экрана. Как только код обнаруживает плоскость, он устанавливает родителя блока в качестве привязки плоскости.

Это все очень примитивно, но должно помочь вам. Если вы хотите, чтобы узел плавал в центре экрана, раскомментируйте SCNTransaction s в обратном вызове willRenderScene. Если вы хотите, чтобы окно всегда было лицом к пользователю, вы можете добавить 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)
    }
}
...