12.6K Views
February 11, 23
スライド概要
可視化技術や人間計測/空間計測技術を活用した問題解決に関する研究開発。 ARコンテンツ作成勉強会(tryAR)を主催。
Babylon.js x WebXRハンズオン for HoloLens 2 / Meta Quest
もろもろのダウンロード https://github.com/TakashiYoshinaga/AR-Fukuoka/ raw/main/Babylonjs_20230211/Sample.zip
⾃⼰紹介 ⽒名︓吉永崇 (Takashi Yoshinaga) 仕事︓AR/VR応⽤に関するR&D。主に医療⽀援 ウェアラブル・モーションキャプチャ技術開発 Volumetric Video遠隔コミュニケーション コミュニティ︓ARコンテンツ作成勉強会を主催
ARコンテンツ作成勉強会(略称:AR Fukuoka)の概要 [形式] AR/VRコンテンツの作り⽅や関連技術を主にハンズオン形式で体験。 [規模] 参加⼈数はコロナ前は約5~10名/回、現在は約10~20名/回。 [参加条件] AR/VRの開発に興味があれば初⼼者⼤歓迎。専⾨知識は不要。
Twitterと勉強会ページで情報を発信しています @AR_Fukuoka Googleで「AR勉強会」で検索
ハッシュタグ #AR_Fukuoka + #エンジニアカフェ #DoMCN #XR信州 現地会場
本題に⼊ります
本⽇のゴール https://youtu.be/iok646xGtd0 Babylon.jsの基本的な使い⽅とMRTKによるインタラクションの活⽤について紹介
テンプレートの複製 https://glitch.com/~babylon-template GET STARTED
テンプレートの複製 Remix Your Own
テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 index.html
テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview
テンプレートの確認 index.htmlをクリックし、コードが表⽰されることを確認 エディタ Preview
補⾜︓Previewが表⽰されない場合 PREVIEW
補⾜︓Previewが表⽰されない場合 Open preview pane
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成 HoloLens/Quest XRモード MRTKによるインタラクション 手のオブジェクト表示
テンプレートの確認 Lesson01
テンプレートの確認 ライブラリの読み込み 描画やインタラクション の記述(今⽇のメイン) 描画領域のレイアウト
テンプレートの確認 描画領域のレイアウト
HTMLの記述の解説
<!--描画する領域-->
<canvas id="renderCanvas" style="width: 100%; height: 100%;"></canvas>
idはjavascriptからアクセスする際に使⽤
ウィンドウ内、めいっぱいのサイズでcanvasを貼り付け
テンプレートの確認 ライブラリの読み込み
テンプレートの確認 描画やインタラクション の記述(今⽇のメイン)
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成 HoloLens/Quest XRモード MRTKによるインタラクション 手のオブジェクト表示
変数の宣⾔ ここに変数を追加 //ページの読み込み終了後に各種初期化を⾏う window.onload = function() { } //3D空間の初期化 function createScene() { } //WebXRの初期化 async function initializeXR(){ } //表⽰オブジェクトの初期化 function addObjects(){ }
変数の宣⾔ 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 = 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
確認 マウス操作で視点を変更することで追加した、地⾯に相当する板を観察できる 初期視点 左クリック+ドラッグで回転 スクロールで前後移動 右クリック+ドラッグで 上下左右移動
オブジェクトを描画
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;
Lesson09
確認 箱が追加される
オブジェクトを描画
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;
Lesson10
確認 箱と⼋⾯体が表⽰される
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成 HoloLens/Quest XRモード MRTKによるインタラクション 手のオブジェクト表示
QuestやHoloLens2で体験可能にしよう window.onload = function() { /*スペースの都合上、省略*/ //描画オブジェクトの作成 addObjects(); //XRモードの初期化 initializeXR(); //毎フレーム描画を更新 engine.runRenderLoop(function () { if (scene && scene.activeCamera) { scene.render(); } }); } //WebXRの初期化 async function initializeXR(){ let xr = await scene.createDefaultXRExperienceAsync({ /*オプション*/ }); } Lesson11
実機での体験前にURLを変更 Settingsをクリック
実機での体験前にURLを変更 Edit project details ここを分かりやすく変更 最後にSave
URLを確認 をクリック Copy Link
URLを確認 テキストエディタなどに貼り付けてURLを確認 https://⾃⾝でつけた名前.glitch.me/
動作確認 HoloLens2 URLを⼊⼒ ゴーグルボタン Quest URLを⼊⼒ ゴーグルボタン WebブラウザのアドレスバーにコンテンツのURLを⼊⼒後、ゴーグルボタンをタップ/クリック
動作確認
終了⽅法 HoloLens2 ホームボタン Quest 閉じるボタン ⼿⾸タップ(HoloLens2)やOculusボタン(Quest)からウィンドウを表⽰してコンテンツを終了
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成 HoloLens/Quest XRモード MRTKによるインタラクション 手のオブジェクト表示
オブジェクトを操作
function addObjects(){
/*スペースの都合上、省略*/
//箱の⾊をランダムに設定
let boxMaterial = new BABYLON.StandardMaterial("material");
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;
//boxに⼿で掴んで移動できる属性を追加
let dragBehavior = new BABYLON.SixDofDragBehavior();
dragBehavior.allowMultiPointer = false;
dragBehavior.rotateWithMotionController = false;
box.addBehavior(dragBehavior);
}
Lesson12
PCで動作確認(マウス操作) DragBehaviorを適⽤した オブジェクトのみ操作可能
実機で動作確認 再読み込み 再読み込み 必ず再読み込みボタンをクリック
実機で動作確認 Questユーザーは現時点ではハンドトラッキングでの⼿の表⽰がおかしい (あとで修正)
ハンズオンの⼿順 PCのWebブラウザ 3D空間の作成 HoloLens/Quest XRモード MRTKによるインタラクション 手のオブジェクト表示
⼿のオブジェクト表⽰ (For Quest)
//WebXRの初期化
async function initializeXR() {
let xr = await scene.createDefaultXRExperienceAsync({});
//XRモード利⽤可能か不可かを確認
if (!xr.baseExperience) { }
else {
//利⽤可能な場合はハンドトラッキングをオンにする
xr.baseExperience.featuresManager.enableFeature(
BABYLON.WebXRFeatureName.HAND_TRACKING,
"latest",
{xrInput: xr.input}
);
}
}
Lesson13
実機で動作確認
基本⼿順は以上︕
Next Step 3Dモデルを利⽤しよう
3Dモデルも表⽰可能(GLB, OBJなど)
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);
/*以下省略*/
Lesson14
3Dモデルのアップロード Assets
3Dモデルのアップロード ブラウザ内にドラッグ&ドロップ figure.glb
3Dモデルのアップロード index.htmlに戻る
3Dモデルファイルの読み込み
function addObjects(){
/*スペースの都合上、省略*/
let boxMaterial = new BABYLON.StandardMaterial("material");
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;
//boxに⼿で掴んで移動できる属性を追加
let dragBehavior = new BABYLON.SixDofDragBehavior();
dragBehavior.allowMultiPointer=false;
dragBehavior.rotateWithMotionController=false;
box.addBehavior(dragBehavior);
}
オブジェクトを読み込むコードを追加(次⾴)
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) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 [詳細] let glbMesh = container.meshes[1]; //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); } Lesson15
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) { //Babylon.jsでは0番⽬のメッシュはただのroot。1番⽬にモデルの実体。 let glbMesh = container.meshes[1]; //scene(3D空間)にオブジェクトを追加 scene.addMesh(glbMesh); } ); } Lesson15
オブジェクトの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); } ); Lesson16
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); } ); Lesson17
マニピュレーション追加 //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
実機で動作確認
参考 Camera https://doc.babylonjs.com/divingDeeper/cameras/camera_introduction WebXR Experience Helper https://doc.babylonjs.com/divingDeeper/webXR/webXRExperienceHelpers#webxr-defaultexperience-helper MRTK https://doc.babylonjs.com/divingDeeper/gui/mrtk SixDofDragBehaviour https://doc.babylonjs.com/typedoc/classes/BABYLON.SixDofDragBehavior Hand Tracking https://doc.babylonjs.com/divingDeeper/webXR/WebXRSelectedFeatures#hand-tracking SceneLoader https://doc.babylonjs.com/typedoc/classes/BABYLON.SceneLoader ARモード(Questパススルー対応) https://doc.babylonjs.com/features/featuresDeepDive/webXR/webXRARFeatures#features
今⽇の完成品 GitHubでも公開しています https://github.com/TakashiYoshinaga/babylonjs-webxr