前回はローダーを用いてglTF形式の3Dオブジェクトの表示までを行いました。
今回は初回に作成したシンプルなボールと「モンキー」をXRカメラで表示してみます。
テストにはAndroidスマートフォンと、Google Cardboard等のVRゴーグルを準備して下さい。
VR表示
以前までBABYLON.jsでのVR表示には、「createDefaultVRExperience()」のVRカメラのヘルパー関数が用意されていました。現在はVR表示とAR表示両方に対応するXRカメラのヘルパー関数「createDefaultXRExperienceAsync()」が用意されていますので、そちらを使用してVR表示を行ってみます。
追加する処理は以下のヘルパー関数の呼び出しのみです。
scene.createDefaultXRExperienceAsync({
floorMeshes: [oGnd]
});
上記関数を初回の表示に足したものは以下のコードになります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>Babylon VR Test</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<style>
html, body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
let canvas, engine, scene;
window.onload = function(){
canvas = document.getElementById("renderCanvas");
engine = new BABYLON.Engine(canvas, true);
scene = new BABYLON.Scene(engine);
scene.gravity = new BABYLON.Vector3(0, -0.98, 0);
scene.collisionsEnabled = true;
scene.clearColor = new BABYLON.Color3.Black;
let camera = new BABYLON.UniversalCamera ("Camera", new BABYLON.Vector3(0, 1.2,-5), scene);
let lightD = new BABYLON.DirectionalLight("LightD", new BABYLON.Vector3(0, 0, 0), scene);
let lightH = new BABYLON.HemisphericLight("LightH", new BABYLON.Vector3(1, 1, 0), scene);
lightD.intensity = 0.8;
lightH.intensity = 0.6;
let oGnd = BABYLON.MeshBuilder.CreateGround("Ground", {width: 100, height: 100});
oGnd.checkCollisions = true;
camera.ellipsoid = new BABYLON.Vector3(0.25, 0.8, 0.25);
camera.checkCollisions = true;
camera.applyGravity = true;
camera.speed = 0.3;
camera.attachControl(canvas, true);
camera.cameraDirection = new BABYLON.Vector3(0, 1.7, 0);
var oSph = BABYLON.Mesh.CreateIcoSphere("Sphere", {radius:0.5, subdivisions:2}, scene);
oSph.position.y = 2;
oSph.checkCollisions = true;
scene.registerBeforeRender(function(){
oSph.rotation.y += 0.001*scene.getEngine().getDeltaTime();
oSph.rotation.x += 0.001*scene.getEngine().getDeltaTime();
});
scene.createDefaultXRExperienceAsync({
floorMeshes: [oGnd]
}).then(function(xrExperience){
console.log("Done, WebXR is enabled.");
});
window.addEventListener("resize", function(){engine.resize();});
engine.runRenderLoop(function(){scene.render();});
}
</script>
</body>
</html>
実際に動かすと以下の通りになります。
VR表示機器の無いパソコンでは、初回と同様の表示のみになります。
本ページをスマートフォンで表示した場合、画面右下にVR表示切替ボタンが表示されます
AR表示
次にAR表示も行ってみましょう。
VR表示時と同様に以下のヘルパー関数を呼び出します。
scene.createDefaultXRExperienceAsync({
uiOptions:{
sessionMode: "immersive-ar",
referenceSpaceType: "local-floor"
}
});
前回の「モンキー」(スザンヌさん)をAR表示するサンプルは以下の通りになります。
AR表示には地面が不要なため、地面のメッシュ及び、重力を無効にします。
また、透過色をsceneに指定します。
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta http-equiv='Content-Type' content='text/html' charset='utf-8'/>
<title>Babylon AR Test</title>
<script src='https://cdn.babylonjs.com/babylon.js'></script>
<script src='https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js'></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
</head>
<body>
<canvas id='renderCanvas'></canvas>
<script>
let canvas, engine, scene;
canvas = document.getElementById('renderCanvas');
engine = new BABYLON.Engine(canvas, true);
scene = new BABYLON.Scene(engine);
scene.gravity = new BABYLON.Vector3(0, -0.98, 0);
scene.collisionsEnabled = true;
scene.clearColor = new BABYLON.Color3.Black;
let camera = new BABYLON.UniversalCamera ('Camera', new BABYLON.Vector3(0, 1.2, 5), scene);
let lightD = new BABYLON.DirectionalLight('LightD', new BABYLON.Vector3(0, 0, 0), scene);
let lightH = new BABYLON.HemisphericLight('LightH', new BABYLON.Vector3(0, 1000, 0), scene);
lightD.intensity = 0.8;
lightH.intensity = 0.6;
camera.ellipsoid = new BABYLON.Vector3(0.25, 0.8, 0.25);
camera.checkCollisions = true;
camera.speed = 0.3;
camera.attachControl(canvas, true);
camera.rotation.y = Math.PI;
BABYLON.SceneLoader.ImportMeshAsync('', './', 'blender_to_babylon_blog.glb', scene)
.then((result) => {
for(let i = 1; i < result.meshes.length; i++){
switch(result.meshes[i].name){
case 'モンキー':
result.meshes[i].scaling = new BABYLON.Vector3(0.5, 1, 0.5);
break;
default: //Not working
}
}
});
scene.createDefaultXRExperienceAsync({
uiOptions:{
sessionMode: 'immersive-ar',
referenceSpaceType: 'local-floor',
}
}).then(function(xrExperience){
console.log('Done, WebXR is enabled.(iframe)');
});
window.addEventListener('resize', function(){engine.resize();});
engine.runRenderLoop(function(){scene.render();});
</script>
</body>
</html>
実際に動かすと以下の通りになります。
ヘルパー関数
BABYLON.jsでは、XRカメラの作成を容易にするため、ヘルパー関数が用意されています。
公式マニュアルを参考に引数と返り値のpromiseについて記述していきます。
オプション名 | 内容 |
---|---|
disableDefaultUI | XRに入るデフォルトUIを無効にするか? |
disableNearInteraction | 近接対話(3Dオブジェクトをイベントトリガとして扱う際、そのオブジェクトが近くにある場合)を無効にするか? |
disablePointerSelection | ポインターを無効化するか?(テレポーテーションも動作しなくなる) |
disableTeleportation | テレポーテーションを無効化するか? |
floorMeshes | テレポーテーションでベースとなる地面を指定する |
ignoreNativeCameraTransformation | 現在のカメラ位置情報を無視するか引き継ぐか? |
inputOptions | XR入力の設定。デフォルトのコントローラメッシュを非表示にしたり、独自のコントローラメッシュを表示させる場合に使用する(詳細オプションは別表を参照) |
nearInteractionOptions | 近接対話(3Dオブジェクトをイベントトリガとして扱う際、そのオブジェクトが近くにある場合)の設定。(詳細オプションは別表を参照) |
optionalFeatures | セッション開始のための設定リストを指定する。または値としてtrueを指定すると全機能が有効になる |
outputCanvasOptions | 出力先のcanvasの設定(詳細オプションは別表を参照) |
pointerSelectionOptions | ポインタ選択の設定(詳細オプションは別表を参照) |
renderingGroupId | レンダリンググループIDを指定する(テレポーテーション、ポインタ、コントローラのメッシュ用) |
teleportationOptions | テレポーテーションの設定 |
uiOptions | UIの設定。主にセッションと参照空間の設定に使用する(詳細オプションは別表を参照) |
useStablePlugins | 安定版を使うか?(テレポーテーションとポインタを使う場合は安定版が推奨される) |
inputOptionsの詳細オプションは下表の通りです。
オプション名 | 内容 |
---|---|
controllerOptions | コントローラ設定(inputOptionsによって上書きされる)
|
customControllersRepositoryURL | コントローラリポジトリのURLを指定する |
disableControllerAnimation | コントローラのアニメーションを無効化するか? |
disableOnlineControllerRepository | コントローラリポジトリからのロードを無効化するか?(Babylon単体で使えるコントローラを使用する場合に設定) |
doNotLoadControllerMeshes | コントローラのメッシュを読み込まないようにするか? |
forceInputProfile | コントローラに適用するプロファイルを指定する |
nearInteractionOptionsの詳細オプションは下表の通りです。
オプション名 | 内容 |
---|---|
customUtilityLayerScene | メッシュの描画に使うsceneを指定する |
disableSwitchOnClick | 近接対話のコントローラ切替えを無効化するか? |
enableNearInteractionOnAllControllers | 全コントローラで近接対話を有効化するか? |
farInteractionFeature | 遠距離対話(3Dオブジェクトをイベントトリガとして扱う際、そのオブジェクトが遠くにある場合)の設定(近接対話優先時は無効) |
motionControllerOrbMaterial | モーションコントローラの球体に適用するマテリアルを指定する |
nearInteractionControllerMode | モーションコントローラ使用時の近接対話設定
|
preferredHandedness | 近接対話に優先的に使うハンドを指定する |
useUtilityLayer | メッシュを別レイヤーに表示するか? |
xrInput | 近接対話に使用するXR入力の設定
|
outputCanvasOptionsの詳細オプションは下表の通りです。
オプション名 | 内容 |
---|---|
canvasElement | canvasを指定する(未指定なら新規作成される) |
canvasOptions | XRレイヤー出力設定
|
newCanvasCssStyle | 新規作成されるcanvas用のCSSを指定する |
pointerSelectionOptionsの詳細オプションは下表の通りです。
オプション名 | 内容 |
---|---|
customUtilityLayerScene | メッシュを描画するsceneを指定する |
disablePointerUpOnTouchOut | XRコントローラが破棄された場合にポインタアップイベントを無効化するか?(ターゲットレイモードがgazeまたはscreenの場合に設定する) |
disableScenePointerVectorUpdate | シーンのpointerXとpointerYの更新を無効化するか? |
disableSwitchOnClick | ポインタのコントローラ切替えを無効化するか? |
enablePointerSelectionOnAllControllers | 全コントローラでポインタを有効化するか? |
forceGazeMode | ポインタまたはコントローラの注視モードを使うか? |
gazeCamera | 視線による選択を使うカメラを指定する |
gazeModePointerMovedFactor | 注視モードのポインタ移動の係数を指定する |
maxPointerDistance | ポインタ選択の距離の最大値を指定する |
overrideButtonId | 別のボタンを使用する場合に指定する |
preferredHandedness | ポインタ選択を優先使用するハンドを指定する |
renderingGroupId | レンダリンググループIDを指定する(ポインタのメッシュ用) |
timeToSelect | 注視モードで選択状態になるまでの時間をミリ秒で指定する |
useUtilityLayer | メッシュを別レイヤーに表示するか? |
xrInput | ポインタ選択に使用するXR入力の設定 |
uiOptionsの詳細オプションは下表の通りです。
オプション名 | 内容 |
---|---|
customButtons | XR機能の切替えボタンを指定する(未指定ならデフォルトの物が使われる) |
ignoreSessionGrantedEvent | セッション許可イベントを無視し、ユーザの「enter XR」ボタン押下を強制するか?(未指定ならXRセッションが自動で開始される) |
onError | XR開始時にUIがエラーになった場合に実行する関数を定義する |
optionalFeatures | セッション開始時のオプションを指定する |
referenceSpaceType | ボタン作成時の参照空間タイプを指定する(デフォルトはlocal-floor) |
renderTarget | 描画対象の設定 |
requiredFeatures | セッション開始時のオプションを指定する |
sessionMode | ボタン作成時のセッションモードを指定する(デフォルトはimmersive-vr) |
おまけ
VRで視力が回復する話もあります。
そこでその話に乗っかって、視力回復アプリを作ってみようかと思いました。
頭を動かさないで、画面のボールを眼で追いかけてください。