I want to display text alongside my 3D model using SceneKit in iOS. It just has to appear like it is 2D. So the text should always be facing the camera, however I rotate the 3D model. I have an SCNNode
with a SCNText
geometry and I attached an SCNLookAtConstraint
like so:
let constraint = SCNLookAtConstraint(target: cameraNode)
constraint.gimbalLockEnabled = true
textNode.constraints = [constraint]
They seem to be facing the camera, but only the wrong way! I see all text mirrored! Also, sometimes the text rotates, I want it to be aligned horizontally at all times. So this is all the behaviour I don't want.
Can somebody help me out here? I just want to have some text that follows a few nodes in my 3D object. I don't care how. It doesn't have to be SCNText for all I care, if this can be done with a simple UILabel: fine with me! Just tell me how!
From the documentation:
When SceneKit evaluates a look-at constraint, it updates the constrained node’s transform property so that the node’s negative z-axis points toward the constraint’s target node.
You can workaround that by setting the node's pivot
or by using an intermediate node. That node would be constrained, and would have the text as a child node (which would be rotated by π along the y axis)
Update
Starting iOS 11.0 the SCNLookAtConstraint
class exposes the localFront
property which allows you to specify a different front axis. It defaults to (0, 0, -1)
and you can change it to (0, 0, 1)
to achieve what you want.
Based on @mnuages response, setting the node's pivot to the following should do the trick.
node.pivot = SCNMatrix4Rotate(node.pivot, Float.pi, 0, 1, 0)
I faced this problem on iOS11 beta 5, Swift4:
//1. Rotate your `textNode`, and don't add `textNode` into `sceneView`
textNode.eulerAngles = SCNVector3Make(0, .pi, 0)
//2. Create new wrapper node, add `textNode` as a child node
let textWrapperNode = SCNNode()
textWrapperNode.addChildNode(textNode)
//3. Add constraint for wrapper node
let constraint = SCNLookAtConstraint(target: cameraNode)
constraint.gimbalLockEnabled = true
textWrapperNode.constraints = [constraint]
//4. Add wrapper node into `sceneView`
sceneView.scene.rootNode.addChildNode(textNode)
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