ARKit - Как исправить зависание экрана при вызове рендера func (_ рендер: SCNSceneRenderer, узел didAdd: SCNNode, для якоря: ARAnchor) - PullRequest
0 голосов
/ 02 июля 2019

Я настраиваю ARKit-App на iPhone 7 и сталкиваюсь с коротким зависанием экрана, как только обнаруживается первый (из трех) ARImageAnchor. Чтобы представить узлы SCN в UIView, я использую метод func renderer-didAdd в ARSCNViewDelegate. Чтобы переключаться между логикой, которая почти одинакова для всех сцен, различных ARReferenceImages, я использую оператор switch-case. Кроме того, я использую DispatchQueue.main.async-Statement для целей многопоточности. 3D-контент предоставляется в трех разных .scn-сценах (см. Код).

Странная вещь в этой проблеме заключается в том, что экран зависает на короткий период времени, когда загружается первая сцена (только один объект), но работает плавно при загрузке сцены 2 и 3 (с несколькими более сложными объектами).

Для решения этой проблемы я уже пытался переместить операторы DispatchQueue в разные позиции - что, похоже, не влияет на зависание. Кроме того, я посмотрел статистику и обнаружил, что процессор во время остановки до 100% занят рендерингом 3D-контента с экрана 1.

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    //
        if let imageAnchor = anchor as? ARImageAnchor {
            DispatchQueue.main.async {
            let name = imageAnchor.referenceImage.name!
            switch name {

            // Adding 3D Content associated with Marker A to positionImageAnchorA
            case "Trigger_A":   print ("Anchor A Deteced") //Debug
                                let boxNode = createImageOverlayNode(for: imageAnchor, DisScene: self.DisassemblySceneA)
                                self.positionImageAnchorA = boxNode
                                self.disStateCounter = 1
                                self.MarkerTracked.append(ARMarker(name: name, node: self.positionImageAnchorA)) // Information for Marker.isTracked?
                                self.MarkerADetected = true
                                node.addChildNode(self.positionImageAnchorA!)
                                return
            // Adding 3D Content associated with Marker B to positionImageAnchorB
            case "Trigger_B":   print ("Anchor B Deteced") //Debug
                                self.MarkerBDetected = true
                                self.MarkerTracked.append(ARMarker(name: name, node: self.positionImageAnchorB)) // Information for Marker.isTracked?
                                let boxNode = createImageOverlayNode(for: imageAnchor, DisScene: self.DisassemblySceneB)
                                self.positionImageAnchorB = boxNode
                                node.addChildNode(self.positionImageAnchorB!)
                                return

            // Adding 3D Content associated with Marker C to PositionImageAnchorC
            case "Trigger_C":   print ("Anchor C detected") // Debug
                                self.MarkerCDetected = true
                                self.MarkerTracked.append(ARMarker(name: name, node: self.positionImageAnchorC)) // Information for Marker.isTracked?
                                let boxNode = createImageOverlayNode(for: imageAnchor, DisScene: self.DisassemblySceneC)
                                self.positionImageAnchorC = boxNode
                                node.addChildNode(self.positionImageAnchorC!)
                                return
            // Default closing statement
            default: return

            }
        }
    }
}

/////////////////////////////////////////////////////////////////////
If interested in the logic createImageOverlayNode - please see below:
/////////////////////////////////////////////////////////////////////

func createImageOverlayNode(for anchor: ARImageAnchor, DisScene: SCNNode) -> SCNNode? {

// Creating green box for visualization of Tracking of AR Reference Image
    let box = SCNBox(width: anchor.referenceImage.physicalSize.width, height: 0.001, length: anchor.referenceImage.physicalSize.height, chamferRadius: 0)
    if let material = box.firstMaterial {
        material.diffuse.contents = UIColor.green
        material.transparency = 0.3
    }
    let boxNode = SCNNode(geometry: box)
    boxNode.name = "AR_Marker_B"

// Creating rootNode (Position of ARAnchor)
let rootNode = SCNNode()
rootNode.addChildNode(boxNode)

// Creating plane for showing 2D Text for spring removal and position in correctly
let planeForSpringNode = createTextOutputForSpringRemoval(anchor: anchor)
planeForSpringNode.name = "SpringRemoval"
planeForSpringNode.eulerAngles.x = -.pi / 2
planeForSpringNode.position = SCNVector3 (-0.06,0.016,0.016)

// Creating plane for showing 2D Arrow and position it correctly
let planeBoldNode = createBoldPlane()
planeBoldNode.name = "BoldRemoval"
planeBoldNode.eulerAngles.x = -.pi / 2

// Adding 3D Content to rootNode (Position of AR Anchor)
if DisScene.name == Optional("Scene_A") {
            rootNode.addChildNode(DisScene)
            return rootNode
}
else if DisScene.name == Optional("Scene_B") {

        // Adding 3D Content constructed via code (in here)
        rootNode.addChildNode(planeForSpringNode)
        rootNode.addChildNode(planeBoldNode)

        // Adding all ChildNodes of DisScene as ChildNodes of "boxnode"
        DisScene.childNodes.forEach{ element in
            addChildNodes(destinationNode: rootNode, sourceNode: element)
            print (element)
        }


        // Hiding all ChildNodes of "boxnode" -> Unhide in ARSCNDelegate when needed
        rootNode.childNodes.forEach{ element in
            hideSCNNodeWithMarkerPlane(inputNode: element)
            }

        // Positioning constructed planes to SCNNodes Coordinates
        let positionFederhalterLang = rootNode.childNode(withName: "Federhalter_lang", recursively: false)!.position
        let positionSpring = rootNode.childNode(withName: "Feder", recursively: false)!.position
        rootNode.childNode(withName: "BoldRemoval", recursively: false)!.position = positionFederhalterLang
        rootNode.childNode(withName: "SpringRemoval", recursively: false)!.position = addTwoVectors(first: positionSpring,second: SCNVector3(0,0,-0.01))

        // Hide green box for AR Reference Image again
        rootNode.childNode(withName: boxNode.name!, recursively: false)!.isHidden = true

        return rootNode
    }

else if DisScene.name == Optional("Scene_C"){

    // Adding all ChildNodes of DisScene as ChildNodes of "boxnode"
    DisScene.childNodes.forEach{ element in
        addChildNodes(destinationNode: rootNode, sourceNode: element)
    }
    // Hiding all ChildNodes of "boxnode" -> Unhide in ARSCNDelegate when needed
    rootNode.childNodes.forEach{ element in
        hideSCNNodeWithMarkerPlane(inputNode: element)
    }
    // Hide green box for AR Reference Image again
    rootNode.childNode(withName: boxNode.name!, recursively: false)!.isHidden = true

    return rootNode
}
return nil
}
...