0

I'm trying to make a 360 degree video player, by projecting a video on a sphere & then turning the normals inside out & placing the camera inside the sphere, however I'm getting a black screen when I try to play the video on the sphere, but I can hear the audio play.

   override func viewDidLoad() {
        super.viewDidLoad()

        //create sphere
        makeSphere();

        //create user-interface
        resizeScreen();

    }

ViewDidLoad ^ I call resizeScreen(); which makes the video player 'adapt' to the screen.

 //set variables
        var player : AVPlayer? = nil;
        var playerLayer : AVPlayerLayer? = nil;
        var asset : AVAsset? = nil;
        var playerItem : AVPlayerItem? = nil;
        var timer = NSTimer();

        //start functions
        func resizeScreen() {

            //Get device screen width & height
            var screenSize: CGRect = UIScreen.mainScreen().bounds;

            //set screen width and height in variables
            var screenWidth = screenSize.width;
            var screenHeight = screenSize.height;

            //change size of video player
            playerLayer?.frame.size.height = screenHeight * 0.75;
            playerLayer?.frame.size.width = screenWidth * 1.0;

            //change size of button
            PlayVid.frame.size.height = screenHeight * 0.75;
            PlayVid.frame.size.width = screenWidth * 1;

            //set position of text label
            TemporaryURL.center.x = screenWidth * 0.5;
            TemporaryURL.center.y = screenHeight * 0.9

        }

resizeScreen();, as mentioned above makes the video player and button adapt to the screen size.

        func makeSphere() {
            let sceneView = SCNView(frame: self.view.frame);
            self.view.addSubview(sceneView);

            //Get device screen width & height
            var screenSize: CGRect = UIScreen.mainScreen().bounds;

            //set screen width and height in variables
            var screenWidth = screenSize.width;
            var screenHeight = screenSize.height;

            //set scene's height, width and x-position
            sceneView.frame.size.height = screenHeight * 0.75;
            sceneView.frame.size.width = screenWidth * 1;
            sceneView.center.x = screenWidth * 0.5;

            //create scene
            let scene = SCNScene();
            sceneView.scene = scene;

            //camera positioning
            let camera = SCNCamera();
            let cameraNode = SCNNode();
            cameraNode.camera = camera;
            cameraNode.position = SCNVector3(x: -3.0, y: 3.0, z: 3.0);

            //lighting
            let light = SCNLight();
            light.type = SCNLightTypeOmni;
            let lightNode = SCNNode();
            lightNode.light = light;
            lightNode.position = SCNVector3(x: 0, y: 0, z: 0);

            //create a sphere
            let sphereGeometry = SCNSphere(radius: 2.5);

            //create sphere node
            let sphereNode = SCNNode(geometry: sphereGeometry);

            //create constraint for sphere
            let constraint = SCNLookAtConstraint(target: sphereNode);
            //constraint.gimbalLockEnabled = true;
            cameraNode.constraints = [constraint];

            //set nodes
            //scene.rootNode.addChildNode(lightNode);
            scene.rootNode.addChildNode(cameraNode);
            scene.rootNode.addChildNode(sphereNode);


             inlineVideo();
             player!.play();

            //make variable
            let videoMaterial = SCNMaterial();
            var imgURL = NSURL(string: "http://imgurl");
            var videoURLWithPath = "http://videourl";
            var videoURL = NSURL(string: videoURLWithPath);

            //apply texture to variable
            videoMaterial.diffuse.contents = AVPlayerLayer(player: self.player);
            videoMaterial.specular.contents = UIColor.redColor();
            videoMaterial.shininess = 1.0;

            //set texture on object of name sphereGeomtetry
            sphereGeometry.materials = [videoMaterial];
        }

makeSphere(); this creates the sphere & initialises the video for said Sphere.

        func inlineVideo(){
            //play inline video

            //insert url of video into textfield
            var PasteBoard = UIPasteboard.generalPasteboard().string;
            TemporaryURL.text = PasteBoard;

            //get path of video
            //var videoURLWithPath = PasteBoard;
            var videoURLWithPath = "http://videourl";
            var videoURL = NSURL(string: videoURLWithPath);

            if (videoURL == nil){
                videoURL = NSURL(string: "http://videourl");
            }else{
                //do nothing
            }

            //get video url & set it
            asset = AVAsset(URL: videoURL!) as AVAsset;
            playerItem = AVPlayerItem(asset:asset!);

            //set target for video
            player = AVPlayer(playerItem: self.playerItem!);
            playerLayer = AVPlayerLayer(player: self.player);
        }

This is the video player code I use to initialise the regular video, I tried to bind PlayerLayer to the texture of the sphere, but all I'm getting is a black screen, even though im hearing sound, why isn't the video projecting on the sphere? I think that something like this should work?

Gerwin
  • 1,572
  • 5
  • 23
  • 51
  • 1
    see http://stackoverflow.com/questions/29805632/using-mpmovieplayercontroller-as-texture-in-scenekit – mnuages Feb 12 '16 at 11:48
  • @mnuages & I can't seem to get SKVideoNode to work, I keep getting a black screen, but the sound is playing – Gerwin Feb 12 '16 at 12:12
  • @mnuages it's swapping between the first frame, and a black screen :/ – Gerwin Feb 12 '16 at 12:16
  • 1
    there's some issues with video in SceneKit. I think the only people that know how to use it work for Apple, in France, and create SceneKit. – Confused Feb 17 '16 at 12:00
  • I think this is the main reason why the iOS YouTube app still has no cardboard-compatible viewer for 360 video. I have something that works here. But appears to have a memory leak and will eventually crash : https://github.com/kosso/simple360player_iOS – Kosso Feb 28 '16 at 22:23

3 Answers3

1

Check the following links:

There are 3 different approaches (e.g. OpenGL/SceneKit, shader/fixed-function pipeline, swift/obj-c, RGB/YCbCr) so everyone should find any handy piece of code.

lechec
  • 839
  • 1
  • 8
  • 17
  • here's a swift implementation of a cylindrical video player using SceneKit: https://github.com/jglasse/OSVR – jglasse Mar 14 '16 at 06:12
0

You need to use SKVideoNode to display a video on a sphere, see SKVideoNode only on a small part of SCNSphere - still minor issues, will update when it's fixed.

Community
  • 1
  • 1
Gerwin
  • 1,572
  • 5
  • 23
  • 51
  • Note that in recent versions of SceneKit using a `SKScene` and a `SKVideoNode` is not necessary. You can directly set the `AVPlayer` as the contents of a `SCNMaterialProperty` instance. – mnuages Apr 22 '18 at 22:40
0

Set up your player and start playing before you assign it as material to make it work.

var player = AVPlayer(url: yourURL)
player.play()
node.geo.material.emissive.contents = player
Rom4in
  • 532
  • 4
  • 13