Babylon.jsに入門してみる
Babylon.jsを選んだ経緯
p5.jsという2Dプログラムアート向けのライブラリを使用していたが、そろそろ3Dのプログラムアートを試してみたくなった。
p5.jsにも3D向けの機能はあるがおまけ的な印象があったので、本格的な3D向けのライブラリを探していた。
他の候補としてはThree.jsとGLSLがあった。
しかし、実際触ってみるとThree.jsはnpmやなんかバンドル系のものとの併用が前提のようでそれらの知識がない自分には不都合があった。(具体的には一部機能を別にインポートする必要が生じるがうまくいかなかった)
また、仕様変更が度々あるようでネット上のチュートリアルに沿ってコーディングしても動かないということが度々あって参ってしまった。
次にそもそものシェーダーであるGLSL書けるようになればいいじゃーんと思ったが、かなりの職人芸的な世界で思っていたのとさっぱり違ったので諦めた。
というかThree.js自体がWebGLを簡単に扱えるようにしたライブラリであることを後で知った。
その次に候補として見つかったのがBabylon.jsで、こちらはウェブ上でエディタがあるので環境構築不要でもはじめられること、書き方も一行が長くなりがちだがやってることは素直であるという印象ではじめたらとりあえず続けられそうな感じだったので覚えていきたい。
Playgroundのざっくり概要
プレイグラウンドを開くと次のようなエディタが開く。
主な機能としては
・JS/TSの切り替え
・ビューワー
・コードの補完機能
・コードの保存/ダウンロード
・インスペクター(データの確認やビューワーオプションの切り替えなど)
サンプルコードも主にプレイグラウンドを通じて公開されている。
プレイグラウンドを通してコードを公開する方法
上部メニューの保存ボタンを押すとタイトル、説明、タグの入力欄が表示される。
それらを任意に入力して(必須ではない)保存ボタンを押すとURLの末尾に文字列が追加されて固有のURLになる。
それをコピーして貼り付ければブラウザを通じてコードを公開することができる。
更新して保存した場合更に末尾に#1というように番号が増えていき分岐させることができる。
学習の進め方
Babylon.jsはまだ日本語情報も少なく、英語でも入門向けの記事は豊富とは言えない印象がある。
そのため学習は公式のドキュメントを中心に進めるのがベターに思える。
ドキュメントは公式サイトトップのハンバーガーメニュー→「Tool」→「Document」から飛べる。
「Features」→「Introduction」に進むと入門チュートリアルがある。
このチュートリアルは全体の機能の概要、出来ることのサンプルと言った感じ。
なので個々の機能について深く知りたい場合には
同じく「Features」から→「DeepDive」
を開くと個々に機能について細かい解説がある。
右側のフレームにはサンプルコードがあるのでそれを見ながら実際の書き方を覚えていく。
Babylon.jsの日本語情報
公式チュートリアルの和訳
Babylon.js日本コミュニティ
分からないことがあれば↑のディスコードコミュニティで先人達に質問出来るのでどんどん活用させてもらおう。メソッドを使用するときにstaticかどうか判断する手段
いくつかのメソッドを使用していてインスタンス化が必要かどうかの判断をどこですればいいのか分からなかった。
例えばMeshBuilderを通じたCreateはいかにもインスタンス化が必要そうだが実際はstatic関数になっているのでnewは必要ない。それらをどこで判断すればいいのか戸惑った。
DocumentetionからAPIを開くと一覧が載っている。
classのページを開くとメソッドの一覧の横にアイコンでスタティックがどうかが視覚的に分かるようになっている。(〇なら通常のメソッド、□ならスタティック)
また、APIのページでFunctionに分類されているものがある。これらはインスタンス化が必要ないようだ。
カスタムメッシュの作成方法
自分の目的はプログラムアートなのでメッシュは自分でつくりたい場合が多い。
最低限必要なデータは
1.メッシュ
2. 頂点情報
3. 頂点位置
4. 頂点インデックス
の4つになる。
//カスタムメッシュの作成
const mesh = new BABYLON.Mesh("customMesh", scene);
//頂点データ、位置、インデックスの作成
const vertexData = new BABYLON.VertexData();
const positions = [0,0,0,0,3,1,3,0,-1];
const indices = [0,1,2];
//頂点データに位置とインデックスを適用
vertexData.positions = positions;
vertexData.indices = indices;
//メッシュと頂点データの関連付け
vertexData.applyToMesh(mesh);
頂点位置は前から3つずつが座標の[x,y,z]に対応している。
上記では[0,0,0],[0,3,1],[3,0,-1]で三点があることが分かる。
頂点インデックスは頂点の位置情報に対してどういう順番でインデックスするかを定義する。
0から順番に割り当てるのが基本になるが、別の順番でもできる。その場合法線方向に注意(法線方向は時計回り)
最後にメッシュと頂点データの関連付けをすれば完了。
座標軸の見え方
サンプルによってxのプラス方向が右方向だったり左方向だったりして分かりにくかったので確認してみた。
当然カメラ位置によってどの軸がどう見えるかは変わるのだが
FreeCameraでz位置がプラスの場合、左がxのプラス方向。
FreeCameraでz位置がマイナスの場合、右がxのプラス方向。
ArcRotateCameraでαがプラスの場合、左がxのプラス方向。
ArcRotateCameraでαがマイナスの場合、右がxのプラス方向。
一般的に2Dの座標軸はxのプラス方向が右になるのでカメラのz位置は統一した方がよさそうだ。
カメラの種類
UniversalCamera
const camera = new BABYLON.UniversalCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
基本となるカメラでマウスや矢印キーで操作することができる。
サンプルでたまに見かけるFreeCameraやTouch Camerathe、Gamepad Cameraは現在これに置き換わっているので注意。
ArcRotateCamera
const camera = new BABYLON.ArcRotateCamera("camera1", -Math.PI/2,Math.PI/3,10,BABYLON.Vector3.Zero(), scene);
ArcRotateCameraは指定の方向を常に向いた状態で回転ができるカメラで鑑賞系コンテンツとの相性がよい。
引数はカメラ名、α、β、radius、ターゲット位置、シーンの順でα、βは地球における経度、緯度のようなものにあたる。radiusは中心位置からの距離で、ターゲット位置はカメラの向く方向になる。
2次元のx,y座標をx,y,z座標に拡張したように、2次元の極座標を拡張したものと考えてもよさそう。
他にもオブジェクトに追従するFollowCamera、宙に浮いたような視点のFlyCameraなどがあるが上記の二つを知っておけばとりあえず大丈夫そう。
ラインメッシュの作り方
まずはラインを作りたい位置の頂点をVector3で配列化する。
//頂点座標をVecor3で配列化
const pos = [];
for(let t = 0; t <= Math.PI*2; t += angleStep){
const x0 = r * Math.cos(t);
const y0 = 0;
const z0 = r * Math.sin(t);
pos.push(new BABYLON.Vector3(x0,y0,z0));
}
次にMeshBuilder.CreateLinesの引数に配列を渡して完了。
//ラインメッシュの作成
const line = BABYLON.MeshBuilder.CreateLines("line",{points: pos},scene);
円柱を自分でつくってみる
座標軸や頂点インデックスの数、法線方向の間違えが多くて意外と時間がかかってしまった。基礎的なところなので繰り返して身に付けよう。
アニメーションの作り方
用意するもの
・アニメーション対象のオブジェクト
・フレームレート
・アニメーションデータ
・キーフレーム設定
・アニメーションデータにキーフレームを登録
・オブジェクトにアニメーションデータを登録
・シーンのアニメーションを開始
アニメーションの種類
constant:通常のアニメーション、キーフレーム終わったら止まる
cycle:ループアニメーション、キーフレーム終わったら最初に戻る
relative:cycleと同じような挙動、なにが違うのか謎。情報求
colorやvector,floatなどの型の指定とオブジェクトメソッドの指定
パーティクル(粒子)
パーティクルの種類
パーティクルシステムには3つの種類がある。
1.ベーシックパーティクル
2. ソリッドパーティクル
3. 点群パーティクル
主な違いは描画に扱うオブジェクトがそれぞれ異なり、
1.画像
2. ソリッドモデル(球や立方体のようなポリゴン図形)
3. 頂点
であること。
背景色の変更の方法
sceneオブジェクトのclearColorメソッドから色を変更することができる
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color4(0,0,0,1.0);
2種のskyBOX
BABYLONにおけるskyBOXは二種類あるようで、単に立方体の内側にHDR画像を張るタイプと、シーンのコンストラクタにセットできるskyBOXがある。
基本的には後者のシーンに適用するものを使うと思われる。
ノードマテリアルエディターで作成したノードを保存してコードに埋め込む方法
インスペクターを開いて「Material」右クリック→Add new node materialでノードマテリアルを作成できる。
編集したノードマテリアルはGenerate codeからコードとして生成することができる。
これを保存してコード中に埋めてマテリアルとオブジェクトをリンクさせるとノードをコードして利用することが出来る。
コードになっているのでコード上で変更しても当然変更が反映される。