Flashゲーム講座 & アクションスクリプトサンプル集



単位クォータニオンを作成する

 
 


 
クォータニオンの型


実数部を w 虚数部を xyz としたオブジェクト形式で表現しています。

ここで扱うクォータニオンの形式

    var quat = {
        x : 0, 	// 虚数
        y : 0, 	// 虚数
        z : 0, 	// 虚数
        w : 1	// 実数
    };
 
クォータニオン生成


クォータニオンを生成する関数です。
 
クォータニオンの作成

function QuatCreate(x,y,z,w){
    return {x:x,y:y,z:z,w:w};
}
 
使用例です。

例)クォータニオンを作成する

  var quat = QuatCreate(0,0,0,1);
 
 

 




クォータニオン同士を足し算する

 
 


 
クォータニオン同士を足し算

第01引数にクォータニオン
第02引数にクォータニオン
戻り値にクォータニオンが返ります。

クォータニオン同士を足し算

function QuatAdd(q1,q2){
    return {
        w : q1.w + q2.w,
        x : q1.x + q2.x,
        y : q1.y + q2.y,
        z : q1.z + q2.z
    }
}
 
使用例です。

例)クォータニオンの加算

  var quat1 = QuatCreate(0,0,0,1);
  var quat2 = QuatCreate(1,1,1,1);
  var quat3 = QuatAdd(quat1,quat2);
 

 




クォータニオン同士を引き算する

 
 


 
クォータニオン同士を引き算

第01引数にクォータニオン
第02引数にクォータニオン
戻り値にクォータニオンが返ります。

クォータニオン同士を引き算

function QuatSub(q1,q2){
    return {
        w : q1.w - q2.w,
        x : q1.x - q2.x,
        y : q1.y - q2.y,
        z : q1.z - q2.z
    }
}
 
使用例です。

例)クォータニオンの減算

  var quat1 = QuatCreate(0,0,0,1);
  var quat2 = QuatCreate(1,1,1,1);
  var quat3 = QuatSub(quat1,quat2);
 

 




クォータニオン同士を掛け算する

 
 


 
クォータニオン同士を掛け算

第01引数にクォータニオン
第02引数にクォータニオン
戻り値にクォータニオンが返ります。

クォータニオン同士を掛け算

function QuatMul(q1,q2){
  return {
    w : q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
    x : q1.y * q2.z - q1.z * q2.y + q1.w * q2.x + q1.x * q2.w,
    y : q1.z * q2.x - q1.x * q2.z + q1.w * q2.y + q1.y * q2.w,
    z : q1.x * q2.y - q1.y * q2.x + q1.w * q2.z + q1.z * q2.w
  }
}
 
使用例です。

例)クォータニオンの掛け算

  var quat1 = QuatCreate(0,0,0,1);
  var quat2 = QuatCreate(1,1,1,1);
  var quat3 = QuatMul(quat1,quat2);
 

 




クォータニオンを実数掛け算する

 
 


 
クォータニオンを実数掛け算

第01引数にクォータニオン
第02引数にスケーリング値
戻り値にクォータニオンが返ります。

クォータニオンを実数掛け算

function QuatScale(q,s){
    return {
        w : q.w * s,
        x : q.x * s,
        y : q.y * s,
        z : q.z * s
    }
}
 
使用例です。

例)クォータニオンの実数掛け算

  var quat1 = QuatCreate(0,0,0,1);
  var quat2 = QuatScale(quat1,0.5);
 

 




クォータニオンの絶対値を計算する

 
 


 
クォータニオンの絶対値(ノルム)を計算

第01引数にクォータニオン
戻り値にノルムが返ります。

クォータニオンの絶対値を計算

function QuatNorm(q){
    return Math.sqrt(q.w * q.w + q.x * q.x + q.y * q.y
+ q.z * q.z); }
 
使用例です。

例)クォータニオンの絶対値

  var quat = QuatCreate(0,0,0,1);
  var norm = QuatNorm(quat);







クォータニオンの絶対値の2乗を計算

第01引数にクォータニオン
戻り値に絶対値の2乗が返ります。

クォータニオンの絶対値の2乗を計算

function QuatNormSqr(q){
    var n = Math.sqrt(q.w * q.w + q.x * q.x + q.y * q.y
+ q.z * q.z); return n * n; }
 
使用例です。

例)クォータニオンの絶対値の2乗

  var quat = QuatCreate(0,0,0,1);
  var norm_2 = QuatNormSqr(quat);
 

 




任意軸の回転クォータニオンを作成する

 
 


 
任意軸の回転クォータニオンを作成

第01引数に回転軸を表す3Dベクトル
第02引数に回転する角度
戻り値にクォータニオンが返ります。

任意軸の回転クォータニオンを作成

function QuatRotate (v,r){	
    var rad = r * (Math.PI / 180.0) / 2.0;
    var s = Math.sin(rad);
    return {
        w : Math.cos(rad),
        x : v.x * s,
        y : v.y * s,
        z : v.z * s
    }
}
 
使用例です。

例)回転クォータニオンの作成

  var vec = {x:1,y:0,z:0};
  var quat = QuatRotate(vec,90);
 

 
クォータニオン × 回転クォータニオン

回転クォータニオンを生成してから、別のクォータニオンの前に置いて乗算する関数です。

第01引数に回転軸を表す3Dベクトル
第02引数に回転する角度
第03引数にクォータニオン
戻り値にクォータニオンが返ります。

回転クォータニオンを別のクォータニオンの前に置いて乗算

function QuatRotatePref (v,r,q){	
  var rad = r * (Math.PI / 180.0) / 2.0;
  var s = Math.sin(rad);
  var qw = Math.cos(rad);
  var qx = v.x * s;
  var qy = v.y * s;
  var qz = v.z * s;
  return {
    w : q.w * qw - q.x * qx - q.y * qy - q.z * qz,
    x : q.y * qz - q.z * qy + q.w * qx + q.x * qw,
    y : q.z * qx - q.x * qz + q.w * qy + q.y * qw,
    z : q.x * qy - q.y * qx + q.w * qz + q.z * qw
  }
}
 
使用例です。

例)[ y 軸に 45 回転] × [ x 軸に 90 回転]

  var axis_x = {x:1,y:0,z:0};
  var quat1 = QuatRotate(axis_x,90);
  var axis_y = {x:0,y:1,z:0};
  var quat2 = QuatRotatePref(axis_y,45,quat1);
 

 
回転クォータニオン × クォータニオン

回転クォータニオンを生成してから、別のクォータニオンの後に置いて乗算する関数です。

第01引数に回転軸を表す3Dベクトル
第02引数に回転する角度
第03引数にクォータニオン
戻り値にクォータニオンが返ります。

回転クォータニオンを別のクォータニオンの後に置いて乗算

function QuatRotatePost (v,r,q){
  var rad = r * (Math.PI / 180.0) / 2.0;
  var s = Math.sin(rad);
  var qw = Math.cos(rad);
  var qx = v.x * s;
  var qy = v.y * s;
  var qz = v.z * s;
  return {
    w : qw * q.w - qx * q.x - qy * q.y - qz * q.z,
    x : qy * q.z - qz * q.y + qw * q.x + qx * q.w,
    y : qz * q.x - qx * q.z + qw * q.y + qy * q.w,
    z : qx * q.y - qy * q.x + qw * q.z + qz * q.w
  }
}
 
使用例です。

例)[ x 軸に 90 回転] × [ y 軸に 45 回転]

  var axis_x = {x:1,y:0,z:0};
  var quat1 = QuatRotate(axis_x,90);
  var axis_y = {x:0,y:1,z:0};
  var quat2 = QuatRotatePost(axis_y,45,quat1);
 

 




回転クォータニオンからベクトルを射影変換する

 
 


 
座標の射影変換

第01引数に3Dベクトル
第02引数にクォータニオン
戻り値に変換後のベクトルが返ります。

ベクトルをクォータニオンに射影する

function QuatTransformVector(v,q){
    var w =-q.x * v.x - q.y * v.y - q.z * v.z;
    var x = q.y * v.z - q.z * v.y + q.w * v.x;
    var y = q.z * v.x - q.x * v.z + q.w * v.y;
    var z = q.x * v.y - q.y * v.x + q.w * v.z;
    return {
        x : y * -q.z + z * q.y - w * q.x + x * q.w,
        y : z * -q.x + x * q.z - w * q.y + y * q.w,
        z : x * -q.y + y * q.x - w * q.z + z * q.w
    }
}
 
例)座標(1,2,3)をクォータニオンに射影した後の座標を求める

  var axis_x = {x:1,y:0,z:0};
  var quat = QuatRotate(axis_x,30);

  var vec = {x:1,y:2,z:3};
  var pos = QuatTransformVector(vec,quat);
 

 




回転行列からクォータニオンに変換する

 
 


 
回転行列からクォータニオンに変換

第01引数に行列
戻り値に変換後のクォータニオンが返ります。

3Dベクトルをクォータニオンで射影する

function QuatConvertFromMatrix(m){

    var s;
    var tr = m._00 + m._11 + m._22 + 1.0;
    if (tr >= 1.0) {
        s = 0.5 / Math.sqrt(tr);
        return {
            w : 0.25 / s,
            x : (m._12 - m._21) * s,
            y : (m._20 - m._02) * s,
            z : (m._01 - m._10) * s
        }
    } else {
        var max;
        if(m._11 > m._22)    max = m._11;
        else                 max = m._22;
        
        if (max < m._00) {
            s = Math.sqrt(m._00 - (m._11 + m._22) + 1.0);
            var x = s * 0.5;
            s = 0.5 / s;
            return {
                x : x,
                y : (m._01 + m._10) * s,
                z : (m._20 + m._02) * s,
                w : (m._12 - m._21) * s
            }
        } else if (max == m._11) {
            s = Math.sqrt(m._11 - (m._22 + m._00) + 1.0);
            var y = s * 0.5;
            s = 0.5 / s;
            return {
                x : (m._01 + m._10) * s,
                y : y,
                z : (m._12 + m._21) * s,
                w : (m._20 - m._02) * s
            }
        } else {
            s = Math.sqrt(m._22 - (m._00 + m._11) + 1.0);
            var z = s * 0.5;
            s = 0.5 / s;
            return {
                x : (m._20 + m._02) * s,
                y : (m._12 + m._21) * s,
                z : z,
                w : (m._01 - m._10) * s
            }
        }
    }

}
 
例)回転行列からクォータニオンに変換

  var m {
    _00 : 1,  _01 : 0,  _02 : 0,
    _10 : 0,  _11 : 1,  _12 : 0,
    _20 : 0,  _21 : 0,  _22 : 1,
    _30 : 0,  _31 : 0,  _32 : 0
  };

  var quat = QuatConvertFromMatrix(m);
 

 




クォータニオンから回転行列に変換する

 
 


 
クォータニオンから行列に変換する

第01引数クォータニオン
戻り値に変換後の行列が返ります。

クォータニオンから行列に変換する

function QuatConvertToMatrix(q){
    var sx = q.x * q.x;
    var sy = q.y * q.y;
    var sz = q.z * q.z;
    var cx = q.y * q.z;
    var cy = q.x * q.z;
    var cz = q.x * q.y;
    var wx = q.w * q.x;
    var wy = q.w * q.y;
    var wz = q.w * q.z;

    return {
        _00 : 1.0 - 2.0 * (sy + sz),
        _01 : 2.0 * (cz + wz),
        _02 : 2.0 * (cy - wy),
        _10 : 2.0 * (cz - wz),
        _11 : 1.0 - 2.0 * (sx + sz),
        _12 : 2.0 * (cx + wx),
        _20 : 2.0 * (cy + wy),
        _21 : 2.0 * (cx - wx),
        _22 : 1.0 - 2.0 * (sx + sy),
        _30 : 0.0,
        _31 : 0.0,
        _32 : 0.0
    };
}
 
例)クォータニオンから行列に変換する

  var axis_x = {x:1,y:0,z:0};
  var quat = QuatRotate(axis_x,90);

  var m = QuatConvertToMatrix(quat);







クォータニオンから回転行列に変換する

第01引数クォータニオン
戻り値に変換後の行列が返ります。

クォータニオンから回転行列に変換する

function QuatRotateConvertToMatrix(q){
    var s = Math.sqrt(q.w * q.w + q.x * q.x + q.y * q.y
+ q.z * q.z); s = 2.0 / (s * s); var vx = q.x * s; var vy = q.y * s; var vz = q.z * s; var wx = vx * q.w; var wy = vy * q.w; var wz = vz * q.w; var sx = q.x * vx; var sy = q.y * vy; var sz = q.z * vz; var cx = q.y * vz; var cy = q.z * vx; var cz = q.x * vy; return { _00 : 1.0 - sy - sz, _01 : cz + wz, _02 : cy - wy, _10 : cz - wz, _11 : 1.0 - sx - sz, _12 : cx + wx, _20 : cy + wy, _21 : cx - wx, _22 : 1.0 - sx - sy, _30 : 0.0, _31 : 0.0, _32 : 0.0 }; }
 
例)クォータニオンから回転行列に変換する

  var axis_x = {x:1,y:0,z:0};
  var quat = QuatRotate(axis_x,90);

  var m = QuatRotateConvertToMatrix(quat);
 

 




クォータニオン同士を球面線形補間する

 
 


 
クォータニオン同士を球面線形補間する

第01引数にクォータニオン
第02引数にクォータニオン
第03引数に係数(0.0 ~ 1.0)
戻り値に補間されたクォータニオンが返ります。

クォータニオン同士を球面線形補間する

function QuatSlerp(q1,q2,d){
  var qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y
+ q1.z * q2.z; var ss = 1.0 - (qr * qr); if (ss == 0.0){ return { x : q1.x, y : q1.y, z : q1.z, w : q1.w }; }else{ var ph = Math.acos(qr); if(qr < 0.0 && ph > Math.PI / 2.0){ var s1,s2; qr = - q1.w * q2.w - q1.x * q2.x - q1.y * q2.y
- q1.z * q2.z; ph = Math.acos(qr); s1 = Math.sin(ph * (1.0 - d)) / Math.sin(ph); s2 = Math.sin(ph * d ) / Math.sin(ph); return { x : q1.x * s1 - q2.x * s2, y : q1.y * s1 - q2.y * s2, z : q1.z * s1 - q2.z * s2, w : q1.w * s1 - q2.w * s2 }; }else{ var s1,s2; s1 = Math.sin(ph * (1.0 - d)) / Math.sin(ph); s2 = Math.sin(ph * d ) / Math.sin(ph); return { x : q1.x * s1 + q2.x * s2, y : q1.y * s1 + q2.y * s2, z : q1.z * s1 + q2.z * s2, w : q1.w * s1 + q2.w * s2 } } } }
 
例)クォータニオン同士を球面線形補間する

  var axis_x = {x:1,y:0,z:0};
  var quat1 = QuatRotate(axis_x,90);
  var axis_y = {x:0,y:1,z:0};
  var quat2 = QuatRotate(axis_y,45);

  var quat3 = QuatSlerp(quat1,quat2,0.5);
 

 




ソースをダウンロード

 
 





- 関数をまとめたソース -

quat.as(10kバイト)ActionScript ファイル