Babylon.jsで始めるQuest対応WebXR

14.1K Views

November 03, 23

スライド概要

2023/11/03に開催のBabylon.jsハンズオン資料

profile-image

可視化技術や人間計測/空間計測技術を活用した問題解決に関する研究開発。 ARコンテンツ作成勉強会(AR_Fukuoka)を主催。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Babylon.jsで始めるQuest対応WebXR

2.

もろもろのダウンロード https://github.com/TakashiYoshinaga/AR-Fukuoka/raw/main/ChatGPT-20230324/Project.zip

3.

⾃⼰紹介 ⽒名︓吉永崇 (Takashi Yoshinaga) 仕事︓AR/VR応⽤に関するR&D。主に医療⽀援 ウェアラブル・モーションキャプチャ技術開発 趣味︓AR/画像・点群処理を使ったプロトタイピング コミュニティ︓ARコンテンツ作成勉強会を主催

4.

ARコンテンツ作成勉強会(略称:AR Fukuoka)の概要 [形式] AR/VRコンテンツの作り⽅や関連技術を主にハンズオン形式で体験。 [規模] 参加⼈数はコロナ前は約5~10名/回、現在は約10~20名/回。 [参加条件] AR/VRの開発に興味があれば初⼼者⼤歓迎。専⾨知識は不要。

5.

X(旧Twitter) で情報を発信しています @AR_Fukuoka

6.

会場 [福岡] #AR_Fukuoka [札幌] #DoMCN じゅんさん(@jun_mh4g) ※福岡はリアル会場なし [⿅児島] #XRm⿅児島 あぶちさん(@abricheese) さって〜さん (@s_haya_0820)

7.

ハッシュタグ #AR_Fukuoka + #DoMCN #XRm⿅児島 現地会場

8.

本題に⼊ります

9.

本⽇のゴール [YouTube] Babylon.jsの基本的な使い⽅、XRモード、MRTKによるインタラクションについて紹介

10.

テンプレートの複製 https://glitch.com/~babylon-template GET STARTED

11.

テンプレートの複製 Remix Your Own

12.

テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 index.html

13.

テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview

14.

補⾜︓Previewが表⽰されない場合 PREVIEW

15.

補⾜︓Previewが表⽰されない場合 Open preview pane

16.

補⾜︓Previewが表⽰されない場合 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview

17.

ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション

18.

テンプレートの確認 Lesson01

19.

テンプレートの確認 ライブラリの読み込み 描画やインタラクション の記述(今⽇のメイン) 描画領域のレイアウト

20.

テンプレートの確認 描画領域のレイアウト

21.
[beta]
HTMLの記述の解説
<!--描画する領域-->
<canvas id="renderCanvas" style="width: 100%; height: 100%;"></canvas>

idはjavascriptからアクセスする際に使⽤

ウィンドウ内、めいっぱいのサイズでcanvasを貼り付け

22.

テンプレートの確認 ライブラリの読み込み

23.

テンプレートの確認 描画やインタラクション の記述(今⽇のメイン)

24.

ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション

25.

3D描画の準備︓変数の宣⾔ ここに変数を追加 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { } //3D空間の初期化 function createScene() { } //WebXRの初期化 async function initializeXR(){ } //表⽰オブジェクトの初期化 function addObjects(){ }

26.

3D描画の準備︓変数の宣⾔ let canvas; //canvas要素 (描画領域) ← 「どこに」描画するか let engine; //Babylon.jsによる描画機能 ← 「何を使って」描画するか let scene; //仮想3D空間 ← 「何を」描画するか //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { } //3D空間の初期化 function createScene() { } //WebXRの初期化 async function initializeXR(){ } Lesson02

27.

Babylon.jsを⽤いた描画機能の初期化 let canvas; //canvas要素 (描画領域) let engine; //Babylon.jsによる描画機能 let scene; //仮想3D空間 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { //描画領域(canvas要素)をHTMLから取得 canvas = document.getElementById("renderCanvas"); //Babylon.jsを使って描画する準備 (引数︓描画先,アンチエイリアス) engine = new BABYLON.Engine(canvas, true); //カメラやライトの設定を⾏ったscene(3D空間)を取得 scene= createScene(); } //3D空間の初期化 function createScene() { } Lesson03

28.

シーン(3D空間)の初期化 let canvas; //canvas要素 (描画領域) let engine; //Babylon.jsによる描画機能 let scene; //仮想3D空間 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { //描画領域(canvas要素)を取得 canvas = document.getElementById("renderCanvas"); //Babylon.jsを使って描画する準備 (引数︓描画先,アンチエイリアス) engine = new BABYLON.Engine(canvas, true); //カメラやライトの設定を⾏ったscene(3D空間)を作成 createScene(); } //3D空間の初期化 function createScene() { } シーンの初期化処理を記述(次⾴) Lesson04

29.
[beta]
シーン(3D空間)の初期化
function createScene() {
//3D空間を作成
scene = new BABYLON.Scene(engine);
//背景⾊を設定
scene.clearColor = new BABYLON.Color3.Black();
//Lightを設定 (引数︓名前,反射の⽅向,追加先)
let light = new BABYLON.HemisphericLight("light",
new BABYLON.Vector3(1, 1, -0.5) ,scene);
//カメラを作成 [詳細]
let camera = new BABYLON.ArcRotateCamera(
"camera",
//名前
-Math.PI/2, Math.PI/2, 3, //alpha,beta,距離
new BABYLON.Vector3(0, 0, 0)); //注視点
//マウスやキーボードによるカメラ操作を可能にする
camera.attachControl(canvas, true);
}

Lesson05

30.

この時点ではまだ何も表⽰されません︕

31.

実際に描画しよう (window.onload内) //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { //描画領域(canvas要素)を取得 canvas = document.getElementById("renderCanvas"); //Babylon.jsで描画する準備 (引数︓描画先,アンチエイリアス) engine = new BABYLON.Engine(canvas, true); //カメラやライトの設定を⾏ったscene(3D空間)を作成 createScene(); //毎フレーム描画を更新 engine.runRenderLoop(function () { if (scene && scene.activeCamera) { scene.render(); //描画︕ } }); } Lesson06

32.

確認 Previewの背景が指定した⾊(=⿊)になる

33.

オブジェクトを描画 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { //描画領域(canvas要素)を取得 canvas = document.getElementById("renderCanvas"); //Babylon.jsで描画する準備 (引数︓描画先,アンチエイリアス) engine = new BABYLON.Engine(canvas, true); //カメラやライトの設定を⾏ったscene(3D空間)を作成 createScene(); //描画オブジェクトの作成 addObjects(); //毎フレーム描画を更新 engine.runRenderLoop(function () { if (scene && scene.activeCamera) { scene.render(); } }); Lesson07 }

34.

オブジェクトを描画 次はここを編集

35.
[beta]
オブジェクトを描画︓地⾯
function addObjects(){

}

//地⾯を作成 (原点の位置確認⽤。後で削除してOK)
let ground = BABYLON.MeshBuilder.CreateGround(
"ground", {width: 1, height: 1});
//箱状のオブジェクト作成 (30cm)
let box = BABYLON.MeshBuilder.CreateBox(
"box", {width: 0.3, height: 0.3, depth: 0.3});
box.position.x = 0.0;
box.position.y = 1; //地⾯(ground)から1mの⾼さ
//マテリアルを作成
let boxMaterial = new BABYLON.StandardMaterial("material");
//箱の⾊を設定 (今回はランダムに変化)、そのあとboxに適⽤
boxMaterial.diffuseColor = BABYLON.Color3.Random();
box.material = boxMaterial;
//8⾯体を作成
let octa = BABYLON.MeshBuilder.CreatePolyhedron("octa", {type:1,size: 0.15});
octa.position.x=0.5;
octa.position.y=1;
Lesson08

36.

確認 attatchControlで追加したマウスでの視点変更によりgroundオブジェクトを観察可能 初期視点 左クリック+ドラッグで回転 スクロールで前後移動 右クリック+ドラッグで 上下左右移動

37.
[beta]
オブジェクトを描画︓Box
function addObjects(){

}

//地⾯を作成 (原点の位置確認⽤。後で削除してOK)
let ground = BABYLON.MeshBuilder.CreateGround(
"ground", {width: 1, height: 1});
//箱状のオブジェクト作成 (30cm)
let box = BABYLON.MeshBuilder.CreateBox(
"box", {width: 0.3, height: 0.3, depth: 0.3});
box.position.x = 0.0;
box.position.y = 1; //地⾯(ground)から1mの⾼さ
//マテリアルを作成
let boxMaterial = new BABYLON.StandardMaterial("material");
//マテリアルに箱の⾊を設定 (今回はシアン)、そのあとboxに適⽤
boxMaterial.diffuseColor = new BABYLON.Color3(0.0,1.0,1.0);
box.material = boxMaterial;
//8⾯体を作成
let octa = BABYLON.MeshBuilder.CreatePolyhedron("octa", {type:1,size: 0.15});
octa.position.x=0.5;
octa.position.y=1;
Lesson09

38.

確認 箱が追加される

39.

[補⾜] 様々な基本図形 https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/set

40.

ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション

41.

3Dモデルファイルの読み込み準備 ライブラリの読み込み Babylon.jsが提供するオブジェクト 読み込み機能を利⽤できるようにする

42.
[beta]
3Dモデルファイルの読み込み準備
<!--babylon.jsの読み込み-->
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<!--実際の処理の実装-->
<script type="text/javascript">
let canvas; //canvas要素 (描画領域)
let engine; //Babylon.jsによる描画機能
let scene; //仮想3D空間
//ページの読み込み終了後に各種初期化を⾏う
window.onload = function () {
//描画領域(canvas要素)をHTMLから取得
canvas = document.getElementById("renderCanvas");
//Babylon.jsを使ってcanvasに描画する準備 (引数︓描画先,アンチエイリアス)
engine = new BABYLON.Engine(canvas, true);
/*以下省略*/

Lesson10

43.

3Dモデルのアップロード Assets

44.

3Dモデルのアップロード ブラウザ内にドラッグ&ドロップ figure.glb

45.

3Dモデルのアップロード index.htmlに戻る

46.
[beta]
3Dモデルファイルの読み込み
function addObjects(){
//地⾯を作成(原点の位置確認⽤。あとで削除してOK)
let ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 1, height: 1});
//箱状のオブジェクト作成(30cm)
let box = BABYLON.MeshBuilder.CreateBox("box", {width: 0.3, height: 0.3, depth: 0.3});
box.position.x = 0.0;
box.position.y = 1;
//箱の⾊をシアンに設定
let boxMaterial = new BABYLON.StandardMaterial("material");
boxMaterial.diffuseColor = new BABYLON.Color3(0.0,1.0,1.0);
box.material = boxMaterial;

オブジェクトを読み込むコードを追加(次⾴)
}

47.

3Dモデルファイルの読み込み function addObjects(){ /*スペースの都合上、省略*/ boxMaterial.diffuseColor = new BABYLON.Color3(0.0,1.0,1.0); box.material = boxMaterial; //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", //3Dモデルが置かれたフォルダ or 3DモデルのURL "", //3Dモデルのファイル名。上記でモデルのURLを指定した場合は空でOK scene, //オブジェクトを追加する先のScene function (container) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 [詳細] let glbMesh = container.meshes[1]; //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); } Lesson11

48.

3Dモデルファイルの読み込み function addObjects(){ /*スペースの都合上、省略*/ boxMaterial.diffuseColor = new BABYLON.Color3(0.0,1.0,1.0); box.material = boxMaterial; //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", //3Dモデルが置かれたフォルダ or 3DモデルのURL "", //3Dモデルのファイル名。上記でモデルのURLを指定した場合は空でOK scene, //オブジェクトを追加する先のScene function (container) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); }

49.

オブジェクトのURL Assets

50.

オブジェクトのURL figure.glbをクリック

51.

オブジェクトのURL Copy URL

52.

オブジェクトのURL 閉じる

53.

オブジェクトのURL index.htmlに戻る

54.

3Dモデルファイルの読み込み function addObjects(){ /*スペースの都合上、省略*/ dragBehavior.rotateWithMotionController=false; box.addBehavior(dragBehavior); //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", //3Dモデルが置かれたフォルダ or 3DモデルのURL "", //3Dモデルのファイル名。上記でモデルのURLを指定した場合は空でOK "と scene, //オブジェクトを追加する先のScene function (container) { "の間にURLをペースト //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); }

55.

確認 すごく⼩さい

56.

3Dモデルの調整 //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", //3Dモデルが置かれたフォルダ or 3DモデルのURL "", //3Dモデルのファイル名。上記でモデルのURLを指定した場合は空でOK scene, //オブジェクトを追加する先のScene function (container) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //スケールを10倍 glbMesh.scaling=new BABYLON.Vector3(10,10,10); //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); Lesson12

57.

3Dモデルの調整 //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", //3Dモデルが置かれたフォルダ or 3DモデルのURL "", //3Dモデルのファイル名。上記でモデルのURLを指定した場合は空でOK scene, //オブジェクトを追加する先のScene function (container) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //スケールを10倍 glbMesh.scaling=new BABYLON.Vector3(10,10,10); //Y軸(=鉛直⽅向の軸)を中⼼に180度(=πラジアン)回転 glbMesh.rotation =new BABYLON.Vector3(0, Math.PI, 0); //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); Lesson13

58.

ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション

59.

WebXRを有効化してQuestで体験しよう 次はここを編集 ここも編集

60.

WebXRを有効化してQuestで体験しよう window.onload = function() { /*スペースの都合上、省略*/ //描画オブジェクトの作成 addObjects(); //XRモードの初期化 initializeXR(); //毎フレーム描画を更新 engine.runRenderLoop(function () { if (scene && scene.activeCamera) { scene.render(); } }); } //WebXRの初期化 async function initializeXR(){ let xr = await scene.createDefaultXRExperienceAsync({ /*オプション*/ }); } Lesson14

61.

実機での体験前にURLを変更 Settingsをクリック

62.

実機での体験前にURLを変更 Edit project details ここを分かりやすく変更 最後にSave

63.

URLを確認 をクリック Copy Link

64.

URLを確認 テキストエディタなどに貼り付けてURLを確認 https://⾃⾝でつけた名前.glitch.me/

65.

Questでのアクセス⽅法① (要Metaアカウント) PCのWebブラウザで下記にアクセス https://www.oculus.com/open_url/?url=コンテンツのURL 開く

66.

Questでのアクセス⽅法② URLを⼊⼒ ゴーグルボタン QuestのWebブラウザのアドレスバーにコンテンツのURLを⼊⼒後、ゴーグルボタンをタップ/クリック

67.

動作確認

68.

終了⽅法 Oculusボタン Metaボタン 閉じるボタン コントローラのOculus/Metaボタンからウィンドウを表⽰してコンテンツを終了

69.
[beta]
カメラパススルーを有効にしてAR化
//WebXRの初期化
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync(
{
/*ここでオプションも設定可能*/
uiOptions: {
sessionMode: 'immersive-ar'
}
}
);
}
Lesson15

70.
[beta]
カメラパススルーを有効にしてAR化︓問題点
//WebXRの初期化
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync(
{
/*ここでオプションも設定可能*/
uiOptions: {
sessionMode: 'immersive-ar'
}
}
);
}

カメラの位置が
強制的にセットされる

71.
[beta]
視点の位置の補正
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync({/*オプション*/});
if (xr.baseExperience) { //XRモードに成功していれば
//XRモードに遷移したタイミングでカメラの初期位置を調整
xr.baseExperience.onStateChangedObservable.add((state)=>{
if(state === BABYLON.WebXRState.IN_XR){
xr.baseExperience.camera.position.set
(0,scene.activeCamera.position.y,-2);
});
}
}

-2[m]

position.y[m]

}

Lesson16

72.

実機で動作確認 再読み込み 目の前にオブジェクトが表示される

73.

ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション

74.

オブジェクトを操作 次はここを編集

75.

オブジェクトを操作 function addObjects(){ /*スペースの都合により省略*/ //箱の⾊をランダムに設定 let boxMaterial = new BABYLON.StandardMaterial("material"); boxMaterial.diffuseColor = BABYLON.Color3.Random(); box.material = boxMaterial; //boxに⼿で掴んで移動できる属性を追加 let dragBehavior = new BABYLON.SixDofDragBehavior(); dragBehavior.allowMultiPointer = false; dragBehavior.rotateWithMotionController = false; box.addBehavior(dragBehavior); //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( /*スペースの都合により省略*/ ); Lesson17

76.

PCで動作確認(マウス操作) DragBehaviorを適⽤した オブジェクトのみ操作可能

77.

実機で動作確認 再読み込み 現時点ではハンドトラッキングでの⼿の表⽰がおかしい (あとで修正)

78.

3Dモデルを操作可能にする //SceneLoaderを使って3Dモデルを読み込む BABYLON.SceneLoader.LoadAssetContainer( "3DモデルのURL", "", scene, function (container) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //スケールを10倍 glbMesh.scaling=new BABYLON.Vector3(10,10,10); //Y軸(=鉛直⽅向の軸)を中⼼に180度(=πラジアン)回転 glbMesh.rotation =new BABYLON.Vector3(0, Math.PI, 0); //読み込んだオブジェクト⽤にマニピュレーションの挙動を作成 let dragBehavior2 = new BABYLON.SixDofDragBehavior(); dragBehavior2.allowMultiPointer=false; dragBehavior2.rotateWithMotionController=false; glbMesh.addBehavior(dragBehavior2); //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); Lesson18

79.
[beta]
ハンドトラッキング機能をON
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync({/*オプション*/});
if (xr.baseExperience) {
//カメラの初期位置を調整
xr.baseExperience.onStateChangedObservable.add((state)=>{/*省略*/});
//利⽤可能な場合はハンドトラッキングをオンにする
let xrHandFeature = xr.baseExperience.featuresManager.enableFeature(
BABYLON.WebXRFeatureName.HAND_TRACKING,
"latest",
{
xrInput: xr.input
}
);
}
Lesson19
}

80.

実機で動作確認 手のオブジェクトも正しく表示される

81.

おまけ:指の位置の取得⽅法 左右それぞれ25関節取得可能 [詳細] 左右の人差し指が近づいたら回転

82.
[beta]
おまけ:指の位置の取得⽅法
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync({/*オプション*/});
if (xr.baseExperience) {
//カメラの初期位置を調整
xr.baseExperience.onStateChangedObservable.add((state)=>{/*省略*/});
//利⽤可能な場合はハンドトラッキングをオンにする
let xrHandFeature = xr.baseExperience.featuresManager.enableFeature(
BABYLON.WebXRFeatureName.HAND_TRACKING,
"latest",
{
xrInput: xr.input
}
);
指の位置を取得するコードを記述

83.
[beta]
おまけ:指の位置の取得⽅法
if(xrHandFeature){
let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {
let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

});
}

Lesson20

84.
[beta]
おまけ:指の位置の取得⽅法
⼿を使えるなら
if(xrHandFeature){
let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {

⼿を取得

let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

});
}

Lesson20

85.
[beta]
おまけ:指の位置の取得⽅法
if(xrHandFeature){
let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {
let rightHand = xrHandFeature.getHandByHandedness("right");
取得できたなら

let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

});
}

Lesson20

86.
[beta]
おまけ:指の位置の取得⽅法
if(xrHandFeature){
let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {
let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){

⼈差し指

let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

距離を計算

});
}

Lesson20

87.
[beta]
おまけ:指の位置の取得⽅法
if(xrHandFeature){
let box=scene.getMeshByName("box");
実⾏タイミング

//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () { //毎フレームレンダリングする直前に実⾏
let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

});
}

Lesson20

88.
[beta]
おまけ:指の位置の取得⽅法
前半で作った
Box取得

if(xrHandFeature){

let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {
let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let length = BABYLON.Vector3.Distance(indexR,indexL);
}

Boxを操作するコードを記述

});
}

Lesson20

89.
[beta]
おまけ:指の間の距離を⽤いてBoxを回転
let box=scene.getMeshByName("box");
//描画する直前に毎フレーム⾏う処理
scene.registerBeforeRender(function () {
let rightHand = xrHandFeature.getHandByHandedness("right");
let leftHand = xrHandFeature.getHandByHandedness("left");
if(rightHand && leftHand){
let indexR = rightHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
let indexL = leftHand.getJointMesh(
BABYLON.WebXRHandJoint.INDEX_FINGER_TIP).position;
2cm未満なら

let length = BABYLON.Vector3.Distance(indexR,indexL);
if(length<0.02){

0.01[rad]加算

box.rotation=new BABYLON.Vector3(0,box.rotation.y+0.01,0);
}
}
});

90.

完成︕

91.

参考① Camera https://doc.babylonjs.com/divingDeeper/cameras/camera_introduction 基本図形 https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/set WebXR Experience Helper https://doc.babylonjs.com/divingDeeper/webXR/webXRExperienceHelpers#webxrdefault-experience-helper MRTK https://doc.babylonjs.com/divingDeeper/gui/mrtk SixDofDragBehaviour https://doc.babylonjs.com/typedoc/classes/BABYLON.SixDofDragBehavior Scene Loader https://doc.babylonjs.com/typedoc/classes/BABYLON.SceneLoader

92.

参考② ARモード(Questパススルー対応) https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRARFeatures#feat ures Hand Trackingの概要 https://doc.babylonjs.com/divingDeeper/webXR/WebXRSelectedFeatures#handtracking ⼿を取得する⽅法 https://doc.babylonjs.com/typedoc/classes/BABYLON.WebXRHandTracking#getHandB yHandedness ⼿の関節 https://doc.babylonjs.com/typedoc/classes/BABYLON.WebXRHand#getJointMesh ⼿の関節の名称 https://doc.babylonjs.com/typedoc/enums/BABYLON.WebXRHandJoint

93.

今⽇の完成品 GitHubでも公開しています https://github.com/TakashiYoshinaga/babylonjs-webxr