Away3D TypeScriptではじめる3次元表現

第3回ライブラリとクラスの読込みが変わった

今回は予告と内容を変えて、緊急特番だ。前回第2回の記事が公開された翌日2014年11月5日付でAway3Dのビルドが改められた。ライブラリの名前も数も、さらにクラスの読込み方も変わった。勝手がわかってしまえばよいものの、初めは途方に暮れてもおかしくない。そこで今回は、第2回コード2球体にテクスチャを貼って3次元空間で回すを、新しいビルドで動くように書き直す。でき上がりは、つぎのサンプル1だ。

サンプル1 Away3D 14/11/05: Rotating a texture mapped sphere in the 3D space

Away3Dのライブラリが変わった

まず、ライブラリはつぎの5つを使う。前回まで用いていた2014年8月26日付ビルドでは3ライブラリだった図1上⁠。新たなライブラリは、名前の頭が「awayjs-」で揃ったのはわかりやすくてよい。JavaScript(JS)ファイルだけでなく、それぞれのmapも与えられているため、同じ場所に入れておこう図1下⁠。

  1. awayjs-core
  2. awayjs-display
  3. awayjs-renderergl
  4. awayjs-stagegl
  5. awayjs-methodmaterials
図1 Away3Dで用いるライブラリのファイル
図1 Away3Dで用いるライブラリのファイル
2014年8月26日付
図1 Away3Dで用いるライブラリのファイル
2014年11月5日付

なお、ライブラリはGitHubのAwayJSからダウンロードする。Away3D TypeScriptサイト「Source Files」の欄には、本稿執筆時ではこれまでのまま、3つのライブラリと作例(⁠⁠GitHub: Examples⁠⁠)のリンクしかない図2⁠。

図2 Away3D TypeScriptサイトの「Source Files」の欄
図2 Away3D TypeScriptサイトの「Source Files」の欄

そして、script要素で読込むライブラリを、これまでの3つから、新たな5つのJSファイルに書き替える。ライブラリ名から「next」が除かれたのは、そろそろ正規リリースが近いのかと期待される。何より、こういう大きな変更はそろそろ終わりにしてほしい。

<!--
<script src="lib/awayjs-core.next.min.js"></script>
<script src="lib/stagegl-core.next.min.js"></script>
<script src="lib/stagegl-extensions.next.min.js"></script>
-->
<script src="lib/awayjs-core.min.js"></script>
<script src="lib/awayjs-display.min.js"></script>
<script src="lib/awayjs-renderergl.min.js"></script>
<script src="lib/awayjs-stagegl.min.js"></script>
<script src="lib/awayjs-methodmaterials.min.js"></script>

require()関数でクラスを読込む

これまでAway3Dのクラスは「away」から始まる長い名前空間を添えて参照した。新たなライブラリでは、require()関数でクラスの参照を得る。それを変数に与えて用いるというやり方だ。変数名はクラスと同じにするとわかりやすい。

var 変数 = require(クラスのパス)
var LoaderEvent = require("awayjs-core/lib/events/LoaderEvent");
var AssetLibrary = require("awayjs-core/lib/library/AssetLibrary");
var URLRequest = require("awayjs-core/lib/net/URLRequest");
var RequestAnimationFrame = require("awayjs-core/lib/utils/RequestAnimationFrame");
var View = require("awayjs-display/lib/containers/View");
var DirectionalLight = require("awayjs-display/lib/entities/DirectionalLight");
var StaticLightPicker = require("awayjs-display/lib/materials/lightpickers/StaticLightPicker");
var PrimitiveSpherePrefab = require("awayjs-display/lib/prefabs/PrimitiveSpherePrefab");
var DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
var TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");

新たなライブラリでは、⁠away」から始まる名前空間でクラスを参照することができない。けれど、require()関数でクラスと同じ名前の変数に参照を与えたので、名前空間は取り去ってしまえばよい。たとえば、第2回コード2の初期設定の関数(initialize())は、つぎのように書き替える。AssetLibraryクラスは名前空間から参照しない。あらかじめrequire()関数でクラス名の変数(AssetLibrary)に納めてあるので、直にクラス名を書く。

function initialize() {

  // var AssetLibrary = away.library.AssetLibrary;

  // AssetLibrary.addEventListener(away.events.LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
  AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
  // AssetLibrary.load(new away.net.URLRequest(imageDiffuse));
  AssetLibrary.load(new URLRequest(imageDiffuse));
  // timer = new away.utils.RequestAnimationFrame(rotate);
  timer = new RequestAnimationFrame(rotate);

}

あとは、残りのコードの名前空間の記述を、変数に定めた直のクラス名にひたすら書き直すだけだ。これでとにかくコードは動く。第2回コード2と同じく、ビーチボールのテクスチャを貼った球体が回る図3⁠。

図3 ビーチボールのテクスチャを貼った球体が回る
図3 ビーチボールのテクスチャを貼った球体が回る

LoaderEvent.RESOURCE_COMPLETEイベントで素材が正しく読み込まれる

ひとつよい知らせがある。第2回「物体にテクスチャを貼って回す」3次元空間でボールを回すで、LoaderEvent.RESOURCE_COMPLETEイベントのリスナー関数(onResourceComplete())が呼び出されてLoaderEvent.assetsプロパティの参照がとれても、その配列は空のときがある」と述べた。このたびのビルドで、問題は解消した。したがって、リスナー関数はつぎのようにすっきりと書き直せる。

function onResourceComplete(eventObject) {
  var assets = eventObject.assets;
  // if (assets.length > 0) {
  var material = sphere.material;
  material.texture = assets[0];
  view.render();
  /* } else {
    var AssetLibrary = away.library.AssetLibrary;
    var RESOURCE_COMPLETE = away.events.LoaderEvent.RESOURCE_COMPLETE;
    AssetLibrary.removeEventListener(RESOURCE_COMPLETE, onResourceComplete);
    AssetLibrary.addEventListener(RESOURCE_COMPLETE, onResourceComplete);
    AssetLibrary.load(new away.net.URLRequest(eventObject.url));
  } */
}

第2回コード2を新たなライブラリで動くように書き直したのが、つぎのコード1だ。script要素に読込むライブラリのJSファイルを差替え、require()関数でクラスの参照を得た。Away3Dの処理の組立ては変わっていない。ただ、LoaderEvent.RESOURCE_COMPLETEイベントの問題がなくなったので、リスナー関数は素直に定めた。jsdo.itのコードは、初めにサンプル1として掲げた。

コード1 球体にテクスチャを貼って3次元空間で回す
<script src="lib/awayjs-core.min.js"></script>
<script src="lib/awayjs-display.min.js"></script>
<script src="lib/awayjs-renderergl.min.js"></script>
<script src="lib/awayjs-stagegl.min.js"></script>
<script src="lib/awayjs-methodmaterials.min.js"></script>
<script>
var LoaderEvent = require("awayjs-core/lib/events/LoaderEvent");
var AssetLibrary = require("awayjs-core/lib/library/AssetLibrary");
var URLRequest = require("awayjs-core/lib/net/URLRequest");
var RequestAnimationFrame = require("awayjs-core/lib/utils/RequestAnimationFrame");
var View = require("awayjs-display/lib/containers/View");
var DirectionalLight = require("awayjs-display/lib/entities/DirectionalLight");
var StaticLightPicker = require("awayjs-display/lib/materials/lightpickers/StaticLightPicker");
var PrimitiveSpherePrefab = require("awayjs-display/lib/prefabs/PrimitiveSpherePrefab");
var DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
var TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");
var view;
var sphere;
var imageDiffuse = "assets/beachball_diffuse.jpg";
var timer;
function initialize() {
  var directionalLight = createDirectionalLight(0.25, 0xFFFFFF);
  view = createView(240, 180, 0x0);
  sphere = createSphere(300, 32, 24, directionalLight);
  view.scene.addChild(sphere);
  AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
  AssetLibrary.load(new URLRequest(imageDiffuse));
  timer = new RequestAnimationFrame(rotate);
  timer.start();
  view.render();
  view.render();
}
function createView(width, height, backgroundColor) {
  var defaultRenderer = new DefaultRenderer();
  var view = new View(defaultRenderer);
  view.width = width;
  view.height = height;
  view.backgroundColor = backgroundColor;
  return view;
}
function createSphere(radius, segmentsH, segmentsV, light) {
  var material = new TriangleMethodMaterial();
  var sphere = new PrimitiveSpherePrefab(radius, segmentsH, segmentsV)
  .getNewObject();
  sphere.material = material;
  material.lightPicker = new StaticLightPicker([light]);
  return sphere;
}
function createDirectionalLight(ambient, color) {
  var light = new DirectionalLight();
  light.ambient = ambient;
  light.color = color;
  return light;
}
function onResourceComplete(eventObject) {
  var assets = eventObject.assets;
  var material = sphere.material;
  material.texture = assets[0];
  view.render();
}
function rotate(timeStamp) {
  sphere.rotationX = (sphere.rotationX + 1) % 360;
  sphere.rotationY = (sphere.rotationY + 1) % 360;
  view.render();
}
</script>

前回予告してあったテクスチャつきの床を加えることと、ドラッグによりカメラの視界を移すインタラクションは、今回のコード1をもとにして次回仕上げる。

おすすめ記事

記事・ニュース一覧