JavaScriptは、ECMAという言語仕様のバージョンによって書き方が変わります。いろいろ調べたところ、2015年に策定されたES2015 (ES6) で大きく変化し、Mozilla Hubsなど、JavaScriptのOSSの多くはES6以降の仕様で書かれている印象です。
一方、Babylon.js公式ドキュメントやPlayground (サンプルコードの共有サイト) では、まだES2015 (ES6) の仕様で書かれていない記事が多いです。私はBabylon.jsから本格的にJavaScriptの勉強に入ったため、ES6の仕様については曖昧なところが多いままでした。
今回は勉強を兼ねて、比較的よく知っているBabylon.jsでのコーディングをES6の仕様で書く方法をまとめました。
1. JavaScript、ECMAScriptについて
まず、JavaScriptとは何かについてです。
JavaScriptという言葉は狭義にはMozillaが仕様を策定し実装しているスクリプト言語を指す。このスクリプト言語はEcmaインターナショナルでECMAScript (ECMA-262) として標準化されており、多くのウェブブラウザ等はこの標準化されたECMAScriptを実装している。
ECMAScriptは仕様自体に独自の拡張を条件付きで認める記述があり、現在主要なブラウザが実装しているスクリプト言語はすべてECMAScriptに準拠していることになる。広義の意味でこれをJavaScriptと呼ぶ場合、主要なブラウザが実装しているスクリプト言語はマイクロソフトやGoogle、アップルの実装も含めてJavaScriptである。
次にECMAScriptについてです。
ECMAScriptはECMA Internationalのもとで標準化されているJavaScriptの仕様です。
JavaScriptは1995年にBrendan Eich氏によって開発され、Webとともに急速に普及していきました。 しかし、当初はブラウザベンダーが独自に言語仕様を拡張していたため、ブラウザ間の互換性が低い状態でした。
そこで、1997年にECMA Internationalが中心となり、JavaScriptの中核となる機能を抜き出して標準化したものがECMAScriptです。 ECMAScriptによる標準化によってブラウザ間の互換性もある程度確立され、以降JavaScriptは多くのWebブラウザで使用されるようになっていきます。
その後、2009年5月に公開されたES5では、言語仕様の解釈を明文化し各ブラウザの実装として標準化されました。 このES5が現在のブラウザがサポートしている標準仕様となります。
引用元:ES2015(ECMAScript 2015)とは何か | Think IT(シンクイット)
ECMAScriptは言語仕様、策定された仕様のバージョンをES1、ES2、ES3、、と呼びます。ただし、2015年から、バージョン表記にリリース年を含むことになり、ES2015と変わったようです。2015年は従来であればES6に相当するリリースでした。 つまり、ES1、ES2、ES3、ES4、ES5、ES2015、ES2016、、となるのが厳密には正しいですが、海外のサイト(今回のBabylon.jsも)を含め、ES2015のことは習慣的にES6と書かれることが多いようです。(この記事ではES6で表記します)
ES6の名称の方がエンジニアコミュニティに中では浸透しているらしく、ES6と記載されていることが多い。
ES6によるコードの書き方は、たとえば下記にまとまっています。
2. ES6 (以降) の仕様でBabylon.jsのコードを書く手順
この章は、以下の公式ドキュメントの手順を補完したものです。なお、Node.jsとNPMは既知として説明します。
Babylon.js ES6 support with Tree Shaking | Babylon.js Documentation
ES6の仕様で書くためには、まずnpm (Node Package Manager) を使って、Babylon.jsのコードがまとまったjsファイルをフォルダに配置する必要があります。
これは、今まで下記のようにまとまっていたものを、もっと細かい単位で個別の.jsファイルに分けたものです。
<script src="https://preview.babylonjs.com/babylon.js"></script> <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script> <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script> <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script> <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
以下、Babylon.jsをES6のルールで使う手順のApplication Creation Summaryに沿って説明します。
1. Create new folder MyAwesomeApp
まずは任意の場所にフォルダを作ります。ここでは、フォルダの名称を"MyAwesomeApp"としています。
2. Open GitBash (or similar) for MyAwesomeApp
GitBashとは、Windows用のgit環境です。ここではターミナルソフトがあればよいので、Windows Powershellや、Macのターミナル、Visual Studio Codeについているターミナル機能などでも問題ありません。
3. npm init
これは、作ったフォルダをnpmで管理できるようにするという初期設定です。この辺りは多数の記事が出ているので省略します。
例:
4. npm install webpack webpack-cli webpack-dev-server --save-dev
Webサーバ環境を作るため、webpackという仕組みを導入 (npm install
) します。webpackとは、複数のJavaScriptファイルをまとめて1つのJavaScriptファイルにする仕組みです。この辺りがわかりやすいです。
webpack-cliとは、webpackをコマンド実行するために導入します。webpack-dev-serverは、開発環境でサーバを立てるための仕組みです。導入後、webpack-dev-serverを起動するだけで、作ったコードがWebサーバ上で動きます。たとえば、この辺りがわかりやすいです。
5. npm install --save-dev @babylonjs/core
引き続き、npm install
を使って、ES6に対応したBabylon.jsのコア機能のパッケージを導入します。
2020/10/24追記
10/24時点でwebpackにバグがあり、npm i webpackでそのままインストールすると、以下のリンクに記載されているエラーが出てしまいます。
Cannot find module 'webpack-cli/bin/config-yargs'
解決策がはっきりしないので、解決までは本ブログ記事投稿時に合わせて公開したリポジトリで使ったwebpackのバージョンでインストールするのがよさそうです。
$ npm i webpack@4.43.0 $ npm i webpack-cli@3.3.11 $ npm i webpack-dev-server@3.10.3
また、公式ドキュメントでは説明の途中に書いていますが、この段階で以下も実行しておきます。
npm install --save-dev @babylonjs/materials
--save-devとは、今回のディレクトリだけに導入するという意味です。また、"@babylonjs/core"のように"@"がついているものは、babylonjsという中に複数のパッケージが含まれていることを指すようです。
今回の場合、babylonjsの中にcoreだけでなくloaders、materialsなどがありますが、上記のコマンドではcoreだけを選択してインストールしています。
6. Create index.html file in MyAwesomeApp as described in First App Section below
MyAwesomeAppフォルダにindex.htmlを作り、以下のコードを貼り付けます。
$ touch index.html
7. Create Folder src in MyAwesomeApp
srcフォルダを作ります。
$ mkdir src
8. Create index.js file in src as described in First App Section below
srcディレクトリにindex.jsを作り、以下のコードを貼り付けます。
$ cd src $ touch index.js
2020/10/23 追記
Babylon.jsの公式ドキュメントでは次にnpx webpack-dev-serverを実行するように書いていますが、実際はwebpack.config.jsが必要です。
この記事後半で示したGithubのリポジトリには入れていますが、同じものを貼っておきます。
トップディレクトリで以下を実行してからこのコードを貼り付けておきます。
$ touch webpack.config.js
2023/9/16 追記
WebPack 5.8.8の状態で同じことを実行すると、npx webpack-dev-serverコマンド実行時に以下のエラーが出ました。
webpack v4以降でwebpack.config.jsの文法が変わったためです。(この記事を書いたときはv4で動いていたはずなのですが、、)
このエラーを解消するには、contentsBaseとwatchContentsBaseの記載を変更します。
修正したwebpack.config.jsはこちらです。
以下を参考にさせていただいています。
qiita.com
9. npx webpack-dev-server to check result in http://localhost:8080/
$ npx webpack-dev-server
このコマンドを実行することで、index.jsの冒頭でimportしたEngineからGridMaterialまでの実体の.jsファイルが1つに統合されてmain.jsとなります。また、Webサーバが立ち上がります。index.htmlは、このmain.jsを読み込みます。Webブラウザで表示された結果です。
なお、この時点のmain.jsは実体としては存在しません。
10. npx webpack _to create dist folder
$ npx webpack
このコマンドを実行すると、distというフォルダにmain.jsの実体が生成されます。
3. 自分で任意のモジュールを追加してみる
ES6以降の書き方を理解するため、上記のサンプルコードに2つの機能をもつ関数を追加してみました。
今回のソースコード全体は、以下のリポジトリに置きました。
3.1 任意の3Dモデルを読み込む機能
src/の中にmodelImport.jsを追加し、以下のコードを書きました。
gist4d0743e06ccaa54ed2630cb809188adc6
Babylon.jsでは3Dモデルを読み込むために、ImportMeshという関数を使います。この関数はAPI Documentationによると、SceneLoaderの階層で定義されています。そこで、import〜from
を使ってBabylon.jsのSceneLoaderを読み込み、SceneLoaderとして使います。
const ImportModel={〜
で定義した中には連想配列関数という形で具体的な処理を書いています。ここでは、importMeshModelという名前で実質的に関数の役割をしています。
SceneLoader.ImportMesh(〜
はBabylon.jsで提供されているAPIです。
最後の export
は定義したものを他の.jsファイルでも使えるようにします。
ここまで書いてから、メインの処理 (index_mod.js) に処理を追加しました。
gistda098c525ba8cd05c3085fa8b4aa4602
別途assetsというディレクトリを作り、.glb形式の3Dモデルを入れました。結果、インポート指示をした3Dモデルが表示されるようになります。
3.2 指定したメッシュを光らせる機能
続けて、先ほどインポートした3Dモデルの特定部位だけ光らせる処理を追加します。
src/の中に、Effects.jsを追加し、以下のコードを書きました。
gistafd9db8368fdc324f9c8cf6f786bde6f
こちらは、Babylon.jsのGlowLayerをimportして使えるようにしています。特定のメッシュを光らせる処理は公式ドキュメントのControlling glow color per meshを参考にしています。
次に、メインの処理 (index_mod.js) に処理を追加しました。
rootNodeというのは、Babylon.jsで管理されている3Dモデルと考えてよさそうです。配置されている順番は、Babylon.jsのSandBoxにアクセスして3Dモデルをインポートして、Inspectorを表示して、目のアイコンを選択して表示/非表示を切り替えれば、簡単に確認できます。
今回は、赤枠で囲ったところが"CurveRail_0"でrootNode[0]でした。
GlowLayer機能を使って、"CurveRail_0"だけを光らせた結果がこちらです。
4. おわりに
冒頭にも少し書いた通り、ES6以降の書き方がわかるとWebXRで使われているOSSの理解がしやすくなります。時間があれば、ES6以降の書き方について詰まったことをtipsとして書き出してみる予定です。