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

第11回Away3D TypeScriptが2015年3月13日付でビルドを改めた

今回から取組むお題は、Away3D TypeScriptの「Examples」からいただくAnimating particles simulating fire図1⁠。ただ、本論に入る前に説明しなければならないことがある。Away3Dのライブラリが2015年3月13日付で改められた。そのJavaScriptファイルに差し替えると、この連載でこれまで書いたコードがおおかた動かなくなる。今回は、その解説にあてたい。

図1 Away3D TypeScriptサイトの作例「Animating particles simulating fire」
図1 Away3D TypeScriptサイトの作例「Animating particles simulating fire」

床の平面にテクスチャを貼ってカメラで回り込む

とはいえ、お題からまったく離れてしまう訳ではない。この連載をずっと読んできた方は、お題の床に見覚えがあろう(再掲第4回図2⁠。床の平面にテクスチャを貼って、カメラで回り込むスクリプトは、第4回コード3HoverControllerオブジェクトによるカメラのパンとチルトをマウスドラッグで動かすからほぼそのまま抜き出して使うつもりだった。

第4回 図2 3次元空間のビーチボールの下に石畳の床が置かれた(再掲)
第4回 図2 3次元空間のビーチボールの下に石畳の床が置かれた(再掲)

ところが、前述のとおり、このコードは新ライブラリでは動かない。そこで、今回は新たなビルドでコードを書き改めることにする。まずは、第4回コード3から、床にテクスチャを与えて、カメラが回り込むスクリプトを抜き出したのが以下のコード1だ。これまでのライブラリを使えば、床の平面に石畳のテクスチャが貼られて、ドラッグするとカメラが回り込む図1⁠。

図2 床の平面に石畳のテクスチャが貼られた
図2 床の平面に石畳のテクスチャが貼られた
コード1 石畳のテクスチャが貼られた床の周囲をドラッグでカメラが回り込む(これまでのライブラリ向け)
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 PrimitivePlanePrefab = require("awayjs-display/lib/prefabs/PrimitivePlanePrefab");
var DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
var TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");
var HoverController = require("awayjs-display/lib/controllers/HoverController");
var view;
var plane;
var cameraController;
var timer;
var planeDiffuse = "assets/floor_diffuse.jpg";
var lastMouseX;
var lastMouseY;
var lastPanAngle;
var lastTiltAngle;
function initialize() {
  var directionalLight = createDirectionalLight(0.25, 0xFFFFFF);
  view = createView(240, 180, 0x0);
  var scene = view.scene;
  plane = createPlane(800, 800, directionalLight, -300);
  scene.addChild(plane);
  cameraController = setupCameraController(view.camera, 1000, 0, 90, 45, 20);
  AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
  AssetLibrary.load(new URLRequest(planeDiffuse));
  document.onmousedown = startDrag;
  timer = new RequestAnimationFrame(render);
  timer.start();
}
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 createPlane(width, height, light, y) {
  var material = new TriangleMethodMaterial();
  var plane = new PrimitivePlanePrefab(width, height).getNewObject();
  plane.material = material;
  material.lightPicker = new StaticLightPicker([light]);
  plane.y = y;
  return plane;
}
function createDirectionalLight(ambient, color) {
  var light = new DirectionalLight();
  light.ambient = ambient;
  light.color = color;
  return light;
}
function setupCameraController(camera, distance, minTiltAngle, maxTiltAngle, panAngle, tiltAngle) {
  var cameraController = new HoverController(camera);
  cameraController.distance = distance;
  cameraController.minTiltAngle = minTiltAngle;
  cameraController.maxTiltAngle = maxTiltAngle;
  cameraController.panAngle = panAngle;
  cameraController.tiltAngle = tiltAngle;
  return cameraController;
}
function onResourceComplete(eventObject) {
  var assets = eventObject.assets;
  var material;
  var count = assets.length;
  var url = eventObject.url;
  for (var i = 0; i 

新ライブラリで動くように書替える

ところが、新しいライブラリに差し替えて前掲コード1を試すと床が表れない。ブラウザの開発ツールで確かめると、TriangleMethodMaterialクラスが見つからないというエラーが示される図3⁠。したがって、TriangleMethodMaterialクラスのコンストラクタも呼び出せないということだ。

図3 Google Chromeの[JavaScriptコンソール]に示されたエラー
図3 Google Chromeの[JavaScriptコンソール]に示されたエラー

たしかに、awayjs-methodmaterialsのライブラリからTriangleMethodMaterialとTriangleMaterialModeのふたつのクラスがなくなっている。そして、新ライブラリには、MethodMaterialとMethodMaterialModeというクラスが替わりに納められていた図4⁠。したがって、この書替えをしなければならない。

図4 awayjs-methodmaterialsライブラリの中身が変わった

図4 awayjs-methodmaterialsライブラリの中身が変わった
2014年11月5日付ビルド
図4 awayjs-methodmaterialsライブラリの中身が変わった
2015年3月13日付ビルド

さらに調べてみると、新たなクラスをあとふたつ加えることになった。前掲コード1require()関数のコードがどう書き替わるのかを先に示しておこう。つぎのように、クラスTriangleMethodMaterialはMethodMaterialに差し替え、さらにふたつのクラスDefaultMaterialManagerとMethodRendererPoolを追加した。

var DefaultMaterialManager = require("awayjs-display/lib/managers/DefaultMaterialManager");

// var TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");
var MethodMaterial = require("awayjs-methodmaterials/lib/MethodMaterial");
var MethodRendererPool = require("awayjs-methodmaterials/lib/pool/MethodRendererPool");

クラスTriangleMethodMaterialと差し替えるMethodMaterialのコンストラクタには、引数としてテクスチャを渡す。そして、デフォルトのテクスチャは、DefaultMaterialManager.getDefaultTexture()メソッドで得る。したがって、MethodMaterial()コンストラクタはつぎのように呼び出す。すると、前掲コード1の平面をつくる関数(createPlane())は、以下のように書き替えなければならない。

new MethodMaterial(DefaultMaterialManager.getDefaultTexture())
function createPlane(width, height, light, y) {
  // var material = new TriangleMethodMaterial();
  var material = new MethodMaterial(DefaultMaterialManager.getDefaultTexture());

}

もうひとつ、View()コンストラクタに渡すDefaultRendererオブジェクトも、つくり方が変わった。DefaultRenderer()コンストラクタには、引数にMethodRendererPoolクラスを渡すことになった。したがって、前掲コード1のViewオブジェクトをつくる関数(createView())は、以下のように書き替える。

new DefaultRenderer(MethodRendererPool)
function createView(width, height, backgroundColor) {
  // var defaultRenderer = new DefaultRenderer();
  var defaultRenderer = new DefaultRenderer(MethodRendererPool);
  var view = new View(defaultRenderer);

}

前掲コード1にこれらの書き替えを加えたのがつぎのコード2だ。新しい2015年3月13日付ライブラリのもとで、石畳のテクスチャが貼られた床の周囲をドラッグでカメラが回り込む。あわせて、サンプル1をjsdo.itに掲げた。

コード2 石畳のテクスチャが貼られた床の周囲をドラッグでカメラが回り込む(2015年3月13日付ライブラリ向け)
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 DefaultMaterialManager = require("awayjs-display/lib/managers/DefaultMaterialManager");
var StaticLightPicker = require("awayjs-display/lib/materials/lightpickers/StaticLightPicker");
var PrimitivePlanePrefab = require("awayjs-display/lib/prefabs/PrimitivePlanePrefab");
var DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
var MethodMaterial = require("awayjs-methodmaterials/lib/MethodMaterial");
var MethodRendererPool = require("awayjs-methodmaterials/lib/pool/MethodRendererPool");
var HoverController = require("awayjs-display/lib/controllers/HoverController");
var view;
var plane;
var cameraController;
var timer;
var planeDiffuse = "assets/floor_diffuse.jpg";
var lastMouseX;
var lastMouseY;
var lastPanAngle;
var lastTiltAngle;
function initialize() {
  var directionalLight = createDirectionalLight(0.25, 0xFFFFFF);
  view = createView(240, 180, 0x0);
  var scene = view.scene;
  plane = createPlane(800, 800, directionalLight, -300);
  scene.addChild(plane);
  cameraController = setupCameraController(view.camera, 1000, 0, 90, 45, 20);
  AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
  AssetLibrary.load(new URLRequest(planeDiffuse));
  document.onmousedown = startDrag;
  timer = new RequestAnimationFrame(render);
  timer.start();
}
function createView(width, height, backgroundColor) {
  var defaultRenderer = new DefaultRenderer(MethodRendererPool);
  var view = new View(defaultRenderer);
  view.width = width;
  view.height = height;
  view.backgroundColor = backgroundColor;
  return view;
}
function createPlane(width, height, light, y) {
  var material = new MethodMaterial(DefaultMaterialManager.getDefaultTexture());
  var plane = new PrimitivePlanePrefab(width, height).getNewObject();
  plane.material = material;
  material.lightPicker = new StaticLightPicker([light]);
  plane.y = y;
  return plane;
}
function createDirectionalLight(ambient, color) {
  var light = new DirectionalLight();
  light.ambient = ambient;
  light.color = color;
  return light;
}
function setupCameraController(camera, distance, minTiltAngle, maxTiltAngle, panAngle, tiltAngle) {
  var cameraController = new HoverController(camera);
  cameraController.distance = distance;
  cameraController.minTiltAngle = minTiltAngle;
  cameraController.maxTiltAngle = maxTiltAngle;
  cameraController.panAngle = panAngle;
  cameraController.tiltAngle = tiltAngle;
  return cameraController;
}
function onResourceComplete(eventObject) {
  var assets = eventObject.assets;
  var material;
  var count = assets.length;
  var url = eventObject.url;
  for (var i = 0; i < count; i++) {
    var asset = assets[i];
    switch (url) {
      case (planeDiffuse):
        material = plane.material;
        material.texture = asset;
        break;
    }
  }
}
function render(timeStamp) {
  view.render();
}
function startDrag(eventObject) {
  lastMouseX = eventObject.clientX;
  lastMouseY = eventObject.clientY;
  lastPanAngle = cameraController.panAngle;
  lastTiltAngle = cameraController.tiltAngle;
  document.onmousemove = drag;
  document.onmouseup = stopDrag;
}
function drag(eventObject) {
  cameraController.panAngle = 0.5 * (eventObject.clientX - lastMouseX) + lastPanAngle;
  cameraController.tiltAngle = 0.3 * (eventObject.clientY - lastMouseY) + lastTiltAngle;
}
function stopDrag(eventObject) {
  document.onmousemove = null;
  document.onmouseup = null;
}
サンプル1 Away3D 15/03/13: A plane added texture to with the camera panned and tilted by the mouse

これまで書いたコードを新ライブラリで動かすには

この連載でこれまで書いたコードを2015年3月13日付ライブラリで動かすにはどう書き替えればよいか。

前掲コード2の下敷きにした第4回コード3「HoverControllerオブジェクトによるカメラのパンとチルトをマウスドラッグで動かす」は、第1回から都合4回かけて仕上げたお題だ。これは、前述の直しを入れればビーチボールを含めて正しく動く。

また、第7回からつくり始めて前回でき上がった第10回コード2マウスポインタの画面中央からの座標に応じてカメラを水平および垂直に動かすも同じように書き替えればよい。参考までに、サンプル2としてjsdo.itに掲げた。

サンプル2 Away3D 15/03/13: Dealing with the mouse interactions for objects and the camera

第5回と第6回で書き上げたお題の第6回コード3背景の映り込んだドーナッツ型を上下左右にに回るカメラで捉えるについては、前述の修正に加えてSkyboxMaterialクラスがなくなった。そして、Skybox()コンストラクタには、素材のキューブマップがそのまま渡せるようになった。そのため、スカイボックスをつくる関数(setupSkybox())はつぎのように書き替えることになる。

// var SkyboxMaterial = require("awayjs-renderergl/lib/materials/SkyboxMaterial");

function setupSkybox(cubeTexture) {
  // var skybox = new Skybox(new SkyboxMaterial(cubeTexture));
  var skybox = new Skybox(cubeTexture);
  view.scene.addChild(skybox);
  torus.material.addEffectMethod(new EffectEnvMapMethod(cubeTexture));
}

2015年3月13日付Away3D TypeScriptについては、とりあえずこれくらい説明すればよいだろう。さて次回は、床にパーティクルを加えたい。

おすすめ記事

記事・ニュース一覧