前回の第7回
Matrix3Dクラスで座標を回転する
オブジェクトをランダムに変換する前に,
たとえば,
Away3DのMatrix3Dクラスが変換するのは3次元座標だ。パラメータを変えることにより,
Matrix3Dクラスに備わる回転・
appendRotation(角度, 回転軸)
表1 Matrix3Dクラスの回転・
座標変換 | 前変換 | 後変換 |
---|---|---|
回転 | prependRotation(degrees, axis) | appendRotation(degrees, axis) |
伸縮 | prependScale(xScale, yScale, zScale) | appendScale(xScale, yScale, zScale) |
移動 | prependTranslation(x, y, z) | appendTranslation(x, y, z) |
Matrix3Dクラスで,
Matrix3Dオブジェクト.transformVector(Vector3Dオブジェクト)
var Matrix3D = require("awayjs-core/lib/geom/Matrix3D");
function getPolarPosition(distance, rotationY) {
// var vector = new Vector3D();
var vector = new Vector3D(distance, 0, 0);
// vector.x = distance * Math.cos(-rotationY * Math.PI / 180);
// vector.z = distance * Math.sin(-rotationY * Math.PI / 180);
var matrix = new Matrix3D();
matrix.appendRotation(rotationY, Vector3D.Y_AXIS);
// return vector;
return matrix.transformVector(vector);
}
これで,
コード1 円軌道上に複数のオブジェクトを行列変換により配置してカメラで回り込む
var LoaderEvent = require("awayjs-core/lib/events/LoaderEvent");
var Vector3D = require("awayjs-core/lib/geom/Vector3D");
var Matrix3D = require("awayjs-core/lib/geom/Matrix3D");
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 PrimitiveCubePrefab = require("awayjs-display/lib/prefabs/PrimitiveCubePrefab");
var DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
var TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");
var view;
var cube;
var imageDiffuse = "assets/trinket_diffuse.jpg";
var timer;
var ORIGIN = new Vector3D();
var angle = -Math.PI / 2;
var distance = 1500;
var stageWidth = 240;
var stageHeight = 180;
function initialize() {
var directionalLight = createDirectionalLight(0.5, 0xFFFFFF);
view = createView(stageWidth, stageHeight, 0x0);
cube = createCube(400, 400, 400, directionalLight);
setCamera(view.camera, distance, angle);
view.scene.addChild(cube);
cloneMesh(cube, 5);
AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
AssetLibrary.load(new URLRequest(imageDiffuse));
timer = new RequestAnimationFrame(rotate);
timer.start();
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 createCube(width, height, depth, light) {
var material = new TriangleMethodMaterial();
var cube = new PrimitiveCubePrefab(width, height, depth, 1, 1, 1, false)
.getNewObject();
cube.material = material;
material.lightPicker = new StaticLightPicker([light]);
return cube;
}
function cloneMesh(mesh, count) {
var scene = view.scene;
var distance = 1000;
var degrees = 360 / count;
for (var i = 0; i < count; i++) {
var clone = mesh.clone();
var rotationY = degrees * i;
var position = getPolarPosition(distance, rotationY);
clone.x = position.x;
clone.y = position.y;
clone.z = position.z;
clone.rotationY = rotationY;
scene.addChild(clone);
}
}
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 = cube.material;
material.texture = assets[0];
view.render();
}
function rotate(timeStamp) {
var camera = view.camera;
angle += timeStamp / 2000;
setCamera(camera, distance, angle);
view.render();
}
function setCamera(camera, distance, angle) {
camera.x = Math.cos(angle) * distance;
camera.z = Math.sin(angle) * distance;
camera.lookAt(ORIGIN);
}
function getPolarPosition(distance, rotationY) {
var vector = new Vector3D(distance, 0, 0);
var matrix = new Matrix3D();
matrix.appendRotation(rotationY, Vector3D.Y_AXIS);
return matrix.transformVector(vector);
}
- ※1
- 行列についてもう少し詳しくは,
「行列? なにそれ? 」おいしいの? 参照。15分間のビデオでもご覧いただける。 - ※2
- 一応説明しておくと,
行列による座標変換は掛け算で行われる。しかし, 実数の乗算と異なり, 行列は掛ける順序が変わると答えが違ってしまう (交換法則が成立たない)。これは, フィルタでモザイクを掛けてからぼかすのと, ぼかしてからモザイクを掛けたのでは画像が変わることからもわかるだろう。そこで, 掛け算の左右 (前後) どちらに置くのか, メソッドが分けて用意されているのだ。 - ※3
- 前回xz平面におけるy軸回りの回転が数学とは反対方向だということで,
角度 (rotationY) を正負逆にした (再掲第7回図6)。しかし, もちろんAway3DのMatrix3Dクラスはコンピュータグラフィックス向けにつくられているので, そのような考慮はしなくてよい。