我试图保持SCNNode始终离摄像机前方一米远,并操纵节点,使X轴和Z轴始终与地面平行,而节点围绕Y轴旋转,以便节点总是对着相机。
下面的代码在很大程度上实现了我的目标,但是当顺时针或逆时针转动超过90˚时,节点开始转动。我该如何解决这个问题?
override func viewDidLoad() {
super.viewDidLoad()
boxParent.position = (sceneView.pointOfView?.position)!
boxParent.orientation = (sceneView.pointOfView?.orientation)!
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
sceneView.scene.rootNode.addChildNode(boxParent)
boxOrigin.position = SCNVector3(0,0,-1)
boxParent.addChildNode(boxOrigin)
box = SCNNode(geometry: SCNBox(width: 0.5, height: 0.2, length: 0.3, chamferRadius: 0))
box.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
box.position = SCNVector3(0,0,0)
boxOrigin.addChildNode(box)
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
boxParent.orientation = (sceneView.pointOfView?.orientation)!
boxParent.position = (sceneView.pointOfView?.position)!
box.position = boxOrigin.worldPosition
box.eulerAngles.y = (sceneView.pointOfView?.eulerAngles.y)!
print(box.eulerAngles)
sceneView.scene.rootNode.addChildNode(box)
}
您同时使用两种类型的旋转。这是不对的!
boxParent.orientation = (sceneView.pointOfView?.orientation)! //quaternion
此变量使用节点的方向,表示为quaternion
(4个分量:x,y,z,w)。
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
节点的旋转,以俯仰,偏航和滚转角度表示,以弧度表示(3个分量:x,y,z)。
您需要决定使用哪个变量:
orientation
或eulerAngles
。我想你会选择方向。
阅读this useful article和this one关于Quaternions
和Gimbal Lock
是什么。
此外,使用SCNLookAtConstraint
对象(节点的负z轴指向约束的目标节点)或SCNBillboardConstraint
对象(自动调整节点的方向,使其局部z轴始终指向节点的pointOfView),以自动调整节点的方向,因此相机总是指向另一个节点。