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

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

问题描述

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

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.

结果

课程

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))
    }
}

实施

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:

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

  • 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)

  • 将文本数据透视表从左下角调整到中心:

    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)
    

  • 创建一个PlaneNode并将textNode添加为PlaneNode的childNode:

  • 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)
    

  • ,最后将PlaneNode添加到sceneView:

  • and at the end add the PlaneNode to sceneView:

    sceneView.scene.rootNode.addChildNode(planeNode)
    

  • 这就是结果:

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

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