TypeScriptAway3Dはオープンソースのリアルタイム3Dエンジンです。Flashプラットフォーム向けに開発されました。TypeScript」としてJavaScriptライブラリへの移植が進んでおり、現在アルファリリースが公開されています。TypeScriptを使ったごく簡単なJavaScriptコードで、3次元空間に立方体をつくって回してみましょう。TypeScript」サイトには、作例やソースファイルのリンクなどが掲げられています。Extentions」の3つのリンクからダウンロードできます(図001)。Examples」も掲げられています。TypeScriptを試してみるには、ソースファイルの3つのリンクからダウンロードしたファイルの中から3つのライブラリ「awayjs-core.next.min.js」と「stagegl-core.next.min.js」および「stagegl-extensions.next.min.js」を使います(図002)[*1]。これらのJavaScript(JS)ファイルを、これから書くコードのライブラリ用に定めたフォルダ(本稿では「lib」)に配置します。図002■Away3Dで使う3つのライブラリのJSファイルHTMLドキュメントには、まずscript要素にAway3Dの3つのJSファイルawayjs-core.next.min.jsとstagegl-core.next.min.jsおよびstagegl-extensions.next.min.jsを読込みます。つぎに、JavaScriptコードには初めに呼出す関数(initialize())を設け、body要素のonload属性にその呼出しを加えます。これで準備が整いました。Away3Dのコードを書いていきましょう。onload="initialize();">Away3Dの3次元表現で用意しなければならないのは、つぎの3つです。第1に、舞台となる3次元空間をつくります。第2に、その舞台に照明を備えます。第3に、役者となる物体を舞台に登場させます。項を改めて、順にご説明します。TypeScript(2014年8月15日付まで)では、ライブラリは名前の異なるつぎの3つのJSファイルからなりました。Viewクラスで3次元空間の表示領域を定める第1につくらなければならないのは、3次元空間の表示領域を定めるViewオブジェクトです。3次元の座標空間や、それを表示領域に映すカメラもオブジェクトの中にもちます。View()コンストラクタの引数はレンダラです。ここでは、DefaultRendererオブジェクトを渡すことにします。away.render.DefaultRenderer())Viewオブジェクトには、プロパティで設定が加えられます(表001)。プロパティの数は多いものの、多くはデフォルト値が定められています。今回は、ごく基本的なプロパティのみ定めることにします。表示される領域の幅と高さ。デフォルト値は黒(0x000000)。表示領域を描くために用いられるCamera3Dオブジェクト。表示領域を描くもととなる3次元空間のScene3Dオブジェクト。Viewオブジェクトをつくって返す関数(createView())は新たに設けます。引数には、表示領域の幅と高さ、および背景色を渡します。背景色)できあがりのJavaScriptは、後にまとめてコード001として掲げます。関数(createView())は、つぎの抜書きのように定めました(第16〜23行目)。初期設定の関数(initialize())から呼出します(第10行目)。行番号は後掲コード001にもとづきます。DirectionalLightクラスで平行光源を定める第2に、光源を定めます。3次元空間をつくっても、光がなければ見えません。神と同じく「光りあれ」と、光をつくらなければならないのです。3次元表現で使われる光源はいくつかあります。太陽の光のように同じ向き(平行)に進み、距離によって強さが変わりません(図003右上)。平行光源は、DirectionalLight()コンストラクタで定めます[*2]。引数はなくて構いません。この光で、後からつくる物体の表面を照らします。away.entities.DirectionalLight()もっとも、太陽光だけでは、月のように光の当たっていない部分は暗闇になってしまいます。light)があることで、陰も見えるのです。そこで、DirectionalLightオブジェクトをつくって返す関数(createDirectionalLight())は、環境光の強さとその光の色を引数に与えてつぎのように定めます。光の色)DirectionalLightオブジェクトのambientプロパティに強さの数値を与えると、環境光が加わります(第35行目)。colorプロパティで光の色を定めます(第36行目)。directionプロパティには、Vector3Dオブジェクトの3次元ベクトルで光源の位置を与えます(第34行目)。TypeScriptのaway.entitiesパッケージに移されました。Rendererのaway.lightsパッケージは除かれています。PrimitiveCubePrefabクラスからつくった立方体のオブジェクトを水平および垂直の向きに回すようやく、舞台と照明が整いました。第3の、役者となる物体のインスタンスを登場させます。そのためには、まず立方体のひながた(プレハブ)となるPrimitiveCubePrefabオブジェクトをつくります。コンストラクタに与える引数は立方体の幾何情報です。つぎに、そのひながたの参照に対してgetNewObject()メソッドを呼出すと、物体のインスタンスが得られます[*3]。ふたつのメソッドは、つぎのように続けて呼出せます。奥行き).getNewObject()表面素材は、デフォルトのテクスチャからつくることにします。静的メソッドDefaultMaterialManager.getDefaultTexture()で得られたオブジェクトを、TriangleMethodMaterial()コンストラクタの引数に渡します[*4]。away.materials.TriangleMethodMaterial(away.materials.DefaultMaterialManager.getDefaultTexture())物体の表面を照らす光はStaticLightPickerオブジェクトで定め、素材のオブジェクトのlightPickerプロパティに加えます。StaticLightPicker()コンストラクタには、光源のオブジェクトを配列に納めて渡します。away.materials.StaticLightPicker(光源の配列)これらのオブジェクトから立方体のインスタンスをつくって返す関数(createCube())はつぎのように定めます。引数には、立方体の幅と高さと奥行きに加えて、光源のオブジェクトを渡します。光源)関数(createCube())は、つぎのようにPrimitiveCubePrefabオブジェクトから立方体のインスタンスをつくり、テクスチャと光源のオブジェクトを設定して返します(第24〜31行目)。この関数は、初期設定の関数(initialize())から呼出して、できあがったインスタンスを3次元空間に加えます(第10〜11行目)。3次元空間のScene3DオブジェクトはView.sceneプロパティで参照し(前掲表001)、Scene3D.addChild()メソッドの引数としてインスタンスを渡します(第12行目)。mesh;}そして忘れていけないのが、3次元空間を表示領域に描くには、必ずView.render()メソッドを呼出さなければならないことです。3次元空間の立方体を上下左右に回してみましょう。アニメーションは、RequestAnimationFrameクラスで扱います。一定の時間間隔で行うアニメーションの処理を関数で定め、コンストラクタの引数として渡します。コールバック関数が呼出される頻度は、1秒間に約60回です[*5]。コールバックの呼出しは、RequestAnimationFrame.start()メソッドにより始まります。away.utils.RequestAnimationFrame(コールバック)RequestAnimationFrameオブジェクト.start()これらふたつのメソッドは、初期設定の関数(initialize())から呼出します(第13〜14行目)。RequestAnimationFrame()コンストラクタに渡したコールバック関数(rotate())は、立方体(Meshオブジェクト)のプロパティrotationXとrotationYに角度をそれぞれ1度ずつ加えて回しました(第40〜41行目)[*6]。コールバックの最後には、View.render()メソッドを呼出します。角度を360度の剰余(%)としているのは、(絶対)値が果てしなく大きくなることを避けるためです。360;view.render();}これで、3次元空間に置いた立方体をx軸とy軸で回すアニメーションが描けます(図004)。script要素全体を以下のコード001にまとめました。実際の動きが確かめられるよう、jsdo.itにサンプルコードも併せて掲げています(サンプル001)[*7]。ひながた(プレハブ)のクラスは、2014年5月のビルドで加えられました。3月18日付のライブラリでは、つぎのようにCubeGeometryとMeshクラスから物体のインスタンスをつくりました。TypeScriptの2014年8月15日付ビルドで備わりました。それより前に用いられていたTriangleMaterialに替わるクラスです。したがって、2014年8月15日までのビルドで書かれたJavaScriptコードは、つぎのようにクラスTriangleMaterialをTriangleMethodMaterialに差替えなければなりません。RequestAnimationFrameオブジェクトは、内部的にwindow.requestAnimationFrame()メソッドを使っています。window.requestAnimationFrame()は、ブラウザが画面を描画し直そうとするとき、コールバック関数を呼出すメソッドです。再描画は画面のリフレッシュレートにもとづきますので、呼出しの頻度は一般的な60Hzでは1秒間に60回ほどです。x軸とy軸だけで、z軸は使わなくても、上下左右の回転はできます。z軸による回転は、xy平面で回すことを意味します。同じように、x軸ならyz平面上の回転になります。yz平面はy軸で90度回せば、xy平面に重なります。x軸とy軸で、z軸と同じ回転が表せるのです。サンプル001では、つぎのようにPrimitiveCubePrefab()コンストラクタの第4引数以降も与えています(第21行目)。立方体の各面の表示が少し変わるだけで、前掲コード001と実質的な違いはほぼありません。false).getNewObject();コンストラクタの第4〜6引数は、それぞれxyz各軸方向のセグメント数(ポリゴン分割数)で、デフォルト値は1です。第7引数はuvマッピングの仕方で、デフォルト値のtrueが3×2グリッド、falseではイメージ全体がそれぞれの面にマッピングされます。映し出される立方体の角度をカメラの動きで変化させるそれでは仕上げとして、立方体の向きをマウスでインタラクティブに変えましょう。前掲コード001と違って、立方体そのものは動かしません。Away3Dでは、オブジェクトを映すカメラの位置や向きが動かせます。そのカメラによって、立方体の見せ方をコントロールするのです。カメラワークは、コントローラを使うと扱いやすくなります。中でも表現が多彩なHoverControllerクラスを用いることにします。HoverController()コンストラクタの第1引数には、カメラのオブジェクトを与えます。コンストラクタにはほかにも多くの引数が渡せるものの、後から必要な値だけプロパティで定める方がわかりやすいでしょう。away.controllers.HoverController(カメラ)HoverControllerオブジェクトを用いると、カメラのパンやチルトができます(オリオン技研株式会社「パン・チルト・ロールとはなにですか」参照)。オブジェクトに向けたカメラを上下左右に回り込ませることで、オブジェクトがさまざまな角度から捉えられます。今回使うHoverControllerクラスのプロパティは、つぎの表002に掲げました。Camera(s)」参照)。カメラと撮影対象との距離で、デフォルト値は1000。チルトできる角度の範囲の最大度数(デフォルト値90)と最小度数(デフォルト値-90)。カメラがy軸を中心に回る度数の角度で、デフォルト値は0。カメラの仰角を示す度数で、デフォルト値は90。前掲コード001に手を加えていきます。HoverControllerクラスのオブジェクトでコントローラをつくるクラスは、つぎのような関数(setupCameraController())として定めます。引数にはカメラオブジェクトのほか、前掲表002のHoverControllerクラスのプロパティに定める値を渡します。チルト度数)でき上がったJavaScript全体は、後にコード002としてまとめました。抜書きしたHoverControllerオブジェクトのコントローラをつくる関数(setupCameraController())はつぎのとおりです(第42〜50行目)。新たにつくったHoverControllerオブジェクトのプロパティに、引数の値を定めて返します。前述のとおり、パンとチルトはトゥイーンしますので、アニメーションの関数は名前を変えて(render())、View.render()メソッドの呼出しのみ行います(第16行目および第51〜53行目)。360;view.render();}この書替えだけでも、HoverController.panAngleとHoverController.tiltAngleプロパティに定めたパンとチルトの位置にカメラはトゥイーンして、立方体の映る角度が変わります(図005)。この後さらに、マウスドラッグでパンとチルトをインタラクティブに動かします。図005■立方体を映すカメラのパンとチルトがトゥイーンする→ドラッグは、3つのマウスイベントで扱うのがお約束です。第1に、マウスボタンを押すと(onmousedownイベント)ドラッグが始まります(第15行目)。コールバック関数(startDrag())は、マウスポインタの座標やカメラのパンとチルト角など、必要な値を変数にとります(第55〜58行目)。マウスポインタを動かしたとき(onmousemoveイベント)のドラッグと、ボタンを放したとき(onmouseupイベント)の終了のイベントハンドラ(drag()とstopDrag())をそれぞれ定めます(第59〜60行目)。第2に、ドラッグ(onmousemoveイベント)のコールバック関数(drag())は、マウスポインタの水平な動きからパン(HoverController.panAngleプロパティ)を、垂直な動きでチルト(HoverController.tiltAngleプロパティ)を増減させます(第63〜64行目)。このとき、ドラッグ開始時(startDrag())にとっておいたマウス座標とパンおよびチルト角の変数値から差を求めています。第3に、マウスボタンを放すと(onmouseupイベント)ドラッグは終わりです。イベントハンドラ(stopDrag())は、onmousemoveとonmouseupイベントにnullを代入してコールバック関数の定めは消します(第67〜68行目)。これで、マウスドラッグを扱う流れがひとつ済みました。null;}これらの書替えで、マウスドラッグによりカメラが立方体の周りをパンあるいはチルトします。カメラワークでオブジェクトの周りを回って撮るインタラクティブなアニメーションです。JavaScript全体はつぎのコード002にまとめました。jsdo.itにもサンプルコードを掲げてあります(サンプル002)。2014年8月26日付ビルドの更新にもとづき、細かい表記と画像の一部を変更。2014年8月18日付ビルドの更新にもとづき、ふたつのJavaScriptライブラリ名を変更し(注[*1])、クラスTriangleMaterialをTriangleMethodMaterialに差替えた(注[*4])。若干の細かなスクリプトの表記修正。2014年6月24日付ビルドの更新にもとづき、クラスDirectionalLightのパッケージをaway.entitiesに書替え、注[*2]を追加した。2014年6月13日付ビルドの更新にもとづき、クラスTextureMaterialをTriangleMaterialに差替え、注[*4]を追加した。2014年5月13日付ビルドの更新にもとづき、動作確認のうえビルド日付変更。TypeScriptライブラリを使う」の解説を改めた。2014年5月初めのビルドで変わった仕様にもとづき、とくに04「PrimitiveCubePrefabクラスからつくった立方体のオブジェクトを水平および垂直の向きに回す」を大幅に書替えた。立方体を回してみる」を全面改訂。