ARKit使用“ UIView”作为“ SCNNode”中的内容

时间:2018-07-10 17:48:32

标签: ios swift scenekit augmented-reality arkit

我有一个奇怪的问题,或者也许我在做的事情很奇怪。

我有一个ARKit应用,当检测到条形码时,该应用会显示一个SCNNode,其中嵌入了数据视图。当点击数据视图时,我想将其与节点分离,并将其作为子视图添加到主视图中。再次点击时,我想将其重新连接到SCNNode。

我发现this code至少完成了我想要的部分。

我的应用程序第一次运行良好。数据出现在SCNNode中:

{
    let transform = anchor.transform
    let label = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)


    let plane = SCNPlane(width: self.sceneView.bounds.width/2000, height: self.sceneView.bounds.height/2000/2)  //was sceneView

    label.update(dataItem.title!, andValue: dataItem.value!, withTrend: dataItem.trend)
    label.delegate = self

    plane.firstMaterial?.blendMode = .alpha
    plane.firstMaterial?.diffuse.contents = label.view //self.contentController?.view

    let planeNode = SCNNode(geometry: plane)
    planeNode.opacity = 0.75
    planeNode.simdPosition = float3(transform.columns.3.x + ( base * count), 0, transform.columns.3.z)
    node.addChildNode(planeNode)
    childControllers[label] = planeNode
    label.myNode = planeNode
    label.parentNode = node

    if("Speed" == anchorLabels[anchor.identifier]!) {

        let constraint = SCNBillboardConstraint()
        planeNode.constraints = [constraint]
    }  
    count += 1
}

SimpleValueViewController具有一个点击识别器,可以在子视图和节点内部之间切换。

这是问题所在。

它很好。该视图位于节点内部。

点击时,它会附加到主视图。

再次点按该节点只会显示一个白色正方形,而点按不再有效。

我最终放弃了并重新创建了一个新的viewController,但偶尔还是会失败,只有一个白色正方形:

这是分离/附加的代码,因为我一直在研究它一段时间,所以很混乱:

func detach(_ vc:Detachable) {

    if let controller = vc as? SimpleValueViewController {
        controller.view.removeFromSuperview();
        self.childControllers.removeValue(forKey: controller)
        let node = controller.myNode
        let parent = controller.parentNode
        let newController = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)
        if let v = newController.view {
            print("View: \(v)")
            newController.myNode = node
            newController.parentNode = parent
            newController.update(controller.titleString!, andValue: controller.valueString!, withTrend: controller.trendString!)
            newController.delegate = self
            newController.scaley = vc.scaley
            newController.scalex = vc.scalex
            newController.refreshView()

            let plane = node?.geometry as!  SCNPlane
            plane.firstMaterial?.blendMode = .alpha
            plane.firstMaterial?.diffuse.contents = v
           // newController.viewWillAppear(false)
            newController.parentNode?.addChildNode(newController.myNode!)
            newController.attached = false;
            self.childControllers[newController] = node
        }  
    } else {
        print("Not a know type of controller")
    }
}

func attach(_ vc:Detachable) {
    DispatchQueue.main.async {
    if let controller = vc as? SimpleValueViewController {
        self.childControllers.removeValue(forKey: controller)
        let newController = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)
        let node = controller.myNode
        let parent = controller.parentNode

        let scaleX = vc.scalex!/self.view.frame.size.width
        let scaleY = vc.scaley!/self.view.frame.size.height
        let scale = min(scaleX, scaleY)

        let transform = CGAffineTransform(scaleX: scale, y: scale)
        newController.view.transform = transform
        newController.myNode = node
        newController.parentNode = parent
        newController.update(controller.titleString!, andValue: controller.valueString!, withTrend: controller.trendString!)
        newController.delegate = self
        newController.scaley = vc.scaley
        newController.scalex = vc.scalex
        node?.removeFromParentNode()
        self.childControllers[newController] = node

        newController.attached = true

        self.view.addSubview(newController.view)
    } else {
        print("Not a know type of controller to attach")
    }
    }
}

我当时认为这是一个时序问题,因为从笔尖加载视图的工作很懒惰,所以我在SimpleValueViewController(nibName:“ SimpleValueViewController”,bundle:nil)之后进入睡眠状态1秒钟,但这没有帮助。

还有什么我可以尝试的吗?我离基地远吗?我希望不必在每次切换数据时都重新创建视图控制器。

谢谢。

渲染功能:

func renderer(_ renderer:SCNSceneRenderer,didAdd节点:SCNNode,锚点:ARAnchor){

// func renderer(_ renderer:SCNSceneRenderer,nodeFor锚点:ARAnchor)-> SCNNode? {

// updateQueue.async {

//Loop through the near and far data and add stuff

let data = "Speed" == anchorLabels[anchor.identifier]! ? nearData : farData
let base = "Speed" == anchorLabels[anchor.identifier]! ? 0.27 : 0.2 as Float
print ("Getting Node for: " + self.anchorLabels[anchor.identifier]!)
var count = 0.0 as Float
for dataItem in data {
    let transform = anchor.transform
    let label = SimpleValueViewController(nibName: "SimpleValueViewController", bundle: nil)


    let plane = SCNPlane(width: self.sceneView.bounds.width/2000, height: self.sceneView.bounds.height/2000/2)  //was sceneView

    label.update(dataItem.title!, andValue: dataItem.value!, withTrend: dataItem.trend)
    label.delegate = self

    plane.firstMaterial?.blendMode = .alpha
    plane.firstMaterial?.diffuse.contents = label.view //self.contentController?.view

    let planeNode = SCNNode(geometry: plane)
    planeNode.opacity = 0.75
    planeNode.simdPosition = float3(transform.columns.3.x + ( base * count), 0, transform.columns.3.z)
    node.addChildNode(planeNode)
    childControllers[label] = planeNode
    label.myNode = planeNode
    label.parentNode = node

    if("Speed" == anchorLabels[anchor.identifier]!) {
        let constraint = SCNBillboardConstraint()
        planeNode.constraints = [constraint]         
    } 
    count+=1
}

并更新

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

    guard currentBuffer == nil else {
        return
    }
    self.updateFocusSquare(isObjectVisible: false)
    // Retain the image buffer for Vision processing.
    self.currentBuffer = sceneView.session.currentFrame?.capturedImage
    classifyCurrentImage() 
}

ClassifyCurrentImage是条形码识别器所在的位置。如果找到条形码,它将在场景中的位置添加锚点。

0 个答案:

没有答案