如何将标签/UIView 固定到 ARKit 中的节点

How to pin a label / UIView to a node in ARKit

我想让 UILabel 位于 ARKit 中的节点之上,类似于 iOS 12 的 Measure 应用程序中的维度标签。 我试过将标签添加为平面节点并使用广告牌约束,但是当你离开时文本会变小,这并不理想。 在 WWDC 上,他们将此称为屏幕 Space,但没有说明如何实现它。

提前致谢!

尝试使用 SCNText 几何图形,几个月前我使用了以下代码:

    var txtNote    = SCNText()
    txtNote.string = "Hello AR word!"
    txtNote.font   = UIFont.systemFont(ofSize: 2)
    txtNote.extrusionDepth = 1.0
    txtNote.containerFrame = CGRect(x: 2.5, y: 0, width: 16, height: 10)
    txtNote.isWrapped      = true
    txtNote.alignmentMode  = kCAAlignmentLeft
    txtNote.materials.first?.diffuse.contents = UIColor.black.cgColor

    var txtNode = SCNNode(geometry: txtNote)

我想出了以下解决方案来让它工作。

首先,我创建了 UILabel 并将其添加为子视图。接下来,我将我要跟随的节点的位置转换为renderer(_: updateAtTime:)中的屏幕坐标。现在标签正确地跟随节点并保持固定比例。但是,标签与屏幕保持水平,这看起来很奇怪。为了使其与世界保持水平,我根据 ARCamera 的偏航(z 旋转)旋转标签。

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

    // Convert the node's position to screen coordinates
    let screenCoordinate = self.sceneView.projectPoint(node.position)

    DispatchQueue.main.async {
    // Move the label 
    label.center = CGPoint(x: CGFloat(screenCoordinate.x), y: CGFloat(screenCoordinate.y))

    // Hide the label if the node is "behind the screen"
    label.isHidden = (screenCoordinate.z > 1)

    // Rotate the label
    if let rotation = sceneView.session.currentFrame?.camera.eulerAngles.z {
        label.transform = CGAffineTransform(rotationAngle: CGFloat(rotation + Float.pi/2))
    }
    }

}