I play with a 360 degree video player using SpriteKit, SceneKit and CoreMotion. The player is still working, but the video is always increasing. It seems that the camera position is not at (0,0,0), but somehow wrong on the Z axis. Unfortunately, I did not find a way to adjust this. To reproduce the behavior, simply tap the screen when the video is playing and press the zoom out button. This allows you to control the camera using gestures, double-tap returns to control the camera using the device.
import UIKit
import SceneKit
import CoreMotion
import SpriteKit
import AVFoundation
class Video360VC: UIViewController {
let motionManager = CMMotionManager()
let cameraNode = SCNNode()
@IBOutlet weak var sceneView: SCNView!
@IBAction func exitBtnClicked(_ sender: Any) {
performSegueToReturnBack()
}
func createSphereNode(material: AnyObject?) -> SCNNode {
let sphere = SCNSphere(radius: 20.0)
sphere.firstMaterial!.isDoubleSided = true
sphere.firstMaterial!.diffuse.contents = material
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = SCNVector3Make(0,0,0)
sphereNode.rotation = SCNVector4Make(1, 0, 0, Float.pi)
return sphereNode
}
func configureScene(node sphereNode: SCNNode) {
let scene = SCNScene()
sceneView.scene = scene
sceneView.showsStatistics = true
sceneView.allowsCameraControl = true
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3Make(0, 0, 0)
scene.rootNode.addChildNode(sphereNode)
scene.rootNode.addChildNode(cameraNode)
}
func startCameraTracking() {
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
motionManager.startDeviceMotionUpdates(to: OperationQueue.main) {
[weak self](data: CMDeviceMotion?, error: Error?) in
guard let data = data else { return }
let attitude: CMAttitude = data.attitude
self?.cameraNode.eulerAngles = SCNVector3Make(- Float(attitude.roll + Double.pi/2), Float(attitude.yaw), -Float(attitude.pitch))
}
}
override func viewDidLoad() {
super.viewDidLoad()
guard let fileURL = Bundle.main.url(forResource: "360Test2", withExtension: "mp4") else {
print("Video File not found")
return
}
let player = AVPlayer(url: fileURL)
let videoNode = SKVideoNode(avPlayer: player)
let size = CGSize(width: 1280, height: 720)
videoNode.size = size
videoNode.position = CGPoint(x: size.width/2, y: size.height/2)
let spriteScene = SKScene(size: size)
spriteScene.scaleMode = .resizeFill
spriteScene.addChild(videoNode)
let sphereNode = createSphereNode(material:spriteScene)
configureScene(node: sphereNode)
guard motionManager.isDeviceMotionAvailable else {
fatalError("Device motion is not available")
}
startCameraTracking()
player.play()
}
override func viewWillAppear(_ animated: Bool) {
self.sceneView.play(self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I used this video for testing, which can also be downloaded. Many thanks!