SceneKit - неправильно центрирован SCNText
Я попытался сделать текстовую строку (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, чтобы увидеть его ограничивающую рамку
Решение 1:
Из ответа 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)
Решение 2:
Мне нужно переместить текст в нулевую позицию (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)
4 ответа
Отличие 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)
Чтобы найти центр ограничительной рамки, вам нужно сложить (не вычесть) мин и макс, прежде чем делить на 2.
textNode.position = SCNVector3(x: (minVec.x + maxVec.x) / 2, y: minVec.y + maxVec.y, z: 0)
Я думаю, что вы можете быть укушены необычной обработкой происхождения SCNText. IIRC ноль Y находится на базовой линии строки, а не внизу спусков.
Включи showBoundingBoxes
в debugOptions
и посмотрим, поможет ли это.