銀杏 舞い散る
もう直ぐ秋。
だというのに、この暑さはいったいなんなんでしょう。
しかもこちとら北国なのに。
軸回転の計算と、奥行き→2次元変換
今回は、X軸Y軸Z軸、それぞれの方向に回転する方法です(以前紹介した角座標とは、アプローチが違います。混同しないようにお願いします。)
まずは、こちらを見てください。
赤球はX軸、青球はY軸、黄球はZ軸に回転してます。
さらに、視点から遠いものは、小さく、狭く、見えてます。
これを踏まえて、これらの球にリンクしたクラスを読んでみてください。
class View3D extends MovieClip{
var focalView = 100;
var PI_half;
var center_x = 200;
var center_y = 200;
var center_z = 100;
var scale;
//回転の速度
var rx = 0;
var ry = 0;
var rz = 0;
//シフトの速度
var sx = 0;
var sy = 0;
var sz = 0;
//「本当の座標」
var real_x;
var real_y;
var real_z;
var changed = false;
function onLoad(){
PI_half = Math.PI/180;
viewOnVirtualAxis();
}
function onEnterFrame(){
if( rx != 0 ) rotateX(rx);
if( ry != 0 ) rotateY(ry);
if( rz != 0 ) rotateZ(rz);
if( sx != 0 ) shiftX(sx);
if( sy != 0 ) shiftY(sy);
if( sz != 0 ) shiftZ(sz);
if( changed ) viewOnVirtualAxis();
}
function setRealAxis(x,y,z){
real_x = x;
real_y = y;
real_z = z;
changed = true;
}
//「本当の座標」を2次元の見え方に変換する。
function viewOnVirtualAxis(){
scale = getVirtualScale(real_z+center_z);
_xscale = _yscale = scale * 100;
_x = real_x * scale + center_x;
_y = real_y * scale + center_y;
changed = false;
}
function getVirtualScale(z){
return focalView/(focalView+z);
}
//回転の計算(「本当の座標」で計算する)
function rotateX(angle){
var new_x= real_x;
var new_y= real_y * Math.cos(angle*PI_half)
+ real_z*Math.sin(angle*PI_half);
var new_z= - real_y * Math.sin(angle*PI_half)
+ real_z*Math.cos(angle*PI_half);
setRealAxis(new_x,new_y,new_z);
}
function rotateY(angle){
var new_x = real_x*Math.cos(angle*PI_half)
- real_z*Math.sin(angle*PI_half);
var new_y = real_y;
var new_z = real_x*Math.sin(angle*PI_half)
+ real_z*Math.cos(angle*PI_half);
setRealAxis(new_x,new_y,new_z);
}
function rotateZ(angle){
var new_x= real_x*Math.cos(angle*PI_half)
+ real_y*Math.sin(angle*PI_half);
var new_y= - real_x*Math.sin(angle*PI_half)
+ real_y*Math.cos(angle*PI_half);
var new_z= real_z;
setRealAxis(new_x,new_y,new_z);
}
//平行移動の計算(軸の中心をずらしてる)
function shiftX(interval){
center_x += interval;
}
function shiftY(interval){
center_y += interval;
}
function shiftZ(interval){
center_z += interval;
}
}
「function rotateナニガシ()」の中でやってる計算は、ナニガシ軸まわりの回転を計算するための公式です。
注意したいのは、3次元座標(実世界の座標)を計算して保存してから、最後の最後、表示する時点で3次元座標を2次元座標(Flashの世界の座標)に変換します(viewOnVirtualAxis)。
つまり、計算バッファは、MovieClip._x/_y とは、別のエリアに持ちます。ここさえ気をつければ、意外と簡単ではないでしょうか?
このクラスをリンクして、rotateZしながらshiftZすれば、冒頭のようになります。こんなゴツイ計算しなければできないのか?と言われれば、そうでもないと思うのですが、このライブラリを持っていれば、アイディア次第で、いろいろな効果を出すことができそうです。