[JavaScript] A-Frameとthree-vrmでVRMアバターをWebVRに組み込む

はじめに

Webブラウザ上で3Dコンテンツを簡単に表示するために、A-Frameというフレームワークを使用します。A-Frameは、HTMLベースのVR(仮想現実)コンテンツを作成するためのライブラリで、VRやARの体験をシンプルに実装できます。さらに、three-vrmライブラリを利用することで、VRM形式の3Dアバター(主にVRMやアバター系の3Dモデル)を簡単に読み込んで表示することができます。

このガイドでは、A-Frameを使用して、three-vrmでVRMアバターを表示し、以下の基本的なインタラクションを実装する方法を説明します:

  • VRMモデルの読み込み
  • アバターの表情やポージングを変更する方法
  • カメラの制御と視点の調整
  • VRMアバターをWebVRで表示するための基本的なコードサンプル

これらのステップを通じて、ブラウザ上でインタラクティブな3D体験を作成できるようになります。初心者でもすぐに試せるように、シンプルなコードを使って、段階的に進めていきますので、ぜひ一緒に学びながら進めていきましょう。

1. 必要なライブラリを準備

まず、A-Frame と three-vrm を使うためのライブラリを読み込む。これらは HTML ファイル内で CDN 経由で読み込むだけでも動かせる。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>VRM Sample</title>
    <!-- A-Frame -->
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <!-- three-vrm → three.js + VRMローダ -->
    <script src="https://cdn.jsdelivr.net/npm/three-vrm@1.0.0-alpha.10/dist/three-vrm.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
        <!-- VRMファイルをプリロード -->
        <a-asset-item id="vrmModel" src="path/to/your/model.vrm"></a-asset-item>
      </a-assets>

      <!-- VRMモデルを表示するエンティティ -->
      <a-entity vrm-model="src: #vrmModel" position="0 1.5 -3" rotation="0 180 0"></a-entity>
    </a-scene>
  </body>
</html>

補足ポイント

  • three-vrm は元来 Three.js 向けのライブラリだけど、A-Frame 環境でも使われるアダプタ/コンポーネントとして使える実装が複数存在する。 ([GitHub][1])
  • three‑vrm の公式レポジトリで提供されているサンプル(basic.html など)をベースにすると、まず「読み込んで表示する」だけなら比較的簡単に動かすことができる。 ([GitHub][2])
  • VRMモデルを読み込むだけでなく、ボーン操作や表情変更、アニメーションといったインタラクションにも対応。例えば、腕を動かしたり、表情を変えたりといった操作が可能。 ([note(ノート)][3])


[1]: https://github.com/binzume/aframe-vrm?utm_source=chatgpt.com “binzume/aframe-vrm: VRM components for A-Frame” [2]: https://github.com/pixiv/three-vrm?utm_source=chatgpt.com “pixiv/three-vrm: Use VRM on Three.js” [3]: https://note.com/npaka/n/n477c15fedaef?utm_source=chatgpt.com “three.js で VRM を表示する (1) - 事始め|npaka”

2. VRMモデルの読み込み

VRMファイルを読み込むには、A-Frameの a-asset-item タグを使用して、VRMファイルのパスを指定します。その後、three-vrmのvrm-modelコンポーネントを使って、VRMアバターをシーンに配置します。

<!DOCTYPE html>
<html>
  <head>
    <title>VRM Sample</title>
    <!-- A-Frame -->
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <!-- VRM for A-Frame -->
    <script src="https://cdn.jsdelivr.net/npm/three-vrm@1.0.0-alpha.10/dist/three-vrm.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
        <!-- VRMファイルをプリロード -->
        <a-asset-item id="vrmModel" src="path/to/your/model.vrm"></a-asset-item>
      </a-assets>

      <!-- VRMアバターを表示するエンティティ -->
      <a-entity vrm-model="src: #vrmModel" position="0 1.5 -3" rotation="0 180 0"></a-entity>
    </a-scene>
  </body>
</html>

説明

  • a-assetsタグ内に a-asset-item を使って、VRMモデルをプリロードしています。これにより、シーンの読み込み前にVRMファイルが準備され、エラーを避けることができます。
  • vrm-modelコンポーネントを使って、VRMアバターをシーンに配置します。src属性でプリロードしたVRMファイルを指定し、VRMアバターをシーン内に配置できます。

主なポイント

  • position=“0 1.5 -3”:これはVRMアバターの位置を指定するもので、x, y, z軸で位置を決めています。ここでは、アバターが地面から1.5単位の高さに配置され、カメラから-3単位の距離に設定されています。
  • rotation=“0 180 0”:アバターを反転させるための回転を指定しています。0 180 0はY軸周りに180度回転させる設定で、VRMファイルが通常の向きであれば、この反転を加えることで正しい視点で表示できます。

追加のカスタマイズ

VRMアバターの表示位置や向きは、positionやrotationの値を調整することで自由にカスタマイズできます。例えば、以下のようにカメラからの距離や角度を変えることができます:

<!-- カメラに向かって少し前方に配置 -->
<a-entity vrm-model="src: #vrmModel" position="0 1.5 -5" rotation="0 90 0"></a-entity>

これにより、VRMアバターがカメラに近い位置に配置され、角度も調整されます。

3. アバターの表情を変更する

VRMファイルには、アバターの表情を変更するための機能が組み込まれています。この機能を利用することで、簡単にアバターの表情を操作することができます。three-vrmを使って表情を変更するには、expressionManagerを使用します。

// アバターが読み込まれた後に表情を変更
const vrmEntity = document.querySelector('[vrm-model]');
vrmEntity.addEventListener('model-loaded', () => {
  const vrm = vrmEntity.getObject3D('mesh');

  // "happy"という表情を0.7に設定
  vrm.expressionManager.setValue('happy', 0.7);
});

説明

  • vrmEntity.addEventListener(‘model-loaded’, …):

    • VRMモデルが読み込まれた後に、表情を変更する処理を行っています。model-loadedイベントを使うことで、VRMアバターがシーンに読み込まれたタイミングで表情変更を行うことができます。
  • expressionManager.setValue(‘happy’, 0.7):

    • expressionManager.setValueを使って、アバターの表情を変更します。ここでは、“happy"という表情を0.7に設定しています。0は無表情、1は完全に表情がある状態です。0.7は「やや笑顔」程度の表情に相当します。

表情の設定

VRMアバターには、複数の表情(例えば、「happy」、「angry」、「surprised」など)が設定されており、それぞれの表情に数値を与えることで、表情の強さを調整できます。以下のような表情を使うことができます:

  • happy: 幸せな表情
  • angry: 怒った表情
  • surprised: 驚いた表情
  • sad: 悲しい表情

例えば、angryの表情を強くしたい場合は次のように設定します:

vrm.expressionManager.setValue('angry', 1.0);  // 完全に怒った表情

表情を動的に変更

expressionManagerを使うことで、プレイヤーのアクションやゲーム内のイベントに合わせて、表情を動的に変更することもできます。例えば、プレイヤーが勝利したときにアバターが喜びの表情をする、逆に敗北したときに悲しい表情に切り替える、というようなインタラクションが可能です。

// 勝利時に「happy」を強くする
vrm.expressionManager.setValue('happy', 1.0);

// 敗北時に「sad」を強くする
vrm.expressionManager.setValue('sad', 1.0);

まとめ

  • expressionManager.setValue を使うことで、VRMアバターの表情を簡単に変更できます。
  • 表情の強さは 0(無表情) から 1(最大表情) の範囲で調整できます。
  • アバターの表情をゲーム内イベントに合わせて動的に変更することで、インタラクティブで感情的な表現を追加できます。

4. VRMアバターのポージング

VRMアバターのポージング(ボーンの回転)を変更することもできます。例えば、腕を動かす場合、getNormalizedBoneNodeを使ってボーンを取得し、その回転を変更することができます。

// 左右の腕を動かす
vrmEntity.addEventListener('model-loaded', () => {
  const vrm = vrmEntity.getObject3D('mesh');

  const leftArm = vrm.humanoid.getNormalizedBoneNode('leftUpperArm');
  const rightArm = vrm.humanoid.getNormalizedBoneNode('rightUpperArm');

  // 左腕を少し回転
  leftArm.rotation.z = 1.1;

  // 右腕を逆方向に回転
  rightArm.rotation.z = -1.1;
});

説明

  • getNormalizedBoneNode(’leftUpperArm’):

    • getNormalizedBoneNodeを使って、VRMアバターの左腕(leftUpperArm)のボーンを取得します。この関数を使うことで、アバターのボーンにアクセスし、位置や回転などを操作できます。
  • rotation.z:

    • rotation.zは、ボーン(ここでは腕)の回転をZ軸周りに設定するためのプロパティです。1.1という値を設定することで、腕を一定角度回転させることができます。zの値を変更することで、腕を自由に動かすことができます。
    • 同様に、rotation.xやrotation.yでX軸やY軸周りの回転も制御できます。
  • 左右の腕の回転:

    • 左腕と右腕をそれぞれ異なる方向に回転させることで、アバターに自然な動きを与えることができます。例えば、右腕を反対方向に回転させると、両腕が異なる方向を向くポーズが作れます。

ポージングの活用方法

  • アニメーションを作成する際に、ボーンの回転を変更することで、アバターに動きを加えることができます。例えば、ジャンプや歩行のアニメーションを作成するために、腕や脚のボーンを回転させてポージングを変更します。

  • インタラクションに応じて、ポージングを変更することも可能です。例えば、プレイヤーがボタンを押したときにアバターがポーズをとる、あるいは手を振るといった動きができます。

例: 手を振る動作

以下は、アバターが手を振る動作をするためのコードです。leftUpperArmとrightUpperArmのrotation.zを時間経過に応じて変更することで、アバターが手を振るようなアニメーションを作成できます。

let angle = 0;
setInterval(() => {
  // 手を振る動き
  const leftArm = vrm.humanoid.getNormalizedBoneNode('leftUpperArm');
  const rightArm = vrm.humanoid.getNormalizedBoneNode('rightUpperArm');

  // 左右の腕を交互に動かす
  leftArm.rotation.z = Math.sin(angle) * 1.5; // 左腕の動き
  rightArm.rotation.z = Math.cos(angle) * 1.5; // 右腕の動き

  angle += 0.1;  // 時間経過でアニメーションを更新
}, 1000 / 60);  // 60FPSで更新

このコードでは、Math.sinとMath.cosを使って、左右の腕が交互に動くような手を振るアニメーションを実現しています。

まとめ

  • ボーンの操作を通じて、アバターのポーズを自由に変更できます。
  • 左右の腕や脚など、異なるボーンの回転を変更することで、アバターの動きやポーズを表現できます。
  • アニメーションやインタラクションに応じて、ボーンの回転を変更することで、リアルでダイナミックな動きを作り出せます。

5. カメラの追従

VRMアバターが動いているときに、カメラがその動きに合わせて追従する処理を追加すると、より没入感が増します。A-Frameでは、カメラを動かすために<a-camera>タグを使用します。

<!-- カメラをプレイヤーの後ろに配置 -->
<a-camera position="0 1.6 -5" look-at="[camera]" id="camera"></a-camera>

説明

  • a-camera タグ:

    • A-Frameでカメラを作成するためのタグです。カメラの位置や向きを指定することができます。
  • position=“0 1.6 -5”:

    • position属性でカメラの位置を指定します。0 1.6 -5は、カメラがプレイヤーからX軸0、Y軸1.6、Z軸-5の位置に配置されていることを示しています。この位置にカメラを配置することで、プレイヤーの背後にカメラを設定することができます。
  • look-at="[camera]”:

    • look-at属性を使用することで、カメラが常に特定のターゲットを向くように設定できます。この場合、look-at="[camera]“で、カメラが常にプレイヤーを向くようになります。つまり、プレイヤーの位置に合わせてカメラが追従し、プレイヤーが動くたびにカメラもその動きに追従します。
  • id=“camera”:

    • idを指定することで、他の要素からカメラを参照したり、JavaScriptで制御したりすることができます。

カメラの動きの調整

上記のコードは基本的なカメラの追従設定ですが、さらにカメラの動きを滑らかにしたり、距離や角度を微調整することも可能です。

  1. カメラのスムーズな追従:

    • 例えば、カメラが急に動かず、プレイヤーの動きにスムーズに追従するようにするためには、補間(Lerp)を使います。これにより、カメラの動きがより自然になります。
// プレイヤーの位置
const playerPos = new THREE.Vector3(0, 1.6, 0);  // プレイヤーの位置

// カメラの目標位置
let targetPos = playerPos.clone().add(new THREE.Vector3(0, 1.6, -5));  // プレイヤーの後ろ

// カメラの現在位置(初期設定)
let cameraPos = new THREE.Vector3(0, 1.6, -5);

// 毎フレーム更新
function updateCamera() {
  // カメラをスムーズにプレイヤーの位置に追従させる
  cameraPos.lerp(targetPos, 0.1);  // 0.1は補間の速度
  camera.position.set(cameraPos.x, cameraPos.y, cameraPos.z);
  camera.lookAt(playerPos);  // プレイヤーを常に見つめる
}

setInterval(updateCamera, 1000 / 60);  // 60FPSで更新

このコードでは、カメラの位置を補間(lerp)を使ってプレイヤーの位置にスムーズに追従させています。0.1という値で追従の速度を調整できます。

  1. カメラの高さや距離の調整:

    • プレイヤーからの距離やカメラの高さを微調整することで、視点をより動的に変更できます。例えば、プレイヤーがジャンプした時にカメラを少し上に移動させるなどの処理を加えることができます。
// ジャンプした時にカメラを少し上に移動させる例
if (player.isJumping) {
  camera.position.y = 2.5;  // カメラを少し上に移動
} else {
  camera.position.y = 1.6;  // 普段の高さに戻す
}

まとめ

  • カメラの追従を設定することで、プレイヤーの動きに合わせてカメラを動かし、没入感のある体験を提供できます。
  • positionとlook-atを使うことで、カメラの位置と向きを簡単に制御でき、プレイヤーを常に追いかけることができます。
  • スムーズなカメラ追従を実現するためには、補間(Lerp)を使ってカメラの位置を滑らかに更新することができます。

6. まとめ

  • A-Frameとthree-vrmを組み合わせることで、ブラウザ上で簡単に3Dアバターやインタラクションを実装できます。これにより、WebVR体験が簡単に構築でき、ブラウザ上で動作するインタラクティブな3Dコンテンツを作成できます。

  • 表情やポージング、カメラの制御も直感的に行え、ユーザーとのインタラクションを通じて、より没入感のある体験を提供することができます。これにより、ユーザーはアバターを自由にカスタマイズしたり、視点を動かして体験を楽しんだりできます。

  • A-Frameを使用することで、VRMモデルの読み込みからカスタマイズまで、非常にシンプルに3Dコンテンツを作成できます。A-Frameは、初心者でも簡単に扱えるフレームワークであり、さらにthree-vrmを加えることで、VRM形式のアバターをすぐにブラウザに組み込むことができます。

関連リンク