ARKit - 如何在另一个 SCNNode 中包含 SCNText(语音气泡) [英] ARKit - How to contain SCNText within another SCNNode (speech bubble)

查看:30
本文介绍了ARKit - 如何在另一个 SCNNode 中包含 SCNText(语音气泡)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 ARKit 的对话气泡中创建一个带有简单文本的报价生成器.

我可以用文字显示对话泡泡,但文字总是从中间开始并溢出对话泡泡之外.

任何帮助使其在对话气泡的左上角对齐并在对话气泡内环绕将不胜感激.

结果

课程

class SpeechBubbleNode: SCNNode {私人让 textNode = TextNode()var 字符串:字符串?{已设置{textNode.string = 字符串}}覆盖初始化(){超级初始化()//会话框让平面 = SCNPlane(宽度:200.0,高度:100.0)平面角半径 = 4.0plane.firstMaterial?.isDoubleSided = true几何 = 平面//文本节点textNode.position = SCNVector3(position.x, position.y, position.z + 1.0)//textNode.position = convertPosition(SCNVector3(0.0, 0.0, 1.0), to: textNode)//textNode.position = SCNVector3(0.0, 0.0, position.z + 1.0)添加子节点(文本节点)}需要初始化?(编码器aDecoder:NSCoder){super.init(编码器:aDecoder)}}类文本节点:SCNNode {私人让 textGeometry = SCNText()var 字符串:字符串?{已设置{更新TextContainerFrame()textGeometry.string = 字符串}}覆盖初始化(){超级初始化()textGeometry.truncationMode = CATextLayerTruncationMode.middle.rawValuetextGeometry.isWrapped = truetextGeometry.alignmentMode = CATextLayerAlignmentMode.left.rawValue让 blackMaterial = SCNMaterial()blackMaterial.diffuse.contents = UIColor.blackblackMaterial.locksAmbientWithDiffuse = truetextGeometry.materials = [blackMaterial]几何 = 文本几何}需要初始化?(编码器aDecoder:NSCoder){super.init(编码器:aDecoder)}私有 func updateTextContainerFrame() {让(最小,最大)= boundingBox让宽度 = CGFloat(max.x - min.x)让高度 = CGFloat(max.y - min.y)打印(宽度:",max.x - min.x,高度:",max.y - min.y,深度:",max.z - min.z)textGeometry.containerFrame = CGRect(x: 0.0, y: 0.0, width: width, height: height)//textGeometry.containerFrame = CGRect(origin: .zero, size: CGSize(width: 1.0, height: 1.0))}}

实施

private func makeSpeechBubbleNode(forBobbleheadNode bobbleheadNode: BobbleheadNode) {让节点 = SpeechBubbleNode()node.position = sceneView.scene.rootNode.convertPosition(bobbleheadNode.position, to: node)node.scale = SCNVector3(0.002, 0.002, 0.002)sceneView.scene.rootNode.addChildNode(speechBubbleNode)self.speechBubbleNode = SpeechBubbleNodeSpeechBubbleNode.string = "一些可能很长的随机字符串,应该包含在语音气泡中"}

解决方案

我遇到了同样的问题,最后我解决了如下:

  • 创建一个 SCNText 并将其作为几何图形添加到 SCNNode:

    let string = "用平面覆盖文本:)"让文本 = SCNText(字符串:字符串,挤压深度:0.1)text.font = UIFont.systemFont(ofSize: 1)文本.平坦度 = 0.005让 textNode = SCNNode(几何:文本)让 fontScale: Float = 0.01textNode.scale = SCNVector3(fontScale, fontScale, fontScale)

  • I am trying to create a quote generator with simple text within a speech bubble in ARKit.

    I can show the speech bubble with text, but the text always starts in the middle and overflows outside of the speech bubble.

    Any help getting it align in the top left of the speech bubble and wrapping within the speech bubble would be appreciated.

    Result

    Classes

    class SpeechBubbleNode: SCNNode {
        private let textNode = TextNode()
    
        var string: String? {
            didSet {
                textNode.string = string
            }
        }
    
        override init() {
            super.init()
    
            // Speech Bubble
            let plane = SCNPlane(width: 200.0, height: 100.0)
            plane.cornerRadius = 4.0
            plane.firstMaterial?.isDoubleSided = true
            geometry = plane
    
            // Text Node
            textNode.position = SCNVector3(position.x, position.y, position.z + 1.0)
    //        textNode.position = convertPosition(SCNVector3(0.0, 0.0, 1.0), to: textNode)
    //        textNode.position = SCNVector3(0.0, 0.0, position.z + 1.0)
            addChildNode(textNode)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    }
    
    class TextNode: SCNNode {
        private let textGeometry = SCNText()
    
        var string: String? {
            didSet {
                updateTextContainerFrame()
                textGeometry.string = string
            }
        }
    
        override init() {
            super.init()
    
            textGeometry.truncationMode = CATextLayerTruncationMode.middle.rawValue
            textGeometry.isWrapped = true
            textGeometry.alignmentMode = CATextLayerAlignmentMode.left.rawValue
    
            let blackMaterial = SCNMaterial()
            blackMaterial.diffuse.contents = UIColor.black
            blackMaterial.locksAmbientWithDiffuse = true
            textGeometry.materials = [blackMaterial]
    
            geometry = textGeometry
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        private func updateTextContainerFrame() {
            let (min, max) = boundingBox
            let width = CGFloat(max.x - min.x)
            let height = CGFloat(max.y - min.y)
            print("width :",max.x - min.x,"height :",max.y - min.y,"depth :",max.z - min.z)
            textGeometry.containerFrame = CGRect(x: 0.0, y: 0.0, width: width, height: height)
    //        textGeometry.containerFrame = CGRect(origin: .zero, size: CGSize(width: 1.0, height: 1.0))
        }
    }
    

    Implementation

    private func makeSpeechBubbleNode(forBobbleheadNode bobbleheadNode: BobbleheadNode) {
        let node = SpeechBubbleNode()
        node.position = sceneView.scene.rootNode.convertPosition(bobbleheadNode.position, to: node)
        node.scale = SCNVector3(0.002, 0.002, 0.002)
    
        sceneView.scene.rootNode.addChildNode(speechBubbleNode)
        self.speechBubbleNode = speechBubbleNode
    
        speechBubbleNode.string = "Some random string that could be long and should wrap within speech bubble"
    }
    

    解决方案

    I had the same problem and finally I have solved it as following:

    • Create a SCNText and add it as a geometry to SCNNode:

      let string = "Coverin text with a plane :)"
      let text = SCNText(string: string, extrusionDepth: 0.1)
      text.font = UIFont.systemFont(ofSize: 1)
      text.flatness = 0.005
      let textNode = SCNNode(geometry: text)
      let fontScale: Float = 0.01
      textNode.scale = SCNVector3(fontScale, fontScale, fontScale)
      

    • Coordinate the text pivot form left bottom to center:

      let (min, max) = (text.boundingBox.min, text.boundingBox.max)
      let dx = min.x + 0.5 * (max.x - min.x)
      let dy = min.y + 0.5 * (max.y - min.y)
      let dz = min.z + 0.5 * (max.z - min.z)
      textNode.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)
      

    • Create a PlaneNode and add the textNode as a childNode of the PlaneNode:

      let width = (max.x - min.x) * fontScale
      let height = (max.y - min.y) * fontScale
      let plane = SCNPlane(width: CGFloat(width), height: CGFloat(height))
      let planeNode = SCNNode(geometry: plane)
      planeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
      planeNode.geometry?.firstMaterial?.isDoubleSided = true
      planeNode.position = textNode.position
      textNode.eulerAngles = planeNode.eulerAngles
      planeNode.addChildNode(textNode)
      

    • and at the end add the PlaneNode to sceneView:

      sceneView.scene.rootNode.addChildNode(planeNode)
      

    and that's the result:

    这篇关于ARKit - 如何在另一个 SCNNode 中包含 SCNText(语音气泡)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆