我正在iPhone 7上设置ARKit-App
,并且在检测到第一个(三分之一)ARImageAnchor
时面临屏幕冻结的问题。要将SCNNodes引入UIView,我正在ARSCNViewDelegate中使用func renderer-didAdd方法。为了在不同ARReferenceImages
的逻辑(对于所有场景几乎相等)之间进行切换,我使用了switch-case语句。此外,我将DispatchQueue.main.async-Statement用于多线程目的。在三个不同的.scn-Scenes中提供3D内容(请参见代码)。
此问题的奇怪之处在于,屏幕在加载第一个场景(仅一个对象)时会冻结一小段时间,但是在加载场景2和3(包含多个更复杂的对象)时会平稳运行。
为解决此问题,我已经尝试将DispatchQueue语句移到不同的位置-似乎不影响冻结。另外,我查看了统计信息,发现CPU在冻结到100%忙于从屏幕1渲染3D内容。
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
}