Я настраиваю 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
}