Aframe arのドキュメント
いつもわすれるので。
なぜかなと思って、ずっと別の方法で誤魔化していたが解決したので記。
ダメなパターンは以下、a-cameraを使っている。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" /> <script type="text/javascript" src="https://aframe.io/releases/1.2.0/aframe.min.js "></script> <script type="text/javascript" src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js" ></script> </head> <body style="margin: 0; overflow: hidden; height: 100%"> <a-scene embedded arjs="trackingMethod: best; sourceType: webcam; detectionMode:mono_and_matrix; debugUIEnabled: false;" > <a-camera></a-camera> <a-marker type="barcode" value="1" > <a-box position="0 0.5 0" wireframe="true" color="black"></a-box> </a-marker> </a-scene> </body> </html>
実行するとこんな感じ
変えたところだけ。 これを
<a-camera></a-camera>
こう変える
<a-entity camera></a-entity>
ピッタリ来た。
a-cameraはVRようにY=1.6になってる。
<a-entity camera>でプレーンなカメラを作ることで解消するということ
わかってみれば簡単だが、長らくわからなくてドキュメントもGPTもあてにならなかった。
a-marker-cameraも同様にYを持ってるので厄介。 すっきりしたのでよかった・。
Astroからaxiosやfetchやらで、RestAPIを呼ぼうとするとCORSの制限に引っかかる。
ローカルだとClientとServerをそれぞれポートを分けて立てたりするから。
仮に以下のようにするとする
Astro => http://localhost:3000/
Server => http://localhost:8080/api/
Astro側のpackage.jsonに"proxy": "http://localhost:8080/
と、サーバーのホストを知らせてやれば良い。
{ "name": "sampleservice", "type": "module", "proxy": "http://localhost:8080/, "version": "0.0.1", ・・・ }
サーバーサイドにも
import cors from "cors"; // 中略 // CORSをexpressに設定 const origin ="http://localhost:3000"; const app = express(); app.use( cors({ origin: origin, credentials: true, preflightContinue: true, }) ); // 中略 const server = app.listen(config.get("server_port"), () => { console.log(config); console.log("listen to " + config.get("server_port")); });
Git のプッシュでWriteが終わり、Total 6626 (delta 1700), reused 0 (delta 0), pack-reused 0と出たあとに止まってしまう。 ある程度大きなファイルがあるときは、以下のようにバッファを増やしてからpush する。
git config http.postBuffer 157M
大きすぎてエラーが出る場合は、LFSを使う。
A-Frameを使ったVRをいくつか作っていて、いつも設定で回避していることを備忘録的に記載します。
最終形を始めに示し、以降で構成要素を見ていくことにします。
<!DOCTYPE html> <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-asset-item id="asset1" src="xxx.glb"></a-asset-item> --> </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の手軽なところですね。
<!DOCTYPE html> <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サイトに切り替えてこの画面をリロードしてください。"
vr-mode-ui="enterARButton: #myEnterARButton"
device-orientation-permission-ui
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>