リアルとバーチャルの間

気まぐれに書いてます。

GoPro6台で360度撮影 動画とネット技術で新世界

360度ぐりぐりと回してみる事のできる動画です。
サイトはこちら

クリックしながらマウスを動かすと360度色んな確度から見る事ができます。
WEBGLが早くiPhoneに実装される事が待ち遠しいですよね。

さて、こんな動画をどうやって作ったのかっという話ですが

海外の”360HEROS”から購入する所から始まります。
私が購入したのはGoProが6台つけられるタイプのものです。

この取り付けるやつですが、7万円くらいして結構高い><
3Dプリンターでも作れちゃう感じなので案件が落ち着いたら自分で作って
Gitとかで無料配布しようかと思うので作ったらまた告知しますね。

購入すると1週間くらいしたら送られてきます。

それで、コイツにGoProを取り付けようとするのですが
固いのなんの。 ちょ、これあんまりグイグイ曲げると折れるんじゃないの?って
思うくらいハラハラしますが、とりあえずけっこう曲げちゃっても大丈夫なのでご安心を!

これでとりあえずは、ぽちぽち録画ボタンさえ押せば6方向から撮影できるのですが
GoProのwifi設定を使って遠隔のリモコンと6台のGoProを通信させる事をお勧めします。

それで、そんな感じで録画した映像を3DCGの球体にマッピングできるように結合する必要があるのですが
auto pano videoというツールを使うのがオススメです。

こいつは、GoProから動画を取り込んでSynchronizationボタンを押してしまえば
あっという間に出来上がってしまいます。
厳密に動画の始まりを合わせる方法として、カチンコなどで音の始まりを押させておいてしまい
Synchronoization内にある音同期のボタンを押せばさらに良いと思います。

Unityカンファレンスで登壇させて頂いた時にも360度の撮影から実装までを話しています。
http://japan.unity3d.com/events/usc2014/pdf/1400_ROOM1_Kayac.pdf

カメラ撮影から実装までさせて頂いた案件

明治エッセルスーパーカップ20周年プロモーション|受託実績|面白法人カヤック



そうして書き出された動画を使ってブラウザへ表示されているのです。
いやー。ほんといい時代なったものですね。

ソースは以下みたいな感じ。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="container"></div>

<script src="./js/Detector.js"></script>
<script src="./js/RequestAnimationFrame.js"></script>
<script src="./js/threejs/three_r65.js"></script>
<script src="./js/threejs/TrackballControls.js"></script>
<!--<script src="./js/threejs/OrbitControls.js"></script>-->
<script type="text/javascript">

if (Detector.webgl)
{

    var MODEL_DATA = './screen.js';

    var renderer,
        scene,
        light,
        camera,
        geometry,
        material,
        mesh,
        controls;

    var video,
        videoImage,
        videoImageContext,
        videoTexture;

    var loader = new THREE.JSONLoader();

    loader.load(MODEL_DATA, function (geometry, materials)
    {
        var material = new THREE.MeshBasicMaterial({map: videoTexture, overdraw: true, side:THREE.DoubleSide});
        mesh = new THREE.Mesh(geometry, material);
        mesh.scale.set(100, 100, 100);
        scene.add(mesh);

        draw();
    });

    function init()
    {
        var WIDTH = 1200;
        var HEIGHT = 600;

        renderer = new THREE.WebGLRenderer();
        renderer.setSize(WIDTH, HEIGHT);
        renderer.setClearColor(new THREE.Color(0xFFFFFF));
        document.getElementById('container').appendChild(renderer.domElement);

        scene = new THREE.Scene();

        camera = new THREE.PerspectiveCamera(45, WIDTH/HEIGHT, 1, 1000);
        camera.position.set(0, 0, 80);
        scene.add(camera);

        light = new THREE.PointLight( 0xFFFFFF );
        light.position.set(10, 50, 130);
        scene.add(light);

        controls = new THREE.TrackballControls(camera, renderer.domElement);

        // video
        video = document.createElement('video');
        video.src = 'low-movie.mp4';
        video.load();
        video.play();

        videoImage = document.createElement('canvas');
        videoImage.width = 1024;
        videoImage.height = 512;

        videoImageContext = videoImage.getContext('2d');
        videoImageContext.fillStyle = '#000000';
        videoImageContext.fillRect(0, 0, videoImage.width, videoImage.height);

        videoTexture = new THREE.Texture(videoImage);
        videoTexture.minFilter = THREE.LinearFilter;
        videoTexture.magFilter = THREE.LinearFilter;
    }

    function draw()
    {
        if (video.readyState === video.HAVE_ENOUGH_DATA) {
            videoImageContext.drawImage(video, 0, 0);
            if (videoTexture) {
                videoTexture.needsUpdate = true;
            }
        }

        controls.update();
        renderer.render(scene, camera);
        requestAnimationFrame(draw);
    }


    init();

}
</script>

</body>
</html>