如何在 ARKit 中设置文本方向?
How can I set text orientation in ARKit?
我正在使用 ARKit 创建一个简单的应用程序,我在其中向场景中的点击位置添加了一些文本:
@objc func tapped(sender: UITapGestureRecognizer){
let sceneView = sender.view as! ARSCNView
let tapLocation = sender.location(in: sceneView)
let hitTest = sceneView.hitTest(tapLocation, types: .featurePoint)
if !hitTest.isEmpty{
self.addTag(tag: "A", hitTestResult: hitTest.first!)
}
else{
print("no match")
}
}
func addTag(tag: String, hitTestResult: ARHitTestResult){
let tag = SCNText(string:tag, extrusionDepth: 0.1)
tag.font = UIFont(name: "Optima", size: 1)
tag.firstMaterial?.diffuse.contents = UIColor.red
let tagNode = SCNNode(geometry: tag)
let transform = hitTestResult.worldTransform
let thirdColumn = transform.columns.3
tagNode.position = SCNVector3(thirdColumn.x,thirdColumn.y - tagNode.boundingBox.max.y / 2,thirdColumn.z)
print("\(thirdColumn.x) \(thirdColumn.y) \(thirdColumn.z)")
self.sceneView.scene.rootNode.addChildNode(tagNode)
}
它可以工作,但我对文本的方向有疑问。当我用相机的原始位置添加它时,文本方向没问题,我可以看到正面的文本(示例 1)。但是当我向左/向右转动相机并通过点击添加文本时,我可以从侧面看到添加的文本(示例2)。
示例 1:
示例 2:
我知道应该有一些简单的技巧来解决它,但作为这个主题的初学者我到目前为止找不到它。
您希望文本始终面向相机吗? SCNBillboardConstraint
是你的朋友:
tagNode.constraints = [SCNBillboardConstraint()]
当您点击(无论您碰巧面对什么)时,您希望文本面对相机,但随后保持静止,我说得对吗?
有多种方法可以调整任何节点的方向。对于这种情况,我建议简单地将文本节点的 eulerAngles
设置为等于相机的 eulerAngles
,在实例化文本的位置。
在您的 addTag()
函数中添加:
let eulerAngles = self.sceneView.session.currentFrame?.camera.eulerAngles
tagNode.eulerAngles = SCNVector3(eulerAngles.x, eulerAngles.y, eulerAngles.z + .pi / 2)
额外的 .pi / 2
是为了确保文本的方向正确,因为 ARKit 的默认设置是横向的,因此文本看起来很有趣。这将应用围绕局部 z 轴的旋转。
使用节点的 .localRotate()
或访问它的 transform
属性 也是合理的(有些人可能认为这样更好),但是我喜欢同时操纵两者的方法位置和 eulerAngles 直接。
希望这对您有所帮助。
编辑:将 Float(1.57)
替换为 .pi / 2
。
我正在使用 ARKit 创建一个简单的应用程序,我在其中向场景中的点击位置添加了一些文本:
@objc func tapped(sender: UITapGestureRecognizer){
let sceneView = sender.view as! ARSCNView
let tapLocation = sender.location(in: sceneView)
let hitTest = sceneView.hitTest(tapLocation, types: .featurePoint)
if !hitTest.isEmpty{
self.addTag(tag: "A", hitTestResult: hitTest.first!)
}
else{
print("no match")
}
}
func addTag(tag: String, hitTestResult: ARHitTestResult){
let tag = SCNText(string:tag, extrusionDepth: 0.1)
tag.font = UIFont(name: "Optima", size: 1)
tag.firstMaterial?.diffuse.contents = UIColor.red
let tagNode = SCNNode(geometry: tag)
let transform = hitTestResult.worldTransform
let thirdColumn = transform.columns.3
tagNode.position = SCNVector3(thirdColumn.x,thirdColumn.y - tagNode.boundingBox.max.y / 2,thirdColumn.z)
print("\(thirdColumn.x) \(thirdColumn.y) \(thirdColumn.z)")
self.sceneView.scene.rootNode.addChildNode(tagNode)
}
它可以工作,但我对文本的方向有疑问。当我用相机的原始位置添加它时,文本方向没问题,我可以看到正面的文本(示例 1)。但是当我向左/向右转动相机并通过点击添加文本时,我可以从侧面看到添加的文本(示例2)。
示例 1:
示例 2:
我知道应该有一些简单的技巧来解决它,但作为这个主题的初学者我到目前为止找不到它。
您希望文本始终面向相机吗? SCNBillboardConstraint
是你的朋友:
tagNode.constraints = [SCNBillboardConstraint()]
当您点击(无论您碰巧面对什么)时,您希望文本面对相机,但随后保持静止,我说得对吗?
有多种方法可以调整任何节点的方向。对于这种情况,我建议简单地将文本节点的 eulerAngles
设置为等于相机的 eulerAngles
,在实例化文本的位置。
在您的 addTag()
函数中添加:
let eulerAngles = self.sceneView.session.currentFrame?.camera.eulerAngles
tagNode.eulerAngles = SCNVector3(eulerAngles.x, eulerAngles.y, eulerAngles.z + .pi / 2)
额外的 .pi / 2
是为了确保文本的方向正确,因为 ARKit 的默认设置是横向的,因此文本看起来很有趣。这将应用围绕局部 z 轴的旋转。
使用节点的 .localRotate()
或访问它的 transform
属性 也是合理的(有些人可能认为这样更好),但是我喜欢同时操纵两者的方法位置和 eulerAngles 直接。
希望这对您有所帮助。
编辑:将 Float(1.57)
替换为 .pi / 2
。