ARKit, ScenceKit. How to render several SCNNode?

У меня есть моя routeFinishNode

 var routeFinishNode: SCNNode? = nil {
    didSet {
       oldValue?.removeFromParentNode()
        if let node = routeFinishNode {
          sceneView.scene.rootNode.addChildNode(node)
        }
     }
  }

Также у меня есть массив маршрутов

private var routes: [MKRoute] = []

Передо мной стоит задача отобразить метки на сцене с использование кастомной вьюшки и лейбла для отображения дистанции до объекта.

Моя вьюшка и лейбел:

var routeFinishView: UIView? = nil {
        didSet {
            oldValue?.removeFromSuperview()
            if let routeFinishView = routeFinishView {
                view.addSubview(routeFinishView)
            }
        }
    }

    var routeDistanceLabel: UILabel? = nil {
        didSet {
            oldValue?.removeFromSuperview()
            if let label = routeDistanceLabel {
                view.addSubview(label)
            }
        }
    

Что я делаю: я прохожусь по массиву маршрутов и инициализирую ноду, вьюшку и лейбел:

func showRouteFinishNodes() {
    routes.forEach { (route) in
      let routePointsCount = route.polyline.pointCount
      let routePoints = route.polyline.points()
      var geoRoute: [CLLocationCoordinate2D] = []
      for pointIndex in 0..<routePointsCount {
        let point: MKMapPoint = routePoints[pointIndex]
        geoRoute.append(MKCoordinateForMapPoint(point))
      }
      
      let route = geoRoute
        .map { engine.convert(coordinate: $0) }
        .compactMap { $0 }
        .map { CGPoint(position: $0) }
      
      guard route.count == geoRoute.count else {
        return
      }
      
      guard let routeFinishPoint = route.last else { return }
      
      let node = SCNNode()
      node.position = routeFinishPoint.positionIn3D
      nodesArray.append(node)
    }
    
      nodesArray.forEach {
        
        print($0.position)
        routeFinishNode = $0
        sceneView.scene.rootNode.addChildNode(routeFinishNode ?? SCNNode())
        print(sceneView.scene.rootNode.childNodes.count)
        
        routeFinishHint = makeFinishNodeHint()
        routeFinishView = makeFinishNodeView()
        routeDistanceLabel = makeDistanceLabel()
      }
      
  }

Для отображения и рендеринга вьюшки и лейбла я использую делегат renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval)

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
        guard let routeFinishNode = routeFinishNode else { return }
        print(routeFinishNode.position)
        guard let parent = routeFinishNode.parent else { return }
        guard let pointOfView = renderer.pointOfView else { return }

        let bounds = UIScreen.main.bounds

        let positionInWorld = routeFinishNode.worldPosition
        let positionInPOV = parent.convertPosition(routeFinishNode.position, to: pointOfView)
        let projection = sceneView.projectPoint(positionInWorld)
        let projectionPoint = CGPoint(x: CGFloat(projection.x), y: CGFloat(projection.y))

        let annotationPositionInRFN = SCNVector3Make(0.0, 1.0, 0.0) // in Route finish node coord. system
        let annotationPositionInWorld = routeFinishNode.convertPosition(annotationPositionInRFN, to: nil)
        let annotationProjection = sceneView.projectPoint(annotationPositionInWorld)
        let annotationProjectionPoint = CGPoint(x: CGFloat(annotationProjection.x), y: CGFloat(annotationProjection.y))
        let rotationAngle = Vector2.y.angle(with: (Vector2(annotationProjectionPoint) - Vector2(projectionPoint)))

        let screenMidToProjectionLine = CGLine(point1: bounds.mid, point2: projectionPoint)
        let intersection = screenMidToProjectionLine.intersection(withRect: bounds)

        let povWorldPosition: Vector3 = Vector3(pointOfView.worldPosition)
        let routeFinishWorldPosition: Vector3 = Vector3(positionInWorld)
        let distanceToFinishNode = (povWorldPosition - routeFinishWorldPosition).length

        DispatchQueue.main.async { [weak self] in
            guard let slf = self else { return }
            guard let routeFinishHint = slf.routeFinishHint else { return }
            guard let routeFinishView = slf.routeFinishView else { return }
            guard let routeDistanceLabel = slf.routeDistanceLabel else { return }
            let placemarkSize = ViewController.finishPlacemarkSize(
                forDistance: CGFloat(distanceToFinishNode),
                closeDistance: 10.0,
                farDistance: 25.0,
                closeDistanceSize: 100.0,
                farDistanceSize: 50.0
            )

            let distance = floor(distanceToFinishNode)

            let point: CGPoint = intersection ?? projectionPoint
            let isInFront = positionInPOV.z < 0
            let isProjectionInScreenBounds: Bool = intersection == nil

            if slf.routeUISwitch.isOn {
                routeFinishHint.isHidden = (isInFront && intersection == nil)
                routeFinishView.isHidden = !routeFinishHint.isHidden
                routeDistanceLabel.isHidden = routeFinishView.isHidden
            } else {
                routeFinishHint.isHidden = true
                routeFinishView.isHidden = true
                routeDistanceLabel.isHidden = true
            }

            if isInFront {
                routeFinishHint.center = point
            } else {
                if isProjectionInScreenBounds {
                    routeFinishHint.center = CGPoint(
                        x: reflect(point.x, of: bounds.mid.x),
                        y: bounds.height
                    )
                } else {
                    routeFinishHint.center = CGPoint(
                        x: reflect(point.x, of: bounds.mid.x),
                        y: reflect(point.y, of: bounds.mid.y)
                    )
                }
            }

            routeFinishView.center = projectionPoint
            routeFinishView.bounds.size = CGSize(width: placemarkSize, height: placemarkSize)
            routeFinishView.layer.cornerRadius = placemarkSize / 2

            let distanceString = "\(distance) м"
            let distanceAttrStr = ViewController.distanceText(forString: distanceString)
            routeDistanceLabel.attributedText = distanceAttrStr
            routeDistanceLabel.center = projectionPoint
            let size = distanceAttrStr.boundingSize(width: .greatestFiniteMagnitude)
            routeDistanceLabel.bounds.size = size
            routeDistanceLabel.transform = CGAffineTransform(rotationAngle: CGFloat(rotationAngle - .pi))
        }
    }

Моя проблема заключается в том, что из всех созданных нод на сцене рендериться только одна - последняя из массива. Как сделать так, чтобы рендерилась каждая нода ?

Как работает сейчас:

Как отображается сейчас:

Как нужно чтобы работало:

введите сюда описание изображения


Ответы (0 шт):