銀杏 舞い散る

Flashで3D計算。軸周辺の回転と、視点と奥行きを感じる計算方法。

銀杏 舞い散る


もう直ぐ秋。

だというのに、この暑さはいったいなんなんでしょう。
しかもこちとら北国なのに。


軸回転の計算と、奥行き→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すれば、冒頭のようになります。こんなゴツイ計算しなければできないのか?と言われれば、そうでもないと思うのですが、このライブラリを持っていれば、アイディア次第で、いろいろな効果を出すことができそうです。


コメント

コメントしてください

closed.