2
4

Webカメラ映像の中に入りこんでしまったかのようなパノラマビューを実現したゲーム。

Last updated at Posted at 2024-10-03

スクリーンショット 2024-10-04 044851.png

スクリーンショット 2024-10-04 044824.png

カーソルキー上下左右でパノラマを操作します。

コードをメモ帳などのテキストエディタに貼り付け、ファイルを「index.html」などの拡張子が.htmlのファイルとして保存します。その後、保存したファイルをブラウザで開けば、コードが実行されます。

説明:

Webカメラ映像の取得とテクスチャ化:

Webカメラの映像を取得し、VideoTextureオブジェクトを使ってテクスチャに変換します。これを後で円筒に貼り付けます。

円筒の作成:

CylinderGeometryで円筒形状を作成し、その上にWebカメラの映像をテクスチャとして貼り付けます。テクスチャは内側から見えるようにTHREE.DoubleSideを使用しています。

カメラ位置の設定:

カメラは円筒の内部の中心に位置しており、視点が常に円筒の中心を向くように設定されています。

キー入力による回転制御:

上下キーで円筒のX軸(横回転)を制御し、左右キーでY軸(縦回転)を制御します。キーが押されるたびに、指定された回転速度で回転角度が増減します。

アニメーションの更新:

animate関数で、フレームごとに円筒の回転状態を更新し、シーン全体をカメラの視点からレンダリングしています。

このコードを使うと、Webカメラで撮影した映像を貼り付けた円筒の内部で、キー操作に応じて視点が移動するパノラマビューを楽しめます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>360度パノラマビュー</title>
  <style>
    body { margin: 0; } /* ページの余白をなくす */
    canvas { display: block; } /* キャンバスの表示設定 */
  </style>
</head>
<body>
  <!-- Three.js ライブラリの読み込み -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script>
    // グローバル変数宣言
    let camera, scene, renderer, cylinder; // カメラ、シーン、レンダラー、円筒オブジェクト
    let videoTexture; // Webカメラの映像をテクスチャにするための変数
    let cylinderRotationX = Math.PI / 2; // 円筒のX軸回転角度の初期値(90度横向きに倒す)
    let cylinderRotationY = 0; // 円筒のY軸回転角度の初期値
    const rotationSpeed = 0.02; // 円筒の回転速度

    // 初期化関数
    function init() {
      // シーンの作成
      scene = new THREE.Scene();

      // レンダラーの作成とサイズ設定
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement); // レンダラーのDOM要素をページに追加

      // カメラを作成し、円筒の中心に配置
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.set(0, 0, 0); // カメラの位置を円筒の中心にセット

      // Webカメラの映像を取得
      const video = document.createElement('video'); // video要素を作成
      navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
        video.srcObject = stream; // Webカメラのストリームを設定
        video.play(); // 映像再生

        // 映像を横向きにするためのCSS回転設定
        video.style.transform = 'rotate(90deg)';

        // Webカメラ映像をテクスチャに変換
        videoTexture = new THREE.VideoTexture(video);

        // 円筒のジオメトリ(形状)を作成(円周5, 高さ10, 分割数32)
        const geometry = new THREE.CylinderGeometry(5, 5, 10, 32, 1, true);

        // テクスチャを適用したマテリアルを作成し、内側が見えるようにDoubleSide設定
        const material = new THREE.MeshBasicMaterial({ map: videoTexture, side: THREE.DoubleSide });

        // 円筒メッシュの作成と回転設定
        cylinder = new THREE.Mesh(geometry, material);
        cylinder.rotation.x = cylinderRotationX; // X軸に90度回転させて横向きに配置
        scene.add(cylinder); // シーンに円筒を追加

        // アニメーション開始
        animate();
      });

      // ウィンドウサイズ変更時にカメラとレンダラーの調整
      window.addEventListener('resize', () => {
        renderer.setSize(window.innerWidth, window.innerHeight); // レンダラーサイズ更新
        camera.aspect = window.innerWidth / window.innerHeight; // カメラのアスペクト比更新
        camera.updateProjectionMatrix(); // カメラの投影行列更新
      });

      // キーボード入力で円筒の回転を制御
      window.addEventListener('keydown', (event) => {
        if (event.key === 'ArrowLeft') {
          cylinderRotationY += rotationSpeed; // 左キーで円筒のY軸回転を増加
        } else if (event.key === 'ArrowRight') {
          cylinderRotationY -= rotationSpeed; // 右キーで円筒のY軸回転を減少
        } else if (event.key === 'ArrowUp') {
          cylinderRotationX += rotationSpeed; // 上キーで円筒のX軸回転を増加
        } else if (event.key === 'ArrowDown') {
          cylinderRotationX -= rotationSpeed; // 下キーで円筒のX軸回転を減少
        }
      });
    }

    // アニメーションループ
    function animate() {
      requestAnimationFrame(animate); // フレームごとの再描画リクエスト

      // 円筒のX軸とY軸を回転させる
      cylinder.rotation.x = cylinderRotationX; // X軸回転角度を適用
      cylinder.rotation.y = cylinderRotationY; // Y軸回転角度を適用

      // シーンをカメラの視点でレンダリング
      renderer.render(scene, camera);
    }

    // 初期化関数の実行
    init();
  </script>
</body>
</html>

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4