我正在使用 iOS 构建 360 度视频查看器SceneKit https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/框架。
我想用一个UIPan手势识别器 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPanGestureRecognizer_Class/来控制相机的方向。
SCNNode https://developer.apple.com/library/mac/documentation/SceneKit/Reference/SCNNode_Class/s 有几个属性我们可以用来指定它们的旋转:rotation
(旋转矩阵),orientation
(四元数),eulerAngles
(每轴角度)。
我读过的所有内容都说要避免使用欧拉角以避免万向节锁 https://en.wikipedia.org/wiki/Gimbal_lock.
我想使用四元数有几个原因,我不会在这里讨论。
我很难让它正常工作。相机控制几乎是我想要的位置,但有一些问题。尽管我尝试只影响 X 轴和 Y 轴,但相机似乎正在绕 Z 轴旋转。
我相信这个问题与我的四元数乘法逻辑有关。我已经很多年没有做过任何与四元数相关的事情了:( 我的平移手势处理程序在这里:
func didPan(recognizer: UIPanGestureRecognizer)
{
switch recognizer.state
{
case .Began:
self.previousPanTranslation = .zero
case .Changed:
guard let previous = self.previousPanTranslation else
{
assertionFailure("Attempt to unwrap previous pan translation failed.")
return
}
// Calculate how much translation occurred between this step and the previous step
let translation = recognizer.translationInView(recognizer.view)
let translationDelta = CGPoint(x: translation.x - previous.x, y: translation.y - previous.y)
// Use the pan translation along the x axis to adjust the camera's rotation about the y axis.
let yScalar = Float(translationDelta.x / self.view.bounds.size.width)
let yRadians = yScalar * self.dynamicType.MaxPanGestureRotation
// Use the pan translation along the y axis to adjust the camera's rotation about the x axis.
let xScalar = Float(translationDelta.y / self.view.bounds.size.height)
let xRadians = xScalar * self.dynamicType.MaxPanGestureRotation
// Use the radian values to construct quaternions
let x = GLKQuaternionMakeWithAngleAndAxis(xRadians, 1, 0, 0)
let y = GLKQuaternionMakeWithAngleAndAxis(yRadians, 0, 1, 0)
let z = GLKQuaternionMakeWithAngleAndAxis(0, 0, 0, 1)
let combination = GLKQuaternionMultiply(z, GLKQuaternionMultiply(y, x))
// Multiply the quaternions to obtain an updated orientation
let scnOrientation = self.cameraNode.orientation
let glkOrientation = GLKQuaternionMake(scnOrientation.x, scnOrientation.y, scnOrientation.z, scnOrientation.w)
let q = GLKQuaternionMultiply(combination, glkOrientation)
// And finally set the current orientation to the updated orientation
self.cameraNode.orientation = SCNQuaternion(x: q.x, y: q.y, z: q.z, w: q.w)
self.previousPanTranslation = translation
case .Ended, .Cancelled, .Failed:
self.previousPanTranslation = nil
case .Possible:
break
}
}
我的代码在这里是开源的:https://github.com/alfiehanssen/360Player/ https://github.com/alfiehanssen/360Player/
查看pan-gesture
特别是分支:https://github.com/alfiehanssen/360Player/tree/pan-gesture https://github.com/alfiehanssen/360Player/tree/pan-gesture
如果您下载代码,我相信您将必须在设备而不是模拟器上运行它。
我在这里发布了一个视频来演示该错误(请原谅视频文件的低分辨率):https://vimeo.com/174346191 https://vimeo.com/174346191
预先感谢您的任何帮助!