19.4K Views
November 03, 23
スライド概要
2023/11/03に開催のBabylon.jsハンズオン資料
可視化技術や人間計測/空間計測技術を活用した問題解決に関する研究開発。 ARコンテンツ作成勉強会(tryAR)を主催。
Babylon.jsで始めるQuest対応WebXR
もろもろのダウンロード https://github.com/TakashiYoshinaga/AR-Fukuoka/raw/main/ChatGPT-20230324/Project.zip
⾃⼰紹介 ⽒名︓吉永崇 (Takashi Yoshinaga) 仕事︓AR/VR応⽤に関するR&D。主に医療⽀援 ウェアラブル・モーションキャプチャ技術開発 趣味︓AR/画像・点群処理を使ったプロトタイピング コミュニティ︓ARコンテンツ作成勉強会を主催
ARコンテンツ作成勉強会(略称:AR Fukuoka)の概要 [形式] AR/VRコンテンツの作り⽅や関連技術を主にハンズオン形式で体験。 [規模] 参加⼈数はコロナ前は約5~10名/回、現在は約10~20名/回。 [参加条件] AR/VRの開発に興味があれば初⼼者⼤歓迎。専⾨知識は不要。
X(旧Twitter) で情報を発信しています @AR_Fukuoka
会場 [福岡] #AR_Fukuoka [札幌] #DoMCN じゅんさん(@jun_mh4g) ※福岡はリアル会場なし [⿅児島] #XRm⿅児島 あぶちさん(@abricheese) さって〜さん (@s_haya_0820)
ハッシュタグ #AR_Fukuoka + #DoMCN #XRm⿅児島 現地会場
本題に⼊ります
本⽇のゴール [YouTube] Babylon.jsの基本的な使い⽅、XRモード、MRTKによるインタラクションについて紹介
テンプレートの複製 https://glitch.com/~babylon-template GET STARTED
テンプレートの複製 Remix Your Own
テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 index.html
テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview
補⾜︓Previewが表⽰されない場合 PREVIEW
補⾜︓Previewが表⽰されない場合 Open preview pane
補⾜︓Previewが表⽰されない場合 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション
テンプレートの確認 Lesson01
テンプレートの確認 ライブラリの読み込み 描画やインタラクション の記述(今⽇のメイン) 描画領域のレイアウト
テンプレートの確認 描画領域のレイアウト
HTMLの記述の解説
<!--描画する領域-->
<canvas id="renderCanvas" style="width: 100%; height: 100%;"></canvas>
idはjavascriptからアクセスする際に使⽤
ウィンドウ内、めいっぱいのサイズでcanvasを貼り付け
テンプレートの確認 ライブラリの読み込み
テンプレートの確認 描画やインタラクション の記述(今⽇のメイン)
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション
3D描画の準備︓変数の宣⾔ ここに変数を追加 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { } //3D空間の初期化 function createScene() { } //WebXRの初期化 async function initializeXR(){ } //表⽰オブジェクトの初期化 function addObjects(){ }
3D描画の準備︓変数の宣⾔ let canvas; //canvas要素 (描画領域) ← 「どこに」描画するか let engine; //Babylon.jsによる描画機能 ← 「何を使って」描画するか let scene; //仮想3D空間 ← 「何を」描画するか //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { } //3D空間の初期化 function createScene() { } //WebXRの初期化 async function initializeXR(){ } Lesson02
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
シーン(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
シーン(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
この時点ではまだ何も表⽰されません︕
実際に描画しよう (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
確認 Previewの背景が指定した⾊(=⿊)になる
オブジェクトを描画 //ページの読み込み終了後に各種初期化を⾏う 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 }
オブジェクトを描画 次はここを編集
オブジェクトを描画︓地⾯
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
確認 attatchControlで追加したマウスでの視点変更によりgroundオブジェクトを観察可能 初期視点 左クリック+ドラッグで回転 スクロールで前後移動 右クリック+ドラッグで 上下左右移動
オブジェクトを描画︓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
確認 箱が追加される
[補⾜] 様々な基本図形 https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/set
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション
3Dモデルファイルの読み込み準備 ライブラリの読み込み Babylon.jsが提供するオブジェクト 読み込み機能を利⽤できるようにする
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
3Dモデルのアップロード Assets
3Dモデルのアップロード ブラウザ内にドラッグ&ドロップ figure.glb
3Dモデルのアップロード index.htmlに戻る
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;
オブジェクトを読み込むコードを追加(次⾴)
}
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
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); } ); }
オブジェクトのURL Assets
オブジェクトのURL figure.glbをクリック
オブジェクトのURL Copy URL
オブジェクトのURL 閉じる
オブジェクトのURL index.htmlに戻る
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); } ); }
確認 すごく⼩さい
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
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
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション
WebXRを有効化してQuestで体験しよう 次はここを編集 ここも編集
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
実機での体験前にURLを変更 Settingsをクリック
実機での体験前にURLを変更 Edit project details ここを分かりやすく変更 最後にSave
URLを確認 をクリック Copy Link
URLを確認 テキストエディタなどに貼り付けてURLを確認 https://⾃⾝でつけた名前.glitch.me/
Questでのアクセス⽅法① (要Metaアカウント) PCのWebブラウザで下記にアクセス https://www.oculus.com/open_url/?url=コンテンツのURL 開く
Questでのアクセス⽅法② URLを⼊⼒ ゴーグルボタン QuestのWebブラウザのアドレスバーにコンテンツのURLを⼊⼒後、ゴーグルボタンをタップ/クリック
動作確認
終了⽅法 Oculusボタン Metaボタン 閉じるボタン コントローラのOculus/Metaボタンからウィンドウを表⽰してコンテンツを終了
カメラパススルーを有効にしてAR化
//WebXRの初期化
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync(
{
/*ここでオプションも設定可能*/
uiOptions: {
sessionMode: 'immersive-ar'
}
}
);
}
Lesson15
カメラパススルーを有効にしてAR化︓問題点
//WebXRの初期化
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync(
{
/*ここでオプションも設定可能*/
uiOptions: {
sessionMode: 'immersive-ar'
}
}
);
}
カメラの位置が
強制的にセットされる
視点の位置の補正
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
実機で動作確認 再読み込み 目の前にオブジェクトが表示される
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成と 基本図形の表示 Quest 3Dモデル(glb) の読み込み XRモードに対応 PC and Quest マウスや手、コントローラを 用いたインタラクション
オブジェクトを操作 次はここを編集
オブジェクトを操作 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
PCで動作確認(マウス操作) DragBehaviorを適⽤した オブジェクトのみ操作可能
実機で動作確認 再読み込み 現時点ではハンドトラッキングでの⼿の表⽰がおかしい (あとで修正)
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
ハンドトラッキング機能を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
}
実機で動作確認 手のオブジェクトも正しく表示される
おまけ:指の位置の取得⽅法 左右それぞれ25関節取得可能 [詳細] 左右の人差し指が近づいたら回転
おまけ:指の位置の取得⽅法
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
}
);
指の位置を取得するコードを記述
おまけ:指の位置の取得⽅法
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
おまけ:指の位置の取得⽅法
⼿を使えるなら
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
おまけ:指の位置の取得⽅法
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
おまけ:指の位置の取得⽅法
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
おまけ:指の位置の取得⽅法
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
おまけ:指の位置の取得⽅法
前半で作った
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
おまけ:指の間の距離を⽤いて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);
}
}
});
完成︕
参考① 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
参考② 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
今⽇の完成品 GitHubでも公開しています https://github.com/TakashiYoshinaga/babylonjs-webxr