Having fun with the alignmentMode option on SCNText. Been googling around and it looks like there is a problem with alignmentMode and containerFrame. The alternatives I've found suggest using the get bounding box function to find the text size and then manually adjust accordingly. Great except I cant get the function to work. When I try to get the two vectors I get an error:
'SCNVector3' is not convertible to 'UnsafeMutablePointer < SCNVector3>'
I get that both on the geometry and the node. example of the code is below
func setCounterValue(counterValue:Int) {
var v1 = SCNVector3(x: 0,y: 0,z: 0)
var v2 = SCNVector3(x: 0,y: 0,z: 0)
_counterValue = counterValue
let newText = SCNText(string: String(format: "%06d", counterValue), extrusionDepth:sDepth)
newText.font = UIFont (name: "Arial", size: 3)
newText.firstMaterial!.diffuse.contents = UIColor.whiteColor()
newText.firstMaterial!.specular.contents = UIColor.whiteColor()
newText.getBoundingBoxMin(v1, max: v2)
_textNode = SCNNode(geometry: newText)
_textNode.getBoundingBoxMin(v1, max: v2)
}
Any suggestions greatly appreciated.
OK so my final code solution looks like:
func setCounterValue(counterValue:Int) {
var v1 = SCNVector3(x: 0,y: 0,z: 0)
var v2 = SCNVector3(x: 0,y: 0,z: 0)
_textNode.removeFromParentNode()
_counterValue = counterValue
let newText = SCNText(string: String(format: "%08d", counterValue), extrusionDepth:sDepth)
newText.font = UIFont (name: "Arial", size: 3)
newText.firstMaterial!.diffuse.contents = UIColor.whiteColor()
newText.firstMaterial!.specular.contents = UIColor.whiteColor()
_textNode = SCNNode(geometry: newText)
_textNode.getBoundingBoxMin(&v1, max: &v2)
let dx:Float = Float(v1.x - v2.x)/2.0
let dy:Float = Float(v1.y - v2.y)
_textNode.position = SCNVector3Make(dx, dy, Float(sDepth/2))
node.addChildNode(_textNode)
}
I've left in my couple of global variables, but should make sense.
Thanks for the help all.
EDIT: Functions with out-pointer arguments suck in Swift, so in Swift 3 Apple replaced this method (and the corresponding setter method) with a property whose type is a tuple:
var boundingBox: (min: SCNVector3, max: SCNVector3) { get set }
So you can just write something like:
let (min, max) = textNode.boundingBox
More generally...
Functions that take an out-parameter of UnsafeMutablePointer
type in Swift can be called by passing an inout
reference as the parameter. So for the Swift 2 version of this method, or for similar methods elsewhere:
_textNode.getBoundingBoxMin(&v1, max: &v2)
You can add text by using this code, it is written in Swift 5
import ARKit
class ARSceneViewController: UIViewController {
@IBOutlet var sceneView: ARSCNView!
let config = ARWorldTrackingConfiguration()
private func addTextToTheWorld() {
let text = SCNText(string: "HELLO WORLD", extrusionDepth: 0.02)
let font = UIFont(name: "Futura", size: 0.22)
text.font = font
text.alignmentMode = CATextLayerAlignmentMode.center.rawValue
text.firstMaterial?.diffuse.contents = UIColor.red
text.firstMaterial?.specular.contents = UIColor.white
text.firstMaterial?.isDoubleSided = true
text.chamferRadius = 0.01
let (minBound, maxBound) = text.boundingBox
let textNode = SCNNode(geometry: text)
textNode.pivot = SCNMatrix4MakeTranslation( (maxBound.x - minBound.x)/2, minBound.y, 0.02/2)
textNode.scale = SCNVector3Make(0.1, 0.1, 0.1)
textNode.position = SCNVector3(0.1, 0.1, -0.1)
sceneView.scene.rootNode.addChildNode(textNode)
}
// MARK: - View lifeCycle methods
override func viewDidLoad() {
super.viewDidLoad()
//ARKit Debugging:
// Show Axis and feature points
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
sceneView.session.run(config)
self.addTextToTheWorld()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With