A-Frameを使ったVRをいくつか作っていて、いつも設定で回避していることを備忘録的に記載します。
最終形
最終形を始めに示し、以降で構成要素を見ていくことにします。
<html >
<head>
<meta name="description" content="VR template" />
<meta charset="utf-8" />
<title>VR Template</title>
<script type="text/javascript" src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v6.1.1/dist/aframe-extras.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<style>
html{
height: 100%;
}
body{
font-size: 0.625%;
overflow: hidden;
touch-action: manipulation;
margin: 0;
height: 100%;
}
</style>
<script type="text/babel">
AFRAME.registerComponent("init", {
init: async () => {
const message:string = "init start";
console.log(message);
}
});
</script>
<a id="myEnterARButton" href="#"></a>
</head>
<body>
<a-scene init renderer="colorManagement: true" vr-mode-ui="enterARButton: #myEnterARButton"
device-orientation-permission-ui="enabled:true;denyButtonText:いいえ;allowButtonText:はい;cancelButtonText:キャンセル;deviceMotionMessage:向きのセンサーにアクセスしてよろしいですか;mobileDesktopMessage:モバイル用Webサイトに切り替えてこの画面をリロードしてください。"
gltf-model="dracoDecoderPath:https://www.gstatic.com/draco/v1/decoders/" >
<a-assets>
</a-assets>
<a-box color="red" ></a-box>
<a-entity id="rig" movement-controls position="0 0 4">
<a-entity
look-controls="pointerLockEnabled: false"
id="main-camera"
camera=""
>
<a-entity
id="cursor"
cursor="rayOrigin: mouse;fuse:false"
raycaster="objects: .clickable"
></a-entity>
</a-entity>
</a-entity>
<a-entity laser-controls raycaster="objects: .clickable; far: 10"></a-entity>
<a-entity laser-controls raycaster="objects: .clickable; far: 10"></a-entity>
</a-scene>
</body>
</html>
説明のいらないところから
とりあえず、最終形から分解して説明のいらない基本セットを用意します。
A-Frameのライブラリを呼んで、a-sceneを読み込むだけです。これだけでも3Dシーンが作られるのがA-Frameの手軽なところですね。
<html >
<head>
<title>VR Template</title>
<script type="text/javascript" src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
</head>
<body >
<a-scene >
</a-scene>
</body>
</html>
スタイル
スタイル設定は主にスマホでのズームを抑制するものです。
<style>
html{
height: 100%;
}
body{
font-size: 0.625%;
overflow: hidden;
touch-action: manipulation;
margin: 0;
height: 100%;
}
</style>
viewportメタタグも拡大縮小を抑制します。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
シーンの設定について
a-scene要素での設定は、以下です。
<a-scene init renderer="colorManagement: true" vr-mode-ui="enterARButton: #myEnterARButton"
device-orientation-permission-ui="enabled:true;denyButtonText:いいえ;allowButtonText:はい;cancelButtonText:キャンセル;deviceMotionMessage:向きのセンサーにアクセスしてよろしいですか;mobileDesktopMessage:モバイル用Webサイトに切り替えてこの画面をリロードしてください。"
draco圧縮
Draco圧縮は、Googleのオープンソース技術でZIP圧縮したものよりも、圧倒的に高い圧縮率を実現できます。
Draco圧縮するためのツールをインストールします。
npm install -g gltf-pipeline
Draco圧縮をコマンドラインで実施します。
gltf-pipeline -i xxx_from.glb -o xxx_to.glb -d
カメラはリグに入れる
カメラをリグに入れることで、カメラの方向をプログラムから変えることができます。
マウスのタップを有効にするには、カメラの配下にraycaster属性を持った要素を持ちます。
cursorのrayOriginをmouseにするだけかと思いきや、fuse:falseにしないと、マウスクリックやタップで2回クリックが発生するという罠があります
<a-entity id="rig" movement-controls position="0 0 4">
<a-entity
look-controls="pointerLockEnabled: false"
id="main-camera"
camera=""
>
<a-entity
id="cursor"
cursor="rayOrigin: mouse;fuse:false"
raycaster="objects: .clickable"
></a-entity>
</a-entity>
</a-entity>
<a-entity laser-controls raycaster="objects: .clickable; far: 10"></a-entity>
<a-entity laser-controls raycaster="objects: .clickable; far: 10"></a-entity>
</a-scene>
この設定にあるmovement-controls
属性のために以下のaframe-extrasが必要です。
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v6.1.1/dist/aframe-extras.min.js"></script>
movement-controls
を設定すると、スマホで画面タップしたときに直進する機能が付加されます
AFrameのコンポーネントを作るためのregisterComponentをTypescriptで書けるようにtype="text/babel"でスクリプトを作ります。
このコンポーネントは、a-sceneで設定しています。
<script type="text/babel">
AFRAME.registerComponent("init", {
init: async () => {
const message:string = "init start";
console.log(message);
}
});
</script>
Babelのためにインポートが必要ですね。TypescriptにしないまたはWebpackなどでビルドするなら不要です。
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>