Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save igor11191708/2784ff7841e48199b14d3d3ac5a1b99f to your computer and use it in GitHub Desktop.
Save igor11191708/2784ff7841e48199b14d3d3ac5a1b99f to your computer and use it in GitHub Desktop.
Transforming Standard Videos into Immersive Spherical Experiences
import SwiftUI
import SceneKit
import AVFoundation
// the video is from https://www.videvo.net/video/chicago-skate-park-from-above/578690/#rs=video-box
struct ContentView: View {
var body: some View {
CustomSceneView()
.ignoresSafeArea()
}
}
struct CustomSceneView: UIViewRepresentable {
func makeUIView(context: Context) -> SCNView {
let sceneView = SCNView()
sceneView.scene = setupScene()
sceneView.allowsCameraControl = true
sceneView.autoenablesDefaultLighting = true
sceneView.isPlaying = true // Keep updating the view even when there are no interactions
return sceneView
}
func updateUIView(_ uiView: SCNView, context: Context) {
// Update the view if necessary
}
private func setupScene() -> SCNScene {
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.camera?.fieldOfView = 75
cameraNode.position = SCNVector3(x: 0, y: 0, z: -10)
cameraNode.eulerAngles.y = .pi // Rotate the camera 180 degrees around the Y-axis
scene.rootNode.addChildNode(cameraNode)
let videoNode = SCNNode()
let sphere = SCNSphere(radius: 25)
sphere.firstMaterial?.diffuse.contents = setupPlayer()
sphere.firstMaterial?.isDoubleSided = true
sphere.firstMaterial?.cullMode = .front
videoNode.geometry = sphere
videoNode.position = SCNVector3(x: 0, y: 0, z: -5)
scene.rootNode.addChildNode(videoNode)
return scene
}
private func setupPlayer() -> AVPlayer? {
guard let url = Bundle.main.url(forResource: "Chicago_Skatepark_1596465264", withExtension: "mp4") else {
print("Video file not found")
return nil
}
let player = AVPlayer(url: url)
let playerItem = AVPlayerItem(url: url)
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: playerItem, queue: .main) { _ in
player.seek(to: CMTime.zero) { _ in
player.play()
}
}
player.replaceCurrentItem(with: playerItem)
player.play()
return player
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment