这是360度视频播放器项目。
我将一个cameranode(SCNNode
)添加到根节点,将cameranode放在SCNSphere
的中心(0,0,0),它现在可以播放视频。
现在我必须使用devicemotion。设备移动时我需要旋转相机。不只是旋转一定的角度。 (不仅仅是设备移动,当我拿着设备时,我的动作就是设备在移动。因为我发现如果我使用deviceMotion.attitude.roll
,那么cameranode只会在设备自行移动时移动,而不是当我转身时装置)
当设备位于(x1,y1,z1)位置时,cameranode将随设备移动而旋转,当设备再次位于(x1,y1,z1)位置时,视图应与设备相同最后我们离开了。
这就是我所做的:
if (self.motionManager.gyroAvailable) {
self.motionManager.gyroUpdateInterval = 1.0/60.0;
[self.motionManager startGyroUpdatesToQueue:self.queue withHandler:^(CMGyroData *gyroData, NSError *error){
if (error) {
[self.motionManager stopGyroUpdates];
NSLog(@"Gyroscope encountered error:%@",error);
}else {
CGFloat tempX = 0;
CGFloat tempY = 0;
CGFloat tempZ = 0;
if ((fabs(gyroData.rotationRate.y)/60) > 0.002) {
tempY = gyroData.rotationRate.y/60;
}
tempX = gyroData.rotationRate.x/60;
tempZ = gyroData.rotationRate.z/60;
[self.cameraNode runAction:[SCNAction rotateByX:-tempY y:tempX z:tempZ duration:0]];
}
}];
}else {
NSLog(@"This device has no gyroscope");
}
数学可能是错误的,我不知道为什么我会划分60,但它似乎是我使用[self.cameraNode runAction:[SCNAction rotateByX:-tempY y:tempX z:tempZ duration:0]];
时所需的最接近的值
这是问题吗?
CMGyroData
或CMDeviceMotion
。如果使用CMDeviceMotion
,我应该使用哪个特定值? deviceMotion.attitude
,deviceMotion.attitude.quaternion
,deviceMotion.gravity
+ (SCNAction *)rotateByX:(CGFloat)xAngle y:(CGFloat)yAngle z:(CGFloat)zAngle duration:(NSTimeInterval)duration;
+ (SCNAction *)rotateToX:(CGFloat)xAngle y:(CGFloat)yAngle z:(CGFloat)zAngle duration:(NSTimeInterval)duration;
答案 0 :(得分:25)
设备运动最佳,因为它连接多个传感器并以有意义的方式将数据融合在一起。最好避免使用欧拉角,因为它们遭受所谓的万向节锁定。相反,请使用四元数并使用它们设置相机方向。
我创建了a Swift class extension for CMDeviceMotion,可让您确定设备正在查看的内容(对于屏幕的任何方向)。
从那里,旋转相机很简单。首先,设置您的设备动作(在视图中确实显示,或其他适当的位置):
if motionManager.deviceMotionAvailable {
motionManager.deviceMotionUpdateInterval = 0.017
motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue(), withHandler: deviceDidMove)
}
然后使用前面提到的CMDeviceMotion扩展来处理deviceDidMove实现中的更新:
func deviceDidMove(motion: CMDeviceMotion?, error: NSError?) {
if let motion = motion {
yourCameraNode.orientation = motion.gaze(atOrientation: UIApplication.sharedApplication().statusBarOrientation)
}
}
现在你的相机应该在太空中跟随你的设备方向。
答案 1 :(得分:2)
使用初始答案中的出色扩展名,您只需执行以下操作即可:
override func viewDidAppear(_ animated: Bool) {
// let motionManager = CMMotionManager() // definition made globally
// CoreMotion
motionManager.startDeviceMotionUpdates()
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
let interfaceOrientation = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.windowScene?.interfaceOrientation // for iOS13 and later
// .xTrueNorthZVertical // always aligns to the real north
// .xArbitraryZVertical // will use this one for initial direction
motionManager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: OperationQueue.main, withHandler: { (motion: CMDeviceMotion?, err: Error?) in
guard let m = motion else { return }
// self.cameraNode.orientation = m.gaze(atOrientation: UIApplication.shared.statusBarOrientation) // before iOS 13
self.cameraNode.orientation = m.gaze(atOrientation: interfaceOrientation!) // for iOS13 and later
})
}