假设SceneKit场景提供类似于Minecraft的视角。有一台相机。摄像机节点的作用类似于" head"一个人的父节点就像"身体一样。"摄像机节点是父节点的子节点,称为" userNode。"
目标:
让用户用一根手指平移以旋转相机。换句话说,相机位置保持固定,但是#34; head"旋转并让用户观看场景,就好像在一个圆圈中转身一样。
让用户用两根手指平移,围绕给定点绕相机运行。换句话说,相机的位置和旋转现在会改变,以便让用户从不同的角度观察同一个点。
到目前为止,下面的代码实现了单指平移行为。问题是如何结合双指泛行为。
选项1:关注this answer,其中介绍了如何绕摄像机旋转。然而,这似乎是次优的,因为场景中已经存在相机节点并且需要额外的节点,同时还在不同相机之间移动场景的视点。
选项2:计算摄像机的新位置和旋转,这样可以避免添加另一个摄像机节点和另一个轨道节点。这感觉就像是更好的答案,但可能更复杂。
func sceneViewPannedTwoFingers(sender: UIPanGestureRecognizer) {
// Get pan distance & convert to radians
let translation = sender.translationInView(sender.view!)
var xRadians = GLKMathDegreesToRadians(Float(translation.x))
// Get X radians only since only moving horizontally
xRadians = (xRadians / 10) + curXRadians
// Rotate & move camera horizontally
userNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: -xRadians)
// Compute new position for camera?
}
func sceneViewPannedOneFinger(sender: UIPanGestureRecognizer) {
// Get pan distance & convert to radians
let translation = sender.translationInView(sender.view!)
var xRadians = GLKMathDegreesToRadians(Float(translation.x))
var yRadians = GLKMathDegreesToRadians(Float(translation.y))
// Get x & y radians
xRadians = (xRadians / 10) + curXRadians
yRadians = (yRadians / 10) + curYRadians
// Limit yRadians to prevent rotating 360 degrees vertically
yRadians = max(Float(-M_PI_2), min(Float(M_PI_2), yRadians))
// Set rotation values to avoid Gimbal Lock
cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: yRadians)
userNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: xRadians)
// Save value for next rotation
if sender.state == UIGestureRecognizerState.Ended {
curXRadians = xRadians
curYRadians = yRadians
}
// Set preview block
setPreviewBlock()
}
问题:
1)在SceneKit中有更简单的方法吗?
2)如果没有,两个选项是否只有两个选项,如果是,那么哪个选择更好?
3)对于选项2,更新userNode
或" body"的位置似乎很简单:只计算中心原点的圆周新位置,即轨道点)。对于" head",除了更新rotation
(或" head")的cameraNode
属性之外还有什么需要注意的吗?似乎将摄像机定向为始终面向轨道点可能更复杂,因为有一部分SceneKit API专用于它,例如SCNLookAtConstraint.