user
user

Reputation: 162

SwiftUI – Setting SceneView background to video

I'm trying to set the SceneViews background to a .mov video. I can get the video to play if I pass it to a VideoPlayer but not if I set it as a material on my Sphere & use it in my SceneView. Ideally I would like the video to play behind the sphere but I would settle for applying it as a material. I have looked at this solution but it hasn't worked, I just see white.

Any help getting a video in my Scene is much appreciated!!

View:

GeometryReader { _ in
  SceneView(scene: testScene, options: [.allowsCameraControl])
}

Scene Creation:

private var testScene: SCNScene? {
  var earthScene = SCNScene()

  let material = SCNMaterial()
  let path = Bundle.main.url(forResource: "test_video", 
                                 withExtension: "mov")!
  let player = AVPlayer(url: path)
  player.play()
  material.diffuse.contents = player

  let earthNode = SCNNode()
  earthNode.geometry = SCNSphere(radius: CGFloat(150))
  earthScene.rootNode.addChildNode(earthNode)
  earthNode.geometry?.materials = [material]

  earthScene.rootNode.addChildNode(earthNode)
  return flowerScene
}

Upvotes: 1

Views: 425

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58563

This code works perfectly in Xcode 14.2 (target is iOS 16.2).

import SwiftUI
import SceneKit
import AVFoundation

struct ContentView: View {
    var body: some View {
        SceneKitter().ignoresSafeArea()
    }
}

struct SceneKitter : UIViewRepresentable {
    
    func makeUIView(context: Context) -> SCNView {
        let sceneView = SCNView(frame: .zero)
        sceneView.scene = sceneMethod()
        sceneView.isPlaying = true                 // solves the problem
        sceneView.allowsCameraControl = true
        return sceneView
    }
    
    func sceneMethod() -> SCNScene {
        let scene = SCNScene()
        scene.background.contents = UIColor.black
        
        let path = Bundle.main.url(forResource: "video",
                                 withExtension: "mp4")!
        let player = AVPlayer(url: path)
        player.play()

        let material = SCNMaterial()
        material.diffuse.contents = player

        let earthNode = SCNNode()
        earthNode.geometry = SCNSphere(radius: 1)
        earthNode.geometry?.materials[0] = material
        scene.rootNode.addChildNode(earthNode)
        return scene
    }
    
    func updateUIView(_ view: SCNView, context: Context) { }
}

Upvotes: 2

Related Questions