はじめに

ローカル環境で、HTTPS接続できるようになったので、早速 MeraQuest2 からローカルサーバに接続して、VScodeの live-serverでVR。

当初は、ブラックアウトして全く表示されなかったのですが、VR用のコードを見直してなんとか動くようになったので、忘れないうちにメモを残しておきます。

Quest2 のキャプチャ動画。


Three.jsで作成した自分で作った世界にVRで入れるのは、感動ものですね。

VRアプリを作って売れるかもですね。

ただ、コントローラーの制御などやるべき課題は山済みなので、まだまだ勉強は必要だと思います。

追記(翌日):

巨大なキャラクターを作ってその下を歩くとか、サイズやカスタマイズは開発者目線だと自由自在なので、過去プレイした市販ゲームの不満はすべて解消できます。

市販ゲームにMODを入れてカスタムするのが、昔も今も?流行ってましたが、ああいうのもどうやって作ってるのかが開発者目線になると、分かるようにもなってきます。

MODを作ってみたいのもありますが、Three.jsで自分で世界を作る方がすスキルアップにもなるし、楽しいです。

昨日は、BlenderとJavaScript Three.jsを空き時間に寝るまでやってたので、ヘトヘトでしたが、今日もまたやると思います。
まずはリファクタと昨日のコードの見直しから。

勢いで、記事を4つぐらい?書きなぐったので誤字脱字も酷いです…。

1. Three.js での基本的なVR設定

まず、Three.js と WebXR を使ったVR環境の設定を行います。以下のコードでは、WebXRのVRボタンを表示して、ユーザーがVRモードに入れるようにします。

基本的なVRシーンのセットアップ

import * as THREE from 'three';
import { VRButton } from 'three/examples/jsm/webxr/VRButton.js';

let scene, camera, renderer;

function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // VRボタンを作成
  document.body.appendChild(VRButton.createButton(renderer));

  // 簡単な立方体を作成してシーンに追加
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

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

function animate() {
  renderer.setAnimationLoop(animate); // VRモードのアニメーションループ
  renderer.render(scene, camera);
}

init();

このコードのポイント

  • VRButton.createButton(renderer) で、VRモードに切り替えるためのボタンを追加しています。
  • 立方体を作成して、VR環境で表示できるようにしています。

2. コントローラーの表示と操作

次に、コントローラーの表示を行います。XRController を使って、VRコントローラーをシーンに追加し、コントローラーの入力(ボタンの押下など)を処理できるようにします。

コントローラーをシーンに追加する

import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js';

let controller1, controller2;
const controllerModelFactory = new XRControllerModelFactory();

function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // VRボタンを作成
  document.body.appendChild(VRButton.createButton(renderer));

  // コントローラーを作成
  controller1 = renderer.xr.getController(0); // 左手
  controller2 = renderer.xr.getController(1); // 右手

  // シーンにコントローラーを追加
  scene.add(controller1);
  scene.add(controller2);

  // 簡単な立方体を作成してシーンに追加
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

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

function animate() {
  renderer.setAnimationLoop(animate); // VRモードのアニメーションループ
  renderer.render(scene, camera);
}

init();

コントローラーの表示

  • renderer.xr.getController(0)renderer.xr.getController(1) を使って、左手と右手のコントローラーを取得し、シーンに追加しています。
  • これにより、VRモードでコントローラーが視覚的に表示されます。

3. コントローラーの入力を処理する

次に、コントローラーの入力(例えば、ボタンが押されたとき)を処理するためのイベントリスナーを追加します。

controller1.addEventListener('selectstart', onSelectStart);
controller1.addEventListener('selectend', onSelectEnd);

controller2.addEventListener('selectstart', onSelectStart);
controller2.addEventListener('selectend', onSelectEnd);

function onSelectStart(event) {
  console.log('コントローラーのボタンが押されました');
  // 必要に応じて、ボタンが押されたときのアクションを追加
}

function onSelectEnd(event) {
  console.log('コントローラーのボタンが放されました');
  // 必要に応じて、ボタンが放されたときのアクションを追加
}

4. VRセッションの開始

VRボタンを押すと、ユーザーはVRセッションに入ります。セッションが開始された後、ユーザーの頭の動きに合わせてカメラの視点が変更されます。

renderer.setAnimationLoop() を使用して、VRモードでのフレームごとの更新を行います。この方法で、VRモードでカメラがユーザーの視点に合わせて動き、VRコントローラーが表示され、ボタン操作やスティックの入力を取得できるようになります。


まとめ

  • カメラ: renderer.xr.getController() を使ってVRコントローラーを表示し、VRButton.createButton(renderer) でVRセッションを開始。
  • コントローラー: XRControllerModelFactory を使って、コントローラーのモデルを表示。
  • コントローラーの入力: selectstartselectend イベントで、ボタン押下を処理。
  • VRモード: renderer.setAnimationLoop(animate) でアニメーションループを開始し、VRセッションのフレームごとの更新を行う。