SceneKit - SCNText 居中不正确
SceneKit - SCNText centering incorrectly
我试图在下面的代码中使一个文本字符串 (SCNText) 适合一个框 (SCNBox)。框的大小看起来正确,但文本不在框的右中心。任何想法或解决方案?谢谢
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 8)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
scnScene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
scnScene.rootNode.addChildNode(boxNode)
已编辑: 我添加了一个新的字符串图像(没有 SCNBox 节点)和 debugOptions showBoundingBoxes 来查看它的边界框
解决方案一:
根据 vdugnist 的回答,我为任何想要测试的人创建了一个游乐场代码:
import UIKit
import SceneKit
import PlaygroundSupport
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 12)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
textNode.position = SCNVector3(x: (minVec.x - maxVec.x) / 2, y: minVec.y - maxVec.y, z: 0)
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x) / 2, 0, 0)
scene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
let boxNode = SCNNode(geometry: geoBox)
boxNode.position = SCNVector3Make((maxVec.x - minVec.x) / 2 + minVec.x, (maxVec.y - minVec.y) / 2 + minVec.y, 0);
textNode.addChildNode(boxNode)
方案二:
我需要将文本移动到位置零 (0, 0, 0) 而不是同时移动文本和环绕框,因此我继续更改解决方案 1 中文本的中心点。现在代码如下以下:
import UIKit
import SceneKit
import PlaygroundSupport
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 12)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x) / 2 + minVec.x, (maxVec.y - minVec.y) / 2 + minVec.y, 0)
scene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.6)
let boxNode = SCNNode(geometry: geoBox)
scene.rootNode.addChildNode(boxNode)
要找到边界框的中心,您需要在除以 2 之前加上(而不是减去)最小值和最大值。
textNode.position = SCNVector3(x: (minVec.x + maxVec.x) / 2, y: minVec.y + maxVec.y, z: 0)
我认为您可能被 SCNText 对来源的不寻常处理所困扰。 IIRC Y 零位于字符串的基线,而不是下降部的底部。
在 debugOptions
中打开 showBoundingBoxes
,看看是否有帮助。
SCNText与其他几何图形的区别在于SCNText原点位于左下角。在其他几何图形中,它是底部中心。
要固定父节点中的文本位置,您可以将其 pivotPoint.x 设置为宽度的一半:
SCNVector3 min, max;
[textNode getBoundingBoxMin:&min max:&max];
textNode.pivot = SCNMatrix4MakeTranslation((max.x - min.x) / 2, 0, 0);
要固定子节点的位置,您应该将它们的位置设置为宽度的一半加上最小值:
SCNVector3 min, max;
[textNode getBoundingBoxMin:&min max:&max];
subnode.position = SCNVector3Make((max.x - min.x) / 2 + min.x, (max.y - min.y) / 2 + min.y, 0);
Swift: 在父节点中正确居中文本节点
let (min, max) = textNode.boundingBox
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)
let textNodeParent = SCNNode()
textNodeParent.addChildNode(textNode)
我试图在下面的代码中使一个文本字符串 (SCNText) 适合一个框 (SCNBox)。框的大小看起来正确,但文本不在框的右中心。任何想法或解决方案?谢谢
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 8)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
scnScene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
scnScene.rootNode.addChildNode(boxNode)
已编辑: 我添加了一个新的字符串图像(没有 SCNBox 节点)和 debugOptions showBoundingBoxes 来查看它的边界框
解决方案一:
根据 vdugnist 的回答,我为任何想要测试的人创建了一个游乐场代码:
import UIKit
import SceneKit
import PlaygroundSupport
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 12)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
textNode.position = SCNVector3(x: (minVec.x - maxVec.x) / 2, y: minVec.y - maxVec.y, z: 0)
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x) / 2, 0, 0)
scene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.5)
let boxNode = SCNNode(geometry: geoBox)
boxNode.position = SCNVector3Make((maxVec.x - minVec.x) / 2 + minVec.x, (maxVec.y - minVec.y) / 2 + minVec.y, 0);
textNode.addChildNode(boxNode)
方案二:
我需要将文本移动到位置零 (0, 0, 0) 而不是同时移动文本和环绕框,因此我继续更改解决方案 1 中文本的中心点。现在代码如下以下:
import UIKit
import SceneKit
import PlaygroundSupport
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView
let geoText = SCNText(string: "Hello", extrusionDepth: 1.0)
geoText.font = UIFont (name: "Arial", size: 12)
geoText.firstMaterial!.diffuse.contents = UIColor.red
let textNode = SCNNode(geometry: geoText)
let (minVec, maxVec) = textNode.boundingBox
textNode.pivot = SCNMatrix4MakeTranslation((maxVec.x - minVec.x) / 2 + minVec.x, (maxVec.y - minVec.y) / 2 + minVec.y, 0)
scene.rootNode.addChildNode(textNode)
let w = CGFloat(maxVec.x - minVec.x)
let h = CGFloat(maxVec.y - minVec.y)
let d = CGFloat(maxVec.z - minVec.z)
let geoBox = SCNBox(width: w, height: h, length: d, chamferRadius: 0)
geoBox.firstMaterial!.diffuse.contents = UIColor.green.withAlphaComponent(0.6)
let boxNode = SCNNode(geometry: geoBox)
scene.rootNode.addChildNode(boxNode)
要找到边界框的中心,您需要在除以 2 之前加上(而不是减去)最小值和最大值。
textNode.position = SCNVector3(x: (minVec.x + maxVec.x) / 2, y: minVec.y + maxVec.y, z: 0)
我认为您可能被 SCNText 对来源的不寻常处理所困扰。 IIRC Y 零位于字符串的基线,而不是下降部的底部。
在 debugOptions
中打开 showBoundingBoxes
,看看是否有帮助。
SCNText与其他几何图形的区别在于SCNText原点位于左下角。在其他几何图形中,它是底部中心。
要固定父节点中的文本位置,您可以将其 pivotPoint.x 设置为宽度的一半:
SCNVector3 min, max;
[textNode getBoundingBoxMin:&min max:&max];
textNode.pivot = SCNMatrix4MakeTranslation((max.x - min.x) / 2, 0, 0);
要固定子节点的位置,您应该将它们的位置设置为宽度的一半加上最小值:
SCNVector3 min, max;
[textNode getBoundingBoxMin:&min max:&max];
subnode.position = SCNVector3Make((max.x - min.x) / 2 + min.x, (max.y - min.y) / 2 + min.y, 0);
Swift: 在父节点中正确居中文本节点
let (min, max) = textNode.boundingBox
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)
let textNodeParent = SCNNode()
textNodeParent.addChildNode(textNode)