MetaQuest2  + A-Frame / BabylonJsを使ったhandtracking


# はじめに

MetaQuest2を使っていて、非常に驚くのがhandtrackingの操作感で、モノを手にとったり、投げたり、
ペンを持ったりと、非常にリアルにできています。
Metaの動画の中にも、"I mean the human hand is an engineering marvel"という風に述べられていて、
( https://youtu.be/Uvufun6xer8?t=2770  )
ARやVRにおいて、手というものの表現に非常に力がいられているのだなと感じました。
MyoSuiteとよばれる正確に人間の骨格を補足し、アバターに反映するようなテクノロジーなども話題になっています。
https://tech.fb.com/artificial-intelligence/2022/05/myosuite/
https://japan.cnet.com/article/35187871/
とはいえ、まず、HandTrackingがどのようなものなのかを、手軽に体験するにはどういった方法があるか調べていました。

# Webでhandtrackingを実装する

WebでHandtrackingコンテンツを作成するためには、いくつかのSDKを利用することで、簡単に体験することができます。
今回は、A-FrameとBabyonJSの2種類を使いました。
A-Frameの方は、過去にもARコンテンツを実装するために利用していたので、期待していたのですが、
handtrackingまわりのバージョンの追従に対して、物理演算系のSDKのバージョンが追従しきれていないなど、
いくつかのハマりポイントがありました。
handtrackingなどのVRを主に考える場合には、BabylonJSの方がよいのかも？と思いながら、いろいろ試しています。

1.A-Frame
2.Babylonjs
3.Handtrack.js
4.WebVR Boilerplate
5.Unity + WebVR

#1.A-Frameの場合

https://aframe.io/docs/1.1.0/components/hand-tracking-controls.html
https://aframe.io/docs/1.2.0/components/hand-tracking-controls.html

##handtrackingの有効化

```javascript
<html>
  <head>
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-entity id="leftHand" hand-tracking-controls="hand: left;"></a-entity>
      <a-entity id="rightHand" hand-tracking-controls="hand: right;"></a-entity>
      <a-sky color="#4CC3D9"></a-sky>
    </a-scene>
  </body>
</html>


// 手の表示をドットにするには、modelStyleを適用
 <a-entity id="leftHand" hand-tracking-controls="hand: left; modelStyle: dots;">
```


## HandTrackingEventを利用する

```javascript
var rightHand = document.getElementById('rightHand');

rightHand.addEventListener('pinchmoved', function (event) {
  var sphere = document.getElementById('sphere');
  sphere.setAttribute('position', event.detail.position);
});
```


## ジェスチャーを検知する

```javascript
var bones = rightHand.components['hand-tracking-controls'].bones;
```


## gltf or obj ?

A-Frameでは、glTFを推奨とのこと
We recommend glTF for distributing assets in production over the web. 

https://aframe.io/docs/1.3.0/components/gltf-model.html
https://aframe.io/docs/1.3.0/primitives/a-obj-model.html

![スクリーンショット 2022-06-23 10.27.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/9dac4802-bb09-11b3-afc4-45dabf59c584.png)

## デバッグ

https://developer.oculus.com/documentation/web/browser-remote-debugging/

## バグなど

### physics

A-Frameの1.2.0 1.3.0で、Physicsを使う場合にうまく動作しない...。
これは既知のバグであるとのこと。
https://aframe.wiki/en/physics
https://aframe.io/docs/1.3.0/introduction/html-and-primitives.html#example-1
1.2.0ではThree.Geometryのpolyfillを利用すればok

### 手がぐにゃぐにゃ
https://github.com/aframevr/aframe/issues/4918

```
  <script src="https://cdn.jsdelivr.net/gh/mrdoob/three.js@r134/examples/js/deprecated/Geometry.js"></script>
```

# 2.BabylonJSの場合

##XR体験を有効にする

https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/javascript/tutorials/babylonjs-webxr-piano/introduction-01

```javascript
const createScene = async function(engine) {
    const scene = new BABYLON.Scene(engine);

    const alpha =  3*Math.PI/2;
    const beta = Math.PI/50;
    const radius = 220;
    const target = new BABYLON.Vector3(0, 0, 0);

    const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene);
    camera.attachControl(canvas, true);

    const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
    light.intensity = 0.6;

    const xrHelper = await scene.createDefaultXRExperienceAsync();

    return scene;
}
```

##ハンドトラッキングを有効化する

https://doc.babylonjs.com/typedoc/classes/BABYLON.WebXRHandTracking

```javascript
  const xrHelper = await scene.createDefaultXRExperienceAsync();
  const featuresManager = xrHelper.baseExperience.featuresManager;

  featuresManager.enableFeature(BABYLON.WebXRFeatureName.HAND_TRACKING, "latest", {
      xrInput: xrHelper.input,
      jointMeshes: {
          disableDefaultHandMesh: true,
          enablePhysics: true
      }
  });
```


## その他

https://doc.babylonjs.com/divingDeeper/webXR/WebXRSelectedFeatures#hand-tracking

https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/javascript/tutorials/babylonjs-webxr-piano/keyboard-interaction-03



# Oculus Browserのflag設定


Oculus Browswerでハンドトラッキングを利用するために、試験ツールの機能をonにする必要があります。

1.アドレスバーに chrome://flags と入力
2.検索でhandと入力する
3.WebXR experiences with hand and joints trackingを有効にする

![Image from iOS (86).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/159616a5-fa31-82e5-9e94-871b08e31af1.jpeg)


# demo

https://www.youtube.com/shorts/om4gkxTrmH0


# 参考

https://github.com/KhronosGroup/glTF-Sample-Models
https://aframe.io/examples/showcase/handtracking/

WebXR - Hand Tracking Examples 
https://webxr-handtracking.vercel.app/

[Babylon.js + Handtracking]

Class WebXRHandTracking
https://doc.babylonjs.com/typedoc/classes/BABYLON.WebXRHandTracking
https://forum.babylonjs.com/t/hand-tracking-support-for-webxr/12724
https://zenn.dev/iwaken71/scraps/8ec50f8a577174
https://zenn.dev/iwaken71/articles/babylonjs-webxr-handtracking

https://www.roadtovr.com/4-steps-to-start-experimenting-with-webvr-in-10-minutes/

https://onetech.jp/blog/what-is-webvr-tutorial-make-demo-webvr-with-unity-webgl-12303

https://blog.tensorflow.org/2019/11/handtrackjs-tracking-hand-interactions.html