SceneKit - SCNText centering incorrectly

二次信任 提交于 2019-11-29 21:13:59

问题


I have tried to make a text string (SCNText) fit inside a box (SCNBox) in the code below. The size of the box looks correct but the text is not in the right center of the box. Any idea or solution? Thanks

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)

Edited: I have added a new image of the string only (no SCNBox node) with debugOptions showBoundingBoxes to see its bounding box

Solution 1:

From vdugnist's answer, I create a playground code for anyone who wants to test:

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)

Solution 2:

I need to move the text to position zero (0, 0, 0) instead of moving both text and the around box, thus I continue to change the pivot of the text from Solution 1. Now the code is as the following:

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)

回答1:


The difference of SCNText from other geometries is that SCNText origin point positioned at bottom left corner. In other geometries, it is a bottom center.

To fix text position in parent node you can set its pivotPoint.x to half of width:

SCNVector3 min, max;
[textNode getBoundingBoxMin:&min max:&max];
textNode.pivot = SCNMatrix4MakeTranslation((max.x - min.x) / 2, 0, 0);

To fix subnodes position, you should set their position to half of width plus min:

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



回答2:


Swift: center text-node in parent-node correctly

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)



回答3:


To find the center of the bounding box you need to add (not subtract) the min and max before you divide by 2.

textNode.position = SCNVector3(x: (minVec.x + maxVec.x) / 2, y: minVec.y + maxVec.y, z: 0)



回答4:


I think you might be getting bitten by SCNText's unusual treatment of origin. IIRC the Y zero is at the string's baseline, not at the bottom of the descenders.

Turn on showBoundingBoxes In the debugOptions and see if that helps.



来源:https://stackoverflow.com/questions/45168896/scenekit-scntext-centering-incorrectly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!