How do you convert a SCNVector3 from local coord, to world coord to screen space in ARSCNView

I want to get the corner coordinates of a plane that ARKit has identified into the ARSCNView screen coordinates.


I've started by adapting Apple's example for creating the planes, so I have a Plane class:


    class Plane : SCNNode {
       
        var anchor : ARPlaneAnchor
       
        init(anchor : ARPlaneAnchor) {
            self.anchor = anchor
            super.init()
           
            self.geometry = SCNPlane(width: CGFloat(Float(anchor.extent.x)), height: CGFloat(anchor.extent.z))
            self.rotation = SCNVector4Make(1.0, 0.0, 0.0, -Float.pi/2.0)
            let material = SCNMaterial()
            material.diffuse.contents = UIColor.yellow
            material.specular.contents = UIColor.white
            self.geometry?.firstMaterial = material
        }
       
        required init?(coder aDecoder: NSCoder) {
            fatalError("Error")
        }
       
        func update(anchor: ARPlaneAnchor) {
            self.anchor = anchor
            if let plane = self.geometry as? SCNPlane {
                plane.width = CGFloat(anchor.extent.x)
                plane.height = CGFloat(anchor.extent.z)
            }
        }
    }


And the ARSCNViewDelegate methods in the view controller to identify and update it:



  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        if let planeAnchor = anchor as? ARPlaneAnchor {
            let plane = Plane(anchor: planeAnchor)
            node.addChildNode(plane)
            planes[planeAnchor] = plane
            print("plane = \(plane)")
        }
       
    }
   
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        if let planeAnchor = anchor as? ARPlaneAnchor {
            planes[planeAnchor]?.update(anchor: planeAnchor)
        }
    }
   
    func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
        if let planeAnchor = anchor as? ARPlaneAnchor {
            planes.removeValue(forKey: planeAnchor)
        }
    }


As I understand it, the plane has it's own local coordinate space in scene kit, so I want to to just create 4 SCNVector3 values, and convert them from the Plane's local space to the scene's world coordinate space, and from them, project them to the screen's space.


This is how I'm doing it:


       func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
            for (_, aPlane) in planes {
                // Vectors representing the corners of the plane
                let maxX = aPlane.anchor.extent.x/2.0
                let minX = -maxX
                let minY = aPlane.anchor.extent.z/2.0
                let maxY = -minY
               
                var point1 = SCNVector3Make(minX, 0.0, minY)
                var point2 = SCNVector3Make(maxX, 0.0, minY)
                var point3 = SCNVector3Make(maxX, 0.0, maxY)
                var point4 = SCNVector3Make(minX, 0.0, maxY)
    //            var point1 = SCNVector3Make(minX, minY, 0.0)
    //            var point2 = SCNVector3Make(maxX, minY, 0.0)
    //            var point3 = SCNVector3Make(maxX, maxY, 0.0)
    //            var point4 = SCNVector3Make(minX, maxY, 0.0)
   
                print("initial nodes ------------------")
                print("point1 = \(point1)")
                print("point2 = \(point2)")
                print("point3 = \(point3)")
                print("point4 = \(point4)")
   
                // Get the root node and convert the coords from the plane's coord system
                let rootNode = sceneView.scene.rootNode
                point1 = rootNode.convertVector(point1, from: aPlane)
                point2 = rootNode.convertVector(point2, from: aPlane)
                point3 = rootNode.convertVector(point3, from: aPlane)
                point4 = rootNode.convertVector(point4, from: aPlane)
   
                print("first conversion nodes ------------------")
                print("point1 = \(point1)")
                print("point2 = \(point2)")
                print("point3 = \(point3)")
                print("point4 = \(point4)")
   
                // Finally, project them to the screen view
                point1 = sceneView.projectPoint(point1)
                point2 = sceneView.projectPoint(point2)
                point3 = sceneView.projectPoint(point3)
                point4 = sceneView.projectPoint(point4)
                print("final conversion nodes ------------------")
                print("point1 = \(point1)")
                print("point2 = \(point2)")
                print("point3 = \(point3)")
                print("point4 = \(point4)")
            }
        }

However, whatever I do, when I have a plane in full view, I still get coordinates outside the bounds of the view. I'm pretty sure it's something simple, but I've tried many combinations now

How do you convert a SCNVector3 from local coord, to world coord to screen space in ARSCNView
 
 
Q